diff --git a/src/features/authFiles/components/AuthFileCard.tsx b/src/features/authFiles/components/AuthFileCard.tsx
index 9e7b910..20aaae7 100644
--- a/src/features/authFiles/components/AuthFileCard.tsx
+++ b/src/features/authFiles/components/AuthFileCard.tsx
@@ -22,6 +22,7 @@ import {
getTypeColor,
getTypeLabel,
isRuntimeOnlyAuthFile,
+ parsePriorityValue,
resolveAuthFileStats,
type QuotaProviderType,
type ResolvedTheme,
@@ -110,6 +111,8 @@ export function AuthFileCard(props: AuthFileCardProps) {
const hasStatusWarning =
Boolean(rawStatusMessage) && !HEALTHY_STATUS_MESSAGES.has(rawStatusMessage.toLowerCase());
+ const priorityValue = parsePriorityValue(file.priority ?? file['priority']);
+
return (
{t('auth_files.file_modified')}: {formatModified(file)}
+ {priorityValue !== undefined && (
+
+ {t('auth_files.priority_display')}: {priorityValue}
+
+ )}
{rawStatusMessage && hasStatusWarning && (
diff --git a/src/i18n/locales/en.json b/src/i18n/locales/en.json
index c6cc4eb..af92324 100644
--- a/src/i18n/locales/en.json
+++ b/src/i18n/locales/en.json
@@ -495,6 +495,11 @@
"search_placeholder": "Filter by name, type, or provider",
"problem_filter_label": "Problem Filter",
"problem_filter_only": "Only show problematic credentials",
+ "sort_label": "Sort",
+ "sort_default": "Default",
+ "sort_az": "A-Z Name",
+ "sort_priority": "Priority",
+ "priority_display": "Priority",
"page_size_label": "Per page",
"page_size_unit": "items",
"view_mode_paged": "Paged",
diff --git a/src/i18n/locales/ru.json b/src/i18n/locales/ru.json
index bc7111e..c9a2564 100644
--- a/src/i18n/locales/ru.json
+++ b/src/i18n/locales/ru.json
@@ -495,6 +495,11 @@
"search_placeholder": "Фильтр по имени, типу или провайдеру",
"problem_filter_label": "Фильтр проблем",
"problem_filter_only": "Показывать только проблемные учётные данные",
+ "sort_label": "Сортировка",
+ "sort_default": "По умолчанию",
+ "sort_az": "A-Z Имя",
+ "sort_priority": "Приоритет",
+ "priority_display": "Приоритет",
"page_size_label": "На странице",
"page_size_unit": "элементов",
"view_mode_paged": "Постранично",
diff --git a/src/i18n/locales/zh-CN.json b/src/i18n/locales/zh-CN.json
index e01a95b..729134b 100644
--- a/src/i18n/locales/zh-CN.json
+++ b/src/i18n/locales/zh-CN.json
@@ -495,6 +495,11 @@
"search_placeholder": "输入名称、类型或提供方关键字",
"problem_filter_label": "问题筛选",
"problem_filter_only": "仅显示有问题凭证",
+ "sort_label": "排序",
+ "sort_default": "默认",
+ "sort_az": "A-Z 名称",
+ "sort_priority": "优先级",
+ "priority_display": "优先级",
"page_size_label": "单页数量",
"page_size_unit": "个/页",
"view_mode_paged": "按页显示",
diff --git a/src/pages/AuthFilesPage.module.scss b/src/pages/AuthFilesPage.module.scss
index b284893..b446c31 100644
--- a/src/pages/AuthFilesPage.module.scss
+++ b/src/pages/AuthFilesPage.module.scss
@@ -632,6 +632,38 @@
border-bottom: 1px solid var(--border-color);
}
+.priorityBadge {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ font-size: 12px;
+ color: var(--text-secondary);
+
+ .priorityValue {
+ font-weight: 600;
+ color: var(--text-primary);
+ font-variant-numeric: tabular-nums;
+ }
+}
+
+.sortSelect {
+ padding: 8px 12px;
+ border: 1px solid var(--border-color);
+ border-radius: $radius-md;
+ background-color: var(--bg-primary);
+ color: var(--text-primary);
+ font-size: 14px;
+ cursor: pointer;
+ height: 38px;
+ box-sizing: border-box;
+ min-width: 140px;
+
+ &:focus {
+ outline: none;
+ border-color: var(--primary-color);
+ }
+}
+
.healthStatusMessage {
font-size: 12px;
color: var(--warning-text);
diff --git a/src/pages/AuthFilesPage.tsx b/src/pages/AuthFilesPage.tsx
index cda317b..30ec0a2 100644
--- a/src/pages/AuthFilesPage.tsx
+++ b/src/pages/AuthFilesPage.tsx
@@ -31,6 +31,7 @@ import {
hasAuthFileStatusMessage,
isRuntimeOnlyAuthFile,
normalizeProviderKey,
+ parsePriorityValue,
type QuotaProviderType,
type ResolvedTheme,
} from '@/features/authFiles/constants';
@@ -74,6 +75,7 @@ export function AuthFilesPage() {
const [detailModalOpen, setDetailModalOpen] = useState(false);
const [selectedFile, setSelectedFile] = useState(null);
const [viewMode, setViewMode] = useState<'diagram' | 'list'>('list');
+ const [sortMode, setSortMode] = useState<'default' | 'az' | 'priority'>('default');
const [batchActionBarVisible, setBatchActionBarVisible] = useState(false);
const floatingBatchActionsRef = useRef(null);
const batchActionAnimationRef = useRef(null);
@@ -281,10 +283,25 @@ export function AuthFilesPage() {
});
}, [filesMatchingProblemFilter, filter, search]);
- const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
+ const sorted = useMemo(() => {
+ if (sortMode === 'default') return filtered;
+ const copy = [...filtered];
+ if (sortMode === 'az') {
+ copy.sort((a, b) => a.name.localeCompare(b.name));
+ } else if (sortMode === 'priority') {
+ copy.sort((a, b) => {
+ const pa = parsePriorityValue(a.priority ?? a['priority']) ?? 0;
+ const pb = parsePriorityValue(b.priority ?? b['priority']) ?? 0;
+ return pb - pa; // 高优先级排前面
+ });
+ }
+ return copy;
+ }, [filtered, sortMode]);
+
+ const totalPages = Math.max(1, Math.ceil(sorted.length / pageSize));
const currentPage = Math.min(page, totalPages);
const start = (currentPage - 1) * pageSize;
- const pageItems = filtered.slice(start, start + pageSize);
+ const pageItems = sorted.slice(start, start + pageSize);
const selectablePageItems = useMemo(
() => pageItems.filter((file) => !isRuntimeOnlyAuthFile(file)),
[pageItems]
@@ -559,6 +576,21 @@ export function AuthFilesPage() {
}}
/>
+
+
+
+
@@ -615,7 +647,7 @@ export function AuthFilesPage() {
)}
- {!loading && filtered.length > pageSize && (
+ {!loading && sorted.length > pageSize && (