navanem/navanem_payload_contact
GitHub: navanem/navanem_payload_contact
为 Payload 3.x 提供开箱即用的联系表单插件,包含前端表单组件、后台消息收件箱及运行时配置功能。
Stars: 0 | Forks: 0
# @navanem/payload-contact
一个用于 **Payload 3.x** 的联系表单插件。它提供了一个公开的表单组件、一个带有内置垃圾邮件防护的已验证提交 endpoint、一个用于阅读和分流消息的管理员**收件箱**,以及一个用于在 runtime 开启/关闭表单并进行调整的 **settings** global —— 无需重新部署。不会发送或暴露任何电子邮件;消息直接存储在您的 Payload 管理后台中。
## 功能
- **消息收件箱** —— 一个 `contact-messages` collection(管理员可读),具有 `new / read / replied` 状态,因此该表单可作为可分流的收件箱使用。
- **设置 global** —— 开启或关闭表单,设置最小/最大长度,要求提供主题,屏蔽垃圾邮件关键字,以及设置成功消息,所有这些均可在 runtime 完成。
- **垃圾邮件防护** —— 一个隐藏的 honeypot 字段,外加基于 IP 的滑动窗口 rate limit;被屏蔽的提交会被静默丢弃(不会向 bot 提供任何有用的信号)。
- **管理后台收件箱视图** —— 一个专门的统计页面 (`/admin/contact-inbox`),包含 KPI(总计 / new / read / replied)、周期过滤器以及最新消息表格。
- **即插即用表单** —— 一个带有样式且支持自定义 theme 的 ` ` client component。
- **可选的电子邮件通知** —— 可通过管理后台设置进行配置的 SMTP 发送(无需静态电子邮件 adapter);默认关闭。
## 安装说明
此插件遵循与 `@navanem/payload-comments` 相同的 **vendored** 模型:将源码复制到您的项目中(以便管理后台组件路径通过您的 import map 解析),或者在发布后通过 npm 安装。
### A. Vendor 模式(推荐)
```
# 将 plugin 源码复制到你的项目中
cp -r node_modules/@navanem/payload-contact/src src/plugins/payload-contact
# (或者 git clone 并复制 src/ 目录)
```
然后在您生成的 `app/(payload)/admin/importMap.js` 中注册管理后台组件:
```
import { ContactInboxView } from '@/plugins/payload-contact/components/ContactInboxView'
import { ContactInboxNavLink } from '@/plugins/payload-contact/components/ContactInboxNavLink'
export const importMap = {
// ...
'@/plugins/payload-contact/components/ContactInboxView#ContactInboxView': ContactInboxView,
'@/plugins/payload-contact/components/ContactInboxNavLink#ContactInboxNavLink': ContactInboxNavLink,
}
```
### B. 通过 npm 安装
```
npm install @navanem/payload-contact
```
## 快速开始
### 1. 注册插件
```
// payload.config.ts
import { contactPlugin } from '@navanem/payload-contact' // or '@/plugins/payload-contact'
export default buildConfig({
// ...
plugins: [
contactPlugin({
notificationEmail: 'you@example.com',
}),
],
})
```
### 2. 创建数据库表
该插件添加了一个 `contact-messages` collection 和一个 `contact-settings` global。生成并运行 migration:
```
payload migrate:create contact_plugin
payload migrate
```
预期创建的表为 `contact_messages`(包含一个 `enum_contact_messages_status` enum 和一个 `payload_locked_documents_rels.contact_messages_id` FK)以及 `contact_settings`。
### 3. 将表单添加到页面
```
import { ContactForm } from '@navanem/payload-contact/client'
export default function ContactPage() {
return
}
```
该表单以 JSON 格式 POST 到插件的 endpoint:
```
POST /api/contact-api/submit { name, email, subject?, message, company? } -> { ok: true }
```
`company` 是 honeypot 字段(由组件保持隐藏)。endpoint 路径位于 `/contact-api/*` 下 —— **而不是** collection slug —— 因此它永远不会与 `contact-messages` 的 REST namespace 冲突。
## 配置
`contactPlugin(options)` —— 所有选项均为可选:
| 选项 | 类型 | 默认值 | 描述 |
| ------------------- | --------------------------------- | ------------------ | ----------- |
| `enabled` | `boolean` | `true` | 接受新提交(可通过 settings global 在 runtime 覆盖)。 |
| `minLength` | `number` | `10` | 消息最小长度。 |
| `maxLength` | `number` | `5000` | 消息最大长度。 |
| `requireSubject` | `boolean` | `false` | 必填主题字段。 |
| `blockedKeywords` | `string[]` | `[]` | 包含其中任意关键字的消息将被视为垃圾邮件丢弃。 |
| `notificationEmail` | `string` | `''` | 为未来的电子邮件通知存储(如果没有 adapter,则不会发送任何电子邮件)。 |
| `successMessage` | `string` | 合理的默认值 | 提交成功后向访问者显示的消息。 |
| `rateLimit` | `{ windowMs: number; max: number }` | `{ 60000, 3 }` | 基于 IP 的滑动窗口限制。 |
| `messagesSlug` | `string` | `contact-messages` | 收件箱 collection 的 slug。 |
| `ipSalt` | `string` | `CONTACT_IP_SALT` 环境变量 | 用于在 rate limiter 中哈希 IP 的 Salt。 |
| `disabled` | `boolean` | `false` | 空操作(collection + global 仍会注册,以保持 schema 稳定)。 |
## Runtime 设置
管理后台("Contact" 分组)中会出现一个 **Contact Settings** global。管理员可以开启/关闭表单、更改最小/最大长度、要求提供主题、编辑被屏蔽的关键字,以及设置成功消息 —— 立即生效,无需重新部署。如果该 global 从未被保存过,endpoint 和页面将**默认使用(fail open)**插件选项。
## 管理后台收件箱
- **Contact Messages** —— collection 列表;打开一条消息,更改其状态。
- **Contact Inbox** (`/admin/contact-inbox`) —— KPI、周期过滤器和最新表格。
- 该视图在服务端受 auth 保护(`if (!req.user) return null`),因此消息数据绝不会泄露到未经身份验证的 SSR 输出中。
## 表单组件
` ` 是一个使用 CSS 模块进行样式设置的 client component,该模块使用了 `--pc-*` 自定义属性(具有合理的默认值),因此您可以通过覆盖这些变量来设置其 theme。
| Prop | 默认值 | 描述 |
| ---------------- | ----------------------------- | ----------- |
| `successMessage` | 默认的感谢语 | 提交后显示。 |
| `disabled` | `false` | 渲染一条“已关闭”通知,而不是表单。 |
| `endpoint` | `/api/contact-api/submit` | 提交 URL。 |
| `className` | — | 根元素上的额外 class。 |
## 电子邮件通知(可选)
默认关闭 —— 消息总是会进入收件箱。如果希望在每次收到新消息时也收到电子邮件通知,请打开管理后台的 **Contact Settings**,展开 **Email notifications**,勾选“每次收到新消息时发送电子邮件”,并填写收件人及 SMTP host/port/user/password/TLS/from。随后,`afterChange` hook 会通过 [nodemailer](https://nodemailer.com/) 在每次新提交时发送邮件。SMTP 凭证存储在一个**仅限管理员读取的** global 中,因此它们永远不会到达客户端。
## 开发
```
pnpm install
pnpm dev # boots a sqlite-backed Payload admin with the plugin registered
```
开发环境位于 `dev/` 中(sqlite,schema 自动推送 —— 无需 migrations)。
## 测试
```
pnpm test # run the vitest suite once
pnpm test:watch # watch mode
```
测试位于 `tests/` 中,通过一个模拟的 `payload` 对象来测试插件的纯逻辑和服务端逻辑 —— 运行它们不需要数据库。
## 文档
- [`docs/configuration.md`](docs/configuration.md) —— 插件选项、runtime 设置、环境变量
- [`docs/frontend-integration.md`](docs/frontend-integration.md) —— ` `、endpoint、主题设置
- [`docs/inbox-and-triage.md`](docs/inbox-and-triage.md) —— 收件箱、状态、电子邮件通知
## 许可证
MIT © navanem · [www.navanem.com](https://www.navanem.com)
标签:Payload插件, Syscall, Web开发, 后台管理, 自动化攻击, 表单组件, 防垃圾