This commit is contained in:
Baobhan Sith
2025-05-16 13:51:10 +08:00
parent 78314b1f0b
commit 10d7921edb
5 changed files with 52 additions and 25 deletions
@@ -226,17 +226,15 @@ onMounted(() => {
<!-- Port Section -->
<div class="p-4 border border-border rounded-md bg-card">
<div class="flex justify-between items-center mb-2">
<h4 class="text-base font-semibold">{{ t('connections.form.sectionBasic.port', '端口') }}</h4>
<h4 class="text-base font-semibold">{{ t('connections.table.port', '端口') }}</h4>
<input type="checkbox" v-model="enablePortEdit" class="form-checkbox h-5 w-5 text-primary rounded border-gray-300 focus:ring-primary" />
</div>
<div v-if="enablePortEdit">
<label for="batch-port" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionBasic.portPlaceholder', '例如: 22') }}</label>
<input
type="text"
id="batch-port"
v-model="formData.port"
class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm"
:placeholder="t('connections.batchEdit.portPlaceholder', '输入新端口号')"
/>
</div>
</div>
@@ -244,21 +242,20 @@ onMounted(() => {
<!-- Auth Section -->
<div class="p-4 border border-border rounded-md bg-card">
<div class="flex justify-between items-center mb-2">
<h4 class="text-base font-semibold">{{ t('connections.form.sectionAuth.title', '认证信息') }}</h4>
<h4 class="text-base font-semibold">{{ t('connections.form.sectionAuth', '认证信息') }}</h4>
<input type="checkbox" v-model="enableAuthEdit" class="form-checkbox h-5 w-5 text-primary rounded border-gray-300 focus:ring-primary" />
</div>
<div v-if="enableAuthEdit" class="space-y-3">
<div>
<label for="batch-username" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionAuth.username', '用户名') }}</label>
<input type="text" id="batch-username" v-model="formData.username" class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm" :placeholder="t('connections.batchEdit.authPlaceholder', '留空表示不更改此字段')" />
<label for="batch-username" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.username', '用户名') }}</label>
<input type="text" id="batch-username" v-model="formData.username" class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm" />
</div>
<div>
<label for="batch-password" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionAuth.password', '密码') }}</label>
<input type="password" id="batch-password" v-model="formData.password" class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm" :placeholder="t('connections.batchEdit.passwordInfoBatch', '输入新密码,或留空不更改')" />
<p class="mt-1 text-xs text-text-alt">{{ t('connections.batchEdit.passwordWarning', '注意:某些连接类型可能不支持空密码或有特定密码策略。') }}</p>
<label for="batch-password" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.authMethodPassword', '密码') }}</label>
<input type="password" id="batch-password" v-model="formData.password" class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm" />
</div>
<div>
<label for="batch-ssh-key" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionAuth.sshKey', 'SSH 密钥') }}</label>
<label for="batch-ssh-key" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.authMethodKey', 'SSH 密钥') }}</label>
<select
id="batch-ssh-key"
v-model="formData.ssh_key_id"
@@ -266,13 +263,12 @@ onMounted(() => {
:disabled="sshKeysStore.isLoading"
>
<option :value="undefined">{{ t('connections.batchEdit.noChange', '-- 不更改 --') }}</option>
<option :value="null">{{ t('connections.form.sectionAuth.noSshKey', '无密钥') }}</option>
<option :value="null">{{ t('connections.form.noSshKey', '无密钥') }}</option>
<option v-if="sshKeysStore.isLoading" disabled>{{ t('common.loading', '加载中...') }}</option>
<option v-for="key in availableSshKeys" :key="key.id" :value="key.id">
{{ key.name }}
</option>
</select>
<p class="mt-1 text-xs text-text-alt">{{ t('connections.batchEdit.sshKeyInfo', '选择密钥将覆盖密码认证(如果连接类型支持)。') }}</p>
</div>
</div>
</div>
@@ -280,34 +276,32 @@ onMounted(() => {
<!-- Advanced Section (Now includes Notes) -->
<div class="p-4 border border-border rounded-md bg-card">
<div class="flex justify-between items-center mb-2">
<h4 class="text-base font-semibold">{{ t('connections.form.sectionAdvanced.title', '高级选项') }}</h4>
<h4 class="text-base font-semibold">{{ t('connections.form.sectionAdvanced', '高级选项') }}</h4>
<input type="checkbox" v-model="enableAdvancedEdit" class="form-checkbox h-5 w-5 text-primary rounded border-gray-300 focus:ring-primary" />
</div>
<div v-if="enableAdvancedEdit" class="space-y-3">
<div>
<label for="batch-proxy" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionAdvanced.proxy.label', '代理') }}</label>
<label for="batch-proxy" class="block text-sm font-medium text-text-secondary">{{ t('connections.form.proxy', '代理') }}</label>
<select id="batch-proxy" v-model="formData.proxy_id" class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-background text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm">
<option :value="undefined">{{ t('connections.batchEdit.noChange', '-- 不更改 --') }}</option>
<option :value="null">{{ t('connections.form.sectionAdvanced.proxy.none', '无代理') }}</option>
<option :value="null">{{ t('connections.form.noProxy', '无代理') }}</option>
<option v-for="proxy in availableProxies" :key="proxy.id" :value="proxy.id">
{{ proxy.name }} ({{ proxy.type }})
</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-text-secondary">{{ t('connections.form.sectionAdvanced.tags.label', '标签') }}</label>
<label class="block text-sm font-medium text-text-secondary">{{ t('connections.table.tags', '标签') }}</label>
<TagInput
:modelValue="formData.tag_ids || []"
@update:modelValue="val => formData.tag_ids = val"
:availableTags="availableTags"
@create-tag="handleCreateTag"
@delete-tag="handleDeleteTag"
:placeholder="t('connections.batchEdit.tagsPlaceholder', '选择或创建标签 (将替换现有标签)')"
:allow-create="true"
:allow-delete="true"
class="mt-1"
/>
<p class="mt-1 text-xs text-text-alt">{{ t('connections.batchEdit.tagsInfoReplace', '选择的标签将替换所有选中连接的现有标签。') }}</p>
</div>
<!-- Notes section moved here, no separate enable checkbox for notes itself -->
<div class="pt-2">
@@ -317,7 +311,6 @@ onMounted(() => {
v-model="formData.notes"
rows="3"
class="mt-1 block w-full px-3 py-2 border border-border rounded-md shadow-sm bg-input text-foreground focus:outline-none focus:ring-1 focus:ring-primary sm:text-sm"
:placeholder="t('connections.batchEdit.notesPlaceholder', '输入新备注,或留空不更改')"
></textarea>
</div>
</div>
@@ -340,7 +333,7 @@ onMounted(() => {
:disabled="isLoading || (!enablePortEdit && !enableAuthEdit && !enableAdvancedEdit)"
> <!-- Removed enableNotesEdit from disabled condition -->
<i v-if="isLoading" class="fas fa-spinner fa-spin mr-2"></i>
{{ t('common.saveChanges', '保存更改') }}
{{ t('common.save', '保存') }}
</button>
</div>
</div>
+12
View File
@@ -127,7 +127,18 @@
"lastConnected": "Last Connected",
"actions": "Actions"
},
"batchEdit":{
"toggleLabel":"Batch Edit",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"invertSelection": "Invert Selection",
"title": "Batch Edit Connections",
"editSelected": "Edit Selected",
"noChange":"No change",
"selectedItems":"{count} items selected"
},
"actions": {
"testAllFiltered":"Test All",
"connect": "Connect",
"edit": "Edit",
"delete": "Delete",
@@ -152,6 +163,7 @@
"confirm": "Confirm Add",
"adding": "Adding...",
"cancel": "Cancel",
"noSshKey":"No SSH Key",
"errorRequiredFields": "Please fill in all required fields.",
"errorPasswordRequired": "Password is required for password authentication.",
"errorPrivateKeyRequired": "Private key is required for key authentication.",
+12
View File
@@ -109,7 +109,18 @@
"copied": "クリップボードにコピーしました"
},
"connections": {
"batchEdit": {
"toggleLabel": "一括編集",
"selectAll": "すべて選択",
"deselectAll": "すべて選択解除",
"invertSelection": "選択を反転",
"title": "接続の一括編集",
"editSelected": "選択した項目を編集",
"noChange": "変更なし",
"selectedItems": "{count} 件選択済み"
},
"actions": {
"testAllFiltered":"すべてテスト",
"connect": "接続",
"delete": "削除",
"edit": "編集",
@@ -150,6 +161,7 @@
"password": "パスワード:",
"port": "ポート:",
"privateKey": "秘密鍵:",
"noSshKey":"SSHキーなし",
"proxy": "プロキシ:",
"saving": "保存中...",
"sectionAdvanced": "詳細設定",
+13
View File
@@ -126,7 +126,19 @@
"lastConnected": "上次连接",
"actions": "操作"
},
"batchEdit":{
"toggleLabel":"批量修改",
"selectAll": "全选",
"deselectAll": "取消全选",
"invertSelection": "反向选择",
"editSelected": "编辑所选",
"title": "批量编辑连接",
"selectedItems": "已选项目",
"noChange": "保持不变",
"tagsPlaceholder": "输入标签 (替换现有)"
},
"actions": {
"testAllFiltered":"测试全部",
"connect": "连接",
"edit": "编辑",
"delete": "删除",
@@ -181,6 +193,7 @@
"testConnection": "测试连接",
"testing": "测试中...",
"sshKey": "SSH 密钥",
"noSshKey":"无 SSH 密钥",
"privateKeyDirect": "私钥内容",
"keyUpdateNoteDirect": "编辑时将私钥和密码短语留空以保留现有密钥。",
"keyUpdateNoteSelected": "编辑时选择其他密钥或使用直接输入来更改密钥。",
@@ -485,7 +485,7 @@ const getTruncatedNotes = (notes: string | null | undefined): string => {
<i :class="['fas', isAscending ? 'fa-arrow-up-a-z' : 'fa-arrow-down-z-a', 'w-4 h-4']"></i>
</button>
</div>
<button @click="openAddConnectionForm" title="Add Connection" class="h-8 w-8 bg-button rounded-md shadow-sm hover:bg-button-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition duration-150 ease-in-out flex items-center justify-center flex-shrink-0 ml-2 sm:ml-0">
<button @click="openAddConnectionForm" :title="t('connections.addConnection', 'Add Connection')" class="h-8 w-8 bg-button rounded-md shadow-sm hover:bg-button-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition duration-150 ease-in-out flex items-center justify-center flex-shrink-0 ml-2 sm:ml-0">
<i class="fas fa-plus" style="color: white;"></i>
</button>
<!-- Test All Filtered Connections Button -->
@@ -498,7 +498,6 @@ const getTruncatedNotes = (notes: string | null | undefined): string => {
<i v-if="isTestingAll" class="fas fa-spinner fa-spin mr-1 sm:mr-2"></i>
<i v-else class="fas fa-check-double mr-1 sm:mr-2"></i>
<span class="hidden sm:inline">{{ t('connections.actions.testAllFiltered') }}</span>
<span class="sm:hidden">{{ t('connections.actions.testAllShort', '测试全部') }}</span>
</button>
</div>
</div>
@@ -560,7 +559,7 @@ const getTruncatedNotes = (notes: string | null | undefined): string => {
</span>
<!-- 备注信息移到这里 -->
<div v-if="conn.notes && conn.notes.trim() !== ''" class="text-xs text-text-secondary mt-1">
<span class="font-medium text-text-alt">{{ t('connections.notes.label', '备注:') }}</span>
<span class="font-medium text-text-alt">{{ t('connections.form.notes', '备注:') }}</span>
<span class="break-words leading-snug ml-1" :title="conn.notes">
{{ getTruncatedNotes(conn.notes) }}
</span>
@@ -619,7 +618,6 @@ const getTruncatedNotes = (notes: string | null | undefined): string => {
class="px-3 py-1.5 bg-transparent text-foreground border border-border rounded-md shadow-sm hover:bg-border focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition duration-150 ease-in-out text-sm font-medium h-9 flex items-center justify-center"
:disabled="isBatchEditMode"
:class="{ 'opacity-50 cursor-not-allowed': isBatchEditMode }"
:title="isBatchEditMode ? t('connections.batchEdit.disabledInBatchMode', '批量模式下禁用') : t('connections.actions.edit', '编辑')"
>
<i class="fas fa-pencil-alt mr-1"></i>{{ t('connections.actions.edit') }}
</button>
@@ -628,7 +626,6 @@ const getTruncatedNotes = (notes: string | null | undefined): string => {
class="px-4 py-2 bg-button text-button-text rounded-md shadow-sm hover:bg-button-hover focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition duration-150 ease-in-out text-sm font-medium h-9 flex items-center justify-center"
:disabled="isBatchEditMode"
:class="{ 'opacity-50 cursor-not-allowed': isBatchEditMode }"
:title="isBatchEditMode ? t('connections.batchEdit.disabledInBatchMode', '批量模式下禁用') : t('connections.actions.connect', '连接')"
>
{{ t('connections.actions.connect') }}
</button>