feat: 增加系列相关服务端逻辑与 Hugo 元数据解析支持
This commit is contained in:
1 parent
fe37e26e5f
commit
592d4e1f6d
2 files changed
+59
-1
No files matched your search
+11
-1
@@ -10,6 +10,8 @@ export interface HugoPostData {
|
||||
updated_at: string;
|
||||
categories: string[];
|
||||
tags: string[];
|
||||
series: string[];
|
||||
series_weight: number | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,6 +43,12 @@ function parseArrayField(val: unknown): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
function parseIntegerField(val: unknown): number | null {
|
||||
if (val === null || val === undefined || val === '') return null;
|
||||
const parsed = typeof val === 'number' ? val : Number(String(val).trim());
|
||||
return Number.isInteger(parsed) ? parsed : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉文件名结尾的格式拓展名,提供纯文件名基础
|
||||
*/
|
||||
@@ -120,6 +128,8 @@ export function parseHugoMarkdown(rawContent: string, fileName = ''): HugoPostDa
|
||||
published_at,
|
||||
updated_at,
|
||||
categories: parseArrayField(meta.categories || meta.category),
|
||||
tags: parseArrayField(meta.tags || meta.tag)
|
||||
tags: parseArrayField(meta.tags || meta.tag),
|
||||
series: parseArrayField(meta.series),
|
||||
series_weight: parseIntegerField(meta.series_weight)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
export class SeriesValidationError extends Error {}
|
||||
|
||||
export function parseSeriesId(value: FormDataEntryValue | null): number | null {
|
||||
if (value === null || value.toString().trim() === '') return null;
|
||||
|
||||
const id = Number(value);
|
||||
if (!Number.isInteger(id) || id <= 0) {
|
||||
throw new SeriesValidationError('系列选择无效');
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
export function parseSeriesWeight(value: FormDataEntryValue | null): number | null {
|
||||
if (value === null || value.toString().trim() === '') return null;
|
||||
|
||||
const weight = Number(value);
|
||||
if (!Number.isInteger(weight)) {
|
||||
throw new SeriesValidationError('系列顺序必须是整数');
|
||||
}
|
||||
|
||||
return weight;
|
||||
}
|
||||
|
||||
export async function resolveSeriesWeight(
|
||||
db: D1Database,
|
||||
seriesId: number | null,
|
||||
requestedWeight: number | null,
|
||||
excludePostId?: string
|
||||
): Promise<number | null> {
|
||||
if (seriesId === null) return null;
|
||||
|
||||
const series = await db.prepare('SELECT id FROM series WHERE id = ?').bind(seriesId).first();
|
||||
if (!series) {
|
||||
throw new SeriesValidationError('所选系列不存在');
|
||||
}
|
||||
|
||||
if (requestedWeight !== null) return requestedWeight;
|
||||
|
||||
const query = excludePostId
|
||||
? 'SELECT COALESCE(MAX(series_weight), 0) + 1 AS next_weight FROM posts WHERE series_id = ? AND id != ?'
|
||||
: 'SELECT COALESCE(MAX(series_weight), 0) + 1 AS next_weight FROM posts WHERE series_id = ?';
|
||||
const result = excludePostId
|
||||
? await db.prepare(query).bind(seriesId, excludePostId).first<{ next_weight: number }>()
|
||||
: await db.prepare(query).bind(seriesId).first<{ next_weight: number }>();
|
||||
|
||||
return result?.next_weight ?? 1;
|
||||
}
|
||||
Reference in new issue
Block a user