织梦如何设置文章过期自动下架

促销活动、招聘信息、限时公告等类型的文章有明确的失效时间,过期后应自动从列表隐藏或直接 404,避免误导用户。织梦本身没有“过期时间”字段,需要扩展字段 + 定时任务实现。本文给出完整方案。

一、需求场景

核心是两点:①列表与详情页能识别“已过期”;②有机制在过期时改变文章状态。

二、第一步:给文档模型增加过期时间字段

后台 核心 - 频道模型 - 内容模型管理 - 普通文章 - 字段管理 - 添加新字段

或直接 SQL 添加:

ALTER TABLE dede_addonarticle ADD COLUMN expiretime INT UNSIGNED DEFAULT 0;

对应在 dede_archives 主表也加一个便于查询:

ALTER TABLE dede_archives ADD COLUMN expiretime INT UNSIGNED DEFAULT 0;

三、第二步:发布文章时填写过期时间

在文章发布模板 /dede/templets/archives_add.htm 增加日期选择框:

<tr>
  <td width="100">过期时间:</td>
  <td>
    <input type="text" name="expiretime" id="expiretime"
           value="0" class="datepicker" />
    <span style="color:#999">留 0 表示不过期</span>
  </td>
</tr>

并在 /dede/archives_add.php 保存逻辑里把日期转为时间戳:

$expiretime=empty($expiretime) ? 0 : strtotime($expiretime);
$expiretime=$expiretime < time() ? 0 : $expiretime;

四、第三步:定时任务自动下架

编写下架脚本 /expire_cron.php

<?php
require_once dirname(__FILE__).'/include/common.inc.php';
$now=time();

// 把已过期文章 arcrank 设为 -1(未审核)
$dsql->ExecuteNoneQuery(
    "UPDATE dede_archives SET arcrank=-1
     WHERE expiretime > 0 AND expiretime < $now AND arcrank >=0"
);

// 同步 arctiny
$dsql->ExecuteNoneQuery(
    "UPDATE dede_arctiny SET arcrank=-1
     WHERE id IN (
         SELECT id FROM dede_archives
         WHERE expiretime > 0 AND expiretime < $now AND arcrank=-1
     )"
);

// 删除已过期文章的静态 HTML
$dsql->SetQuery(
    "SELECT id, typeid, senddate FROM dede_archives
     WHERE expiretime > 0 AND expiretime < $now"
);
$dsql->Execute();
while($row=$dsql->GetArray()){
    $date=date('Y/m/d', $row['senddate']);
    $file=DEDEDATA."/../a/{$date}/{$row['id']}.html";
    if(file_exists($file)) @unlink($file);
}

// 写日志
file_put_contents(__DIR__.'/data/log/expire.log',
    date('Y-m-d H:i:s')." expired check done\n", FILE_APPEND);

宝塔计划任务每小时执行:

0 * * * * /www/server/php/74/bin/php /www/wwwroot/yourdomain.com/expire_cron.php

五、第四步:列表与详情页过滤

1. arclist 过滤已过期文章

模板里 arclist 加 where 条件:

{dede:arclist typeid='1' row='10' where="expiretime=0 OR expiretime>UNIX_TIMESTAMP()"}
  <li><a href="[field:arcurl/]">[field:title/]</a></li>
{/dede:arclist}

2. 详情页过期后显示提示

文章模板 article_article.htm 顶部:

<?php
$aid=(int)$aid;
$row=$dsql->GetOne("SELECT expiretime FROM dede_archives WHERE id=$aid");
if($row['expiretime'] > 0 && $row['expiretime'] < time()){
    header("HTTP/1.1 410 Gone");
    ?>
    <h1>该内容已过期</h1>
    <p>您访问的内容已于 <?php echo date('Y-m-d', $row['expiretime']); ?> 过期下架。</p>
    <p><a href="/">返回首页</a></p>
    <?php
    exit;
}
?>

六、第五步:通知搜索引擎

过期文章下架后:

  1. 更新 sitemap,移除过期 URL;
  2. 把过期 URL 加入死链清单提交百度;
  3. 对过期 URL 返回 410 Gone(比 404 更明确表示“永久删除”)。
// Nginx 对过期文章目录返回 410
location ~ ^/a/2026/(\d+)/(\d+)\.html$ {
    # 由 PHP 判断后返回 410
    try_files $uri @expired;
}
location @expired {
    return 410;
}

七、注意事项

文章过期下架本质是“字段扩展 + 定时任务 + 前台过滤”三件套。建议根据业务场景调整下架策略:促销类直接 410,公告类可保留显示但加“已过期”标识。把过期逻辑跑通后,站点内容始终保持时效性,既提升用户信任也避免被搜索引擎判定为低质过时内容。