feat(frontend): 支持批量编辑和管理已保存登录凭证

为连接表单补充已保存登录凭证的校验与提交流程,
允许新增、批量新增、测试连接时优先使用凭证

在连接列表中新增登录凭证管理入口,并支持批量编辑
时按连接类型筛选和应用已保存凭证

补充中英日文案,并修复 SSH 密钥选择器的绑定兼容性
This commit is contained in:
yinjianm
2026-03-26 00:23:02 +08:00
parent 1081c73254
commit a2ac4047d9
8 changed files with 158 additions and 20 deletions
@@ -2,6 +2,7 @@
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import AddConnectionForm from '../components/AddConnectionForm.vue';
import BatchEditConnectionForm from '../components/BatchEditConnectionForm.vue';
import LoginCredentialManagementModal from '../components/LoginCredentialManagementModal.vue';
import { useConnectionsStore } from '../stores/connections.store';
import { useSessionStore } from '../stores/session.store';
import { useTagsStore } from '../stores/tags.store';
@@ -89,6 +90,7 @@ const tagsSectionExpanded = ref(true);
const showAddEditConnectionForm = ref(false);
const connectionToEdit = ref<ConnectionInfo | null>(null);
const showLoginCredentialManagement = ref(false);
const isBatchEditMode = ref(false);
const selectedConnectionIdsForBatch = ref<Set<number>>(new Set());
@@ -1287,6 +1289,14 @@ onBeforeUnmount(() => {
<i class="fas fa-plus"></i>
<span>{{ t('connections.addConnection', '新增连接') }}</span>
</button>
<button
@click="showLoginCredentialManagement = true"
class="h-11 px-4 rounded-xl border border-border bg-background text-foreground hover:bg-border transition-colors inline-flex items-center gap-2"
:title="t('connections.form.loginCredentialManager', '登录凭证')"
>
<i class="fas fa-key"></i>
<span>{{ t('connections.form.loginCredentialManager', '登录凭证') }}</span>
</button>
<button
@click="handleTestAllFilteredConnections"
:disabled="isTestingAll || isLoadingConnections || !filteredAndSortedConnections.some(c => c.type === 'SSH')"
@@ -1620,6 +1630,11 @@ onBeforeUnmount(() => {
@update:visible="handleBatchEditFormClose"
@saved="handleBatchEditSaved"
/>
<LoginCredentialManagementModal
v-if="showLoginCredentialManagement"
@close="showLoginCredentialManagement = false"
/>
</div>
</div>
</template>