refactor(quota,auth): change page size selector to number input with range 3-30

This commit is contained in:
Supra4E8C
2026-01-02 17:27:35 +08:00
parent 82bf1806ed
commit 3446280987
5 changed files with 49 additions and 33 deletions

1
.gitignore vendored
View File

@@ -12,6 +12,7 @@ CLAUDE.md
AGENTS.md AGENTS.md
antigravity_usage.json antigravity_usage.json
codex_usage.json codex_usage.json
style.md
node_modules node_modules
dist dist

View File

@@ -19,6 +19,12 @@ type QuotaUpdater<T> = T | ((prev: T) => T);
type QuotaSetter<T> = (updater: QuotaUpdater<T>) => void; type QuotaSetter<T> = (updater: QuotaUpdater<T>) => void;
const MIN_CARD_PAGE_SIZE = 3;
const MAX_CARD_PAGE_SIZE = 30;
const clampCardPageSize = (value: number) =>
Math.min(MAX_CARD_PAGE_SIZE, Math.max(MIN_CARD_PAGE_SIZE, Math.round(value)));
interface QuotaPaginationState<T> { interface QuotaPaginationState<T> {
pageSize: number; pageSize: number;
totalPages: number; totalPages: number;
@@ -34,7 +40,7 @@ interface QuotaPaginationState<T> {
const useQuotaPagination = <T,>(items: T[], defaultPageSize = 6): QuotaPaginationState<T> => { const useQuotaPagination = <T,>(items: T[], defaultPageSize = 6): QuotaPaginationState<T> => {
const [page, setPage] = useState(1); const [page, setPage] = useState(1);
const [pageSize, setPageSizeState] = useState(defaultPageSize); const [pageSize, setPageSizeState] = useState(() => clampCardPageSize(defaultPageSize));
const [loading, setLoadingState] = useState(false); const [loading, setLoadingState] = useState(false);
const [loadingScope, setLoadingScope] = useState<'page' | 'all' | null>(null); const [loadingScope, setLoadingScope] = useState<'page' | 'all' | null>(null);
@@ -51,7 +57,7 @@ const useQuotaPagination = <T,>(items: T[], defaultPageSize = 6): QuotaPaginatio
}, [items, currentPage, pageSize]); }, [items, currentPage, pageSize]);
const setPageSize = useCallback((size: number) => { const setPageSize = useCallback((size: number) => {
setPageSizeState(size); setPageSizeState(clampCardPageSize(size));
setPage(1); setPage(1);
}, []); }, []);
@@ -183,17 +189,19 @@ export function QuotaSection<TState extends QuotaStatusState, TData>({
<div className={config.controlsClassName}> <div className={config.controlsClassName}>
<div className={config.controlClassName}> <div className={config.controlClassName}>
<label>{t('auth_files.page_size_label')}</label> <label>{t('auth_files.page_size_label')}</label>
<select <input
className={styles.pageSizeSelect} className={styles.pageSizeSelect}
type="number"
min={MIN_CARD_PAGE_SIZE}
max={MAX_CARD_PAGE_SIZE}
step={1}
value={pageSize} value={pageSize}
onChange={(e) => setPageSize(Number(e.target.value) || 6)} onChange={(e) => {
> const value = e.currentTarget.valueAsNumber;
<option value={6}>6</option> if (!Number.isFinite(value)) return;
<option value={9}>9</option> setPageSize(value);
<option value={12}>12</option> }}
<option value={18}>18</option> />
<option value={24}>24</option>
</select>
</div> </div>
<div className={config.controlClassName}> <div className={config.controlClassName}>
<label>{t('common.info')}</label> <label>{t('common.info')}</label>

View File

@@ -124,7 +124,7 @@
background-color: var(--bg-primary); background-color: var(--bg-primary);
color: var(--text-primary); color: var(--text-primary);
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: text;
height: 38px; height: 38px;
box-sizing: border-box; box-sizing: border-box;

View File

@@ -78,6 +78,11 @@ const OAUTH_PROVIDER_PRESETS = [
]; ];
const OAUTH_PROVIDER_EXCLUDES = new Set(['all', 'unknown', 'empty']); const OAUTH_PROVIDER_EXCLUDES = new Set(['all', 'unknown', 'empty']);
const MIN_CARD_PAGE_SIZE = 3;
const MAX_CARD_PAGE_SIZE = 30;
const clampCardPageSize = (value: number) =>
Math.min(MAX_CARD_PAGE_SIZE, Math.max(MIN_CARD_PAGE_SIZE, Math.round(value)));
interface ExcludedFormState { interface ExcludedFormState {
provider: string; provider: string;
@@ -185,6 +190,13 @@ export function AuthFilesPage() {
const disableControls = connectionStatus !== 'connected'; const disableControls = connectionStatus !== 'connected';
const handlePageSizeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const value = event.currentTarget.valueAsNumber;
if (!Number.isFinite(value)) return;
setPageSize(clampCardPageSize(value));
setPage(1);
};
// 格式化修改时间 // 格式化修改时间
const formatModified = (item: AuthFileItem): string => { const formatModified = (item: AuthFileItem): string => {
const raw = item['modtime'] ?? item.modified; const raw = item['modtime'] ?? item.modified;
@@ -855,20 +867,15 @@ export function AuthFilesPage() {
</div> </div>
<div className={styles.filterItem}> <div className={styles.filterItem}>
<label>{t('auth_files.page_size_label')}</label> <label>{t('auth_files.page_size_label')}</label>
<select <input
className={styles.pageSizeSelect} className={styles.pageSizeSelect}
type="number"
min={MIN_CARD_PAGE_SIZE}
max={MAX_CARD_PAGE_SIZE}
step={1}
value={pageSize} value={pageSize}
onChange={(e) => { onChange={handlePageSizeChange}
setPageSize(Number(e.target.value) || 9); />
setPage(1);
}}
>
<option value={6}>6</option>
<option value={9}>9</option>
<option value={12}>12</option>
<option value={18}>18</option>
<option value={24}>24</option>
</select>
</div> </div>
<div className={styles.filterItem}> <div className={styles.filterItem}>
<label>{t('common.info')}</label> <label>{t('common.info')}</label>

View File

@@ -48,7 +48,7 @@
background-color: var(--bg-primary); background-color: var(--bg-primary);
color: var(--text-primary); color: var(--text-primary);
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: text;
height: 38px; height: 38px;
box-sizing: border-box; box-sizing: border-box;