Files
stash/stash-web/src/items.ts
T
CNWei 11f992cdad feat: 格式从分组下沉到条目(v21)
- entry 新增 format(apps/posters/articles),老数据按根分组 view_mode 回填;seed 按分区写入
- 分组管理移除格式字段/显示,根分组只作容器
- 内容弹窗新增逐条格式选择,列表增加格式列;ItemEditor 保存时保留原格式
- 前台按 entry.format 渲染:卡片/分组页支持同组混合格式,详情按条目格式选模板
- 迁移后 live 20 应用 / 13 海报;cargo test 59 passed;Playwright 验证混合展示
2026-10-31 14:26:28 +08:00

127 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 条目编辑的前端接口。
*
* 读取是公开的(编辑表单要能预览),写入必须登录,并用 `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<ItemResult> {
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<ItemResult> {
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<SimpleResult> {
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<SimpleResult> {
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 }