fix(frontend): 优化代理管理页面工具栏布局

- 将筛选器和操作按钮合并到同一行显示
- 筛选器在左侧,操作按钮在右侧
- 添加响应式支持,窄屏时自动换行并简化按钮文字
This commit is contained in:
shaw
2026-02-07 11:09:34 +08:00
parent 5299f3dcf6
commit 9e80ed0fa8
4 changed files with 56 additions and 46 deletions

View File

@@ -1913,6 +1913,8 @@ export default {
editProxy: 'Edit Proxy', editProxy: 'Edit Proxy',
deleteProxy: 'Delete Proxy', deleteProxy: 'Delete Proxy',
dataImport: 'Import', dataImport: 'Import',
dataImportShort: 'Import',
dataExportShort: 'Export',
dataExportSelected: 'Export Selected', dataExportSelected: 'Export Selected',
dataImportTitle: 'Import Proxies', dataImportTitle: 'Import Proxies',
dataImportHint: 'Upload the exported proxy JSON file to import proxies in bulk.', dataImportHint: 'Upload the exported proxy JSON file to import proxies in bulk.',

View File

@@ -2022,6 +2022,8 @@ export default {
deleteConfirmMessage: "确定要删除代理 '{name}' 吗?", deleteConfirmMessage: "确定要删除代理 '{name}' 吗?",
testProxy: '测试代理', testProxy: '测试代理',
dataImport: '导入', dataImport: '导入',
dataImportShort: '导入',
dataExportShort: '导出',
dataExportSelected: '导出选中', dataExportSelected: '导出选中',
dataImportTitle: '导入代理', dataImportTitle: '导入代理',
dataImportHint: '上传代理导出的 JSON 文件以批量导入代理。', dataImportHint: '上传代理导出的 JSON 文件以批量导入代理。',

View File

@@ -114,6 +114,10 @@
@apply rounded-lg px-3 py-1.5 text-xs; @apply rounded-lg px-3 py-1.5 text-xs;
} }
.btn-md {
@apply rounded-xl px-4 py-2 text-sm;
}
.btn-lg { .btn-lg {
@apply rounded-2xl px-6 py-3 text-base; @apply rounded-2xl px-6 py-3 text-base;
} }

View File

@@ -2,50 +2,10 @@
<AppLayout> <AppLayout>
<TablePageLayout> <TablePageLayout>
<template #filters> <template #filters>
<div class="space-y-3"> <div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
<!-- Row 1: Actions --> <!-- Search + Filters -->
<div class="flex flex-wrap items-center gap-3"> <div class="flex flex-wrap items-center gap-2">
<button <div class="relative min-w-0 flex-1 lg:w-48 lg:flex-none">
@click="loadProxies"
:disabled="loading"
class="btn btn-secondary"
:title="t('common.refresh')"
>
<Icon name="refresh" size="md" :class="loading ? 'animate-spin' : ''" />
</button>
<button
@click="handleBatchTest"
:disabled="batchTesting || loading"
class="btn btn-secondary"
:title="t('admin.proxies.testConnection')"
>
<Icon name="play" size="md" class="mr-2" />
{{ t('admin.proxies.testConnection') }}
</button>
<button
@click="openBatchDelete"
:disabled="selectedCount === 0"
class="btn btn-danger"
:title="t('admin.proxies.batchDeleteAction')"
>
<Icon name="trash" size="md" class="mr-2" />
{{ t('admin.proxies.batchDeleteAction') }}
</button>
<button @click="showImportData = true" class="btn btn-secondary">
{{ t('admin.proxies.dataImport') }}
</button>
<button @click="showExportDataDialog = true" class="btn btn-secondary">
{{ selectedCount > 0 ? t('admin.proxies.dataExportSelected') : t('admin.proxies.dataExport') }}
</button>
<button @click="showCreateModal = true" class="btn btn-primary">
<Icon name="plus" size="md" class="mr-2" />
{{ t('admin.proxies.createProxy') }}
</button>
</div>
<!-- Row 2: Search + Filters -->
<div class="flex flex-wrap items-center gap-3">
<div class="relative w-full sm:w-64">
<Icon <Icon
name="search" name="search"
size="md" size="md"
@@ -60,7 +20,7 @@
/> />
</div> </div>
<div class="w-full sm:w-40"> <div class="w-28 lg:w-36">
<Select <Select
v-model="filters.protocol" v-model="filters.protocol"
:options="protocolOptions" :options="protocolOptions"
@@ -68,7 +28,7 @@
@change="loadProxies" @change="loadProxies"
/> />
</div> </div>
<div class="w-full sm:w-36"> <div class="w-24 lg:w-32">
<Select <Select
v-model="filters.status" v-model="filters.status"
:options="statusOptions" :options="statusOptions"
@@ -77,6 +37,48 @@
/> />
</div> </div>
</div> </div>
<!-- Actions -->
<div class="flex flex-wrap items-center gap-2">
<button
@click="loadProxies"
:disabled="loading"
class="btn btn-secondary btn-sm lg:btn-md"
:title="t('common.refresh')"
>
<Icon name="refresh" size="md" :class="loading ? 'animate-spin' : ''" />
</button>
<button
@click="handleBatchTest"
:disabled="batchTesting || loading"
class="btn btn-secondary btn-sm lg:btn-md"
:title="t('admin.proxies.testConnection')"
>
<Icon name="play" size="md" class="lg:mr-2" />
<span class="hidden lg:inline">{{ t('admin.proxies.testConnection') }}</span>
</button>
<button
@click="openBatchDelete"
:disabled="selectedCount === 0"
class="btn btn-danger btn-sm lg:btn-md"
:title="t('admin.proxies.batchDeleteAction')"
>
<Icon name="trash" size="md" class="lg:mr-2" />
<span class="hidden lg:inline">{{ t('admin.proxies.batchDeleteAction') }}</span>
</button>
<button @click="showImportData = true" class="btn btn-secondary btn-sm lg:btn-md">
<span class="lg:hidden">{{ t('admin.proxies.dataImportShort') }}</span>
<span class="hidden lg:inline">{{ t('admin.proxies.dataImport') }}</span>
</button>
<button @click="showExportDataDialog = true" class="btn btn-secondary btn-sm lg:btn-md">
<span class="lg:hidden">{{ t('admin.proxies.dataExportShort') }}</span>
<span class="hidden lg:inline">{{ selectedCount > 0 ? t('admin.proxies.dataExportSelected') : t('admin.proxies.dataExport') }}</span>
</button>
<button @click="showCreateModal = true" class="btn btn-primary btn-sm lg:btn-md">
<Icon name="plus" size="md" class="lg:mr-2" />
<span class="hidden lg:inline">{{ t('admin.proxies.createProxy') }}</span>
</button>
</div>
</div> </div>
</template> </template>