feat: 新增AI SEO助手插件,支持自动生成SEO内容和导航主题适配
添加完整的AI SEO助手WordPress插件,主要功能包括: - 集成Dify API自动生成SEO优化的标题、描述和关键词 - 支持导航主题的自定义字段适配 - 提供管理界面设置API和文章类型支持 - 包含前端SEO标签自动应用功能 - 添加详细的测试和调试功能
This commit is contained in:
326
AI SEO 助手/README.md
Normal file
326
AI SEO 助手/README.md
Normal 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+
|
238
AI SEO 助手/admin/meta-box.php
Normal file
238
AI SEO 助手/admin/meta-box.php
Normal 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>
|
96
AI SEO 助手/admin/settings.php
Normal file
96
AI SEO 助手/admin/settings.php
Normal 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>
|
503
AI SEO 助手/ai-seo-generator.php
Normal file
503
AI SEO 助手/ai-seo-generator.php
Normal 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();
|
||||
?>
|
387
AI SEO 助手/assets/admin.css
Normal file
387
AI SEO 助手/assets/admin.css
Normal 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;
|
||||
}
|
||||
}
|
258
AI SEO 助手/assets/admin.js
Normal file
258
AI SEO 助手/assets/admin.js
Normal 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>');
|
||||
});
|
37
AI SEO 助手/config/default-settings.json
Normal file
37
AI SEO 助手/config/default-settings.json
Normal 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
346
AI SEO 助手/install.php
Normal 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');
|
||||
}
|
||||
});
|
||||
|
||||
?>
|
345
AI SEO 助手/test/api-test.php
Normal file
345
AI SEO 助手/test/api-test.php
Normal 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);
|
||||
}
|
||||
|
||||
?>
|
Reference in New Issue
Block a user