fix(core): 测试清单 行4-15 — 记住我7天/工作台布局/商品创建选择弹窗/上传图持久化/清空筛选

- 记住我7天:勾选才持久化token+预填用户名,7天过期强制重登(localStorage vs sessionStorage)
- 工作台:最近项目进度/状态列对齐、快捷&提示卡片圆角边框、余额按钮金额左对齐
- 商品创建成功改为复用弹窗,选择 继续创建/去新建项目;主图随创建上传持久化
- 商品卡显示真实主图、点视频进详情视频项目tab
- 商品库/视频项目补 清空筛选 按钮

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-16 14:13:52 +08:00
co-authored by Claude Opus 4.8
parent b2288a2652
commit 57018fb101
10 changed files with 290 additions and 72 deletions
+38 -4
View File
@@ -23,6 +23,28 @@ import type {
const API_BASE = import.meta.env.VITE_API_BASE_URL || "";
const TOKEN_KEY = "airshelf_token";
const REMEMBER_KEY = "airshelf_remember"; // { username, expireAt } · 勾选「记住我 7 天」时写
const REMEMBER_DAYS = 7;
export type RememberInfo = { username: string; expireAt: number };
export function getRemember(): RememberInfo | null {
try {
const raw = localStorage.getItem(REMEMBER_KEY);
return raw ? (JSON.parse(raw) as RememberInfo) : null;
} catch {
return null;
}
}
// 登录成功后调用:勾选记住我则存用户名 + 7 天过期点;否则清除
export function setRemember(username: string | null, remember: boolean) {
if (remember && username) {
localStorage.setItem(REMEMBER_KEY, JSON.stringify({ username, expireAt: Date.now() + REMEMBER_DAYS * 86400000 }));
} else {
localStorage.removeItem(REMEMBER_KEY);
}
}
export class ApiError extends Error {
status: number;
@@ -35,12 +57,24 @@ export class ApiError extends Error {
}
export function getToken() {
return localStorage.getItem(TOKEN_KEY);
// 「记住我 7 天」过期则强制重新登录
const remembered = getRemember();
if (remembered && remembered.expireAt && Date.now() > remembered.expireAt) {
localStorage.removeItem(TOKEN_KEY);
sessionStorage.removeItem(TOKEN_KEY);
localStorage.removeItem(REMEMBER_KEY);
return null;
}
// 记住我 → localStorage(跨会话);不记住 → sessionStorage(关浏览器即失效)
return localStorage.getItem(TOKEN_KEY) || sessionStorage.getItem(TOKEN_KEY);
}
export function setToken(token: string | null) {
if (token) localStorage.setItem(TOKEN_KEY, token);
else localStorage.removeItem(TOKEN_KEY);
export function setToken(token: string | null, remember = true) {
localStorage.removeItem(TOKEN_KEY);
sessionStorage.removeItem(TOKEN_KEY);
if (!token) return;
if (remember) localStorage.setItem(TOKEN_KEY, token);
else sessionStorage.setItem(TOKEN_KEY, token);
}
async function request<T>(path: string, options: RequestInit = {}): Promise<T> {