feat: 增加友链申请、独立页面、投票/悬赏/抽奖帖与侧栏签到,并统一开发数据目录

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-27 06:23:54 +08:00
parent df19752a1e
commit 2208af7070
80 changed files with 9620 additions and 641 deletions

View File

@@ -0,0 +1,53 @@
import { useCallback, useEffect, useState } from 'react';
import { notify } from '@/lib/notify';
import { api } from '../api/client';
import type { CheckInStatus } from '../api/types';
import { useAuth } from './useAuth';
/** 每日签到状态与操作(侧栏、积分页等复用) */
export function useCheckIn(enabled = true) {
const { user, refresh } = useAuth();
const [status, setStatus] = useState<CheckInStatus | null>(null);
const [loading, setLoading] = useState(false);
const [busy, setBusy] = useState(false);
const load = useCallback(() => {
if (!user || !enabled) {
setStatus(null);
setLoading(false);
return;
}
setLoading(true);
api.checkInStatus()
.then(d => setStatus(d.check_in))
.catch(e => notify.error(e instanceof Error ? e.message : '加载签到状态失败'))
.finally(() => setLoading(false));
}, [user, enabled]);
useEffect(() => {
load();
}, [load]);
const doCheckIn = useCallback(async () => {
if (!user) return;
setBusy(true);
try {
const r = await api.checkIn();
notify.success(`签到成功,+${r.check_in.today_points} 积分`);
setStatus(r.check_in);
await refresh();
} catch (e: unknown) {
notify.error(e instanceof Error ? e.message : '签到失败');
} finally {
setBusy(false);
}
}, [user, refresh]);
return {
status,
loading,
busy,
doCheckIn,
reload: load,
};
}