Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 26 additions & 26 deletions src/components/ConnectionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm

{/* Basic Info */}
<div className={groupCls}>
<label className={labelCls}>连接名称</label>
<label className={labelCls}>{t('connection.form.name')}</label>
<Input
value={formData.name}
onChange={e => set({ name: e.target.value })}
placeholder={formData.host ? `${formData.username || 'root'}@${formData.host}` : '我的服务器'}
placeholder={formData.host ? `${formData.username || 'root'}@${formData.host}` : { t('connection.form.nameDesc') }}
/>
</div>

<div className="grid grid-cols-3 gap-3">
<div className={`col-span-2 ${groupCls}`}>
<label className={labelCls}>主机 IP / 域名</label>
<label className={labelCls}>{t('connection.form.hostIp')}</label>
<Input
value={formData.host}
onChange={e => set({ host: e.target.value })}
Expand All @@ -70,7 +70,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
/>
</div>
<div className={groupCls}>
<label className={labelCls}>端口</label>
<label className={labelCls}>{t('connection.form.port')}</label>
<Input
type="number"
value={formData.port}
Expand All @@ -80,7 +80,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
</div>

<div className={groupCls}>
<label className={labelCls}>用户名</label>
<label className={labelCls}>{t('connection.form.username')}</label>
<Input
value={formData.username}
onChange={e => set({ username: e.target.value })}
Expand All @@ -90,7 +90,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm

{/* Auth Type Toggle */}
<div>
<label className={labelCls}>认证方式</label>
<label className={labelCls}>{t('connection.form.authMethod')}</label>
<div className="flex gap-1 bg-secondary/50 rounded-lg p-1 text-xs">
<button
type="button"
Expand All @@ -99,7 +99,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
? 'bg-background shadow text-foreground font-medium'
: 'text-muted-foreground hover:text-foreground'}`}
>
<Lock className="w-3 h-3" /> 密码
<Lock className="w-3 h-3" /> {t('connection.form.password')}
</button>
<button
type="button"
Expand All @@ -108,15 +108,15 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
? 'bg-background shadow text-foreground font-medium'
: 'text-muted-foreground hover:text-foreground'}`}
>
<Key className="w-3 h-3" /> 私钥
<Key className="w-3 h-3" /> {t('connection.form.privKey')}
</button>
</div>
</div>

{/* Auth Fields */}
{formData.authType === 'password' ? (
<div className={groupCls}>
<label className={labelCls}>密码</label>
<label className={labelCls}>{t('connection.form.password')}</label>
<div className="flex gap-1.5">
<Input
type={showPassword ? 'text' : 'password'}
Expand All @@ -138,12 +138,12 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
) : (
<div className="space-y-3">
<div className={groupCls}>
<label className={labelCls}>私钥文件路径</label>
<label className={labelCls}>{t('connection.form.privKeyFilePath')}</label>
<div className="flex gap-1.5">
<Input
value={formData.privateKeyPath}
onChange={e => set({ privateKeyPath: e.target.value })}
placeholder="~/.ssh/id_rsa /path/to/key.pem"
placeholder="~/.ssh/id_rsa {t('connection.form.or')} /path/to/key.pem"
className="flex-1"
/>
<button
Expand All @@ -157,26 +157,26 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
</div>
</div>
<div className={groupCls}>
<label className={labelCls}>私钥密码短语(可选)</label>
<label className={labelCls}>{t('connection.form.passphrase')}</label>
<Input
type="password"
value={formData.passphrase}
onChange={e => set({ passphrase: e.target.value })}
placeholder="若密钥有密码则填写"
placeholder="{t('connection.form.passphraseDesc')}"
/>
</div>
</div>
)}

{/* Tags */}
<div className={groupCls}>
<label className={labelCls}>标签(逗号分隔)</label>
<label className={labelCls}>{t('connection.form.tags')}</label>
<Input
value={(formData.tags || []).join(', ')}
onChange={e => set({ tags: e.target.value.split(',').map(s => s.trim()).filter(Boolean) })}
placeholder="Prod, CN-Hangzhou, Web"
/>
<p className="text-[10px] text-muted-foreground/50 mt-0.5">用于在首页卡片上显示环境/地域标签</p>
<p className="text-[10px] text-muted-foreground/50 mt-0.5">{t('connection.form.tagsDesc')}</p>
</div>

{/* Jump Host (collapsible) */}
Expand All @@ -188,10 +188,10 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
>
<div className="flex items-center gap-2">
<GitMerge className="w-3.5 h-3.5" />
跳板机 / Bastion Host
{t('connection.form.bastion')}
{formData.jumpHost && (
<span className="px-1.5 py-0 rounded-full bg-primary/15 text-primary text-[10px]">
已配置
{t('connection.form.configured')}
</span>
)}
</div>
Expand All @@ -202,15 +202,15 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
<div className="p-3 bg-muted/20 space-y-3 border-t border-border">
<div className="grid grid-cols-3 gap-3">
<div className={`col-span-2 ${groupCls}`}>
<label className={labelCls}>跳板机 IP / 域名</label>
<label className={labelCls}>{t('connection.form.jumpIp')}</label>
<Input
value={formData.jumpHost}
onChange={e => set({ jumpHost: e.target.value })}
placeholder="bastion.example.com"
/>
</div>
<div className={groupCls}>
<label className={labelCls}>端口</label>
<label className={labelCls}>{t('connection.form.port')}</label>
<Input
type="number"
value={formData.jumpPort}
Expand All @@ -219,24 +219,24 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
</div>
</div>
<div className={groupCls}>
<label className={labelCls}>跳板机用户名</label>
<label className={labelCls}>{t('connection.form.jumpUsername')}</label>
<Input
value={formData.jumpUsername}
onChange={e => set({ jumpUsername: e.target.value })}
placeholder="ec2-user"
/>
</div>
<div className={groupCls}>
<label className={labelCls}>跳板机密码</label>
<label className={labelCls}>{t('connection.form.jumpPassword')}</label>
<Input
type="password"
value={formData.jumpPassword}
onChange={e => set({ jumpPassword: e.target.value })}
placeholder="或使用私钥路径"
placeholder="{t('connection.form.JumpPrivKeyDesc')}"
/>
</div>
<div className={groupCls}>
<label className={labelCls}>跳板机私钥路径(可选)</label>
<label className={labelCls}>{t('connection.form.jumpPrivKeyPaht')}</label>
<div className="flex gap-1.5">
<Input
value={formData.jumpPrivateKeyPath}
Expand All @@ -248,7 +248,7 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm
type="button"
onClick={() => pickFile('jumpPrivateKeyPath')}
className="px-2 py-1 rounded-md bg-secondary hover:bg-secondary/80 text-muted-foreground hover:text-foreground transition-colors border border-border"
title="浏览文件"
title="{t('connection.form.browse')}"
>
<FolderOpen className="w-4 h-4" />
</button>
Expand All @@ -260,8 +260,8 @@ export function ConnectionForm({ initialData, onSave, onCancel }: ConnectionForm

{/* Actions */}
<div className="flex justify-end gap-2 pt-2">
<Button type="button" variant="ghost" onClick={onCancel}>取消</Button>
<Button type="submit">保存</Button>
<Button type="button" variant="ghost" onClick={onCancel}>{t('connection.form.cancel')}</Button>
<Button type="submit">{t('connection.form.confirm')}</Button>
</div>
</form>
);
Expand Down
6 changes: 3 additions & 3 deletions src/pages/ConnectionManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,17 @@ export function ConnectionManager({ onConnect, onNavigate, activeSessions = 0 }:
<div className="w-16 h-16 rounded-2xl bg-muted/50 border border-border/40 flex items-center justify-center mb-5 overflow-hidden">
<img src={logoUrl} alt="Reflex" className="h-10 w-10 rounded-xl object-cover" />
</div>
<h3 className="text-sm font-semibold mb-1.5">没有已保存的连接</h3>
<h3 className="text-sm font-semibold mb-1.5">{t('connection.noConnections')}</h3>
<p className="text-xs text-muted-foreground/60 max-w-sm mb-5 leading-relaxed">
添加你的第一个 SSH 服务器,开始远程管理。
{t('connection.addFirstConnection')}
</p>
<Button
onClick={() => { setEditingConnection({}); setIsModalOpen(true); }}
size="sm"
className="gap-1.5 text-xs h-8 px-5 rounded-md"
>
<Plus className="w-3.5 h-3.5" />
添加服务器
{t('connection.add')}
</Button>
</div>
) : filtered.length === 0 ? (
Expand Down
1 change: 1 addition & 0 deletions src/pages/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ export function Settings({ onBack }: SettingsProps) {

const languageOptions = [
{ label: 'English', value: 'en' },
{ label: 'Italiano', value: 'it' },
{ label: '中文', value: 'zh' },
{ label: '日本語', value: 'ja' },
{ label: '한국어', value: 'ko' },
Expand Down
Loading