WordPress + Elementor + ACF 实现产品下载列表:自动显示文件名和文件大小

在使用 WordPress 搭建企业官网或产品展示网站时,产品详情页通常需要提供资料下载功能,例如产品彩页、用户手册、安装说明书、软件包等。

如果每个产品都手动写下载链接,不仅维护麻烦,而且后期更换文件时也容易出错。更好的方式是使用 ACF 给产品添加文件字段,然后在前端自动读取文件信息,生成统一样式的下载列表。

本文介绍一种适用于 WordPress、Elementor 和 ACF 的实现方法,可以在产品详情页中自动显示两个文件下载项,并展示媒体库中文件的真实文件名和文件大小。

实现效果

最终前端会显示一个简洁的下载列表,每一行包含:

文件类型图标,例如 PDF、ZIP
文件名称,自动读取上传到媒体库的文件名
文件大小,例如 35.4MB、1.6MB
点击整行即可下载文件

同时,列表支持悬停交互效果:

鼠标悬停时背景变为浅蓝色
左侧出现蓝色装饰线
文件名称和文件大小变为主题蓝色
文件图标轻微上浮
整体无阴影,更适合放在产品详情页的下载 Tab 中

使用场景

这个方案适合以下页面:

产品详情页
资料下载区
Elementor 自定义产品模板
WooCommerce 产品详情页 Tab
企业官网产品资料模块

例如,一个产品可以在后台上传:

产品彩页下载
产品用户手册下载

前端会自动输出类似这样的下载列表:

SMA26-PRO_Plus-RTK-User-Manual_260427.pdf   35.4MB
SMA26-PRO-survey-system_catalog_260506.pdf   1.6MB

第一步:使用 ACF 添加文件字段

先在 ACF 中给产品添加两个文件字段。

建议字段设置如下:

字段类型:文件
返回值:文件数组
文件库:全部

字段名称可以设置为:

产品彩页下载
产品用户手册下载

需要注意的是,代码中读取的是 ACF 的“字段名称”,不是“字段标签”。如果你的字段名称是英文,例如 product_brochure_downloadproduct_manual_download,那么后面代码中的字段名也要对应修改。

第二步:添加 Shortcode 代码

可以把下面这段代码添加到子主题的 functions.php 文件中,也可以使用 Code Snippets 插件添加。

如果使用 Code Snippets,建议新建一段 PHP 代码,并设置为在前台运行。

/**
 * 产品下载列表 Shortcode
 * 用法:[sma_product_downloads]
 */

add_shortcode('sma_product_downloads', function () {

    if (!function_exists('get_field')) {
        return '';
    }

    $post_id = get_the_ID();

    /**
     * 改成你 ACF 文件字段的“字段名称”
     * 注意:是字段名称,不是字段标签
     */
    $fields = [
        '产品彩页下载',
        '产品用户手册下载',
    ];

    $files = [];

    foreach ($fields as $field_name) {
        $file = get_field($field_name, $post_id);

        if (empty($file)) {
            continue;
        }

        $file_data = sma_get_acf_file_data($file);

        if (!empty($file_data['url'])) {
            $files[] = $file_data;
        }
    }

    if (empty($files)) {
        return '';
    }

    ob_start();
    ?>

    <style>
        .sma-download-list {
            width: 100%;
            max-width: 100%;
            margin: 0;
            padding: 8px 0;
            background: #ffffff;
            border: none;
            box-shadow: none;
        }

        .sma-download-item {
            position: relative;
            display: flex;
            align-items: center;
            justify-content: space-between;
            width: 100%;
            gap: 24px;
            padding: 20px 28px;
            border-bottom: 1px solid #eeeeee;
            background: #ffffff;
            color: #333333;
            text-decoration: none !important;
            box-shadow: none !important;
            outline: none;
            overflow: hidden;
            transition:
                background-color 0.22s ease,
                color 0.22s ease,
                border-color 0.22s ease;
        }

        .sma-download-item:first-child {
            border-top: 1px solid #eeeeee;
        }

        .sma-download-item::before {
            content: "";
            position: absolute;
            left: 0;
            top: 16px;
            bottom: 16px;
            width: 3px;
            background: #0b4f7a;
            border-radius: 3px;
            opacity: 0;
            transform: scaleY(0.35);
            transition:
                opacity 0.22s ease,
                transform 0.22s ease;
        }

        .sma-download-item:hover {
            background: #f6fafd;
            color: #0b4f7a;
            border-bottom-color: #e2edf5;
        }

        .sma-download-item:hover::before {
            opacity: 1;
            transform: scaleY(1);
        }

        .sma-download-left {
            display: flex;
            align-items: center;
            gap: 18px;
            min-width: 0;
            flex: 1 1 auto;
            position: relative;
            z-index: 1;
        }

        .sma-download-icon {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 22px;
            height: 22px;
            min-width: 22px;
            border-radius: 3px;
            background: #25b45b;
            color: #ffffff;
            font-size: 7px;
            line-height: 1;
            font-weight: 700;
            letter-spacing: -0.2px;
            transition:
                background-color 0.22s ease,
                transform 0.22s ease;
        }

        .sma-download-item:hover .sma-download-icon {
            background: #0b4f7a;
            transform: translateY(-1px);
        }

        .sma-download-name {
            display: block;
            font-size: 15px;
            font-weight: 400;
            line-height: 1.55;
            color: inherit;
            word-break: break-word;
        }

        .sma-download-size {
            min-width: 90px;
            text-align: right;
            font-size: 14px;
            font-weight: 400;
            line-height: 1.4;
            color: #333333;
            white-space: nowrap;
            position: relative;
            z-index: 1;
            transition: color 0.22s ease;
        }

        .sma-download-item:hover .sma-download-size {
            color: #0b4f7a;
        }

        .sma-download-item:focus,
        .sma-download-item:active {
            outline: none;
            box-shadow: none !important;
        }

        @media (max-width: 767px) {
            .sma-download-list {
                padding: 4px 0;
            }

            .sma-download-item {
                align-items: flex-start;
                padding: 16px 14px;
                gap: 12px;
            }

            .sma-download-left {
                gap: 12px;
            }

            .sma-download-icon {
                width: 20px;
                height: 20px;
                min-width: 20px;
                font-size: 7px;
                margin-top: 2px;
            }

            .sma-download-name {
                font-size: 14px;
                line-height: 1.5;
            }

            .sma-download-size {
                min-width: auto;
                font-size: 13px;
                padding-top: 2px;
            }
        }

        @media (max-width: 480px) {
            .sma-download-item {
                flex-direction: column;
                align-items: stretch;
            }

            .sma-download-size {
                padding-left: 32px;
                text-align: left;
                color: #777777;
            }
        }
    </style>

    <div class="sma-download-list">
        <?php foreach ($files as $file) : ?>
            <a class="sma-download-item" href="<?php echo esc_url($file['url']); ?>" download>
                <div class="sma-download-left">
                    <span class="sma-download-icon" aria-hidden="true">
                        <?php echo esc_html($file['type']); ?>
                    </span>

                    <span class="sma-download-name">
                        <?php echo esc_html($file['name']); ?>
                    </span>
                </div>

                <?php if (!empty($file['size'])) : ?>
                    <span class="sma-download-size">
                        <?php echo esc_html($file['size']); ?>
                    </span>
                <?php endif; ?>
            </a>
        <?php endforeach; ?>
    </div>

    <?php
    return ob_get_clean();
});


/**
 * 兼容 ACF 文件字段返回:数组 / ID / URL
 */
function sma_get_acf_file_data($file) {

    $url = '';
    $name = '';
    $size = '';
    $type = 'FILE';

    if (is_array($file)) {
        $url = $file['url'] ?? '';
        $id = $file['ID'] ?? 0;

        if (!empty($url)) {
            $name = basename(parse_url($url, PHP_URL_PATH));
            $type = sma_get_file_type_label($name);
        }

        if (!empty($id)) {
            $file_path = get_attached_file($id);

            if ($file_path && file_exists($file_path)) {
                $size = sma_format_file_size(filesize($file_path));
            }
        }

        if (empty($size) && !empty($file['filesize'])) {
            $size = sma_format_file_size($file['filesize']);
        }
    }

    elseif (is_numeric($file)) {
        $id = (int) $file;
        $url = wp_get_attachment_url($id);

        if (!empty($url)) {
            $name = basename(parse_url($url, PHP_URL_PATH));
            $type = sma_get_file_type_label($name);
        }

        $file_path = get_attached_file($id);

        if ($file_path && file_exists($file_path)) {
            $size = sma_format_file_size(filesize($file_path));
        }
    }

    elseif (is_string($file)) {
        $url = $file;
        $name = basename(parse_url($url, PHP_URL_PATH));
        $type = sma_get_file_type_label($name);
    }

    return [
        'url'  => $url,
        'name' => $name,
        'size' => $size,
        'type' => $type,
    ];
}


/**
 * 根据文件扩展名显示图标文字
 */
function sma_get_file_type_label($filename) {

    $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));

    if ($ext === 'pdf') {
        return 'PDF';
    }

    if ($ext === 'zip') {
        return 'ZIP';
    }

    if (in_array($ext, ['doc', 'docx'], true)) {
        return 'DOC';
    }

    if (in_array($ext, ['xls', 'xlsx'], true)) {
        return 'XLS';
    }

    if (in_array($ext, ['jpg', 'jpeg', 'png', 'webp'], true)) {
        return 'IMG';
    }

    return strtoupper(substr($ext, 0, 4)) ?: 'FILE';
}


/**
 * 文件大小格式化
 */
function sma_format_file_size($bytes) {

    $bytes = (int) $bytes;

    if ($bytes <= 0) {
        return '';
    }

    if ($bytes >= 1048576) {
        return round($bytes / 1048576, 1) . 'MB';
    }

    return round($bytes / 1024) . 'KB';
}

第三步:在 Elementor 中调用

代码添加完成后,进入 Elementor 编辑产品详情页模板。

在下载板块中添加一个 Shortcode 小工具,然后输入:

[sma_product_downloads]

保存后,前端就会自动读取当前产品中的 ACF 文件字段,并输出下载列表。

如果前端不是全宽怎么办?

代码中的 .sma-download-list 已经设置为:

width: 100%;
max-width: 100%;

如果前端看起来仍然不是全宽,通常不是代码问题,而是 Elementor 外层容器限制了宽度。

可以检查以下位置:

Elementor Section 或 Container 的 Content Width 是否为 Full Width
外层容器是否设置了固定宽度
Column 或 Container 是否有左右 Padding
主题模板是否限制了产品详情内容宽度

如果想让下载列表铺满当前 Tab 内容区域,只需要确保放 Shortcode 的 Elementor 容器本身是全宽即可。

字段名称如何修改?

如果你的 ACF 字段名称不是中文,而是英文,例如:

product_catalog_download
product_manual_download

那么只需要修改代码中的这一段:

$fields = [
    '产品彩页下载',
    '产品用户手册下载',
];

改成:

$fields = [
    'product_catalog_download',
    'product_manual_download',
];

这样前端就会读取对应的两个文件字段。

代码特点

这段代码兼容 ACF 文件字段的多种返回值:

文件数组
文件 ID
文件 URL

同时会自动判断文件类型,并在前端显示不同的图标文字:

PDF 文件显示 PDF
ZIP 文件显示 ZIP
Word 文件显示 DOC
Excel 文件显示 XLS
图片文件显示 IMG
其他文件显示 FILE

文件大小会自动格式化为 KB 或 MB,前端展示更直观。

总结

通过 ACF 文件字段和 WordPress Shortcode,可以非常方便地为 Elementor 产品详情页添加下载列表。

相比手动写下载链接,这种方式有几个明显优势:

后台上传文件即可自动更新前端
文件名直接读取媒体库文件名
文件大小自动显示
样式统一,方便维护
适合多个产品复用
后期更换文件不需要改页面结构

对于企业官网、WooCommerce 产品页、设备产品资料下载页来说,这种方案维护成本低,展示效果也更加专业。

posted @ 2026-06-25 10:51  还好阿卡  阅读(1)  评论(0)    收藏  举报