feat: 新增AI SEO助手插件,支持自动生成SEO内容和导航主题适配

添加完整的AI SEO助手WordPress插件,主要功能包括:
- 集成Dify API自动生成SEO优化的标题、描述和关键词
- 支持导航主题的自定义字段适配
- 提供管理界面设置API和文章类型支持
- 包含前端SEO标签自动应用功能
- 添加详细的测试和调试功能
This commit is contained in:
2025-08-13 18:52:35 +08:00
commit 1ae6823bd5
9 changed files with 2536 additions and 0 deletions

326
AI SEO 助手/README.md Normal file
View File

@@ -0,0 +1,326 @@
# AI SEO Generator - WordPress插件
## 📖 插件简介
AI SEO Generator 是一个强大的WordPress插件利用人工智能技术自动生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)。插件集成了Dify工作流编排对话型应用API为您的网站内容提供智能化的SEO优化解决方案。
## ✨ 主要功能
### 🤖 AI智能生成
- **自动生成SEO标题**:基于文章内容智能生成吸引人的标题
- **智能描述生成**创建符合搜索引擎要求的meta描述
- **关键词提取**:自动识别和生成相关关键词
- **一键生成**点击按钮即可生成完整的SEO内容
- **支持自定义文章类型**兼容文章、页面及自定义post_type
- **🧭 导航主题适配**:自动识别和利用导航网站的链接和描述信息
### 🎨 用户界面
- **直观的编辑界面**:在文章编辑页面直接操作
- **实时预览**:查看搜索结果页面效果
- **字符计数**:实时显示内容长度和建议
- **SEO质量评分**智能评估SEO内容质量
### 🔧 高级功能
- **前端自动应用**生成的SEO内容自动应用到页面
- **Open Graph标签**使用og:title、og:description等标签避免与WordPress默认标签冲突
- **社交媒体优化**自动添加og:image、og:url等标签提升分享效果
- **支持多种内容类型**:文章、页面等
- **AJAX异步处理**:无需刷新页面
- **快捷键支持**Ctrl+Shift+G快速生成
## 🚀 安装说明
### 方法一:手动安装
1. 下载插件文件到WordPress的 `wp-content/plugins/` 目录
2. 在WordPress后台进入「插件」页面
3. 找到「AI SEO Generator」并点击「启用」
### 方法二:上传安装
1. 将插件文件打包为zip格式
2. 在WordPress后台进入「插件」→「安装插件」
3. 点击「上传插件」并选择zip文件
4. 安装完成后启用插件
## ⚙️ 配置设置
### API配置
1. 进入「设置」→「AI SEO Generator」
2. 配置以下参数:
- **API Key**: 请输入您的Dify API密钥
- **API URL**: 请输入您的Dify API基础URL
3. 选择 **支持的文章类型**(可多选)
- 文章 (post)
- 页面 (page)
- 自定义文章类型如sites、shop等
4. 点击「保存设置」
### 文章类型配置
- 插件会自动检测所有公开的文章类型
- 您可以选择在哪些文章类型的编辑页面显示AI SEO Generator
- 支持主题自定义的post_type如sites、shop、products等
- 如果不选择任何类型,默认支持文章和页面
### API接口说明
- **基础URL**: 您配置的API基础URL
- **端点**: `POST /chat-messages`
- **鉴权方式**: Bearer Token
- **请求头**: `Authorization: Bearer {API_KEY}`
## 📝 使用方法
### 基本使用
1. **编辑文章或页面**
- 进入文章/页面编辑界面
- 在编辑器下方找到「AI SEO Generator」面板
2. **生成SEO内容**
- 点击「生成SEO内容」按钮
- 等待AI处理通常需要几秒钟
- 查看生成的标题、描述和关键词
3. **编辑和优化**
- 根据需要手动调整生成的内容
- 查看实时预览效果
- 参考SEO质量评分进行优化
### 🧭 导航主题适配使用
插件特别针对导航类主题进行了优化,能够自动识别和利用导航网站信息:
#### 支持的自定义字段
- **`_sites_link`**:网站链接地址
- **`_sites_sescribe`**:网站描述信息
#### 功能特点
- 🔍 **自动检测**:插件会自动检测文章中是否包含导航网站信息
- 🎯 **智能优化**针对导航类网站调整AI提示词生成更合适的SEO内容
- 📊 **信息展示**在编辑页面显示检测到的导航信息让用户了解AI使用的数据
- 🎨 **美观界面**为导航信息提供专门的UI展示区域
#### 使用方法
1. 确保您的导航主题将网站信息存储在上述meta字段中
2. 在编辑页面,插件会自动显示检测到的导航信息
3. 点击"生成SEO内容"AI会基于网站链接和描述生成针对性的SEO内容
### 高级功能
- **快捷键**: 使用 `Ctrl+Shift+G` 快速生成SEO内容
- **复制功能**: 点击📋按钮复制内容到剪贴板
- **自动保存**: 内容修改后自动保存
## 🎯 SEO优化建议
### 标题优化
- 长度控制在50-60个字符
- 包含主要关键词
- 具有吸引力和可读性
- 避免关键词堆砌
### 描述优化
- 长度控制在150-160个字符
- 包含相关关键词
- 描述准确且吸引人
- 包含行动号召
### 关键词优化
- 选择3-5个相关关键词
- 避免过度优化
- 确保与内容相关性
- 定期更新和调整
## 📁 文件结构
```
AI-SEO/
├── ai-seo-generator.php # 主插件文件
├── install.php # 安装/卸载脚本
├── admin/
│ ├── settings.php # 设置页面模板
│ └── meta-box.php # 编辑页面meta box模板
├── assets/
│ ├── admin.js # 前端JavaScript功能
│ └── admin.css # 界面样式文件
├── config/
│ └── default-settings.json # 默认配置文件
├── test/
│ └── api-test.php # API测试功能
└── README.md # 完整说明文档
```
## 🔧 技术规格
### 系统要求
- WordPress 5.0+
- PHP 7.4+
- MySQL 5.6+
- 支持cURL扩展
### 兼容性
- 支持所有现代浏览器
- 响应式设计
- 支持多语言
- 兼容主流WordPress主题
## 🛠️ 开发信息
## 📋 版本历史
### v1.0.7 (2025-08-13) - 发布版本
- 🔒 移除所有硬编码的API密钥和URL
- 🚀 创建适合公开发布的安全版本
- 🛡️ 保护敏感测试信息不被泄露
- ⚙️ 保留完整的API配置功能
- 📝 更新文档说明移除测试API信息
### v1.0.6 (2025-08-13)
- 🏷️ 优化SEO标签输出方式
- 📱 使用Open Graph标签替代传统meta标签
- 🔄 避免与WordPress默认meta标签冲突
- 🎯 新增og:title、og:description、og:type、og:url标签
- 🖼️ 自动添加og:image标签当文章有特色图片时
- 🔧 保留keywords标签Open Graph标准未包含
- 📈 提升社交媒体分享效果和SEO兼容性
### v1.0.5 (2025-08-13)
- 🌐 新增导航主题适配功能
- 📊 支持读取wp_postmeta中的导航网站数据
- 🔗 自动识别_sites_link网站链接字段
- 📝 自动识别_sites_sescribe网站描述字段
- 🤖 针对导航类网站优化AI提示词
- 🎨 在编辑页面显示检测到的导航信息
- ✨ 为导航信息添加美观的UI展示
### v1.0.4 (2025-08-13)
- ⏱️ 修复AI生成超时问题
- 🔧 将AJAX超时时间从默认值增加到120秒
- 🌐 将API请求超时时间从30秒增加到120秒
- ⚡ 增加PHP执行时间限制到180秒
- 💬 改进超时错误提示信息
- 🎯 优化用户体验,添加耐心等待提示
### 1.0.3 (2025-08-13)
- ✅ 大幅增强调试功能
- ✅ 添加详细的错误日志记录
- ✅ 改进AJAX错误处理
- ✅ 增加请求和响应的完整日志
- ✅ 优化JSON解析错误检测
- ✅ 提供更准确的错误信息
### 1.0.2 (2025-08-13)
- ✅ 修复Dify API响应解析问题
- ✅ 增强API响应兼容性
- ✅ 支持多种响应格式解析
- ✅ 添加调试日志功能
- ✅ 优化错误处理机制
### 1.0.1 (2025-08-13)
- ✅ 新增自定义文章类型支持
- ✅ 支持sites、shop等自定义post_type
- ✅ 设置页面增加文章类型选择器
- ✅ 自动检测所有公开的文章类型
- ✅ 灵活的文章类型配置管理
### 1.0.0 (2025-08-13)
- ✅ 初始版本发布
- ✅ 基础SEO生成功能
- ✅ Dify API集成
- ✅ 管理界面实现
- ✅ 前端SEO标签应用
- ✅ 完整的安装/卸载脚本
- ✅ API测试功能
- ✅ 实时预览和字符计数
- ✅ SEO质量评分系统
- ✅ 响应式设计界面
- ✅ 快捷键支持
- ✅ 错误处理和日志记录
### 开发计划
- [ ] 批量生成SEO内容
- [ ] 多语言支持
- [ ] SEO分析报告
- [ ] 自定义提示词
- [ ] 集成更多AI服务
## 🐛 故障排除
### 常见问题
**Q: 生成SEO内容失败怎么办**
A: 请检查:
1. API Key和API URL是否正确配置
2. 网络连接是否正常
3. 查看WordPress错误日志中的"AI SEO API Response"信息
4. 确认Dify API返回的数据格式
**Q: 如何查看调试信息?**
A: 插件会在WordPress错误日志中记录详细的调试信息可以通过以下方式查看
1. 启用WordPress调试在wp-config.php中添加 `define('WP_DEBUG_LOG', true);`
2. 查看日志文件wp-content/debug.log
3. 搜索以下关键词:
- "AI SEO Request" - 查看请求信息
- "AI SEO Raw Response" - 查看原始API响应
- "AI SEO Parsed Data" - 查看解析后的数据
- "AI SEO Success" - 查看成功的处理结果
- "AI SEO Failed" - 查看失败的详细原因
- "AI SEO Error" - 查看具体错误信息
**Q: API返回数据但插件显示失败**
A: 这通常是响应格式问题:
1. 检查API返回的JSON格式是否包含title、description、keywords字段
2. 确认数据结构符合预期格式
3. 查看错误日志了解具体的响应内容
**Q: AI生成时间过长导致超时**
A: 插件已优化超时设置支持长时间AI生成
1. AJAX请求超时120秒2分钟
2. API请求超时120秒2分钟
3. PHP执行时间180秒3分钟
4. 如果仍然超时可能需要联系服务器管理员调整PHP配置
5. 建议在生成过程中保持页面打开,不要刷新或关闭
3. 文章内容是否足够
4. API服务是否可用
**Q: 生成的内容质量不理想?**
A: 建议:
1. 确保文章内容丰富且相关
2. 手动调整生成的内容
3. 多次生成选择最佳结果
4. 结合人工优化
**Q: 前端SEO标签不显示**
A: 检查:
1. 主题是否支持wp_head钩子
2. 是否有其他SEO插件冲突
3. 缓存是否已清理
4. 查看页面源代码确认Open Graph标签是否正确输出
**Q: Open Graph标签与其他SEO插件冲突**
A: 本插件使用Open Graph标签格式og:title、og:description等避免了与WordPress默认meta标签的冲突。如果仍有冲突
1. 检查其他SEO插件是否也输出相同的Open Graph标签
2. 考虑禁用其他SEO插件的相关功能
3. 使用浏览器开发者工具检查重复标签
### 调试模式
在wp-config.php中添加以下代码启用调试
```php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
```
## 📞 技术支持
如果您在使用过程中遇到问题,请:
1. 查看本文档的故障排除部分
2. 检查WordPress错误日志
3. 联系技术支持团队
## 📄 许可证
本插件基于GPL v2或更高版本许可证发布。
---
**开发者**: SnowZ
**版本**: 1.0.7
**最后更新**: 2025-08-13
**兼容WordPress版本**: 5.0+

View File

@@ -0,0 +1,238 @@
<div class="ai-seo-meta-box">
<div class="ai-seo-header">
<h4>🤖 AI SEO内容生成器</h4>
<button type="button" id="generate-seo-btn" class="button button-primary">
<span class="dashicons dashicons-update"></span>
生成SEO内容
</button>
</div>
<div id="ai-seo-loading" class="ai-seo-loading" style="display: none;">
<div class="spinner is-active"></div>
<p>AI正在生成SEO内容这可能需要1-2分钟时间,请耐心等待...</p>
</div>
<?php
// 检测导航网站信息
$sites_link = get_post_meta(get_the_ID(), '_sites_link', true);
$sites_describe = get_post_meta(get_the_ID(), '_sites_sescribe', true);
$has_navigation_data = !empty($sites_link) || !empty($sites_describe);
if ($has_navigation_data): ?>
<div class="ai-seo-navigation-info">
<h4>🌐 检测到导航网站信息</h4>
<div class="navigation-data">
<?php if (!empty($sites_link)): ?>
<p><strong>网站链接:</strong> <a href="<?php echo esc_url($sites_link); ?>" target="_blank"><?php echo esc_html($sites_link); ?></a></p>
<?php endif; ?>
<?php if (!empty($sites_describe)): ?>
<p><strong>网站描述:</strong> <?php echo esc_html($sites_describe); ?></p>
<?php endif; ?>
</div>
<p class="description">✅ AI将基于以上导航信息生成针对性的SEO内容</p>
</div>
<?php endif; ?>
<div class="ai-seo-fields">
<div class="ai-seo-field">
<label for="ai_seo_title">
<strong>SEO标题 (Title)</strong>
<span class="ai-seo-counter" id="title-counter">0/60</span>
</label>
<input type="text" id="ai_seo_title" name="ai_seo_title" value="<?php echo esc_attr($seo_title); ?>" class="widefat" maxlength="60" />
<p class="description">建议长度50-60个字符</p>
</div>
<div class="ai-seo-field">
<label for="ai_seo_description">
<strong>Meta描述 (Description)</strong>
<span class="ai-seo-counter" id="desc-counter">0/160</span>
</label>
<textarea id="ai_seo_description" name="ai_seo_description" class="widefat" rows="3" maxlength="160"><?php echo esc_textarea($seo_description); ?></textarea>
<p class="description">建议长度150-160个字符</p>
</div>
<div class="ai-seo-field">
<label for="ai_seo_keywords">
<strong>关键词 (Keywords)</strong>
<span class="ai-seo-counter" id="keywords-counter">0/100</span>
</label>
<input type="text" id="ai_seo_keywords" name="ai_seo_keywords" value="<?php echo esc_attr($seo_keywords); ?>" class="widefat" maxlength="100" />
<p class="description">多个关键词用逗号分隔建议3-5个关键词</p>
</div>
</div>
<div class="ai-seo-preview">
<h4>🔍 搜索结果预览</h4>
<div class="search-preview">
<div class="preview-title" id="preview-title"><?php echo esc_html($seo_title ?: get_the_title()); ?></div>
<div class="preview-url" id="preview-url"><?php echo esc_url(get_permalink()); ?></div>
<div class="preview-description" id="preview-description"><?php echo esc_html($seo_description ?: '暂无描述'); ?></div>
</div>
</div>
<div class="ai-seo-tips">
<h4>💡 SEO优化建议</h4>
<ul>
<li>标题应包含主要关键词长度控制在50-60字符</li>
<li>描述要吸引用户点击包含关键词长度150-160字符</li>
<li>关键词要与内容相关,避免堆砌</li>
<li>定期检查和更新SEO内容以保持相关性</li>
</ul>
</div>
</div>
<style>
.ai-seo-meta-box {
padding: 15px;
}
.ai-seo-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #ddd;
}
.ai-seo-header h4 {
margin: 0;
color: #333;
}
.ai-seo-navigation-info {
background: #f0f8ff;
border: 1px solid #0073aa;
border-radius: 4px;
padding: 15px;
margin-bottom: 20px;
}
.ai-seo-navigation-info h4 {
margin: 0 0 10px 0;
color: #0073aa;
font-size: 14px;
}
.navigation-data p {
margin: 5px 0;
font-size: 13px;
}
.navigation-data strong {
color: #333;
}
.navigation-data a {
color: #0073aa;
text-decoration: none;
}
.navigation-data a:hover {
text-decoration: underline;
}
#generate-seo-btn {
display: flex;
align-items: center;
gap: 5px;
}
.ai-seo-loading {
text-align: center;
padding: 20px;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 20px;
}
.ai-seo-field {
margin-bottom: 20px;
}
.ai-seo-field label {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
font-weight: 600;
}
.ai-seo-counter {
font-size: 12px;
color: #666;
font-weight: normal;
}
.ai-seo-counter.warning {
color: #d63638;
}
.ai-seo-counter.good {
color: #00a32a;
}
.ai-seo-preview {
margin: 20px 0;
padding: 15px;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
}
.ai-seo-preview h4 {
margin-top: 0;
color: #333;
}
.search-preview {
background: white;
padding: 15px;
border-radius: 3px;
font-family: arial, sans-serif;
}
.preview-title {
color: #1a0dab;
font-size: 18px;
line-height: 1.3;
margin-bottom: 5px;
cursor: pointer;
}
.preview-url {
color: #006621;
font-size: 14px;
margin-bottom: 5px;
}
.preview-description {
color: #545454;
font-size: 14px;
line-height: 1.4;
}
.ai-seo-tips {
margin-top: 20px;
padding: 15px;
background: #e7f3ff;
border: 1px solid #b3d9ff;
border-radius: 5px;
}
.ai-seo-tips h4 {
margin-top: 0;
color: #0073aa;
}
.ai-seo-tips ul {
margin: 10px 0 0 20px;
}
.ai-seo-tips li {
margin-bottom: 5px;
color: #333;
}
</style>

View File

@@ -0,0 +1,96 @@
<div class="wrap">
<h1>AI SEO Generator 设置</h1>
<form method="post" action="">
<table class="form-table">
<tr>
<th scope="row">
<label for="api_key">API Key</label>
</th>
<td>
<input type="text" id="api_key" name="api_key" value="<?php echo esc_attr($api_key); ?>" class="regular-text" />
<p class="description">输入您的Dify API Key</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="api_url">API URL</label>
</th>
<td>
<input type="url" id="api_url" name="api_url" value="<?php echo esc_attr($api_url); ?>" class="regular-text" />
<p class="description">Dify API的基础URL</p>
</td>
</tr>
<tr>
<th scope="row">
<label for="supported_post_types">支持的文章类型</label>
</th>
<td>
<?php
// 获取所有公开的post类型
$all_post_types = get_post_types(array('public' => true), 'objects');
$supported_post_types = get_option('ai_seo_supported_post_types', array_keys($all_post_types));
foreach ($all_post_types as $post_type_name => $post_type_obj) {
$checked = in_array($post_type_name, $supported_post_types) ? 'checked' : '';
echo '<label style="display: block; margin-bottom: 5px;">';
echo '<input type="checkbox" name="supported_post_types[]" value="' . esc_attr($post_type_name) . '" ' . $checked . ' /> ';
echo esc_html($post_type_obj->label) . ' (' . esc_html($post_type_name) . ')';
echo '</label>';
}
?>
<p class="description">选择在哪些文章类型的编辑页面显示AI SEO Generator</p>
</td>
</tr>
</table>
<?php submit_button('保存设置'); ?>
</form>
<div class="ai-seo-info">
<h2>使用说明</h2>
<ol>
<li>在上方输入您的Dify API Key和API URL</li>
<li>编辑文章或页面时,在编辑器下方会出现"AI SEO Generator"面板</li>
<li>点击"生成SEO内容"按钮AI将自动为您生成优化的标题、描述和关键词</li>
<li>生成的内容会自动应用到页面的meta标签中</li>
</ol>
<h3>API配置</h3>
<p>请在上方配置您的API密钥和URL以使用AI生成功能。</p>
<p><strong>端点:</strong> POST /chat-messages</p>
<h3>功能特性</h3>
<ul>
<li>✅ 自动生成SEO标题</li>
<li>✅ 自动生成Meta描述</li>
<li>✅ 自动生成关键词</li>
<li>✅ 前端自动应用SEO标签</li>
<li>✅ 支持文章和页面</li>
<li>✅ AJAX异步生成</li>
</ul>
</div>
</div>
<style>
.ai-seo-info {
margin-top: 30px;
padding: 20px;
background: #f9f9f9;
border: 1px solid #ddd;
border-radius: 5px;
}
.ai-seo-info h2, .ai-seo-info h3 {
margin-top: 0;
color: #333;
}
.ai-seo-info ul, .ai-seo-info ol {
margin-left: 20px;
}
.ai-seo-info li {
margin-bottom: 5px;
}
</style>

View File

@@ -0,0 +1,503 @@
<?php
/**
* Plugin Name: AI SEO 助手
* Plugin URI: https://ckk.photo8.site/Photo8/wordpress-plugins
* Description: 使用AI自动生成SEO TDK内容的WordPress插件集成Dify API
* Version: 1.0.7
* Author: SnowZ
* License: GPL v2 or later
* Text Domain: ai-seo-generator
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
// 定义插件常量
define('AI_SEO_PLUGIN_URL', plugin_dir_url(__FILE__));
define('AI_SEO_PLUGIN_PATH', plugin_dir_path(__FILE__));
define('AI_SEO_VERSION', '1.0.0');
// 加载安装脚本
require_once AI_SEO_PLUGIN_PATH . 'install.php';
// 加载测试功能(仅在管理后台)
if (is_admin()) {
require_once AI_SEO_PLUGIN_PATH . 'test/api-test.php';
}
/**
* 主插件类
*/
class AiSeoGenerator {
/**
* 构造函数 - 初始化插件
*/
public function __construct() {
add_action('init', array($this, 'init'));
register_activation_hook(__FILE__, array($this, 'activate'));
register_deactivation_hook(__FILE__, array($this, 'deactivate'));
}
/**
* 插件初始化
*/
public function init() {
// 加载文本域
load_plugin_textdomain('ai-seo-generator', false, dirname(plugin_basename(__FILE__)) . '/languages');
// 添加管理菜单
add_action('admin_menu', array($this, 'add_admin_menu'));
// 添加编辑页面的meta box
add_action('add_meta_boxes', array($this, 'add_meta_boxes'));
// 保存文章时的钩子
add_action('save_post', array($this, 'save_post_meta'));
// 添加AJAX处理
add_action('wp_ajax_generate_seo_content', array($this, 'ajax_generate_seo_content'));
// 加载管理页面样式和脚本
add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_scripts'));
// 前端钩子 - 修改页面标题和meta标签
add_filter('wp_title', array($this, 'custom_wp_title'), 10, 2);
add_action('wp_head', array($this, 'add_meta_tags'));
}
/**
* 插件激活时执行
*/
public function activate() {
// 创建数据库表或设置默认选项
$this->create_options();
}
/**
* 插件停用时执行
*/
public function deactivate() {
// 清理工作
}
/**
* 创建默认选项
*/
private function create_options() {
add_option('ai_seo_api_key', '');
add_option('ai_seo_api_url', '');
}
/**
* 添加管理菜单
*/
public function add_admin_menu() {
add_options_page(
'AI SEO Generator 设置',
'AI SEO Generator',
'manage_options',
'ai-seo-generator',
array($this, 'admin_page')
);
// 添加测试页面子菜单
add_submenu_page(
'options-general.php',
'AI SEO 测试',
'AI SEO 测试',
'manage_options',
'ai-seo-test',
array($this, 'test_page')
);
}
/**
* 管理页面内容
* 处理设置保存包括API配置和支持的文章类型
*/
public function admin_page() {
if (isset($_POST['submit'])) {
// 保存API设置
update_option('ai_seo_api_key', sanitize_text_field($_POST['api_key']));
update_option('ai_seo_api_url', esc_url_raw($_POST['api_url']));
// 保存支持的文章类型设置
$supported_post_types = array();
if (isset($_POST['supported_post_types']) && is_array($_POST['supported_post_types'])) {
// 获取所有公开的post类型进行验证
$all_post_types = get_post_types(array('public' => true), 'names');
foreach ($_POST['supported_post_types'] as $post_type) {
$post_type = sanitize_text_field($post_type);
// 只保存有效的公开post类型
if (in_array($post_type, $all_post_types)) {
$supported_post_types[] = $post_type;
}
}
}
// 如果没有选择任何类型默认支持post和page
if (empty($supported_post_types)) {
$supported_post_types = array('post', 'page');
}
update_option('ai_seo_supported_post_types', $supported_post_types);
echo '<div class="notice notice-success"><p>设置已保存!支持的文章类型:' . implode(', ', $supported_post_types) . '</p></div>';
}
$api_key = get_option('ai_seo_api_key', '');
$api_url = get_option('ai_seo_api_url', '');
include AI_SEO_PLUGIN_PATH . 'admin/settings.php';
}
/**
* 测试页面内容
*/
public function test_page() {
if (!class_exists('AiSeoApiTest')) {
echo '<div class="wrap"><h1>测试功能不可用</h1><p>测试类未加载。</p></div>';
return;
}
echo '<div class="wrap">';
echo '<h1>🧪 AI SEO Generator 测试</h1>';
echo '<p>此页面用于测试API连接和功能验证。</p>';
if (isset($_POST['run_test'])) {
$tester = new AiSeoApiTest();
echo $tester->generate_test_report();
} else {
echo '<form method="post">';
echo '<p><button type="submit" name="run_test" class="button button-primary">🚀 运行测试</button></p>';
echo '</form>';
echo '<div class="ai-seo-test-info">';
echo '<h3>测试内容包括:</h3>';
echo '<ul>';
echo '<li>✅ API连接测试</li>';
echo '<li>✅ SEO内容生成测试</li>';
echo '<li>✅ 系统环境检查</li>';
echo '<li>✅ 插件配置验证</li>';
echo '</ul>';
echo '</div>';
}
echo '</div>';
}
/**
* 添加meta boxes到编辑页面
* 支持所有公开的post类型包括自定义post类型
*/
public function add_meta_boxes() {
// 获取所有公开的post类型
$post_types = get_post_types(array('public' => true), 'names');
// 从设置中获取支持的post类型如果没有设置则使用所有公开类型
$supported_post_types = get_option('ai_seo_supported_post_types', $post_types);
// 确保支持的类型都是公开的
$supported_post_types = array_intersect($supported_post_types, $post_types);
// 为每个支持的post类型添加meta box
foreach ($supported_post_types as $post_type) {
add_meta_box(
'ai-seo-generator',
'AI SEO Generator',
array($this, 'meta_box_callback'),
$post_type,
'normal',
'high'
);
}
}
/**
* Meta box回调函数
*/
public function meta_box_callback($post) {
wp_nonce_field('ai_seo_meta_box', 'ai_seo_meta_box_nonce');
$seo_title = get_post_meta($post->ID, '_ai_seo_title', true);
$seo_description = get_post_meta($post->ID, '_ai_seo_description', true);
$seo_keywords = get_post_meta($post->ID, '_ai_seo_keywords', true);
include AI_SEO_PLUGIN_PATH . 'admin/meta-box.php';
}
/**
* 保存文章meta数据
*/
public function save_post_meta($post_id) {
if (!isset($_POST['ai_seo_meta_box_nonce']) || !wp_verify_nonce($_POST['ai_seo_meta_box_nonce'], 'ai_seo_meta_box')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (isset($_POST['ai_seo_title'])) {
update_post_meta($post_id, '_ai_seo_title', sanitize_text_field($_POST['ai_seo_title']));
}
if (isset($_POST['ai_seo_description'])) {
update_post_meta($post_id, '_ai_seo_description', sanitize_textarea_field($_POST['ai_seo_description']));
}
if (isset($_POST['ai_seo_keywords'])) {
update_post_meta($post_id, '_ai_seo_keywords', sanitize_text_field($_POST['ai_seo_keywords']));
}
}
/**
* 加载管理页面脚本和样式
*/
public function enqueue_admin_scripts($hook) {
if ('post.php' == $hook || 'post-new.php' == $hook || 'settings_page_ai-seo-generator' == $hook) {
wp_enqueue_script('ai-seo-admin', AI_SEO_PLUGIN_URL . 'assets/admin.js', array('jquery'), AI_SEO_VERSION, true);
wp_enqueue_style('ai-seo-admin', AI_SEO_PLUGIN_URL . 'assets/admin.css', array(), AI_SEO_VERSION);
wp_localize_script('ai-seo-admin', 'aiSeoAjax', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('ai_seo_nonce')
));
}
}
/**
* AJAX处理生成SEO内容
* 增强错误处理和调试信息
*/
public function ajax_generate_seo_content() {
// 增加PHP执行时间限制防止长时间AI生成被中断
set_time_limit(180); // 设置为3分钟
check_ajax_referer('ai_seo_nonce', 'nonce');
$post_id = intval($_POST['post_id']);
$post = get_post($post_id);
if (!$post) {
wp_send_json_error('文章不存在');
return;
}
$content = $post->post_content;
$title = $post->post_title;
// 读取导航主题的自定义字段
$sites_link = get_post_meta($post_id, '_sites_link', true);
$sites_describe = get_post_meta($post_id, '_sites_sescribe', true);
// 构建完整的内容信息,包含自定义字段
$full_content = $content;
if (!empty($sites_link)) {
$full_content .= "\n\n网站链接: " . $sites_link;
}
if (!empty($sites_describe)) {
$full_content .= "\n\n网站描述: " . $sites_describe;
}
// 记录请求信息
error_log('AI SEO Request - Post ID: ' . $post_id . ', Title: ' . $title . ', Sites Link: ' . $sites_link . ', Sites Describe: ' . $sites_describe);
// 调用AI API生成SEO内容
$seo_data = $this->generate_seo_with_ai($title, $full_content);
if ($seo_data && is_array($seo_data)) {
// 记录成功信息
error_log('AI SEO Success: ' . json_encode($seo_data));
wp_send_json_success($seo_data);
} else {
// 记录失败信息
error_log('AI SEO Failed: seo_data = ' . var_export($seo_data, true));
wp_send_json_error('生成SEO内容失败请查看错误日志获取详细信息');
}
}
/**
* 调用AI API生成SEO内容
* 增强调试和错误处理功能
*/
private function generate_seo_with_ai($title, $content) {
$api_key = get_option('ai_seo_api_key');
$api_url = get_option('ai_seo_api_url');
// 记录配置信息
error_log('AI SEO Config - API URL: ' . $api_url . ', API Key: ' . (empty($api_key) ? 'Empty' : 'Set'));
if (empty($api_key) || empty($api_url)) {
error_log('AI SEO Error: API Key or URL not configured');
return false;
}
// 检测是否包含导航网站信息
$is_navigation_site = (strpos($content, '网站链接:') !== false || strpos($content, '网站描述:') !== false);
if ($is_navigation_site) {
$prompt = "请根据以下导航网站信息生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)。这是一个网站导航页面,请重点关注网站的功能、特色和用途:\n\n标题:{$title}\n\n内容:" . wp_strip_all_tags($content) . "\n\n请针对导航类网站的特点生成吸引用户点击的SEO内容。以JSON格式返回包含title、description、keywords字段。";
} else {
$prompt = "请根据以下文章标题和内容生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)\n\n标题:{$title}\n\n内容:" . wp_strip_all_tags($content) . "\n\n请以JSON格式返回包含title、description、keywords字段。";
}
$request_body = array(
'inputs' => array(),
'query' => $prompt,
'response_mode' => 'blocking',
'user' => 'wordpress-user'
);
// 记录请求信息
error_log('AI SEO Request Body: ' . json_encode($request_body));
$response = wp_remote_post($api_url . '/chat-messages', array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Content-Type' => 'application/json'
),
'body' => json_encode($request_body),
'timeout' => 120 // 增加超时时间到120秒2分钟
));
if (is_wp_error($response)) {
error_log('AI SEO WP Error: ' . $response->get_error_message());
return false;
}
$response_code = wp_remote_retrieve_response_code($response);
error_log('AI SEO Response Code: ' . $response_code);
$body = wp_remote_retrieve_body($response);
// 记录原始响应
error_log('AI SEO Raw Response: ' . $body);
if (empty($body)) {
error_log('AI SEO Error: Empty response body');
return false;
}
$data = json_decode($body, true);
$json_error = json_last_error();
if ($json_error !== JSON_ERROR_NONE) {
error_log('AI SEO JSON Error: ' . json_last_error_msg());
return false;
}
error_log('AI SEO Parsed Data: ' . json_encode($data));
// 方法1: 检查是否直接返回了SEO数据结构
if (isset($data['title'], $data['description'], $data['keywords'])) {
error_log('AI SEO: Found direct SEO data structure');
return array(
'title' => $data['title'],
'description' => $data['description'],
'keywords' => $data['keywords']
);
}
// 方法2: 检查answer字段中的JSON数据
if (isset($data['answer'])) {
$answer = $data['answer'];
error_log('AI SEO: Found answer field: ' . $answer);
// 尝试直接解析answer作为JSON
$seo_data = json_decode($answer, true);
if ($seo_data && isset($seo_data['title'], $seo_data['description'], $seo_data['keywords'])) {
error_log('AI SEO: Successfully parsed answer as JSON');
return $seo_data;
}
// 尝试从answer中提取JSON字符串
preg_match('/\{.*\}/s', $answer, $matches);
if (!empty($matches[0])) {
error_log('AI SEO: Extracted JSON from answer: ' . $matches[0]);
$seo_data = json_decode($matches[0], true);
if ($seo_data && isset($seo_data['title'], $seo_data['description'], $seo_data['keywords'])) {
error_log('AI SEO: Successfully parsed extracted JSON');
return $seo_data;
}
}
}
// 方法3: 检查data字段中的内容
if (isset($data['data'])) {
$data_content = $data['data'];
error_log('AI SEO: Found data field: ' . json_encode($data_content));
if (is_array($data_content) && isset($data_content['title'], $data_content['description'], $data_content['keywords'])) {
error_log('AI SEO: Successfully found SEO data in data field');
return $data_content;
}
}
error_log('AI SEO: No valid SEO data found in response');
return false;
}
/**
* 自定义页面标题
*/
public function custom_wp_title($title, $sep) {
if (is_single() || is_page()) {
global $post;
$custom_title = get_post_meta($post->ID, '_ai_seo_title', true);
if (!empty($custom_title)) {
return $custom_title;
}
}
return $title;
}
/**
* 添加meta标签到页面头部
* 使用Open Graph标签避免与WordPress默认meta标签冲突
*/
public function add_meta_tags() {
if (is_single() || is_page()) {
global $post;
$seo_title = get_post_meta($post->ID, '_ai_seo_title', true);
$description = get_post_meta($post->ID, '_ai_seo_description', true);
$keywords = get_post_meta($post->ID, '_ai_seo_keywords', true);
// 输出Open Graph标题
if (!empty($seo_title)) {
echo '<meta property="og:title" content="' . esc_attr($seo_title) . '">' . "\n";
}
// 输出Open Graph描述
if (!empty($description)) {
echo '<meta property="og:description" content="' . esc_attr($description) . '">' . "\n";
}
// 保留keywords标签Open Graph没有对应标签
if (!empty($keywords)) {
echo '<meta name="keywords" content="' . esc_attr($keywords) . '">' . "\n";
}
// 添加其他常用的Open Graph标签
echo '<meta property="og:type" content="article">' . "\n";
echo '<meta property="og:url" content="' . esc_url(get_permalink($post->ID)) . '">' . "\n";
// 如果文章有特色图片添加og:image
if (has_post_thumbnail($post->ID)) {
$thumbnail_url = get_the_post_thumbnail_url($post->ID, 'large');
echo '<meta property="og:image" content="' . esc_url($thumbnail_url) . '">' . "\n";
}
}
}
}
// 初始化插件
new AiSeoGenerator();
?>

View File

@@ -0,0 +1,387 @@
/* AI SEO Generator 管理界面样式 */
/* 主容器样式 */
.ai-seo-meta-box {
background: #fff;
border: 1px solid #e1e1e1;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
/* 头部样式 */
.ai-seo-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 15px 20px;
border-radius: 8px 8px 0 0;
margin: -15px -15px 20px -15px;
}
.ai-seo-header h4 {
color: white !important;
font-size: 16px;
font-weight: 600;
}
#generate-seo-btn {
background: rgba(255,255,255,0.2);
border: 1px solid rgba(255,255,255,0.3);
color: white;
border-radius: 6px;
padding: 8px 16px;
font-weight: 500;
transition: all 0.3s ease;
}
#generate-seo-btn:hover {
background: rgba(255,255,255,0.3);
border-color: rgba(255,255,255,0.5);
transform: translateY(-1px);
}
#generate-seo-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
/* 加载状态样式 */
.ai-seo-loading {
background: linear-gradient(45deg, #f0f8ff, #e6f3ff);
border: 2px dashed #4a90e2;
border-radius: 8px;
text-align: center;
padding: 30px;
margin-bottom: 20px;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.7; }
100% { opacity: 1; }
}
.ai-seo-loading .spinner {
margin: 0 auto 10px;
}
.ai-seo-loading p {
color: #4a90e2;
font-weight: 500;
margin: 0;
}
/* 字段样式 */
.ai-seo-field {
background: #fafafa;
border: 1px solid #e1e1e1;
border-radius: 6px;
padding: 15px;
margin-bottom: 15px;
transition: all 0.3s ease;
}
.ai-seo-field:hover {
background: #f5f5f5;
border-color: #d1d1d1;
}
.ai-seo-field label {
color: #333;
font-size: 14px;
margin-bottom: 8px;
}
.ai-seo-field input,
.ai-seo-field textarea {
border: 2px solid #e1e1e1;
border-radius: 4px;
padding: 10px 12px;
font-size: 14px;
transition: border-color 0.3s ease;
background: white;
}
.ai-seo-field input:focus,
.ai-seo-field textarea:focus {
border-color: #667eea;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
outline: none;
}
/* 计数器样式 */
.ai-seo-counter {
background: #e9ecef;
padding: 4px 8px;
border-radius: 12px;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.5px;
}
.ai-seo-counter.good {
background: #d4edda;
color: #155724;
}
.ai-seo-counter.warning {
background: #f8d7da;
color: #721c24;
}
/* 复制按钮样式 */
.copy-btn {
background: transparent;
border: none;
color: #666;
cursor: pointer;
font-size: 12px;
margin-left: 8px;
padding: 2px 6px;
border-radius: 3px;
transition: all 0.2s ease;
}
.copy-btn:hover {
background: #f0f0f0;
color: #333;
}
/* 预览样式 */
.ai-seo-preview {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border: none;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.ai-seo-preview h4 {
color: #2c3e50;
margin-bottom: 15px;
font-size: 15px;
}
.search-preview {
background: white;
border-radius: 6px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
border-left: 4px solid #4285f4;
}
.preview-title {
color: #1a0dab;
font-size: 18px;
line-height: 1.3;
margin-bottom: 8px;
font-weight: 500;
cursor: pointer;
transition: color 0.2s ease;
}
.preview-title:hover {
color: #0d47a1;
text-decoration: underline;
}
.preview-url {
color: #006621;
font-size: 14px;
margin-bottom: 8px;
font-family: 'Courier New', monospace;
}
.preview-description {
color: #545454;
font-size: 14px;
line-height: 1.5;
}
/* SEO评分样式 */
.seo-score {
background: white;
border: 2px solid #e1e1e1;
border-radius: 8px;
padding: 20px;
margin: 20px 0;
}
.seo-score h4 {
margin-top: 0;
color: #333;
display: flex;
align-items: center;
gap: 10px;
}
.score-good {
color: #28a745;
font-weight: bold;
}
.score-ok {
color: #ffc107;
font-weight: bold;
}
.score-poor {
color: #dc3545;
font-weight: bold;
}
.seo-issues {
list-style: none;
padding: 0;
margin: 15px 0 0 0;
}
.seo-issues li {
background: #fff3cd;
border: 1px solid #ffeaa7;
border-radius: 4px;
padding: 10px 15px;
margin-bottom: 8px;
color: #856404;
font-size: 13px;
}
.seo-perfect {
background: #d4edda;
border: 1px solid #c3e6cb;
border-radius: 4px;
padding: 15px;
color: #155724;
margin: 15px 0 0 0;
font-weight: 500;
}
/* 提示样式 */
.ai-seo-tips {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
padding: 20px;
margin-top: 20px;
}
.ai-seo-tips h4 {
color: white !important;
margin-top: 0;
font-size: 15px;
}
.ai-seo-tips ul {
margin: 15px 0 0 20px;
}
.ai-seo-tips li {
margin-bottom: 8px;
color: rgba(255,255,255,0.9);
line-height: 1.5;
}
/* 通知样式 */
.notice {
border-radius: 6px;
margin: 15px 0;
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 响应式设计 */
@media (max-width: 768px) {
.ai-seo-header {
flex-direction: column;
gap: 10px;
text-align: center;
}
.ai-seo-field label {
flex-direction: column;
align-items: flex-start;
gap: 5px;
}
.ai-seo-counter {
align-self: flex-start;
}
}
/* 设置页面样式 */
.ai-seo-info {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
border: none;
border-radius: 8px;
padding: 25px;
margin-top: 30px;
}
.ai-seo-info h2,
.ai-seo-info h3 {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 8px;
margin-bottom: 15px;
}
.ai-seo-info ul li,
.ai-seo-info ol li {
margin-bottom: 8px;
line-height: 1.6;
}
.ai-seo-info ul li:before {
content: "✓";
color: #27ae60;
font-weight: bold;
margin-right: 8px;
}
/* 动画效果 */
.ai-seo-field {
animation: fadeInUp 0.5s ease;
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 深色模式支持 */
@media (prefers-color-scheme: dark) {
.ai-seo-field {
background: #2c3e50;
border-color: #34495e;
color: #ecf0f1;
}
.ai-seo-field input,
.ai-seo-field textarea {
background: #34495e;
border-color: #4a5f7a;
color: #ecf0f1;
}
.search-preview {
background: #2c3e50;
color: #ecf0f1;
}
}

View File

@@ -0,0 +1,258 @@
jQuery(document).ready(function($) {
/**
* 初始化字符计数器
*/
function initCharCounters() {
// 标题计数器
$('#ai_seo_title').on('input', function() {
updateCounter(this, '#title-counter', 60);
updatePreview();
}).trigger('input');
// 描述计数器
$('#ai_seo_description').on('input', function() {
updateCounter(this, '#desc-counter', 160);
updatePreview();
}).trigger('input');
// 关键词计数器
$('#ai_seo_keywords').on('input', function() {
updateCounter(this, '#keywords-counter', 100);
}).trigger('input');
}
/**
* 更新字符计数器
*/
function updateCounter(input, counterSelector, maxLength) {
var length = $(input).val().length;
var counter = $(counterSelector);
var percentage = (length / maxLength) * 100;
counter.text(length + '/' + maxLength);
// 根据长度设置颜色
counter.removeClass('warning good');
if (percentage > 90) {
counter.addClass('warning');
} else if (percentage >= 70) {
counter.addClass('good');
}
}
/**
* 更新搜索结果预览
*/
function updatePreview() {
var title = $('#ai_seo_title').val() || $('#title').val() || '未设置标题';
var description = $('#ai_seo_description').val() || '暂无描述';
$('#preview-title').text(title);
$('#preview-description').text(description);
}
/**
* 生成SEO内容
*/
$('#generate-seo-btn').on('click', function() {
var button = $(this);
var postId = $('#post_ID').val();
if (!postId) {
alert('请先保存文章草稿后再生成SEO内容');
return;
}
// 显示加载状态
button.prop('disabled', true);
$('#ai-seo-loading').show();
$('.ai-seo-fields').css('opacity', '0.5');
// 发送AJAX请求
$.ajax({
url: aiSeoAjax.ajax_url,
type: 'POST',
timeout: 120000, // 设置超时时间为120秒2分钟
data: {
action: 'generate_seo_content',
post_id: postId,
nonce: aiSeoAjax.nonce
},
success: function(response) {
if (response.success && response.data) {
// 填充生成的内容
if (response.data.title) {
$('#ai_seo_title').val(response.data.title).trigger('input');
}
if (response.data.description) {
$('#ai_seo_description').val(response.data.description).trigger('input');
}
if (response.data.keywords) {
$('#ai_seo_keywords').val(response.data.keywords).trigger('input');
}
// 显示成功消息
showNotice('SEO内容生成成功', 'success');
} else {
showNotice('生成失败:' + (response.data || '未知错误'), 'error');
}
},
error: function(xhr, status, error) {
var errorMessage = '请求失败:';
if (status === 'timeout') {
errorMessage = 'AI生成超时请稍后重试。如果问题持续存在请联系管理员。';
} else if (status === 'error') {
errorMessage = '网络错误,请检查网络连接后重试。';
} else {
errorMessage += error;
}
showNotice(errorMessage, 'error');
},
complete: function() {
// 恢复界面状态
button.prop('disabled', false);
$('#ai-seo-loading').hide();
$('.ai-seo-fields').css('opacity', '1');
}
});
});
/**
* 显示通知消息
*/
function showNotice(message, type) {
var noticeClass = type === 'success' ? 'notice-success' : 'notice-error';
var notice = $('<div class="notice ' + noticeClass + ' is-dismissible"><p>' + message + '</p></div>');
$('.ai-seo-meta-box').prepend(notice);
// 自动移除通知
setTimeout(function() {
notice.fadeOut(function() {
notice.remove();
});
}, 5000);
}
/**
* 复制到剪贴板功能
*/
function addCopyButtons() {
$('.ai-seo-field').each(function() {
var field = $(this);
var input = field.find('input, textarea');
if (input.length) {
var copyBtn = $('<button type="button" class="button button-small copy-btn" title="复制到剪贴板">📋</button>');
field.find('label').append(copyBtn);
copyBtn.on('click', function(e) {
e.preventDefault();
input.select();
document.execCommand('copy');
var originalText = copyBtn.text();
copyBtn.text('✅');
setTimeout(function() {
copyBtn.text(originalText);
}, 1000);
});
}
});
}
/**
* 键盘快捷键
*/
$(document).on('keydown', function(e) {
// Ctrl+Shift+G 生成SEO内容
if (e.ctrlKey && e.shiftKey && e.keyCode === 71) {
e.preventDefault();
$('#generate-seo-btn').click();
}
});
/**
* 自动保存功能
*/
var autoSaveTimeout;
$('.ai-seo-field input, .ai-seo-field textarea').on('input', function() {
clearTimeout(autoSaveTimeout);
autoSaveTimeout = setTimeout(function() {
// 这里可以添加自动保存逻辑
console.log('Auto-saving SEO data...');
}, 2000);
});
/**
* 验证SEO内容质量
*/
function validateSeoContent() {
var title = $('#ai_seo_title').val();
var description = $('#ai_seo_description').val();
var keywords = $('#ai_seo_keywords').val();
var issues = [];
if (!title || title.length < 30) {
issues.push('标题太短建议至少30个字符');
}
if (title && title.length > 60) {
issues.push('标题太长建议不超过60个字符');
}
if (!description || description.length < 120) {
issues.push('描述太短建议至少120个字符');
}
if (description && description.length > 160) {
issues.push('描述太长建议不超过160个字符');
}
if (!keywords) {
issues.push('建议添加相关关键词');
}
return issues;
}
/**
* 显示SEO质量评分
*/
function showSeoScore() {
var issues = validateSeoContent();
var score = Math.max(0, 100 - (issues.length * 20));
var scoreHtml = '<div class="seo-score">';
scoreHtml += '<h4>SEO质量评分: <span class="score-' + (score >= 80 ? 'good' : score >= 60 ? 'ok' : 'poor') + '">' + score + '/100</span></h4>';
if (issues.length > 0) {
scoreHtml += '<ul class="seo-issues">';
issues.forEach(function(issue) {
scoreHtml += '<li>⚠️ ' + issue + '</li>';
});
scoreHtml += '</ul>';
} else {
scoreHtml += '<p class="seo-perfect">✅ SEO内容质量良好</p>';
}
scoreHtml += '</div>';
$('.seo-score').remove();
$('.ai-seo-tips').before(scoreHtml);
}
// 初始化所有功能
initCharCounters();
updatePreview();
addCopyButtons();
// 监听内容变化以更新评分
$('.ai-seo-field input, .ai-seo-field textarea').on('input', function() {
setTimeout(showSeoScore, 100);
});
// 初始评分
showSeoScore();
// 添加提示信息
$('.ai-seo-header').append('<small style="color: #666; margin-left: 10px;">快捷键: Ctrl+Shift+G</small>');
});

View File

@@ -0,0 +1,37 @@
{
"ai_seo_api_key": "",
"ai_seo_api_url": "",
"ai_seo_auto_generate": false,
"ai_seo_enable_logging": true,
"ai_seo_cache_duration": 3600,
"ai_seo_max_retries": 3,
"ai_seo_timeout": 30,
"ai_seo_supported_post_types": ["post", "page", "sites", "shop", "products"],
"ai_seo_title_template": "{title}",
"ai_seo_description_template": "{description}",
"ai_seo_keywords_template": "{keywords}",
"ai_seo_enable_frontend": true,
"ai_seo_enable_admin_notices": true,
"ai_seo_prompt_templates": {
"title": "请为以下内容生成一个SEO优化的标题长度控制在50-60个字符\n\n{content}",
"description": "请为以下内容生成一个SEO优化的描述长度控制在150-160个字符\n\n{content}",
"keywords": "请为以下内容提取3-5个相关的SEO关键词用逗号分隔\n\n{content}",
"combined": "请根据以下文章标题和内容生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)\n\n标题{title}\n\n内容{content}\n\n请以JSON格式返回包含title、description、keywords字段。"
},
"ai_seo_quality_thresholds": {
"title_min_length": 30,
"title_max_length": 60,
"description_min_length": 120,
"description_max_length": 160,
"keywords_min_count": 3,
"keywords_max_count": 5
},
"ai_seo_ui_settings": {
"show_preview": true,
"show_character_count": true,
"show_seo_score": true,
"show_tips": true,
"enable_shortcuts": true,
"auto_save": true
}
}

346
AI SEO 助手/install.php Normal file
View File

@@ -0,0 +1,346 @@
<?php
/**
* AI SEO Generator 安装脚本
* 用于插件的安装、升级和卸载操作
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
/**
* 插件安装类
*/
class AiSeoInstaller {
/**
* 插件激活时执行
*/
public static function activate() {
self::create_database_tables();
self::set_default_options();
self::create_directories();
self::schedule_events();
// 刷新重写规则
flush_rewrite_rules();
// 记录激活时间
update_option('ai_seo_activated_time', current_time('timestamp'));
// 显示欢迎消息
set_transient('ai_seo_activation_notice', true, 30);
}
/**
* 插件停用时执行
*/
public static function deactivate() {
// 清理计划任务
wp_clear_scheduled_hook('ai_seo_cleanup_task');
// 刷新重写规则
flush_rewrite_rules();
// 记录停用时间
update_option('ai_seo_deactivated_time', current_time('timestamp'));
}
/**
* 插件卸载时执行
*/
public static function uninstall() {
// 删除选项
self::remove_options();
// 删除用户meta
self::remove_user_meta();
// 删除文章meta
self::remove_post_meta();
// 删除数据库表(可选)
// self::drop_database_tables();
// 清理计划任务
wp_clear_scheduled_hook('ai_seo_cleanup_task');
}
/**
* 创建数据库表
*/
private static function create_database_tables() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
// SEO日志表
$table_name = $wpdb->prefix . 'ai_seo_logs';
$sql = "CREATE TABLE $table_name (
id mediumint(9) NOT NULL AUTO_INCREMENT,
post_id bigint(20) NOT NULL,
action varchar(50) NOT NULL,
old_value text,
new_value text,
user_id bigint(20) NOT NULL,
created_at datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
KEY post_id (post_id),
KEY user_id (user_id),
KEY created_at (created_at)
) $charset_collate;";
require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
// 更新数据库版本
update_option('ai_seo_db_version', '1.0');
}
/**
* 设置默认选项
* 自动检测并支持所有公开的文章类型
*/
private static function set_default_options() {
// 获取所有公开的文章类型作为默认支持类型
$all_post_types = get_post_types(array('public' => true), 'names');
$default_supported_types = !empty($all_post_types) ? $all_post_types : array('post', 'page');
$default_options = array(
'ai_seo_api_key' => '',
'ai_seo_api_url' => '',
'ai_seo_auto_generate' => false,
'ai_seo_enable_logging' => true,
'ai_seo_cache_duration' => 3600, // 1小时
'ai_seo_max_retries' => 3,
'ai_seo_timeout' => 30,
'ai_seo_supported_post_types' => $default_supported_types,
'ai_seo_title_template' => '{title}',
'ai_seo_description_template' => '{description}',
'ai_seo_keywords_template' => '{keywords}',
'ai_seo_enable_frontend' => true,
'ai_seo_enable_admin_notices' => true
);
foreach ($default_options as $option_name => $default_value) {
if (get_option($option_name) === false) {
add_option($option_name, $default_value);
}
}
}
/**
* 创建必要的目录
*/
private static function create_directories() {
$upload_dir = wp_upload_dir();
$ai_seo_dir = $upload_dir['basedir'] . '/ai-seo';
if (!file_exists($ai_seo_dir)) {
wp_mkdir_p($ai_seo_dir);
// 创建.htaccess文件保护目录
$htaccess_content = "Order deny,allow\nDeny from all";
file_put_contents($ai_seo_dir . '/.htaccess', $htaccess_content);
// 创建index.php文件
file_put_contents($ai_seo_dir . '/index.php', '<?php // Silence is golden');
}
// 创建日志目录
$logs_dir = $ai_seo_dir . '/logs';
if (!file_exists($logs_dir)) {
wp_mkdir_p($logs_dir);
file_put_contents($logs_dir . '/index.php', '<?php // Silence is golden');
}
}
/**
* 安排计划任务
*/
private static function schedule_events() {
if (!wp_next_scheduled('ai_seo_cleanup_task')) {
wp_schedule_event(time(), 'daily', 'ai_seo_cleanup_task');
}
}
/**
* 删除插件选项
*/
private static function remove_options() {
$options_to_remove = array(
'ai_seo_api_key',
'ai_seo_api_url',
'ai_seo_auto_generate',
'ai_seo_enable_logging',
'ai_seo_cache_duration',
'ai_seo_max_retries',
'ai_seo_timeout',
'ai_seo_supported_post_types',
'ai_seo_title_template',
'ai_seo_description_template',
'ai_seo_keywords_template',
'ai_seo_enable_frontend',
'ai_seo_enable_admin_notices',
'ai_seo_activated_time',
'ai_seo_deactivated_time',
'ai_seo_db_version'
);
foreach ($options_to_remove as $option) {
delete_option($option);
}
}
/**
* 删除用户meta数据
*/
private static function remove_user_meta() {
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->usermeta}
WHERE meta_key LIKE 'ai_seo_%'"
);
}
/**
* 删除文章meta数据
*/
private static function remove_post_meta() {
global $wpdb;
$meta_keys = array(
'_ai_seo_title',
'_ai_seo_description',
'_ai_seo_keywords',
'_ai_seo_generated_at',
'_ai_seo_last_updated'
);
foreach ($meta_keys as $meta_key) {
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s",
$meta_key
)
);
}
}
/**
* 删除数据库表
*/
private static function drop_database_tables() {
global $wpdb;
$table_name = $wpdb->prefix . 'ai_seo_logs';
$wpdb->query("DROP TABLE IF EXISTS $table_name");
}
/**
* 检查系统要求
*/
public static function check_requirements() {
$requirements = array(
'php_version' => '7.4',
'wp_version' => '5.0',
'extensions' => array('curl', 'json')
);
$errors = array();
// 检查PHP版本
if (version_compare(PHP_VERSION, $requirements['php_version'], '<')) {
$errors[] = sprintf(
'需要PHP版本 %s 或更高,当前版本:%s',
$requirements['php_version'],
PHP_VERSION
);
}
// 检查WordPress版本
global $wp_version;
if (version_compare($wp_version, $requirements['wp_version'], '<')) {
$errors[] = sprintf(
'需要WordPress版本 %s 或更高,当前版本:%s',
$requirements['wp_version'],
$wp_version
);
}
// 检查PHP扩展
foreach ($requirements['extensions'] as $extension) {
if (!extension_loaded($extension)) {
$errors[] = sprintf('需要PHP扩展%s', $extension);
}
}
return $errors;
}
/**
* 数据库升级
*/
public static function upgrade_database() {
$current_version = get_option('ai_seo_db_version', '0');
if (version_compare($current_version, '1.0', '<')) {
self::create_database_tables();
}
// 未来版本的升级逻辑可以在这里添加
}
/**
* 创建示例内容
*/
public static function create_sample_content() {
// 可以在这里创建示例文章或页面
// 用于演示插件功能
}
/**
* 导入默认设置
*/
public static function import_default_settings() {
$settings_file = AI_SEO_PLUGIN_PATH . 'config/default-settings.json';
if (file_exists($settings_file)) {
$settings = json_decode(file_get_contents($settings_file), true);
if ($settings) {
foreach ($settings as $key => $value) {
update_option($key, $value);
}
}
}
}
}
// 注册激活、停用和卸载钩子
register_activation_hook(__FILE__, array('AiSeoInstaller', 'activate'));
register_deactivation_hook(__FILE__, array('AiSeoInstaller', 'deactivate'));
register_uninstall_hook(__FILE__, array('AiSeoInstaller', 'uninstall'));
// 检查数据库版本并升级
add_action('plugins_loaded', function() {
$current_version = get_option('ai_seo_db_version', '0');
if (version_compare($current_version, '1.0', '<')) {
AiSeoInstaller::upgrade_database();
}
});
// 显示激活通知
add_action('admin_notices', function() {
if (get_transient('ai_seo_activation_notice')) {
echo '<div class="notice notice-success is-dismissible">';
echo '<p><strong>AI SEO Generator</strong> 插件已成功激活!请前往 <a href="' . admin_url('options-general.php?page=ai-seo-generator') . '">设置页面</a> 配置API密钥。</p>';
echo '</div>';
delete_transient('ai_seo_activation_notice');
}
});
?>

View File

@@ -0,0 +1,345 @@
<?php
/**
* AI SEO Generator API测试文件
* 用于测试Dify API连接和功能验证
*/
// 防止直接访问
if (!defined('ABSPATH')) {
exit;
}
/**
* API测试类
*/
class AiSeoApiTest {
private $api_key;
private $api_url;
/**
* 构造函数
*/
public function __construct() {
$this->api_key = get_option('ai_seo_api_key', '');
$this->api_url = get_option('ai_seo_api_url', '');
}
/**
* 测试API连接
*/
public function test_connection() {
$test_data = array(
'status' => 'unknown',
'message' => '',
'response_time' => 0,
'details' => array()
);
$start_time = microtime(true);
try {
$response = wp_remote_get($this->api_url, array(
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json'
),
'timeout' => 10
));
$end_time = microtime(true);
$test_data['response_time'] = round(($end_time - $start_time) * 1000, 2);
if (is_wp_error($response)) {
$test_data['status'] = 'error';
$test_data['message'] = $response->get_error_message();
} else {
$status_code = wp_remote_retrieve_response_code($response);
$test_data['details']['status_code'] = $status_code;
if ($status_code >= 200 && $status_code < 300) {
$test_data['status'] = 'success';
$test_data['message'] = 'API连接成功';
} else {
$test_data['status'] = 'error';
$test_data['message'] = 'API返回错误状态码: ' . $status_code;
}
}
} catch (Exception $e) {
$test_data['status'] = 'error';
$test_data['message'] = '连接异常: ' . $e->getMessage();
}
return $test_data;
}
/**
* 测试SEO内容生成
*/
public function test_seo_generation() {
$test_content = array(
'title' => 'WordPress插件开发指南',
'content' => 'WordPress是世界上最流行的内容管理系统之一拥有强大的插件生态系统。本文将介绍如何开发一个WordPress插件包括基本结构、钩子系统、数据库操作等核心概念。我们还将探讨最佳实践和安全考虑帮助开发者创建高质量的插件。'
);
$test_data = array(
'status' => 'unknown',
'message' => '',
'generated_content' => null,
'response_time' => 0
);
$start_time = microtime(true);
try {
$prompt = "请根据以下文章标题和内容生成SEO优化的标题(Title)、描述(Description)和关键词(Keywords)\n\n标题:{$test_content['title']}\n\n内容:{$test_content['content']}\n\n请以JSON格式返回包含title、description、keywords字段。";
$response = wp_remote_post($this->api_url . '/chat-messages', array(
'headers' => array(
'Authorization' => 'Bearer ' . $this->api_key,
'Content-Type' => 'application/json'
),
'body' => json_encode(array(
'inputs' => array(),
'query' => $prompt,
'response_mode' => 'blocking',
'user' => 'test-user'
)),
'timeout' => 30
));
$end_time = microtime(true);
$test_data['response_time'] = round(($end_time - $start_time) * 1000, 2);
if (is_wp_error($response)) {
$test_data['status'] = 'error';
$test_data['message'] = $response->get_error_message();
} else {
$status_code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
$data = json_decode($body, true);
if ($status_code === 200 && isset($data['answer'])) {
// 尝试从AI回答中提取JSON
$answer = $data['answer'];
preg_match('/\{.*\}/s', $answer, $matches);
if (!empty($matches[0])) {
$seo_data = json_decode($matches[0], true);
if ($seo_data && isset($seo_data['title'], $seo_data['description'], $seo_data['keywords'])) {
$test_data['status'] = 'success';
$test_data['message'] = 'SEO内容生成成功';
$test_data['generated_content'] = $seo_data;
} else {
$test_data['status'] = 'error';
$test_data['message'] = '无法解析AI返回的JSON格式';
$test_data['raw_response'] = $answer;
}
} else {
$test_data['status'] = 'error';
$test_data['message'] = 'AI返回格式不正确';
$test_data['raw_response'] = $answer;
}
} else {
$test_data['status'] = 'error';
$test_data['message'] = 'API返回错误: ' . $status_code;
$test_data['raw_response'] = $body;
}
}
} catch (Exception $e) {
$test_data['status'] = 'error';
$test_data['message'] = '生成异常: ' . $e->getMessage();
}
return $test_data;
}
/**
* 运行完整测试套件
*/
public function run_full_test() {
$results = array(
'connection_test' => $this->test_connection(),
'generation_test' => $this->test_seo_generation(),
'system_info' => $this->get_system_info(),
'plugin_info' => $this->get_plugin_info()
);
// 计算总体状态
$overall_status = 'success';
if ($results['connection_test']['status'] === 'error' || $results['generation_test']['status'] === 'error') {
$overall_status = 'error';
}
$results['overall_status'] = $overall_status;
$results['test_time'] = current_time('Y-m-d H:i:s');
return $results;
}
/**
* 获取系统信息
*/
private function get_system_info() {
global $wp_version;
return array(
'wordpress_version' => $wp_version,
'php_version' => PHP_VERSION,
'curl_enabled' => extension_loaded('curl'),
'json_enabled' => extension_loaded('json'),
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'upload_max_filesize' => ini_get('upload_max_filesize')
);
}
/**
* 获取插件信息
*/
private function get_plugin_info() {
return array(
'plugin_version' => AI_SEO_VERSION,
'plugin_path' => AI_SEO_PLUGIN_PATH,
'plugin_url' => AI_SEO_PLUGIN_URL,
'api_key_configured' => !empty($this->api_key),
'api_url_configured' => !empty($this->api_url),
'database_version' => get_option('ai_seo_db_version', '0')
);
}
/**
* 生成测试报告HTML
*/
public function generate_test_report() {
$results = $this->run_full_test();
ob_start();
?>
<div class="ai-seo-test-report">
<h2>🧪 AI SEO Generator 测试报告</h2>
<div class="test-summary">
<h3>测试概览</h3>
<p><strong>总体状态:</strong>
<span class="status-<?php echo $results['overall_status']; ?>">
<?php echo $results['overall_status'] === 'success' ? '✅ 通过' : '❌ 失败'; ?>
</span>
</p>
<p><strong>测试时间:</strong> <?php echo $results['test_time']; ?></p>
</div>
<div class="test-details">
<h3>连接测试</h3>
<div class="test-item">
<p><strong>状态:</strong>
<span class="status-<?php echo $results['connection_test']['status']; ?>">
<?php echo $results['connection_test']['status'] === 'success' ? '✅ 成功' : '❌ 失败'; ?>
</span>
</p>
<p><strong>消息:</strong> <?php echo esc_html($results['connection_test']['message']); ?></p>
<p><strong>响应时间:</strong> <?php echo $results['connection_test']['response_time']; ?>ms</p>
</div>
<h3>内容生成测试</h3>
<div class="test-item">
<p><strong>状态:</strong>
<span class="status-<?php echo $results['generation_test']['status']; ?>">
<?php echo $results['generation_test']['status'] === 'success' ? '✅ 成功' : '❌ 失败'; ?>
</span>
</p>
<p><strong>消息:</strong> <?php echo esc_html($results['generation_test']['message']); ?></p>
<p><strong>响应时间:</strong> <?php echo $results['generation_test']['response_time']; ?>ms</p>
<?php if (isset($results['generation_test']['generated_content'])): ?>
<h4>生成的内容:</h4>
<div class="generated-content">
<p><strong>标题:</strong> <?php echo esc_html($results['generation_test']['generated_content']['title']); ?></p>
<p><strong>描述:</strong> <?php echo esc_html($results['generation_test']['generated_content']['description']); ?></p>
<p><strong>关键词:</strong> <?php echo esc_html($results['generation_test']['generated_content']['keywords']); ?></p>
</div>
<?php endif; ?>
</div>
</div>
<div class="system-info">
<h3>系统信息</h3>
<table class="widefat">
<tbody>
<tr><td>WordPress版本</td><td><?php echo $results['system_info']['wordpress_version']; ?></td></tr>
<tr><td>PHP版本</td><td><?php echo $results['system_info']['php_version']; ?></td></tr>
<tr><td>cURL支持</td><td><?php echo $results['system_info']['curl_enabled'] ? '✅ 是' : '❌ 否'; ?></td></tr>
<tr><td>JSON支持</td><td><?php echo $results['system_info']['json_enabled'] ? '✅ 是' : '❌ 否'; ?></td></tr>
<tr><td>内存限制</td><td><?php echo $results['system_info']['memory_limit']; ?></td></tr>
<tr><td>执行时间限制</td><td><?php echo $results['system_info']['max_execution_time']; ?>秒</td></tr>
</tbody>
</table>
</div>
<div class="plugin-info">
<h3>插件信息</h3>
<table class="widefat">
<tbody>
<tr><td>插件版本</td><td><?php echo $results['plugin_info']['plugin_version']; ?></td></tr>
<tr><td>API Key配置</td><td><?php echo $results['plugin_info']['api_key_configured'] ? '✅ 已配置' : '❌ 未配置'; ?></td></tr>
<tr><td>API URL配置</td><td><?php echo $results['plugin_info']['api_url_configured'] ? '✅ 已配置' : '❌ 未配置'; ?></td></tr>
<tr><td>数据库版本</td><td><?php echo $results['plugin_info']['database_version']; ?></td></tr>
</tbody>
</table>
</div>
</div>
<style>
.ai-seo-test-report {
background: white;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
margin: 20px 0;
}
.test-summary {
background: #f9f9f9;
padding: 15px;
border-radius: 5px;
margin-bottom: 20px;
}
.test-item {
background: #f9f9f9;
padding: 15px;
border-radius: 5px;
margin-bottom: 15px;
}
.status-success {
color: #28a745;
font-weight: bold;
}
.status-error {
color: #dc3545;
font-weight: bold;
}
.generated-content {
background: #e9ecef;
padding: 10px;
border-radius: 4px;
margin-top: 10px;
}
.widefat td {
padding: 8px 12px;
}
</style>
<?php
return ob_get_clean();
}
}
// 如果是AJAX请求返回JSON结果
if (defined('DOING_AJAX') && DOING_AJAX && isset($_POST['action']) && $_POST['action'] === 'ai_seo_run_test') {
$tester = new AiSeoApiTest();
$results = $tester->run_full_test();
wp_send_json($results);
}
?>