Skip to content

Commit 228ad6e

Browse files
committed
update:plugin config path
1 parent 0c23881 commit 228ad6e

5 files changed

Lines changed: 53 additions & 50 deletions

File tree

plugin/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
- 右键或按钮删除文章。
99

1010
## 扩展设置
11-
- `mkBlog.uploadUrl`: 上传接口 URL(PUT, multipart/form-data)
12-
- `mkBlog.listUrl`: 文章列表接口 URL(GET 返回数组或 `{ data: [] }`
13-
- `mkBlog.deleteUrl`: 删除接口 URL,使用 `{id}` 占位符
14-
- `mkBlog.authToken`: 可选 Bearer Token
11+
- `mkBlog.baseUrl`: 后端服务基础地址(例如 `http://localhost:8080`)。各接口会自动拼接 `/api/articles``/api/article/:title``/api/image` 等路径。
12+
- `mkBlog.defaultAuthor`: 若 Markdown 中未声明作者时使用的默认作者。
13+
- `mkBlog.defaultCategory`: 若 Markdown 中未声明分类时使用的默认分类。
14+
- `mkBlog.authToken`: 可选 Bearer Token,会通过 `Authorization: Bearer <token>` 头发送。
1515

1616
## 命令
1717
- `mkBlog: 上传文件夹为博客`

plugin/package.json

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -72,35 +72,25 @@
7272
"type": "object",
7373
"title": "mkBlog Settings",
7474
"properties": {
75-
"mkBlog.uploadArticleUrl": {
75+
"mkBlog.baseUrl": {
7676
"type": "string",
77-
"default": "http://localhost:3000/article/{title}",
78-
"description": "Article upload URL(PUT Article JSON)。Support {title} or {id} as placeholder"
77+
"default": "http://localhost:8080",
78+
"description": "后端服务基础地址,例如 http://localhost:8080"
7979
},
80-
"mkBlog.uploadImageUrl": {
80+
"mkBlog.defaultAuthor": {
8181
"type": "string",
82-
"default": "http://localhost:3000/image",
83-
"description": "Image upload URL(PUT Image JSON,includes title/data/name)"
82+
"default": "",
83+
"description": "文章默认作者(可在 Markdown 元数据中覆盖)"
8484
},
8585
"mkBlog.author": {
8686
"type": "string",
8787
"default": "",
88-
"description": "Default author(Article.Author)"
88+
"description": "(兼容旧版本) 文章默认作者,建议改用 mkBlog.defaultAuthor"
8989
},
9090
"mkBlog.defaultCategory": {
9191
"type": "string",
9292
"default": "General",
93-
"description": "Default category(Article.Category)"
94-
},
95-
"mkBlog.listUrl": {
96-
"type": "string",
97-
"default": "http://localhost:3000/api/articles",
98-
"description": "Article list API URL(GET)"
99-
},
100-
"mkBlog.deleteUrl": {
101-
"type": "string",
102-
"default": "http://localhost:3000/article/{title}",
103-
"description": "Delete article API URL, support placeholder {title} (replace with filename/title) or {id}?"
93+
"description": "文章默认分类(可在 Markdown 元数据中覆盖)"
10494
},
10595
"mkBlog.authToken": {
10696
"type": "string",

plugin/src/extension.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
import * as vscode from 'vscode';
22
import { ArticleProvider, ArticleTreeItem } from './tree/ArticleProvider';
3-
import { fetchArticles, deleteArticleById } from './net/api';
3+
import { fetchArticles, deleteArticleByTitle } from './net/api';
44
import { uploadFolderAsBlog } from './uploader';
55

66
export async function activate(context: vscode.ExtensionContext) {
77
const articleProvider = new ArticleProvider(async () => {
88
const cfg = vscode.workspace.getConfiguration();
9-
const listUrl = cfg.get<string>('mkBlog.listUrl');
9+
const baseUrl = (cfg.get<string>('mkBlog.baseUrl') || '').trim();
1010
const token = cfg.get<string>('mkBlog.authToken') || '';
11-
if (!listUrl) {
12-
vscode.window.showWarningMessage('mkBlog: 未配置 listUrl');
11+
if (!baseUrl) {
12+
vscode.window.showWarningMessage('mkBlog: 未配置 baseUrl');
1313
return [];
1414
}
1515
try {
16-
const items = await fetchArticles(listUrl, token);
16+
const items = await fetchArticles(baseUrl, token);
1717
return items;
1818
} catch (err: any) {
1919
vscode.window.showErrorMessage(`获取文章列表失败: ${err?.message || err}`);
@@ -46,18 +46,14 @@ export async function activate(context: vscode.ExtensionContext) {
4646
);
4747
if (confirm !== '删除') return;
4848
const cfg = vscode.workspace.getConfiguration();
49-
const template = cfg.get<string>('mkBlog.deleteUrl');
49+
const baseUrl = (cfg.get<string>('mkBlog.baseUrl') || '').trim();
5050
const token = cfg.get<string>('mkBlog.authToken') || '';
51-
if (!template) {
52-
vscode.window.showWarningMessage('mkBlog: 未配置 deleteUrl');
51+
if (!baseUrl) {
52+
vscode.window.showWarningMessage('mkBlog: 未配置 baseUrl');
5353
return;
5454
}
55-
// 同时支持 {id} 与 {title} 两种占位符
56-
let url = template;
57-
url = url.replace('{id}', encodeURIComponent(String(picked.id)));
58-
url = url.replace('{title}', encodeURIComponent(String(picked.title)));
5955
try {
60-
await deleteArticleById(url, token);
56+
await deleteArticleByTitle(baseUrl, String(picked.title), token);
6157
vscode.window.showInformationMessage('删除成功');
6258
await articleProvider.refresh();
6359
} catch (err: any) {

plugin/src/net/api.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,14 @@ export interface RawArticle {
55
title: string;
66
}
77

8-
export async function fetchArticles(listUrl: string, token?: string): Promise<RawArticle[]> {
8+
function joinUrl(baseUrl: string, path: string): string {
9+
const base = (baseUrl || '').replace(/\/+$/, '');
10+
const suffix = path.startsWith('/') ? path : `/${path}`;
11+
return `${base}${suffix}`;
12+
}
13+
14+
export async function fetchArticles(baseUrl: string, token?: string): Promise<RawArticle[]> {
15+
const listUrl = joinUrl(baseUrl, '/api/allarticles');
916
const headers: Record<string, string> = { 'Accept': 'application/json' };
1017
if (token) headers['Authorization'] = `Bearer ${token}`;
1118
const res = await fetch(listUrl, { method: 'GET', headers });
@@ -42,7 +49,17 @@ export async function fetchArticles(listUrl: string, token?: string): Promise<Ra
4249
}));
4350
}
4451

45-
export async function deleteArticleById(url: string, token?: string): Promise<void> {
52+
export function buildArticleEndpoint(baseUrl: string, title: string): string {
53+
const encoded = encodeURIComponent(title);
54+
return joinUrl(baseUrl, `/api/article/${encoded}`);
55+
}
56+
57+
export function buildImageEndpoint(baseUrl: string): string {
58+
return joinUrl(baseUrl, '/api/image');
59+
}
60+
61+
export async function deleteArticleByTitle(baseUrl: string, title: string, token?: string): Promise<void> {
62+
const url = buildArticleEndpoint(baseUrl, title);
4663
const headers: Record<string, string> = { 'Accept': 'application/json' };
4764
if (token) headers['Authorization'] = `Bearer ${token}`;
4865
const res = await fetch(url, { method: 'DELETE', headers });

plugin/src/uploader.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from 'vscode';
22
import * as path from 'path';
33
import { findMarkdownFilesWithImageFolders } from './utils/fs';
4+
import { buildArticleEndpoint, buildImageEndpoint } from './net/api';
45

56
function extractMeta(md: string): { author?: string; category?: string; content: string } {
67
let author: string | undefined;
@@ -56,11 +57,10 @@ function extractMeta(md: string): { author?: string; category?: string; content:
5657

5758
export async function uploadFolderAsBlog(uri?: vscode.Uri) {
5859
const cfg = vscode.workspace.getConfiguration();
59-
const uploadArticleUrl = cfg.get<string>('mkBlog.uploadArticleUrl');
60-
const uploadImageUrl = cfg.get<string>('mkBlog.uploadImageUrl');
60+
const baseUrl = (cfg.get<string>('mkBlog.baseUrl') || '').trim();
6161
const token = cfg.get<string>('mkBlog.authToken') || '';
62-
if (!uploadArticleUrl && !uploadImageUrl) {
63-
throw new Error('未配置上传接口:mkBlog.uploadArticleUrl 或 mkBlog.uploadImageUrl');
62+
if (!baseUrl) {
63+
throw new Error('未配置 mkBlog.baseUrl');
6464
}
6565

6666
// 优先使用传入目录;否则使用已打开的工作区根目录;若都没有,再让用户选择
@@ -85,6 +85,8 @@ export async function uploadFolderAsBlog(uri?: vscode.Uri) {
8585
const headers: Record<string, string> = {};
8686
if (token) headers['Authorization'] = `Bearer ${token}`;
8787

88+
const imageEndpoint = buildImageEndpoint(baseUrl);
89+
8890
for (const t of tasks) {
8991
const title = path.basename(t.mdPath, '.md');
9092
// 分离上传:文章 PUT /article/{title},图片逐张 PUT /image
@@ -100,31 +102,29 @@ export async function uploadFolderAsBlog(uri?: vscode.Uri) {
100102
content: meta.content,
101103
};
102104
if (meta.author) article.author = meta.author;
103-
else article.author = cfg.get<string>('mkBlog.defaultAuthor');
105+
else article.author = cfg.get<string>('mkBlog.defaultAuthor') ?? cfg.get<string>('mkBlog.author');
104106

105107
if (meta.category) article.category = meta.category;
106108
else article.category = cfg.get<string>('mkBlog.defaultCategory');
107109

108-
if (uploadArticleUrl) {
109-
try {
110-
const articleUrl = uploadArticleUrl.replace('{title}', encodeURIComponent(title));
110+
try {
111+
const articleUrl = buildArticleEndpoint(baseUrl, title);
111112
const jsonHeaders: Record<string, string> = { ...headers, 'Content-Type': 'application/json' };
112113
const res = await fetch(articleUrl, { method: 'PUT', body: JSON.stringify(article), headers: jsonHeaders });
113114
if (!res.ok) {
114115
const text = await res.text().catch(() => '');
115116
vscode.window.showWarningMessage(`上传文章失败(JSON): ${path.basename(t.mdPath)} -> HTTP ${res.status} ${res.statusText} ${text},将继续上传图片。`);
116117
}
117-
} catch (err: any) {
118-
vscode.window.showWarningMessage(`上传文章异常: ${path.basename(t.mdPath)} -> ${err?.message || err},将继续上传图片。`);
119-
}
118+
} catch (err: any) {
119+
vscode.window.showWarningMessage(`上传文章异常: ${path.basename(t.mdPath)} -> ${err?.message || err},将继续上传图片。`);
120120
}
121121

122-
if (uploadImageUrl) {
122+
if (imageEndpoint) {
123123
for (const img of t.images) {
124124
const base64 = Buffer.from(img.buffer).toString('base64');
125125
const payload = { title, data: base64, name: img.name };
126126
const jsonHeaders: Record<string, string> = { ...headers, 'Content-Type': 'application/json' };
127-
const res = await fetch(uploadImageUrl, { method: 'PUT', body: JSON.stringify(payload), headers: jsonHeaders });
127+
const res = await fetch(imageEndpoint, { method: 'PUT', body: JSON.stringify(payload), headers: jsonHeaders });
128128
if (!res.ok) {
129129
const text = await res.text().catch(() => '');
130130
throw new Error(`上传图片失败(JSON): ${img.name} -> HTTP ${res.status} ${res.statusText} ${text}`);

0 commit comments

Comments
 (0)