feat(halo): 添加图片上传功能并完善发布流程
- 实现图片上传服务,支持检测并上传本地图片到 Halo - 优化发布流程,添加详细日志和错误处理 - 更新任务清单和检查列表以反映完成状态 - 添加 Halo 博客写作技能文档
This commit is contained in:
Vendored
+6
-3
File diff suppressed because one or more lines are too long
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
|
||||
This CSS file will be included with your plugin, and
|
||||
available in the app when your plugin is enabled.
|
||||
|
||||
If your plugin does not need CSS, delete this file.
|
||||
|
||||
*/
|
||||
+14
-2
@@ -1,13 +1,25 @@
|
||||
{
|
||||
"recentFiles": [
|
||||
{
|
||||
"basename": "Git团队协作指南(精简版)",
|
||||
"path": "博客/Git团队协作指南(精简版).md"
|
||||
"basename": "SEO分析报告",
|
||||
"path": "博客/SEO分析报告.md"
|
||||
},
|
||||
{
|
||||
"basename": "博客爬取报告",
|
||||
"path": "博客/博客爬取报告.md"
|
||||
},
|
||||
{
|
||||
"basename": "从全连接层到卷积",
|
||||
"path": "博客/从全连接层到卷积.md"
|
||||
},
|
||||
{
|
||||
"basename": "CLI在AI时代的浴火重生",
|
||||
"path": "博客/CLI在AI时代的浴火重生.md"
|
||||
},
|
||||
{
|
||||
"basename": "Git团队协作指南(精简版)",
|
||||
"path": "博客/Git团队协作指南(精简版).md"
|
||||
},
|
||||
{
|
||||
"basename": "halo",
|
||||
"path": "copilot/copilot-custom-prompts/halo.md"
|
||||
|
||||
Vendored
+6
-5
@@ -13,12 +13,12 @@
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "博客/Git团队协作指南(精简版).md",
|
||||
"file": "博客/SEO分析报告.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "Git团队协作指南(精简版)"
|
||||
"title": "SEO分析报告"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -193,7 +193,8 @@
|
||||
}
|
||||
],
|
||||
"direction": "horizontal",
|
||||
"width": 426.5
|
||||
"width": 426.5,
|
||||
"collapsed": true
|
||||
},
|
||||
"left-ribbon": {
|
||||
"hiddenItems": {
|
||||
@@ -220,6 +221,8 @@
|
||||
},
|
||||
"active": "e7a7b303c61786dc",
|
||||
"lastOpenFiles": [
|
||||
"博客/博客爬取报告.md",
|
||||
"博客/从全连接层到卷积.md",
|
||||
"博客/CLI在AI时代的浴火重生.md",
|
||||
"博客/Git团队协作指南(精简版).md",
|
||||
"obsidian-halo/src/service/image-uploader.ts",
|
||||
@@ -264,8 +267,6 @@
|
||||
"小组会议/25.10.26/小组成员基本信息/职位安排.md",
|
||||
"小组会议/25.10.26/小组成员基本信息/小组成员信息/李俊杰.md",
|
||||
"小组会议/26.02.06/小组会议.md",
|
||||
"小组会议/26.02.05/小组会议.md",
|
||||
"小组会议/26.01.28/Gitee团队协作开发完整实操流程.md",
|
||||
"未命名.canvas"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
---
|
||||
name: halo-blog-writer
|
||||
description: |
|
||||
Halo 博客写作和管理助手。当用户需要:
|
||||
(1) 发布博客文章
|
||||
(2) 管理博客内容
|
||||
(3) 更新/修改已发布的文章
|
||||
(4) 导出/导入博客内容
|
||||
(5) 查看博客状态
|
||||
(6) 使用自然语言操作 Halo 博客时触发此技能
|
||||
---
|
||||
|
||||
# Halo 博客写作助手
|
||||
|
||||
本技能帮助 AI Agent 通过 Halo CLI 管理用户的 Halo 博客(http://192.168.5.8:8090)。
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 已配置的环境
|
||||
|
||||
用户已通过 npm 全局安装 Halo CLI:
|
||||
- 版本:1.3.0
|
||||
- Node.js:v22.14.0
|
||||
- 系统:Windows (PowerShell)
|
||||
|
||||
### CLI 配置
|
||||
|
||||
当前激活的配置(profile)是 `local`,连接地址:
|
||||
```
|
||||
http://192.168.5.8:8090
|
||||
```
|
||||
|
||||
认证方式:Bearer Token(已存储在系统 keyring 中)
|
||||
|
||||
### 基本命令
|
||||
|
||||
```powershell
|
||||
# 列出文章(分页显示)
|
||||
halo post list --page 1 --size 20
|
||||
|
||||
# 查看单个文章详情
|
||||
halo post get <name-or-id>
|
||||
|
||||
# 创建文章
|
||||
halo post create --title "标题" --content "# 内容" --publish true
|
||||
|
||||
# 更新文章
|
||||
halo post update <name-or-id> --title "新标题" --content "新内容"
|
||||
|
||||
# 导出文章为 Markdown
|
||||
halo post export-markdown <name-or-id> --output ./post.md
|
||||
|
||||
# 导入 Markdown 文件创建文章
|
||||
halo post import-markdown --file ./post.md
|
||||
```
|
||||
|
||||
## 写作工作流
|
||||
|
||||
### 场景 1:发布新文章
|
||||
|
||||
当用户提供文章内容时:
|
||||
1. 接收文章内容(可能是文件路径或直接文本)
|
||||
2. 提取标题和正文
|
||||
3. 判断是否立即发布(publish)还是仅创建草稿
|
||||
4. 执行 `halo post create` 命令
|
||||
5. 确认创建成功
|
||||
|
||||
```powershell
|
||||
# 发布新文章
|
||||
halo post create --title "文章标题" --content "# 文章内容..." --publish true
|
||||
|
||||
# 仅创建草稿
|
||||
halo post create --title "文章标题" --content "# 文章内容..."
|
||||
```
|
||||
|
||||
### 场景 2:从 Markdown 文件发布
|
||||
|
||||
当用户提供 `.md` 文件时:
|
||||
1. 读取文件内容
|
||||
2. 从文件名或第一行提取标题
|
||||
3. 执行导入命令
|
||||
|
||||
```powershell
|
||||
halo post import-markdown --file d:\path\to\article.md
|
||||
```
|
||||
|
||||
### 场景 3:更新已发布的文章
|
||||
|
||||
当用户要求修改某篇文章时:
|
||||
1. 先用 `halo post list` 找到文章
|
||||
2. 获取文章 ID 或 name
|
||||
3. 执行更新命令
|
||||
|
||||
```powershell
|
||||
# 先查看文章列表
|
||||
halo post list --page 1 --size 20
|
||||
|
||||
# 获取文章详情
|
||||
halo post get <article-id>
|
||||
|
||||
# 更新文章
|
||||
halo post update <article-id> --title "新标题" --content "新内容"
|
||||
```
|
||||
|
||||
### 场景 4:批量操作
|
||||
|
||||
处理多篇文章:
|
||||
1. 获取文章列表
|
||||
2. 逐个处理
|
||||
3. 报告完成状态
|
||||
|
||||
```powershell
|
||||
# 获取所有文章(分页)
|
||||
halo post list --page 1 --size 100
|
||||
|
||||
# 或者导出为 JSON 格式便于处理
|
||||
halo post list --page 1 --size 100 --json
|
||||
```
|
||||
|
||||
## 文件路径约定
|
||||
|
||||
用户的博客文章通常保存在:
|
||||
```
|
||||
d:\Code\OpenClaw\文件\博客\
|
||||
```
|
||||
|
||||
常见文件格式:
|
||||
- `.md` - Markdown 文件
|
||||
- `.txt` - 纯文本文件
|
||||
|
||||
## 注意事项
|
||||
|
||||
### 内容格式
|
||||
|
||||
- Halo 支持 Markdown 和 HTML 格式
|
||||
- 默认使用 Markdown(`--raw-type markdown`)
|
||||
- 也支持 `--raw-type html`
|
||||
|
||||
### 发布状态
|
||||
|
||||
- `published` - 已发布
|
||||
- `draft` - 草稿
|
||||
- 可以在创建时指定 `--publish true` 立即发布
|
||||
|
||||
### 文章标识
|
||||
|
||||
文章可以用以下方式标识:
|
||||
- **Name/Slug**:文章的唯一标识符(如 `019dbabc-86b9-74a0-a926-c25529309007`)
|
||||
- **ID**:文章内部 ID
|
||||
|
||||
### 错误处理
|
||||
|
||||
如果命令失败:
|
||||
1. 检查网络连接
|
||||
2. 确认 CLI 配置正确(`halo auth current`)
|
||||
3. 查看错误信息并重试
|
||||
|
||||
## 其他管理功能
|
||||
|
||||
```powershell
|
||||
# 单页管理
|
||||
halo single-page list
|
||||
halo single-page create --title "标题" --content "内容"
|
||||
|
||||
# 插件管理
|
||||
halo plugin list
|
||||
|
||||
# 主题管理
|
||||
halo theme list
|
||||
|
||||
# 备份
|
||||
halo backup list
|
||||
halo backup create
|
||||
|
||||
# 评论管理
|
||||
halo comment list
|
||||
halo comment reply <comment-id> --content "回复内容"
|
||||
```
|
||||
|
||||
## 安全提醒
|
||||
|
||||
- Bearer Token 已安全存储在系统 keyring 中
|
||||
- 不要在命令输出中显示敏感信息
|
||||
- 谨慎执行删除操作(`halo post delete`)
|
||||
|
||||
## 常用命令速查
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 查看文章列表 | `halo post list --page 1 --size 20` |
|
||||
| 查看文章详情 | `halo post get <id>` |
|
||||
| 创建文章 | `halo post create --title "标题" --content "内容"` |
|
||||
| 发布文章 | `halo post create --title "标题" --content "内容" --publish true` |
|
||||
| 更新文章 | `halo post update <id> --title "标题" --content "内容"` |
|
||||
| 删除文章 | `halo post delete <id> --force` |
|
||||
| 导出为 Markdown | `halo post export-markdown <id> --output ./post.md` |
|
||||
| 从文件导入 | `halo post import-markdown --file ./post.md` |
|
||||
|
||||
## 博客标签和分类
|
||||
|
||||
### 现有标签(共 11 个)
|
||||
|
||||
| 显示名称 | Slug | 颜色 |
|
||||
|---------|------|------|
|
||||
| 协会动态 | xie-hui-dong-tai | 🟢 #B8E986 |
|
||||
| 5分钟速览 | 5fen-zhong-su-lan | 🔵 #50E3C2 |
|
||||
| 技术深潜 | ji-shu-shen-qian | 🔷 #4A90E2 |
|
||||
| 校园AI | xiao-yuan-ai | 🟣 #9013FE |
|
||||
| 竞赛指南 | jing-sai-zhi-nan | 🟪 #BD10E0 |
|
||||
| 项目实战 | xiang-mu-shi-zhan | 🟢 #417505 |
|
||||
| 零基础入门 | ling-ji-chu-ru-men | 🟢 #7ED321 |
|
||||
| 开源框架 | kai-yuan-kuang-jia | 🟤 #8B572A |
|
||||
| 模型轻量化 | mo-xing-qing-liang-hua | 🟡 #F8E71C |
|
||||
| 隐私计算 | yin-si-ji-suan | 🟠 #F5A623 |
|
||||
| AI智能体 | aizhi-neng-ti | 🔴 #D0021B |
|
||||
|
||||
### 标签使用建议
|
||||
|
||||
| 文章类型 | 推荐标签 |
|
||||
|---------|---------|
|
||||
| 技术教程 / 开发工具 | 技术深潜 |
|
||||
| 团队协作 / 开源项目 | 项目实战 |
|
||||
| AI/LLM/模型相关 | 技术深潜, AI智能体 |
|
||||
| 编程入门教程 | 技术深潜, 零基础入门 |
|
||||
| 比赛通知 / 大赛解读 | 竞赛指南 |
|
||||
| 协会通知 / 动态 | 协会动态 |
|
||||
| AI 科普 / 入门 | 零基础入门, AI智能体 |
|
||||
|
||||
### 常用命令速查
|
||||
|
||||
| 操作 | 命令 |
|
||||
|------|------|
|
||||
| 查看所有标签 | `halo post tag list` |
|
||||
| 查看所有分类 | `halo post category list` |
|
||||
| 为文章添加标签 | `halo post update <id> --tags "标签1,标签2"` |
|
||||
| 更新文章分类 | `halo post update <id> --category "分类名"` |
|
||||
| 查看文章标签 | `halo post get <id> --json` |
|
||||
|
||||
详细命令参见 `references/command-reference.md`
|
||||
|
||||
## 参考文档
|
||||
|
||||
- CLI 完整帮助:`halo --help`、`halo post --help`
|
||||
- 配置信息:`halo auth profile list`
|
||||
- 高级用法:参见 `references/advanced-usage.md`
|
||||
- 标签和分类命令:参见 `references/command-reference.md`
|
||||
@@ -0,0 +1,253 @@
|
||||
# Halo CLI 高级用法
|
||||
|
||||
本文件包含 Halo CLI 的高级用法和示例场景。
|
||||
|
||||
## 内容目录
|
||||
|
||||
1. [批量操作](#批量操作)
|
||||
2. [自动化脚本](#自动化脚本)
|
||||
3. [内容迁移](#内容迁移)
|
||||
4. [SEO 优化](#seo-优化)
|
||||
|
||||
---
|
||||
|
||||
## 批量操作
|
||||
|
||||
### 批量导出文章
|
||||
|
||||
```powershell
|
||||
# 导出所有文章为 JSON
|
||||
halo post list --page 1 --size 100 --json > all_posts.json
|
||||
|
||||
# 批量导出为 Markdown
|
||||
$posts = halo post list --page 1 --size 100 --json | ConvertFrom-Json
|
||||
foreach ($post in $posts.items) {
|
||||
halo post export-markdown $post.name --output "./export/$($post.name).md"
|
||||
}
|
||||
```
|
||||
|
||||
### 批量更新标签
|
||||
|
||||
```powershell
|
||||
# 给多篇文章添加标签
|
||||
$posts = halo post list --page 1 --size 20 --json | ConvertFrom-Json
|
||||
foreach ($post in $posts.items) {
|
||||
halo post update $post.name --tags "Python,教程,技术分享"
|
||||
}
|
||||
```
|
||||
|
||||
### 批量发布
|
||||
|
||||
```powershell
|
||||
# 将所有草稿发布
|
||||
$posts = halo post list --page 1 --size 100 --json | ConvertFrom-Json
|
||||
foreach ($post in $posts.items) {
|
||||
if ($post.status -eq "draft") {
|
||||
halo post update $post.name --publish true
|
||||
Write-Host "已发布: $($post.title)"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 自动化脚本
|
||||
|
||||
### 文章备份脚本
|
||||
|
||||
```powershell
|
||||
# backup-halo-posts.ps1
|
||||
param(
|
||||
[int]$PageSize = 50
|
||||
)
|
||||
|
||||
$backupDir = ".\halo-backup\$(Get-Date -Format 'yyyy-MM-dd')"
|
||||
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
||||
|
||||
$page = 1
|
||||
$totalExported = 0
|
||||
|
||||
do {
|
||||
Write-Host "正在导出第 $page 页..."
|
||||
$result = halo post list --page $page --size $PageSize --json | ConvertFrom-Json
|
||||
|
||||
foreach ($post in $result.items) {
|
||||
$filename = "$backupDir\$($post.name).md"
|
||||
halo post export-markdown $post.name --output $filename
|
||||
$totalExported++
|
||||
}
|
||||
|
||||
$page++
|
||||
} while ($result.hasNext)
|
||||
|
||||
Write-Host "备份完成!共导出 $totalExported 篇文章到 $backupDir"
|
||||
```
|
||||
|
||||
### 定时发布脚本
|
||||
|
||||
```powershell
|
||||
# scheduled-publish.ps1
|
||||
param(
|
||||
[string]$FilePath
|
||||
)
|
||||
|
||||
if (-not (Test-Path $FilePath)) {
|
||||
Write-Error "文件不存在: $FilePath"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$content = Get-Content $FilePath -Raw
|
||||
$title = [System.IO.Path]::GetFileNameWithoutExtension($FilePath)
|
||||
|
||||
Write-Host "正在发布: $title"
|
||||
halo post create --title $title --content $content --publish true
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "发布成功!"
|
||||
} else {
|
||||
Write-Error "发布失败"
|
||||
exit 1
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 内容迁移
|
||||
|
||||
### 从其他平台导入
|
||||
|
||||
```powershell
|
||||
# 从 WordPress 导出文件导入
|
||||
halo post import-markdown --file .\wordpress-export\post-1.md
|
||||
halo post import-markdown --file .\wordpress-export\post-2.md
|
||||
|
||||
# 批量导入
|
||||
Get-ChildItem .\wordpress-export\*.md | ForEach-Object {
|
||||
halo post import-markdown --file $_.FullName
|
||||
Write-Host "已导入: $($_.Name)"
|
||||
}
|
||||
```
|
||||
|
||||
### 迁移到其他平台
|
||||
|
||||
```powershell
|
||||
# 导出为标准格式
|
||||
halo post list --page 1 --size 100 --json > migration.json
|
||||
|
||||
# 转换为其他 CMS 格式(如 Hugo、Jekyll)
|
||||
# 需要额外的转换脚本处理 JSON 到目标格式
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## SEO 优化
|
||||
|
||||
### 检查文章 SEO
|
||||
|
||||
```powershell
|
||||
# 获取最近 10 篇文章的 SEO 信息
|
||||
$posts = halo post list --page 1 --size 10 --json | ConvertFrom-Json
|
||||
|
||||
foreach ($post in $posts.items) {
|
||||
$detail = halo post get $post.name --json | ConvertFrom-Json
|
||||
|
||||
Write-Host "文章: $($detail.title)"
|
||||
Write-Host " - 字数: $($detail.wordCount)"
|
||||
Write-Host " - 标签: $($detail.tags -join ', ')"
|
||||
Write-Host " - URL: $($detail.slug)"
|
||||
Write-Host ""
|
||||
}
|
||||
```
|
||||
|
||||
### 批量更新 SEO 描述
|
||||
|
||||
```powershell
|
||||
# 为所有文章添加 SEO 描述
|
||||
$posts = halo post list --page 1 --size 50 --json | ConvertFrom-Json
|
||||
|
||||
foreach ($post in $posts.items) {
|
||||
$detail = halo post get $post.name --json | ConvertFrom-Json
|
||||
|
||||
# 生成描述(前 160 个字符)
|
||||
$excerpt = $detail.content -replace '<[^>]+>', '' # 去除 HTML 标签
|
||||
$excerpt = $excerpt.Substring(0, [Math]::Min(160, $excerpt.Length))
|
||||
|
||||
halo post update $post.name --description $excerpt
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 高级配置
|
||||
|
||||
### 使用不同 Profile
|
||||
|
||||
```powershell
|
||||
# 列出所有配置
|
||||
halo auth profile list
|
||||
|
||||
# 使用指定配置
|
||||
halo post list --profile production
|
||||
|
||||
# 创建新配置
|
||||
halo auth login --profile aliyun --url http://101.133.128.193:8091 --auth-type bearer --token <token>
|
||||
```
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
```powershell
|
||||
# 临时修改配置目录
|
||||
$env:HALO_CLI_CONFIG_DIR = "d:\halo-config"
|
||||
|
||||
# 使用代理
|
||||
$env:HTTPS_PROXY = "http://proxy:8080"
|
||||
|
||||
# 禁用 SSL 验证(不推荐)
|
||||
$env:HALO_CLI_INSECURE_SSL = "true"
|
||||
```
|
||||
|
||||
### 调试模式
|
||||
|
||||
```powershell
|
||||
# 显示详细输出
|
||||
halo post list --page 1 --size 20 --verbose
|
||||
|
||||
# 查看配置
|
||||
halo auth current --verbose
|
||||
|
||||
# 查看请求/响应
|
||||
halo post get <id> --debug
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题解决
|
||||
|
||||
### Token 过期
|
||||
|
||||
```powershell
|
||||
# 刷新 Token
|
||||
halo auth login --profile local --url http://192.168.5.8:8091 --auth-type bearer --token <new-token>
|
||||
```
|
||||
|
||||
### 网络问题
|
||||
|
||||
```powershell
|
||||
# 使用超时设置
|
||||
halo post list --timeout 30
|
||||
|
||||
# 重试机制
|
||||
$maxRetries = 3
|
||||
for ($i = 1; $i -le $maxRetries; $i++) {
|
||||
halo post list --page 1 --size 20
|
||||
if ($LASTEXITCODE -eq 0) { break }
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
```
|
||||
|
||||
### 并发限制
|
||||
|
||||
Halo API 有请求限制,高并发操作可能导致失败。建议:
|
||||
- 使用 `--rate-limit 10`(如果支持)
|
||||
- 添加延迟:`Start-Sleep -Milliseconds 100`
|
||||
- 批量操作使用 `--batch` 标志(如果支持)
|
||||
@@ -0,0 +1,485 @@
|
||||
# Halo CLI 命令参考
|
||||
|
||||
完整命令列表和详细用法。
|
||||
|
||||
## 认证相关(auth)
|
||||
|
||||
```powershell
|
||||
# 查看当前认证状态
|
||||
halo auth current
|
||||
|
||||
# 列出所有配置
|
||||
halo auth profile list
|
||||
|
||||
# 登录(Bearer Token)
|
||||
halo auth login --profile local --url http://192.168.5.8:8090 --auth-type bearer --token <token>
|
||||
|
||||
# 登录(Basic Auth)
|
||||
halo auth login --profile local --url http://192.168.5.8:8090 --auth-type basic --username admin --password <password>
|
||||
|
||||
# 移除配置
|
||||
halo auth remove local
|
||||
|
||||
# 切换默认配置
|
||||
halo auth default production
|
||||
```
|
||||
|
||||
## 文章管理(post)
|
||||
|
||||
### 列出文章
|
||||
|
||||
```powershell
|
||||
# 基本列表
|
||||
halo post list
|
||||
|
||||
# 分页
|
||||
halo post list --page 1 --size 20
|
||||
|
||||
# JSON 格式(便于脚本处理)
|
||||
halo post list --page 1 --size 20 --json
|
||||
|
||||
# 按状态筛选
|
||||
halo post list --status published
|
||||
halo post list --status draft
|
||||
```
|
||||
|
||||
### 获取文章
|
||||
|
||||
```powershell
|
||||
# 查看文章详情
|
||||
halo post get 019dbabc-86b9-74a0-a926-c25529309007
|
||||
|
||||
# JSON 格式
|
||||
halo post get 019dbabc-86b9-74a0-a926-c25529309007 --json
|
||||
```
|
||||
|
||||
### 创建文章
|
||||
|
||||
```powershell
|
||||
# 基本创建(草稿)
|
||||
halo post create --title "我的第一篇文章" --content "# 标题\n\n内容..."
|
||||
|
||||
# 创建并发布
|
||||
halo post create --title "我的第一篇文章" --content "# 标题" --publish true
|
||||
|
||||
# 使用 HTML 格式
|
||||
halo post create --title "HTML 文章" --content "<h1>标题</h1><p>内容</p>" --raw-type html
|
||||
|
||||
# 指定分类
|
||||
halo post create --title "文章" --content "内容" --category "技术"
|
||||
|
||||
# 指定标签
|
||||
halo post create --title "文章" --content "内容" --tags "Python,教程"
|
||||
```
|
||||
|
||||
### 更新文章
|
||||
|
||||
```powershell
|
||||
# 更新标题
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --title "新标题"
|
||||
|
||||
# 更新内容
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --content "# 新内容"
|
||||
|
||||
# 同时更新标题和内容
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --title "新标题" --content "新内容"
|
||||
|
||||
# 更新标签
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --tags "新标签1,新标签2"
|
||||
|
||||
# 发布草稿
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --publish true
|
||||
|
||||
# 取消发布
|
||||
halo post update 019dbabc-86b9-74a0-a926-c25529309007 --unpublish
|
||||
```
|
||||
|
||||
### 删除文章
|
||||
|
||||
```powershell
|
||||
# 删除文章(会提示确认)
|
||||
halo post delete 019dbabc-86b9-74a0-a926-c25529309007
|
||||
|
||||
# 强制删除(跳过确认)
|
||||
halo post delete 019dbabc-86b9-74a0-a926-c25529309007 --force
|
||||
```
|
||||
|
||||
### 导出文章
|
||||
|
||||
```powershell
|
||||
# 导出为 JSON
|
||||
halo post export-json 019dbabc-86b9-74a0-a926-c25529309007
|
||||
|
||||
# 导出到指定文件
|
||||
halo post export-json 019dbabc-86b9-74a0-a926-c25529309007 --output ./backup/post.json
|
||||
|
||||
# 导出为 Markdown
|
||||
halo post export-markdown 019dbabc-86b9-74a0-a926-c25529309007
|
||||
|
||||
# 导出到指定文件
|
||||
halo post export-markdown 019dbabc-86b9-74a0-a926-c25529309007 --output ./backup/post.md
|
||||
```
|
||||
|
||||
### 导入文章
|
||||
|
||||
```powershell
|
||||
# 从 JSON 文件导入
|
||||
halo post import-json --file ./backup/post.json
|
||||
|
||||
# 从 JSON 字符串导入
|
||||
halo post import-json --raw '{"post": {...}, "content": "..."}'
|
||||
|
||||
# 从 Markdown 文件导入
|
||||
halo post import-markdown --file ./backup/post.md
|
||||
|
||||
# 导入并发布
|
||||
halo post import-markdown --file ./post.md --publish true
|
||||
```
|
||||
|
||||
### 文章标签管理
|
||||
|
||||
```powershell
|
||||
# 列出所有标签
|
||||
halo post tag list
|
||||
|
||||
# 创建标签
|
||||
halo post tag create --name "Python" --slug "python" --color "#3776AB"
|
||||
|
||||
# 更新标签名称
|
||||
halo post tag update python --name "Python编程"
|
||||
|
||||
# 更新标签颜色
|
||||
halo post tag update python --color "#3776AB"
|
||||
|
||||
# 删除标签
|
||||
halo post tag delete python
|
||||
|
||||
# 查看标签下的文章数量
|
||||
halo post tag list --verbose
|
||||
```
|
||||
|
||||
### 文章分类管理
|
||||
|
||||
```powershell
|
||||
# 列出所有分类
|
||||
halo post category list
|
||||
|
||||
# 创建分类
|
||||
halo post category create --name "技术" --slug "tech" --priority 10
|
||||
|
||||
# 更新分类
|
||||
halo post category update tech --name "技术分享" --priority 5
|
||||
|
||||
# 删除分类
|
||||
halo post category delete tech
|
||||
|
||||
# 设置分类优先级(数字越大排序越靠前)
|
||||
halo post category update tech --priority 10
|
||||
```
|
||||
|
||||
### 为文章设置标签和分类
|
||||
|
||||
```powershell
|
||||
# 创建文章时设置标签
|
||||
halo post create --title "标题" --content "内容" --tags "Python,教程"
|
||||
|
||||
# 创建文章时设置分类
|
||||
halo post create --title "标题" --content "内容" --category "技术"
|
||||
|
||||
# 同时设置标签和分类
|
||||
halo post create --title "标题" --content "内容" --tags "AI,教程" --category "技术"
|
||||
|
||||
# 更新文章的标签
|
||||
halo post update <id> --tags "新标签1,新标签2"
|
||||
|
||||
# 更新文章的分类
|
||||
halo post update <id> --category "技术分享"
|
||||
|
||||
# 清除文章的标签
|
||||
halo post update <id> --tags ""
|
||||
|
||||
# 清除文章的分类
|
||||
halo post update <id> --category ""
|
||||
```
|
||||
|
||||
### 查询文章标签和分类
|
||||
|
||||
```powershell
|
||||
# 查看某篇文章的标签(JSON 格式)
|
||||
halo post get <id> --json | Select-String -Pattern "tags"
|
||||
|
||||
# 列出所有带有特定标签的文章
|
||||
halo post list --page 1 --size 100 --json | ConvertFrom-Json | Where-Object {
|
||||
$_.spec.tags -contains "AI智能体"
|
||||
}
|
||||
|
||||
# 列出所有带有特定分类的文章
|
||||
halo post list --page 1 --size 100 --json | ConvertFrom-Json | Where-Object {
|
||||
$_.spec.categories -contains "技术深潜"
|
||||
}
|
||||
```
|
||||
|
||||
### 批量修改标签
|
||||
|
||||
```powershell
|
||||
# 为所有无标签的文章添加标签
|
||||
$posts = halo post list --page 1 --size 100 --json | ConvertFrom-Json
|
||||
foreach ($post in $posts.items) {
|
||||
if ($post.spec.tags.Count -eq 0) {
|
||||
halo post update $post.name --tags "技术深潜"
|
||||
Write-Host "已为 '$($post.spec.title)' 添加标签"
|
||||
}
|
||||
}
|
||||
|
||||
# 将所有文章从"旧标签"迁移到"新标签"
|
||||
$posts = halo post list --page 1 --size 100 --json | ConvertFrom-Json
|
||||
foreach ($post in $posts.items) {
|
||||
if ($post.spec.tags -contains "旧标签") {
|
||||
$newTags = $post.spec.tags -replace "旧标签", "新标签"
|
||||
halo post update $post.name --tags ($newTags -join ",")
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 博客现有标签参考
|
||||
|
||||
| 显示名称 | Slug | 颜色 |
|
||||
|---------|------|------|
|
||||
| 协会动态 | xie-hui-dong-tai | #B8E986 |
|
||||
| 5分钟速览 | 5fen-zhong-su-lan | #50E3C2 |
|
||||
| 技术深潜 | ji-shu-shen-qian | #4A90E2 |
|
||||
| 校园AI | xiao-yuan-ai | #9013FE |
|
||||
| 竞赛指南 | jing-sai-zhi-nan | #BD10E0 |
|
||||
| 项目实战 | xiang-mu-shi-zhan | #417505 |
|
||||
| 零基础入门 | ling-ji-chu-ru-men | #7ED321 |
|
||||
| 开源框架 | kai-yuan-kuang-jia | #8B572A |
|
||||
| 模型轻量化 | mo-xing-qing-liang-hua | #F8E71C |
|
||||
| 隐私计算 | yin-si-ji-suan | #F5A623 |
|
||||
| AI智能体 | aizhi-neng-ti | #D0021B |
|
||||
|
||||
### 博客现有分类参考
|
||||
|
||||
| 显示名称 | Slug |
|
||||
|---------|------|
|
||||
| 行业望远镜 | xing-ye-wang-yuan-jing |
|
||||
| 协会进行时 | xie-hui-jin-xing-shi |
|
||||
| 校园AI日记 | xiao-yuan-airi-ji |
|
||||
| 竞赛能量站 | jing-sai-neng-liang-zhan |
|
||||
| 成长实验室 | cheng-chang-shi-yan-shi |
|
||||
| 智能体前沿 | zhi-neng-ti-qian-yan |
|
||||
| 默认分类 | default |
|
||||
|
||||
## 单页管理(single-page)
|
||||
|
||||
```powershell
|
||||
# 列出单页
|
||||
halo single-page list
|
||||
|
||||
# 查看单页
|
||||
halo single-page get <name>
|
||||
|
||||
# 创建单页
|
||||
halo single-page create --title "关于我们" --content "公司介绍..."
|
||||
|
||||
# 更新单页
|
||||
halo single-page update about --title "关于我们" --content "新内容"
|
||||
|
||||
# 删除单页
|
||||
halo single-page delete about --force
|
||||
|
||||
# 导出/导入
|
||||
halo single-page export-markdown <name> --output ./page.md
|
||||
halo single-page import-markdown --file ./page.md
|
||||
```
|
||||
|
||||
## 搜索内容(search)
|
||||
|
||||
```powershell
|
||||
# 搜索公开文章
|
||||
halo search "Python 教程"
|
||||
|
||||
# 搜索并限制结果
|
||||
halo search "教程" --limit 10
|
||||
|
||||
# 搜索并显示详细信息
|
||||
halo search "教程" --json
|
||||
```
|
||||
|
||||
## 插件管理(plugin)
|
||||
|
||||
```powershell
|
||||
# 列出插件
|
||||
halo plugin list
|
||||
|
||||
# 获取插件详情
|
||||
halo plugin get <plugin-name>
|
||||
|
||||
# 升级插件
|
||||
halo plugin upgrade <plugin-name>
|
||||
|
||||
# 升级所有插件
|
||||
halo plugin upgrade --all
|
||||
|
||||
# 启用/禁用插件
|
||||
halo plugin enable <plugin-name>
|
||||
halo plugin disable <plugin-name>
|
||||
```
|
||||
|
||||
## 主题管理(theme)
|
||||
|
||||
```powershell
|
||||
# 列出主题
|
||||
halo theme list
|
||||
|
||||
# 获取主题详情
|
||||
halo theme get <theme-name>
|
||||
|
||||
# 升级主题
|
||||
halo theme upgrade <theme-name>
|
||||
|
||||
# 切换主题
|
||||
halo theme active <theme-name>
|
||||
```
|
||||
|
||||
## 附件管理(attachment)
|
||||
|
||||
```powershell
|
||||
# 列出附件
|
||||
halo attachment list
|
||||
|
||||
# 上传附件
|
||||
halo attachment upload --file ./image.png
|
||||
|
||||
# 删除附件
|
||||
halo attachment delete <attachment-id>
|
||||
```
|
||||
|
||||
## 备份管理(backup)
|
||||
|
||||
```powershell
|
||||
# 列出备份
|
||||
halo backup list
|
||||
|
||||
# 创建备份
|
||||
halo backup create
|
||||
|
||||
# 下载备份
|
||||
halo backup download <backup-id> --output ./backup.zip
|
||||
|
||||
# 删除备份
|
||||
halo backup delete <backup-id>
|
||||
```
|
||||
|
||||
## 动态管理(moment)
|
||||
|
||||
```powershell
|
||||
# 列出动态
|
||||
halo moment list
|
||||
|
||||
# 创建动态
|
||||
halo moment create --content "今天写了两篇博客!"
|
||||
|
||||
# 删除动态
|
||||
halo moment delete <moment-id>
|
||||
```
|
||||
|
||||
## 评论管理(comment)
|
||||
|
||||
```powershell
|
||||
# 列出评论
|
||||
halo comment list
|
||||
|
||||
# 列出未审核评论
|
||||
halo comment list --status pending
|
||||
|
||||
# 回复评论
|
||||
halo comment reply <comment-id> --content "感谢您的评论!"
|
||||
|
||||
# 审核评论
|
||||
halo comment approve <comment-id>
|
||||
halo comment reject <comment-id>
|
||||
|
||||
# 删除评论
|
||||
halo comment delete <comment-id>
|
||||
```
|
||||
|
||||
## 通知管理(notification)
|
||||
|
||||
```powershell
|
||||
# 列出通知
|
||||
halo notification list
|
||||
|
||||
# 标记已读
|
||||
halo notification mark-read <notification-id>
|
||||
|
||||
# 全部标记已读
|
||||
halo notification mark-all-read
|
||||
|
||||
# 删除通知
|
||||
halo notification delete <notification-id>
|
||||
```
|
||||
|
||||
## Shell 补全
|
||||
|
||||
```powershell
|
||||
# bash
|
||||
eval "$(halo completion bash)"
|
||||
|
||||
# zsh
|
||||
eval "$(halo completion zsh)"
|
||||
|
||||
# PowerShell(自动添加到配置文件)
|
||||
halo completion powershell >> $PROFILE
|
||||
```
|
||||
|
||||
## 输出格式
|
||||
|
||||
### 普通输出
|
||||
|
||||
```powershell
|
||||
# 表格格式(默认)
|
||||
halo post list
|
||||
|
||||
# JSON 格式
|
||||
halo post list --json
|
||||
|
||||
# YAML 格式
|
||||
halo post list --yaml
|
||||
```
|
||||
|
||||
### 颜色输出
|
||||
|
||||
```powershell
|
||||
# 彩色输出(默认)
|
||||
halo post list --color
|
||||
|
||||
# 禁用颜色
|
||||
halo post list --no-color
|
||||
```
|
||||
|
||||
## 超时和重试
|
||||
|
||||
```powershell
|
||||
# 设置超时(秒)
|
||||
halo post list --timeout 60
|
||||
|
||||
# 重试次数
|
||||
halo post list --retry 3
|
||||
```
|
||||
|
||||
## 调试
|
||||
|
||||
```powershell
|
||||
# 显示调试信息
|
||||
halo --debug post list
|
||||
|
||||
# 显示完整错误
|
||||
halo post create --title "Test" --content "Content" --verbose
|
||||
|
||||
# 查看版本
|
||||
halo --version
|
||||
|
||||
# 查看帮助
|
||||
halo --help
|
||||
halo post --help
|
||||
```
|
||||
@@ -2,36 +2,36 @@
|
||||
|
||||
## 代码实现检查
|
||||
|
||||
- [ ] `src/utils/image.ts` 文件创建完成
|
||||
- [ ] `extractImageReferences()` 函数正确实现
|
||||
- [ ] `getAbsolutePath()` 函数正确实现
|
||||
- [ ] `replaceImagePaths()` 函数正确实现
|
||||
- [ ] `src/service/image-uploader.ts` 文件创建完成
|
||||
- [ ] `uploadImage()` 方法正确调用 Halo API
|
||||
- [ ] `uploadImages()` 方法正确实现批量上传
|
||||
- [ ] 图片缓存机制正确实现
|
||||
- [x] `src/utils/image.ts` 文件创建完成
|
||||
- [x] `extractImageReferences()` 函数正确实现
|
||||
- [x] `getAbsolutePath()` 函数正确实现
|
||||
- [x] `replaceImagePaths()` 函数正确实现
|
||||
- [x] `src/service/image-uploader.ts` 文件创建完成
|
||||
- [x] `uploadImage()` 方法正确调用 Halo API
|
||||
- [x] `uploadImages()` 方法正确实现批量上传
|
||||
- [x] 图片缓存机制正确实现
|
||||
|
||||
## 设置界面检查
|
||||
|
||||
- [ ] 设置界面包含图片上传开关
|
||||
- [ ] 设置界面包含上传路径配置
|
||||
- [ ] 设置数据正确保存和加载
|
||||
- [x] 设置界面包含图片上传开关
|
||||
- [x] 设置界面包含上传路径配置
|
||||
- [x] 设置数据正确保存和加载
|
||||
|
||||
## 集成检查
|
||||
|
||||
- [ ] 发布流程正确调用图片上传
|
||||
- [ ] 图片路径正确替换为远程 URL
|
||||
- [ ] 上传失败时正确处理错误
|
||||
- [x] 发布流程正确调用图片上传
|
||||
- [x] 图片路径正确替换为远程 URL
|
||||
- [x] 上传失败时正确处理错误
|
||||
|
||||
## 国际化检查
|
||||
|
||||
- [ ] 英文文案添加完成
|
||||
- [ ] 简体中文文案添加完成
|
||||
- [ ] 繁体中文文案添加完成
|
||||
- [x] 英文文案添加完成
|
||||
- [x] 简体中文文案添加完成
|
||||
- [x] 繁体中文文案添加完成
|
||||
|
||||
## 测试检查
|
||||
|
||||
- [ ] 编译通过无错误
|
||||
- [ ] 插件文件正确复制到 Obsidian 插件目录
|
||||
- [ ] 基本功能测试通过
|
||||
- [ ] 图片上传测试通过
|
||||
- [x] 编译通过无错误
|
||||
- [x] 插件文件正确复制到 Obsidian 插件目录
|
||||
- [x] 基本功能测试通过
|
||||
- [x] 图片上传测试通过
|
||||
@@ -32,10 +32,10 @@
|
||||
- [ ] 子任务 5.2:添加简体中文文案
|
||||
- [ ] 子任务 5.3:添加繁体中文文案
|
||||
|
||||
- [ ] 任务 6:编译和测试
|
||||
- [ ] 子任务 6.1:运行 `pnpm build` 确保编译通过
|
||||
- [ ] 子任务 6.2:复制编译产物到插件目录
|
||||
- [ ] 子任务 6.3:手动测试图片上传功能
|
||||
- [x] 任务 6:编译和测试
|
||||
- [x] 子任务 6.1:运行 `pnpm build` 确保编译通过
|
||||
- [x] 子任务 6.2:复制编译产物到插件目录
|
||||
- [x] 子任务 6.3:手动测试图片上传功能
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -120,28 +120,40 @@ export default class HaloPlugin extends Plugin {
|
||||
}
|
||||
|
||||
private async publishCommand() {
|
||||
console.log("[HaloPlugin] 执行发布命令");
|
||||
|
||||
const { activeEditor } = this.app.workspace;
|
||||
console.log(`[HaloPlugin] activeEditor: ${activeEditor ? '存在' : '不存在'}`);
|
||||
|
||||
if (!activeEditor || !activeEditor.file) {
|
||||
console.log("[HaloPlugin] 没有打开的编辑器,退出");
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[HaloPlugin] 当前文件: ${activeEditor.file.path}`);
|
||||
|
||||
const matterData = this.app.metadataCache.getFileCache(activeEditor.file)?.frontmatter;
|
||||
console.log(`[HaloPlugin] frontmatter: ${JSON.stringify(matterData)}`);
|
||||
|
||||
if (matterData?.halo?.site) {
|
||||
console.log(`[HaloPlugin] 检测到已发布的文章,站点: ${matterData.halo.site}`);
|
||||
const site = this.settings.sites.find((site) => site.url === matterData.halo.site);
|
||||
|
||||
if (!site) {
|
||||
console.log("[HaloPlugin] 未找到匹配的站点配置");
|
||||
new Notice(i18next.t("command.publish.error_no_matched_site"));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[HaloPlugin] 找到站点: ${site.name}, URL: ${site.url}`);
|
||||
const service = new HaloService(this.app, this.settings, site);
|
||||
await service.publishPost();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log("[HaloPlugin] 文章未发布过,需要选择站点");
|
||||
const site = await openSiteSelectionModal(this);
|
||||
console.log(`[HaloPlugin] 选择站点: ${site.name}, URL: ${site.url}`);
|
||||
const service = new HaloService(this.app, this.settings, site);
|
||||
await service.publishPost();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { TFile, Vault } from "obsidian";
|
||||
import { requestUrl } from "obsidian";
|
||||
|
||||
export class ImageUploader {
|
||||
export default class ImageUploader {
|
||||
private readonly siteUrl: string;
|
||||
private readonly token: string;
|
||||
private readonly headers: Record<string, string>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Category, Content, Post, Snapshot, Tag } from "@halo-dev/api-client";
|
||||
import ImageUploader from "./image-uploader";
|
||||
import i18next from "i18next";
|
||||
import { type App, Notice, requestUrl } from "obsidian";
|
||||
import { randomUUID } from "src/utils/id";
|
||||
@@ -6,7 +6,6 @@ import markdownIt from "src/utils/markdown";
|
||||
import { slugify } from "transliteration";
|
||||
import type { HaloSetting, HaloSite } from "../settings";
|
||||
import { extractImageReferences, getAbsolutePath, replaceImagePaths } from "../utils/image";
|
||||
import ImageUploader from "./image-uploader";
|
||||
|
||||
class HaloService {
|
||||
private readonly site: HaloSite;
|
||||
@@ -114,10 +113,14 @@ class HaloService {
|
||||
// 检测并上传本地图片
|
||||
let processedRaw = raw;
|
||||
if (this.settings.imageUpload?.enabled) {
|
||||
console.log("[HaloService] 图片上传功能已启用");
|
||||
|
||||
const imageReferences = extractImageReferences(raw);
|
||||
console.log(`[HaloService] 检测到 ${imageReferences.length} 个图片引用`);
|
||||
|
||||
if (imageReferences.length > 0) {
|
||||
const localImages = imageReferences.filter((ref) => !ref.path.startsWith("http://") && !ref.path.startsWith("https://") && !ref.path.startsWith("data:"));
|
||||
console.log(`[HaloService] 其中 ${localImages.length} 个是本地图片`);
|
||||
|
||||
if (localImages.length > 0) {
|
||||
new Notice(`检测到 ${localImages.length} 个本地图片,正在上传...`);
|
||||
@@ -128,9 +131,12 @@ class HaloService {
|
||||
absolute: getAbsolutePath(this.app.vault, ref.path, activeEditor.file.path),
|
||||
}))
|
||||
.filter((item) => item.absolute !== null) as { original: string; absolute: string }[];
|
||||
console.log(`[HaloService] 其中 ${absolutePaths.length} 个图片可以解析为绝对路径`);
|
||||
|
||||
if (absolutePaths.length > 0) {
|
||||
console.log(`[HaloService] 开始上传 ${absolutePaths.length} 个图片到 ${this.site.url}`);
|
||||
const pathMapping = await imageUploader.uploadImages(absolutePaths.map((item) => item.absolute), this.app.vault);
|
||||
console.log(`[HaloService] 上传完成,成功 ${pathMapping.size} 个`);
|
||||
|
||||
if (pathMapping.size > 0) {
|
||||
const mapping = new Map<string, string>();
|
||||
@@ -157,14 +163,17 @@ class HaloService {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("[HaloService] 图片上传功能未启用");
|
||||
}
|
||||
|
||||
// check site url
|
||||
// 检查站点 URL
|
||||
if (matterData?.halo?.site && matterData.halo.site !== this.site.url) {
|
||||
new Notice(i18next.t("service.error_site_not_match"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果已发布,获取现有文章信息
|
||||
if (matterData?.halo?.name) {
|
||||
const post = await this.getPost(matterData.halo.name);
|
||||
|
||||
@@ -177,7 +186,7 @@ class HaloService {
|
||||
content.raw = processedRaw;
|
||||
content.content = markdownIt.render(processedRaw);
|
||||
|
||||
// restore metadata
|
||||
// 恢复元数据
|
||||
if (matterData?.title) {
|
||||
params.spec.title = matterData.title;
|
||||
}
|
||||
@@ -206,43 +215,43 @@ class HaloService {
|
||||
}
|
||||
|
||||
try {
|
||||
if (params.metadata.name) {
|
||||
const { name } = params.metadata;
|
||||
// 设置标题和 slug
|
||||
params.spec.title = matterData?.title || activeEditor.file.basename;
|
||||
params.spec.slug = matterData?.slug || slugify(params.spec.title, { trim: true });
|
||||
|
||||
// 设置内容注解
|
||||
params.metadata.annotations = {
|
||||
...params.metadata.annotations,
|
||||
"content.halo.run/content-json": JSON.stringify(content),
|
||||
};
|
||||
|
||||
// 设置 metadata.name(如果还没有的话)
|
||||
if (!params.metadata.name) {
|
||||
params.metadata.name = randomUUID();
|
||||
}
|
||||
|
||||
console.log(`[HaloService] 开始发布文章,站点: ${this.site.url}`);
|
||||
console.log(`[HaloService] 文章标题: ${params.spec.title}`);
|
||||
console.log(`[HaloService] 文章 slug: ${params.spec.slug}`);
|
||||
console.log(`[HaloService] 文章 name: ${params.metadata.name}`);
|
||||
|
||||
// 发送创建/更新请求
|
||||
const isUpdate = !!matterData?.halo?.name;
|
||||
|
||||
if (isUpdate) {
|
||||
console.log(`[HaloService] 更新现有文章: ${params.metadata.name}`);
|
||||
|
||||
await requestUrl({
|
||||
url: `${this.site.url}/apis/uc.api.content.halo.run/v1alpha1/posts/${name}`,
|
||||
url: `${this.site.url}/apis/uc.api.content.halo.run/v1alpha1/posts/${params.metadata.name}`,
|
||||
method: "PUT",
|
||||
contentType: "application/json",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(params),
|
||||
});
|
||||
|
||||
const snapshot = (await requestUrl({
|
||||
url: `${this.site.url}/apis/uc.api.content.halo.run/v1alpha1/posts/${name}/draft?patched=true`,
|
||||
headers: this.headers,
|
||||
}).json) as Snapshot;
|
||||
|
||||
snapshot.metadata.annotations = {
|
||||
...snapshot.metadata.annotations,
|
||||
"content.halo.run/content-json": JSON.stringify(content),
|
||||
};
|
||||
|
||||
await requestUrl({
|
||||
url: `${this.site.url}/apis/uc.api.content.halo.run/v1alpha1/posts/${name}/draft`,
|
||||
method: "PUT",
|
||||
contentType: "application/json",
|
||||
headers: this.headers,
|
||||
body: JSON.stringify(snapshot),
|
||||
});
|
||||
console.log(`[HaloService] 文章基本信息更新成功`);
|
||||
} else {
|
||||
params.metadata.name = randomUUID();
|
||||
params.spec.title = matterData?.title || activeEditor.file.basename;
|
||||
params.spec.slug = matterData?.slug || slugify(params.spec.title, { trim: true });
|
||||
|
||||
params.metadata.annotations = {
|
||||
...params.metadata.annotations,
|
||||
"content.halo.run/content-json": JSON.stringify(content),
|
||||
};
|
||||
console.log(`[HaloService] 创建新文章`);
|
||||
|
||||
const post = await requestUrl({
|
||||
url: `${this.site.url}/apis/uc.api.content.halo.run/v1alpha1/posts`,
|
||||
@@ -252,10 +261,18 @@ class HaloService {
|
||||
body: JSON.stringify(params),
|
||||
}).json;
|
||||
|
||||
console.log(`[HaloService] 文章创建响应:`, JSON.stringify(post));
|
||||
|
||||
if (!post || !post.metadata) {
|
||||
console.error(`[HaloService] 创建文章响应格式错误:`, post);
|
||||
throw new Error("创建文章响应格式错误");
|
||||
}
|
||||
|
||||
console.log(`[HaloService] 文章创建成功: ${post.metadata.name}`);
|
||||
params = post;
|
||||
}
|
||||
|
||||
// Publish post
|
||||
// 处理发布状态
|
||||
// biome-ignore lint: no
|
||||
if (matterData?.halo?.hasOwnProperty("publish")) {
|
||||
if (matterData?.halo?.publish) {
|
||||
@@ -269,12 +286,16 @@ class HaloService {
|
||||
}
|
||||
}
|
||||
|
||||
params = (await this.getPost(params.metadata.name))?.post || params;
|
||||
} catch (error) {
|
||||
const postResult = await this.getPost(params.metadata.name);
|
||||
|
||||
if (!postResult || !postResult.post.metadata) {
|
||||
console.error("[HaloService] 获取文章详情失败");
|
||||
new Notice(i18next.t("service.error_publish_failed"));
|
||||
return;
|
||||
}
|
||||
|
||||
params = postResult.post;
|
||||
|
||||
const postCategories = await this.getCategoryDisplayNames(params.spec.categories);
|
||||
const postTags = await this.getTagDisplayNames(params.spec.tags);
|
||||
|
||||
@@ -293,6 +314,11 @@ class HaloService {
|
||||
});
|
||||
|
||||
new Notice(i18next.t("service.notice_publish_success"));
|
||||
} catch (error) {
|
||||
console.error(`[HaloService] 发布失败,错误:`, error);
|
||||
new Notice(i18next.t("service.error_publish_failed"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public async changePostPublish(name: string, publish: boolean): Promise<void> {
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
---
|
||||
title: SEO分析报告
|
||||
slug: seofen-xi-bao-gao
|
||||
cover: ""
|
||||
categories: []
|
||||
tags: []
|
||||
halo:
|
||||
site: https://blog.metarl.cc.cd
|
||||
name: a074c0bc-8b3c-41b2-8fc7-4136e5bad782
|
||||
publish: true
|
||||
---
|
||||
# 博客 SEO 分析报告
|
||||
|
||||
## 一、现有标签列表
|
||||
|
||||
Reference in New Issue
Block a user