feat: 增加友链申请、独立页面、投票/悬赏/抽奖帖与侧栏签到,并统一开发数据目录
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,30 +1,59 @@
|
||||
/** 新建帖本地草稿(localStorage) */
|
||||
|
||||
const STORAGE_KEY = 'j13-compose-draft-v1';
|
||||
const STORAGE_KEY = 'j13-compose-draft-v2';
|
||||
|
||||
export type ComposeDraftPostType = 'normal' | 'question' | 'poll' | 'bounty' | 'lottery';
|
||||
|
||||
export type ComposeDraft = {
|
||||
title: string;
|
||||
tags: string;
|
||||
content: string;
|
||||
boardId: string;
|
||||
postType: 'normal' | 'question';
|
||||
postType: ComposeDraftPostType;
|
||||
pollOptions?: string[];
|
||||
pollMulti?: boolean;
|
||||
pollMaxChoices?: number;
|
||||
pollEndsAt?: string;
|
||||
pollNoEndTime?: boolean;
|
||||
savedAt: number;
|
||||
};
|
||||
|
||||
const VALID_POST_TYPES: ComposeDraftPostType[] = ['normal', 'question', 'poll', 'bounty', 'lottery'];
|
||||
|
||||
function normalizePostType(value: unknown): ComposeDraftPostType {
|
||||
if (typeof value === 'string' && VALID_POST_TYPES.includes(value as ComposeDraftPostType)) {
|
||||
return value as ComposeDraftPostType;
|
||||
}
|
||||
return 'normal';
|
||||
}
|
||||
|
||||
export function loadComposeDraft(): ComposeDraft | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY);
|
||||
if (!raw) return null;
|
||||
const data = JSON.parse(raw) as Partial<ComposeDraft>;
|
||||
if (!data || typeof data !== 'object') return null;
|
||||
return {
|
||||
const postType = normalizePostType(data.postType);
|
||||
const draft: ComposeDraft = {
|
||||
title: typeof data.title === 'string' ? data.title : '',
|
||||
tags: typeof data.tags === 'string' ? data.tags : '',
|
||||
content: typeof data.content === 'string' ? data.content : '',
|
||||
boardId: typeof data.boardId === 'string' ? data.boardId : '',
|
||||
postType: data.postType === 'question' ? 'question' : 'normal',
|
||||
postType,
|
||||
savedAt: typeof data.savedAt === 'number' ? data.savedAt : Date.now(),
|
||||
};
|
||||
if (postType === 'poll') {
|
||||
if (Array.isArray(data.pollOptions) && data.pollOptions.every(o => typeof o === 'string')) {
|
||||
draft.pollOptions = data.pollOptions.length >= 2 ? data.pollOptions : ['', ''];
|
||||
}
|
||||
if (typeof data.pollMulti === 'boolean') draft.pollMulti = data.pollMulti;
|
||||
if (typeof data.pollMaxChoices === 'number' && data.pollMaxChoices > 0) {
|
||||
draft.pollMaxChoices = data.pollMaxChoices;
|
||||
}
|
||||
if (typeof data.pollEndsAt === 'string') draft.pollEndsAt = data.pollEndsAt;
|
||||
if (typeof data.pollNoEndTime === 'boolean') draft.pollNoEndTime = data.pollNoEndTime;
|
||||
}
|
||||
return draft;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
@@ -42,6 +71,8 @@ export function saveComposeDraft(draft: Omit<ComposeDraft, 'savedAt'>): void {
|
||||
export function clearComposeDraft(): void {
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEY);
|
||||
// 清理旧版草稿键
|
||||
localStorage.removeItem('j13-compose-draft-v1');
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
@@ -50,10 +81,14 @@ export function clearComposeDraft(): void {
|
||||
/** 草稿是否有实质内容 */
|
||||
export function composeDraftHasContent(d: ComposeDraft | null | undefined): boolean {
|
||||
if (!d) return false;
|
||||
const hasPollOptions = d.postType === 'poll'
|
||||
&& Array.isArray(d.pollOptions)
|
||||
&& d.pollOptions.some(o => o.trim());
|
||||
return !!(
|
||||
d.title.trim()
|
||||
|| d.tags.trim()
|
||||
|| d.content.trim()
|
||||
|| (d.content && d.content.replace(/<[^>]*>/g, '').trim())
|
||||
|| hasPollOptions
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user