update
This commit is contained in:
@ -1,17 +1,25 @@
|
||||
// src/lib/history.ts — 浏览历史(服务端持久化 + 本地缓存兜底)
|
||||
// src/lib/history.ts — 浏览历史(本地缓存兜底 + 服务端持久化)
|
||||
//
|
||||
// 2026-09-02 语义收敛(用户拍板):
|
||||
// 职责:历史的本地缓存与去重、以及「服务端调用」的编排。
|
||||
// 真正的 HTTP 端点(/me/history*)与单篇回查(getHistoryMeta)在 api.ts。
|
||||
//
|
||||
// 语义(2026-09-02 用户拍板):
|
||||
// - 浏览历史 = 「点开过哪篇文章」,触发时机在 item 详情页(打开某篇走秀/街拍即记一条)。
|
||||
// 列表页(Runway Looks / Street Snaps)进入不再记。
|
||||
// - 后端 histories 表只存 (user_id, target_uid, viewed_at):target_uid 为文章对外编码串
|
||||
// (首字符区分类型:s 开头=街拍 / r 开头=走秀,编码串自带类型,故不再有 kind/target_type 概念),
|
||||
// 表已去掉 title/cover/brand 快照列。
|
||||
// - 账户页 My History 展示:先取服务端 id 列表,再逐篇回查公开详情接口拿 title/cover/brand
|
||||
// (用户选「只存 id、展示时回查」),历史卡片点击跳回文章详情。
|
||||
// 列表页进入不记。
|
||||
// - 服务端只存 (user_id, target_uid, viewed_at):target_uid 为文章对外编码串
|
||||
// (首字符区分类型:s 开头=街拍 / r 开头=走秀)。
|
||||
// - 账户页 My History 展示:先取服务端 id 列表,再逐篇回查公开详情接口拿 title/cover/brand。
|
||||
// - 未登录:纯本地 localStorage(按用户名隔离);登录态写本地 + 后台 POST(失败不回滚本地)。
|
||||
|
||||
import { getHistoryMeta } from "./api"
|
||||
import { getUser, getAccessToken, authJson } from "./auth"
|
||||
import { getUser, getAccessToken } from "./auth"
|
||||
import {
|
||||
getHistoryMeta,
|
||||
addHistory,
|
||||
fetchHistory,
|
||||
deleteHistory,
|
||||
clearAllHistory,
|
||||
type ServerHistory,
|
||||
} from "./api"
|
||||
|
||||
export interface HistoryData {
|
||||
title: string
|
||||
@ -36,12 +44,6 @@ function dedupeKey(id: string): string {
|
||||
return /^[rsij]/.test(s) ? s.slice(1) : s
|
||||
}
|
||||
|
||||
// 后端 HistoryItem 响应结构({data:{items:[...]}} 解包后,仅 id + viewed_at)
|
||||
interface ServerHistory {
|
||||
id: string
|
||||
viewed_at?: number
|
||||
}
|
||||
|
||||
// ---------- 本地存储(兜底 / 离线) ----------
|
||||
function storageKey(): string | null {
|
||||
const u = getUser()
|
||||
@ -90,7 +92,7 @@ export function recordHistory(id: string): void {
|
||||
setLocal(list)
|
||||
|
||||
if (serverMode()) {
|
||||
authJson("POST", "/me/history", { target_uid: id }).catch(() => {
|
||||
addHistory(id).catch(() => {
|
||||
/* 失败不回滚本地 */
|
||||
})
|
||||
}
|
||||
@ -125,12 +127,8 @@ export async function fetchHistoryPage(page = 1, perPage = 24): Promise<HistPage
|
||||
return { items: local, total: local.length, lastPage: 1 }
|
||||
}
|
||||
try {
|
||||
const qs = `page=${page}&per_page=${perPage}`
|
||||
const r = await authJson<{ items: ServerHistory[]; total: number; last_page: number }>(
|
||||
"GET",
|
||||
`/me/history?${qs}`,
|
||||
)
|
||||
const base: HistoryEntry[] = (r?.items ?? []).map((it) => ({
|
||||
const r = await fetchHistory(page, perPage)
|
||||
const base: HistoryEntry[] = (r?.items ?? []).map((it: ServerHistory) => ({
|
||||
id: String(it.id),
|
||||
viewedAt: Number(it.viewed_at) || 0,
|
||||
}))
|
||||
@ -163,7 +161,7 @@ export function removeHistory(id: string): void {
|
||||
const key = dedupeKey(id)
|
||||
setLocal(getLocal().filter((h) => dedupeKey(h.id) !== key))
|
||||
if (serverMode()) {
|
||||
authJson("DELETE", `/me/history/${encodeURIComponent(id)}`).catch(() => {
|
||||
deleteHistory(id).catch(() => {
|
||||
/* 失败不回滚本地 */
|
||||
})
|
||||
}
|
||||
@ -173,7 +171,7 @@ export function removeHistory(id: string): void {
|
||||
export function clearHistory(): void {
|
||||
setLocal([])
|
||||
if (serverMode()) {
|
||||
authJson("DELETE", "/me/history").catch(() => {
|
||||
clearAllHistory().catch(() => {
|
||||
/* 失败不回滚本地 */
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user