⚠️ 浏览器不兼容

抱歉,您的浏览器版本过低或内核不兼容,无法正常显示本站内容。

推荐使用以下浏览器:

⚠️ 风险提示

您正在使用不兼容的浏览器访问本站,可能会遇到以下问题:

警告:继续使用可能导致安全风险或功能异常,所有后果由您自行承担。

2337 字
12 分钟
记录
2026-04-08

一、外部链接跳转提示#

1.功能说明#

当用户点击新窗口打开的外部链接时,会显示一个确认弹窗,提示用户即将离开本站,确保用户了解他们正在访问的网站。

2.实现位置#

  • 代码位置src/layouts/Layout.astro
  • 弹窗HTML:在 <head> 标签内定义了 externalLinkModal 弹窗
  • JavaScript逻辑:在 <script is:inline> 标签内实现了链接点击监听和弹窗显示逻辑

3.禁用方法#

方法一:对单个链接禁用#

为特定链接添加 data-no-external-prompt 属性:

<a href="https://example.com" target="_blank" data-no-external-prompt>外部链接(无提示)</a>

方法二:对整个页面禁用(以下方法选一个就行)#

第一种:在单个文件内设置,无需修改全局文件#

在页面的 body 标签上添加 no-external-prompt 类:

<body class="no-external-prompt">
<!-- 页面内容 -->
</body>

第二种:方便多个同时设置(实际上非常不实用,能用第一个尽量用第一个,这个就是在第一种方式不行的时候作为备选),需要修改全局文件#

步骤 1:修改 Layout.astro 文件中的初始页面加载逻辑#

  • 操作:打开 src/layouts/Layout.astro 文件,找到 disableExternalPrompt 常量的定义(大约在第40行)
  • 作用:这一步确保在页面首次加载时,新添加的页面能够正确禁用外部链接跳转提示
  • 具体修改:在条件判断中添加新页面的路径,例如:
    const disableExternalPrompt = pathname === url("/ym") || pathname === url("/xy") || pathname === url("/about") || pathname === url("/new-page");

步骤 2:修改 Swup 钩子中的页面切换逻辑#

  • 操作:在同一个文件中,找到 visit:start 钩子的定义(大约在第496行)
  • 作用:这一步确保在用户通过页面导航切换到新添加的页面时,外部链接跳转提示也会被正确禁用
  • 具体修改:在条件判断中添加新页面的路径,例如:
    if (toPath === url('/ym') || toPath === url('/xy') || toPath === url('/about') || toPath === url('/new-page')) {
    bodyElement!.classList.add('no-external-prompt');
    } else {
    bodyElement!.classList.remove('no-external-prompt');
    }

关于方法二中的实现方法解释:为什么使用路径检查逻辑#

src/layouts/Layout.astro 文件中,我们添加了对特定页面路径的检查逻辑,原因如下:

  1. 全面禁用:虽然我们可以为每个外部链接添加 data-no-external-prompt 属性,但这种方法需要手动修改每个链接,容易遗漏。通过在 Layout.astro 中添加路径检查逻辑,我们可以确保这些页面的所有外部链接都自动禁用跳转提示。
  2. 一致性:这些页面通常包含多个外部链接(如社交媒体链接、个人网站链接等),用户点击这些链接时,通常已经知道他们要访问的是外部网站,因此不需要再显示跳转提示,这样可以提供更一致的用户体验。
  3. 维护方便:通过集中管理这些页面的外部链接跳转提示设置,后续如果需要添加或修改禁用跳转提示的页面,只需要修改 Layout.astro 文件中的路径检查逻辑即可,不需要逐个修改页面中的链接。
  4. 页面切换时的处理:我们还在 Swup 的 visit:start 钩子中添加了逻辑,确保在页面切换时,body 标签的 no-external-prompt 类也能正确更新,这样即使用户通过页面导航切换到这些页面,外部链接跳转提示也会被正确禁用。

二、全局人机验证组件#

1.组件位置#

  • 文件位置src/components/misc/TurnstileModal.astro

2.功能说明#

提供统一的人机验证功能,可在整个博客中调用,用于防止恶意提交和自动化攻击。

3.调用方式#

(1) 导入组件#

在需要使用人机验证的页面中,首先导入 TurnstileModal 组件:

import TurnstileModal from "../components/misc/TurnstileModal.astro";

(2) 添加组件#

在页面的合适位置添加组件(通常在页面底部):

<!-- 全局人机验证组件 -->
<TurnstileModal />

(3) 调用验证#

在需要验证的地方(例如表单提交前),使用以下代码调用验证:

// 显示人机验证,使用回调函数
window.turnstileInstance.show('formName', 'actionName', async function(token) {
// 验证成功后的回调函数
// 在这里处理表单提交等逻辑
console.log('人机验证成功,token:', token);
// 示例:提交表单
const formData = {
// 表单数据
cfTurnstileResponse: token // 包含验证令牌
};
// 调用API
const response = await fetch('/api/endpoint', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
});
// 处理响应...
});

(4) 参数说明#

  • formName:表单名称,用于标识是哪个表单触发的验证
  • actionName:操作名称,用于 Cloudflare Turnstile 的分析和安全策略
  • callback:验证成功后的回调函数,接收验证令牌作为参数

4.示例:在表单提交时使用#

const form = document.getElementById('myForm');
if (form) {
form.addEventListener('submit', function(e) {
e.preventDefault();
// 显示人机验证
window.turnstileInstance.show('myForm', 'form_submit', async function(token) {
// 验证成功,提交表单
const formData = new FormData(form);
formData.append('cfTurnstileResponse', token);
// 提交表单...
});
});
}

5.环境变量配置#

(1)配置步骤#

  • 登录 Cloudflare 控制台,进入 Pages 项目
  • 在 “设置” > “环境变量” 中添加以下变量:
    • TURNSTILE_SITE_KEY:Cloudflare Turnstile 网站密钥
    • TURNSTILE_SECRET_KEY:Cloudflare Turnstile 秘密密钥
    • SECRET_KEY:用于生成和验证登录令牌的安全密钥

(2)环境变量配置示例#

环境变量名称类型说明
TURNSTILE_SITE_KEY字符串Cloudflare Turnstile 网站密钥
TURNSTILE_SECRET_KEY字符串Cloudflare Turnstile 秘密密钥
SECRET_KEY字符串用于生成和验证登录令牌的安全密钥

(3)代码实现#

环境变量获取方式#

src/utils/auth-utils.ts 文件中,环境变量的获取方式如下:

// 获取环境变量
function getEnv(): Env {
// 在 Astro 项目中,环境变量可以通过 import.meta.env 获取
if (import.meta && import.meta.env) {
return {
SECRET_KEY: import.meta.env.SECRET_KEY,
TURNSTILE_SITE_KEY: import.meta.env.TURNSTILE_SITE_KEY,
TURNSTILE_SECRET_KEY: import.meta.env.TURNSTILE_SECRET_KEY
};
}
// fallback 到 process.env
return {
SECRET_KEY: process.env.SECRET_KEY,
TURNSTILE_SITE_KEY: process.env.TURNSTILE_SITE_KEY,
TURNSTILE_SECRET_KEY: process.env.TURNSTILE_SECRET_KEY
};
}
const env = getEnv();

使用环境变量#

// 验证人机验证
async function validateTurnstile(response: string): Promise<boolean> {
const secretKey = env.TURNSTILE_SECRET_KEY || 'your-turnstile-secret-key';
if (!secretKey) return false;
try {
const res = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `secret=${secretKey}&response=${response}`
});
const data = await res.json();
return data.success;
} catch {
return false;
}
}
// 获取Turnstile站点密钥
export function getTurnstileSiteKey(): string {
return env.TURNSTILE_SITE_KEY || 'your-turnstile-site-key';
}

三、数据库配置#

1.数据库绑定#

  • 配置位置:Cloudflare Pages 的环境变量
  • 配置步骤
    • 登录 Cloudflare 控制台,进入 Pages 项目
    • 在 “设置” > “函数” > “数据库绑定” 中配置
    • 绑定名称:DB
    • 指向的数据库:a14797cb-ed36-49d1-ab8e-0aa46afd848c(boke)

2.密钥配置#

  • Site Key(网站密钥):已硬编码在 src/components/misc/TurnstileModal.astro 文件中
  • Secret Key(秘密密钥):应在 Cloudflare Pages 的环境变量中配置
    • 登录 Cloudflare 控制台,进入 Pages 项目
    • 在 “设置” > “环境变量” 中添加 TURNSTILE_SECRET_KEY 变量

四、顶置文章方法#

1.功能说明#

顶置文章是指在博客首页或文章列表中固定显示在最上方的文章,通常用于展示重要信息或公告。

2.实现方法#

要顶置一篇文章,只需在文章的 frontmatter 中添加 pinned: true 字段:

---
title: 标题
published: 2026-03-29
description: 介绍
image: ""
pinned: true
---

3.注意事项#

  • 优先级:顶置文章会优先显示在文章列表的最上方
  • 多个顶置:如果有多篇文章都设置了 pinned: true,它们会按照发布时间的倒序排列在最上方
  • 取消顶置:要取消顶置,只需将 pinned: true 改为 pinned: false 或删除该字段

五、企业微信消息推送#

1.功能说明#

企业微信消息推送工具,用于向企业微信群机器人发送通知消息,支持文本和 Markdown 格式。

2.环境变量配置#

环境变量名称类型说明
WECOM_WEBHOOK_URL字符串企业微信机器人 Webhook 地址

获取方式:在企业微信群中添加群机器人,复制机器人提供的 Webhook 地址。

3.函数说明#

sendWecomMessage(webhookUrl, message)#

发送企业微信消息(通用方法)。

参数:

  • webhookUrl:string - 企业微信机器人 Webhook 地址
  • message:object - 消息对象
    {
    msgtype: 'text' | 'markdown' | 'image' | 'news' | 'file' | 'voice' | 'template_card',
    text: { content: '消息内容' }, // msgtype 为 text 时
    markdown: { content: '消息内容' }, // msgtype 为 markdown 时
    // ... 其他消息类型
    }

返回值:

{
success: boolean, // 是否发送成功
result: any, // 企业微信返回的结果
error?: string // 错误信息(如果有)
}

sendWecomText(webhookUrl, content)#

发送文本消息(便捷方法)。

参数:

  • webhookUrl:string - 企业微信机器人 Webhook 地址
  • content:string - 文本内容

sendWecomMarkdown(webhookUrl, content)#

发送 Markdown 消息(便捷方法)。

参数:

  • webhookUrl:string - 企业微信机器人 Webhook 地址
  • content:string - Markdown 格式内容

4.调用示例#

在 Cloudflare Pages Functions 中调用#

// 获取 Webhook 地址
const webhookUrl = env.WECOM_WEBHOOK_URL;
if (webhookUrl) {
// 发送 Markdown 消息
const message = `
**🔔 新赞助待审核**
**昵称:** ${nickname}
**金额:** ${amount} 元
**订单号:** ${orderId}
**赞助日期:** ${sponsorDate}
请管理员及时审核!
`.trim();
await sendWecomMarkdown(webhookUrl, message);
}

发送文本消息#

const webhookUrl = env.WECOM_WEBHOOK_URL;
if (webhookUrl) {
await sendWecomText(webhookUrl, '这是一条文本消息');
}

发送 Markdown 消息#

const webhookUrl = env.WECOM_WEBHOOK_URL;
if (webhookUrl) {
const content = `
**标题**
- 列表项1
- 列表项2
> 引用文本
[链接](https://example.com)
`.trim();
await sendWecomMarkdown(webhookUrl, content);
}

5.注意事项#

  • 若未配置 WECOM_WEBHOOK_URL 环境变量,推送功能自动禁用
  • 企业微信机器人必须已添加到目标群中才能正常接收消息
  • Markdown 格式仅支持部分语法,请参考企业微信官方文档
记录
https://www.2v.nz/posts/jl/
作者
微码筑梦
发布于
2026-04-08
许可协议
CC BY-NC-SA 4.0