/** * 条目编辑的前端接口。 * * 读取是公开的(编辑表单要能预览),写入必须登录,并用 `updatedAt` 做乐观锁。 */ export type EntryFormat = 'apps' | 'posters' | 'articles' export type EntryRecord = { key: string format: EntryFormat name: string description: string icon: string href: string cover: string banner: string badge: string comment: string summary: string body: string tags: string[] updated_at: number } export type EntryInput = { name: string /** 条目的展示格式;不传由后端按 apps 处理 */ format?: EntryFormat description: string icon: string tags: string[] badge: string comment: string summary: string body: string cover: string banner: string href: string /** 编辑时传目标分区/分组,可移动条目 */ nodeKey?: string } export type ItemResult = | { ok: true; entry: EntryRecord } | { ok: false; status: number; error: string } export async function fetchItem(key: string): Promise { try { const response = await fetch(`/api/items/${encodeURIComponent(key)}`, { credentials: 'same-origin', }) if (response.ok) { return { ok: true, entry: (await response.json()) as EntryRecord } } const payload = (await response.json().catch(() => null)) as { error?: string } | null return { ok: false, status: response.status, error: payload?.error ?? '读取失败' } } catch (error) { return { ok: false, status: 0, error: error instanceof Error ? error.message : '网络错误' } } } export async function saveItem( key: string, updatedAt: number, item: EntryInput, ): Promise { try { const response = await fetch(`/api/items/${encodeURIComponent(key)}`, { method: 'PATCH', credentials: 'same-origin', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ updatedAt, item }), }) if (response.ok) { return { ok: true, entry: (await response.json()) as EntryRecord } } const payload = (await response.json().catch(() => null)) as { error?: string } | null return { ok: false, status: response.status, error: payload?.error ?? `保存失败(${response.status})`, } } catch (error) { return { ok: false, status: 0, error: error instanceof Error ? error.message : '网络错误' } } } /** 新建条目:指定分区 / 分组与字段 */ export async function createItem(input: { key: string nodeKey: string item: EntryInput }): Promise { try { const response = await fetch('/api/items', { method: 'POST', credentials: 'same-origin', headers: { 'content-type': 'application/json' }, body: JSON.stringify(input), }) if (response.ok) return { ok: true } const payload = (await response.json().catch(() => null)) as { error?: string } | null return { ok: false, error: payload?.error ?? `创建失败(${response.status})` } } catch (error) { return { ok: false, error: error instanceof Error ? error.message : '网络错误' } } } /** 删除条目 */ export async function deleteItem(key: string): Promise { try { const response = await fetch(`/api/items/${encodeURIComponent(key)}`, { method: 'DELETE', credentials: 'same-origin', }) if (response.ok) return { ok: true } const payload = (await response.json().catch(() => null)) as { error?: string } | null return { ok: false, error: payload?.error ?? `删除失败(${response.status})` } } catch (error) { return { ok: false, error: error instanceof Error ? error.message : '网络错误' } } } export type SimpleResult = { ok: true } | { ok: false; error: string }