利用WordPress构建页面快速上线年度报告

前言

2024年年底已经到了,看到网易云音乐和QQ音乐的年度报告,突然觉得,我也可以给同事们安排一个。

实际上这个想法2023年就已经有了,并且也确实做了一些工作,但是因为不懂CSS和JavaScript,所以很难做出来漂亮美观的页面。

在大概8年前,我尝试过用WordPress来搭建博客和个人网站,虽然后来没有再使用,但是对WordPress + Elementor这种直接可视化拖动小部件来搭建网页的方式,印象非常深刻。它能让一个完全不懂前端的人,快速地搭建一个相对美观的网页。

技术方案概览

本文介绍的技术方案,能够让你在对前端一无所知的情况下,也能构建出一个美观的、带有简单动画的年度报告页面。整体技术架构如下:

可视化设计

Simply Static插件

替换占位符

Python脚本渲染

上传

EdgeOne加速

推送链接

WordPress + Elementor Pro

页面构建

导出静态资源

Jinja2模板

个性化HTML页面

腾讯云对象存储

静态网站访问

钉钉工作通知

核心流程

步骤 工具/技术 主要功能
1. 页面设计 WordPress + Elementor Pro 可视化拖拽构建美观页面
2. 静态化导出 Simply Static 插件 将动态网站转换为静态资源
3. 模板化处理 Jinja2 + Python 将数据占位符转换为模板变量
4. 数据渲染 Python + PostgreSQL 从数据库提取数据并渲染页面
5. 部署上线 腾讯云COS + EdgeOne 托管静态资源并提供CDN加速
6. 消息推送 钉钉工作通知 自动推送个性化报告链接

最终效果展示

工作通知效果:

工作通知卡片
通知详情

年度报告页面效果:

报告页面


第一步 构建页面

1.1 Docker部署WordPress环境

使用Docker Compose可以快速搭建WordPress开发环境,以下是完整的配置文件:

services:
  wordpress:
    image: wordpress:php8.3
    restart: always
    volumes:
      - './html/plugins:/var/www/html/wp-content/plugins'
      - './html/uploads:/var/www/html/wp-content/uploads'
      - './html/public_static:/var/www/html/public_static'
      - './php/php.ini:/usr/local/etc/php/php.ini'
    ports:
      - '60080:80'
    environment:
      TZ: "Asia/Shanghai"
      WORDPRESS_DB_NAME: 'wordpress'
      WORDPRESS_DB_USER: 'root'
      WORDPRESS_DB_PASSWORD: '********'
      WORDPRESS_DB_HOST: 'mysql'
      WORDPRESS_CONFIG_EXTRA: |
        define( 'WP_MEMORY_LIMIT', '1024M' );
        define( 'WP_MAX_MEMORY_LIMIT', '2048M' );
        define( 'WP_SITEURL', 'https://<your-domain>' );
        define( 'WP_HOME', 'https://<your-domain>' );
        define( 'WP_CACHE', true );
        define( 'WP_ENVIRONMENT_TYPE', 'production' );
        
  mysql:
    image: mysql:latest
    restart: always
    volumes:
      - 'mysql-data:/var/lib/mysql'
    environment:
      MYSQL_DATABASE: 'wordpress'
      MYSQL_ROOT_PASSWORD: '********'

volumes:
  mysql-data:

配置说明

配置项 说明 重要性
plugins 目录挂载 持久化插件数据,方便备份和迁移 ⭐⭐⭐
uploads 目录挂载 保存上传的媒体文件 ⭐⭐⭐
public_static 目录挂载 Simply Static插件导出目录 ⭐⭐⭐
php.ini 挂载 调整内存限制和上传大小 ⭐⭐
WORDPRESS_CONFIG_EXTRA 自动生成wp-config.php配置 ⭐⭐⭐

💡 提示: 无需手动挂载 wp-config.php 文件,容器启动时会根据环境变量自动生成。

域名和SSL配置

将访问端口接入到腾讯云EdgeOne来获得公网访问域名并添加SSL证书,然后将域名配置到 WORDPRESS_CONFIG_EXTRA 环境变量中。

⚠️ 重要: 如果想要使用Elementor Pro构建器获得更多的页面动态效果、视差效果,则必须使用域名访问,否则无法激活Pro版本插件。

1.2 安装必要插件

Elementor Pro 页面构建器

Elementor Pro是WordPress最强大的可视化页面构建器之一,提供了丰富的小部件和动画效果。

获取方式:

  • 官方购买(推荐)
  • 淘宝购买:价格在18元~30元不等
  • 激活方式:提供网站公网访问地址、管理员用户名和密码给商家

Simply Static 静态网站转换插件

Simply Static可以将WordPress动态网站转换为纯静态HTML文件。

安装方式:

  1. 在WordPress后台插件商店搜索"Simply Static"直接安装
  2. 或访问官网下载后上传到 ./html/plugins 目录

其他推荐插件

插件列表

可以根据需要安装其他Elementor相关插件,获得更加丰富的页面小部件和功能扩展。

1.3 可视化构建页面

创建新页面

  1. 在WordPress后台进入「页面」菜单
  2. 点击「新建页面」
  3. 选择「使用Elementor编辑」

创建页面

页面布局设置

由于年度报告不需要导航栏和菜单栏,建议进行以下设置:

  1. 打开页面设置面板
  2. 将「页面布局」设置为「Elementor 画布
  3. 这样可以获得全屏显示效果

页面布局设置

响应式设计技巧

设置板块

最小高度: 100vh

自适应手机屏幕

满屏显示效果

截图更美观

关键设置:

  • 将每个板块的「最小高度」设置为 100vh
  • 这样每个部分都能动态适应各种型号的手机屏幕
  • 截图时能够更加美观

📌 注意: 最小高度不等于实际高度,如果一个板块中的元素过多,可能会超出手机屏幕的高度。

数据占位符设置

在构建页面时,将需要动态替换的数据部分写成占位符格式:

<div class="user-name">{{name}}</div>
<div class="report-date">{{date}}</div>
<div class="data-value">{{some_data}}</div>

这样在转换成静态页面后,可以轻松地将这些占位符替换成Jinja2模板的实际字段名。

1.4 导出静态页面

完成页面构建并预览效果满意后,使用Simply Static插件进行静态化导出。

配置导出设置

步骤1:设置使用模式

进入插件的 Settings → General 页面,设置为 Offline Usage 模式:

使用模式设置

步骤2:配置导出目录

进入插件的 Settings → Deploy 页面:

  1. 设置为 Local Directory
  2. 配置导出目录为 /var/www/html/public_static

导出目录设置

步骤3:执行导出

  1. 点击 Generate Static Files 按钮
  2. 切换到 Activity Log 标签查看日志
  3. 等待出现 Done! Finished in <time> 字样

导出日志

⚠️ 导出前检查: 建议先到 Diagnostics 诊断工具页面检查是否可以转换、是否存在不兼容插件等情况。


第二步 生成报告

2.1 整理静态资源

./html/public_static 目录中生成的所有静态文件复制到一个新的项目文件夹。

清理不必要的文件

由于我们将需要的页面设置成了网站主页,所以目录下的 index.html 就是我们需要的模板文件。

清理建议:

可删除内容 说明
其他页面HTML 除index.html外的页面文件
文章和评论相关资源 不需要的博客功能资源
未使用的插件资源 页面中未引用的插件文件
未使用的主题资源 不需要的主题文件

💡 清理技巧:

  1. 先做好备份
  2. 在浏览器中打开index.html
  3. 逐步删除文件,观察页面是否异常
  4. 如有异常,立即恢复文件

2.2 编写数据渲染脚本

创建Python脚本,实现从数据库查询数据并渲染到HTML模板的功能。

完整示例代码

from datetime import datetime
import os
import psycopg
from pydantic import BaseModel
from jinja2 import Environment, FileSystemLoader

# 定义教师列表
teachers = ["张三", "李四", "王五"]

# 配置Jinja2模板环境
template_dir = os.path.join(os.path.dirname(__file__), 'static')
env = Environment(loader=FileSystemLoader(template_dir))
template = env.get_template('index.html')

# 定义数据模型
class ReportData(BaseModel):
    name: str
    date: str = datetime.now().strftime("%Y-%m-%d %H:%M")
    some_data: int = 0

# 连接数据库
conn = psycopg.connect("postgresql://<user>:<pwd>@<host>:5432/<database>")
cur = conn.cursor()

# 为每位教师生成报告
for teacher in teachers:
    report_data = ReportData(name=teacher)
    
    # 查询教师数据
    cur.execute("""
        SELECT .... AS some_data FROM table
        WHERE "teacherName" = %s 
        AND "startTime" BETWEEN '2024-01-01' AND '2024-12-31';
    """, [teacher])
    
    record = cur.fetchone()
    if record:
        report_data.some_data = record[0]
    
    # 渲染模板
    output = template.render(report_data.model_dump())
    
    # 保存HTML文件
    with open(f'static/{teacher}.html', 'w', encoding="utf-8") as f:
        f.write(output)

cur.close()
conn.close()

代码流程图

开始

加载Jinja2模板

连接PostgreSQL数据库

遍历教师列表

创建ReportData对象

查询教师数据

查询到数据?

填充数据到对象

使用默认值

渲染模板

保存HTML文件

还有教师?

关闭数据库连接

结束

模板变量替换

在运行脚本前,需要将 index.html 中的占位符替换为实际的模板变量:

原占位符 替换为 说明
{{data}} {{name}} 教师姓名
{{data}} {{date}} 报告生成日期
{{data}} {{some_data}} 统计数据

2.3 测试和调整

运行脚本后,会生成 张三.html李四.html王五.html 三个年度报告文件。

测试流程:

  1. 在浏览器中打开生成的HTML文件
  2. 检查数据是否正确渲染
  3. 检查样式和动画是否正常
  4. 如需调整,可以:
    • 直接修改 index.html 模板
    • 或重新编辑WordPress页面并导出

第三步 部署推送

3.1 配置腾讯云对象存储

创建存储桶

  1. 登录腾讯云控制台
  2. 进入对象存储COS服务
  3. 创建新的存储桶(建议设置为私有读写)

开启静态网站功能

在存储桶设置中找到「静态网站」功能并开启:

静态网站配置

配置项说明:

  • 索引文档:设置为 index.html
  • 错误文档:可设置为 404.html(可选)
  • 强制HTTPS:建议开启

配置EdgeOne加速

使用腾讯云EdgeOne配置域名并接入存储桶:

EdgeOne配置

配置步骤:

  1. 在EdgeOne中添加域名
  2. 配置源站为COS存储桶
  3. 开启HTTPS和CDN加速
  4. 配置缓存规则(建议静态资源长期缓存)

验证配置

上传静态资源到存储桶根目录,访问 http://your-domain/index.html 验证配置是否正确。

文件上传

3.2 实现自动化上传和推送

完整自动化脚本

from datetime import datetime
import os
import uuid
import psycopg
from pydantic import BaseModel
from jinja2 import Environment, FileSystemLoader
from qcloud_cos import CosConfig, CosS3Client
from dagster_dingtalk import DingTalkAppClient

# 初始化COS客户端
cos_client = CosS3Client(
    CosConfig(
        Region="ap-guangzhou",
        SecretId="<your-secretid>",
        SecretKey="<your-secretkey>"
    )
)

# 初始化钉钉客户端
dt_client = DingTalkAppClient(
    app_id="<your-app_id>",
    client_id="<your-client_id>",
    client_secret="<your-client_secret>"
)

# 配置模板和数据库
teachers = ["张三", "李四", "王五"]
template_dir = os.path.join(os.path.dirname(__file__), 'static')
env = Environment(loader=FileSystemLoader(template_dir))
template = env.get_template('index.html')

class ReportData(BaseModel):
    name: str
    date: str = datetime.now().strftime("%Y-%m-%d %H:%M")
    some_data: int = 0

conn = psycopg.connect("postgresql://<user>:<pwd>@<host>:5432/<database>")
cur = conn.cursor()

# 为每位教师生成并推送报告
for teacher in teachers:
    # 创建报告数据对象
    report_data = ReportData(name=teacher)
    
    # 查询数据
    cur.execute("""
        SELECT .... AS some_data FROM table
        WHERE "teacherName" = %s 
        AND "startTime" BETWEEN '2024-01-01' AND '2024-12-31';
    """, [teacher])
    
    record = cur.fetchone()
    if record:
        report_data.some_data = record[0]
    
    # 渲染模板
    output = template.render(report_data.model_dump())
    
    # 生成唯一文件名(UUID后12位)
    uuid_str = str(uuid.uuid4())[-12:]
    
    # 上传到COS
    cos_client.put_object(
        Bucket='<your-bucket>',
        Body=output.encode('utf-8'),
        Key=f'{uuid_str}.html',
        EnableMD5=False
    )
    
    # 构建钉钉消息
    msg = {
        "msgtype": "action_card",
        "action_card": {
            "title": "你的年度教学报告来啦!快来查看吧!",
            "markdown": "![](<cover-image-url>)\n"
                       f"\n### {teacher}老师,您的2024年度教学报告已生成!快来查看吧!",
            "single_title": "点击查看",
            "single_url": f"https://<your-domain>/{uuid_str}.html"
        }
    }
    
    # 发送钉钉通知
    dt_client.即时通信.工作通知.发送工作通知(
        to_all_user=False,
        user_list=[user_id],
        msg=msg
    )

cur.close()
conn.close()

自动化流程图

用户钉钉API腾讯云COSJinja2模板PostgreSQLPython脚本用户钉钉API腾讯云COSJinja2模板PostgreSQLPython脚本loop[遍历每位教师]查询教师数据返回统计数据渲染HTML模板生成HTML内容生成UUID文件名上传HTML文件返回上传成功发送工作通知推送报告链接

安全性设计

为什么使用UUID作为文件名?

方案 优点 缺点 适用场景
使用姓名 简单直观 ❌ 任何人都能猜测URL访问他人报告 公开报告
使用UUID ✅ 无法猜测
✅ 保护隐私
需要维护映射关系 私密报告

通过截取UUID的后12位作为文件名,既保证了唯一性,又增加了URL的不可预测性,有效保护了用户隐私。

⚠️ 注意: 示例代码中使用的 dagster_dingtalk 库是用于dagster环境的第三方库。在实际使用中,建议根据钉钉开放平台文档自行编写与钉钉OpenAPI交互的代码。


总结与展望

方案优势

优势 说明
🎨 零前端门槛 无需CSS/JS知识,可视化拖拽即可完成
快速上线 从设计到上线可在1-2天内完成
🔄 易于维护 样式调整只需在WordPress中修改
📊 数据驱动 支持从数据库动态生成个性化内容
🔒 安全可靠 UUID文件名保护隐私,CDN加速访问
💰 成本低廉 主要成本为Elementor Pro授权和云服务

技术栈总结

年度报告技术栈前端设计后端处理云服务消息推送WordPressElementor ProSimply StaticPythonJinja2PostgreSQL腾讯云COSEdgeOne CDN钉钉OpenAPI工作通知

可扩展方向

  1. 数据可视化增强

    • 集成ECharts/Chart.js生成动态图表
    • 添加更多统计维度和数据分析
  2. 交互功能扩展

    • 添加用户反馈收集功能
    • 实现社交分享功能
  3. 自动化优化

    • 使用定时任务自动生成和推送
    • 集成CI/CD实现自动部署
  4. 多渠道推送

    • 支持企业微信、飞书等多平台
    • 短信/邮件备用推送渠道

注意事项

  • ✅ 确保WordPress使用域名访问以激活Elementor Pro
  • ✅ 定期备份WordPress数据和静态文件
  • ✅ 注意数据库查询性能,大量用户时考虑分批处理
  • ✅ COS存储桶建议设置生命周期规则,定期清理过期文件
  • ✅ 钉钉推送注意频率限制,避免触发限流

至此,一个完整的年度报告生成和推送系统就搭建完成了!这套方案不仅适用于年度报告,也可以扩展到其他需要批量生成个性化页面的场景,如证书生成、成绩单发布等。希望这篇文章能帮助到有类似需求的朋友们!🎉