feat: add ftp root path setting
This commit is contained in:
@@ -68,7 +68,7 @@ const activeTab = ref<SettingsTab>('general')
|
||||
const sidebarItems: Array<{ id: SettingsTab; label: string }> = [
|
||||
{ id: 'general', label: '通用设置' },
|
||||
{ id: 's3', label: '对象存储' },
|
||||
{ id: 'ftp', label: 'FTP / SFTP' },
|
||||
{ id: 'ftp', label: '文件服务' },
|
||||
{ id: 'ssh', label: '远程主机' },
|
||||
{ id: 'llm', label: '智能识图' },
|
||||
{ id: 'ocr', label: '文字提取' },
|
||||
|
||||
@@ -69,6 +69,7 @@ interface FTPConfig {
|
||||
user: string
|
||||
authMethod: 'password' | 'key'
|
||||
password: string
|
||||
rootDirectory: string
|
||||
pathPrefix: string
|
||||
strictHostKey: boolean
|
||||
knownHostsPath: string
|
||||
@@ -169,6 +170,7 @@ function defaultConfig(): AppConfig {
|
||||
user: '',
|
||||
authMethod: 'password',
|
||||
password: '',
|
||||
rootDirectory: '/',
|
||||
pathPrefix: 'snapgo/',
|
||||
strictHostKey: false,
|
||||
knownHostsPath: '',
|
||||
@@ -271,8 +273,8 @@ const sshPathDisplay = computed({
|
||||
})
|
||||
|
||||
// FTP and SFTP both upload relative to the authenticated login directory.
|
||||
// The visible prefix communicates how that location will be copied: FTP uses
|
||||
// its virtual root, while SFTP uses the SSH user's home directory.
|
||||
// RootDirectory is display-only: it is prepended to the uploaded relative path
|
||||
// when that path is copied, without changing where the file is uploaded.
|
||||
const ftpPathDisplay = computed({
|
||||
get: () => config.value.ftp.pathPrefix,
|
||||
set: (raw: string) => {
|
||||
@@ -283,17 +285,26 @@ const ftpPathDisplay = computed({
|
||||
},
|
||||
})
|
||||
|
||||
const ftpPathRootLabel = computed(() =>
|
||||
config.value.ftp.protocol === 'sftp' ? '~/' : '/'
|
||||
)
|
||||
const ftpCopiedPathPreview = computed(() => {
|
||||
const root = config.value.ftp.rootDirectory.trim().replace(/\/+$/, '')
|
||||
const remote = config.value.ftp.pathPrefix
|
||||
.trim()
|
||||
.replace(/^\/+|\/+$/g, '')
|
||||
const remotePrefix = remote ? `${remote}/` : ''
|
||||
return `${root || (config.value.ftp.protocol === 'sftp' ? '~' : '')}/${remotePrefix}2026/07/20260713-110413-18lnbx.png`
|
||||
})
|
||||
|
||||
function changeFTPProtocol(event: Event) {
|
||||
const next = (event.target as HTMLSelectElement).value as FTPProtocol
|
||||
const previous = config.value.ftp.protocol
|
||||
const previousDefault = previous === 'sftp' ? 22 : 21
|
||||
const previousRootDefault = previous === 'sftp' ? '~/' : '/'
|
||||
if (config.value.ftp.port === previousDefault) {
|
||||
config.value.ftp.port = next === 'sftp' ? 22 : 21
|
||||
}
|
||||
if (config.value.ftp.rootDirectory === previousRootDefault) {
|
||||
config.value.ftp.rootDirectory = next === 'sftp' ? '~/' : '/'
|
||||
}
|
||||
config.value.ftp.protocol = next
|
||||
}
|
||||
|
||||
@@ -531,7 +542,7 @@ onMounted(load)
|
||||
|
||||
<!-- FTP/SFTP tab — file-transfer destination for its toolbar action. -->
|
||||
<section v-if="props.tab === 'ftp'" class="card">
|
||||
<h2>FTP / SFTP destination</h2>
|
||||
<h2>文件服务</h2>
|
||||
<div class="grid">
|
||||
<label class="field">
|
||||
<span>Protocol</span>
|
||||
@@ -581,15 +592,20 @@ onMounted(load)
|
||||
<input v-model="config.ftp.password" type="password" />
|
||||
</label>
|
||||
<label class="field full">
|
||||
<span>Remote directory (under login root)</span>
|
||||
<div class="prefixed-input">
|
||||
<span class="input-prefix">{{ ftpPathRootLabel }}</span>
|
||||
<input
|
||||
v-model="ftpPathDisplay"
|
||||
placeholder="snapgo/"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</div>
|
||||
<span>根目录(仅用于拼接复制路径)</span>
|
||||
<input
|
||||
v-model.trim="config.ftp.rootDirectory"
|
||||
:placeholder="config.ftp.protocol === 'sftp' ? '~/' : '/'"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</label>
|
||||
<label class="field full">
|
||||
<span>Remote directory(登录目录下的上传目录)</span>
|
||||
<input
|
||||
v-model="ftpPathDisplay"
|
||||
placeholder="snapgo/"
|
||||
spellcheck="false"
|
||||
/>
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Connect timeout (sec)</span>
|
||||
@@ -615,6 +631,10 @@ onMounted(load)
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<p class="hint">
|
||||
复制路径示例:<code>{{ ftpCopiedPathPreview }}</code>
|
||||
</p>
|
||||
|
||||
<p v-if="config.ftp.protocol === 'ftp'" class="hint warn">
|
||||
FTP sends the username, password, and screenshot without encryption.
|
||||
Prefer SFTP on networks you do not fully trust. SFTP is not FTPS.
|
||||
|
||||
@@ -186,6 +186,7 @@ export namespace domain {
|
||||
user: string;
|
||||
authMethod: string;
|
||||
password: string;
|
||||
rootDirectory: string;
|
||||
pathPrefix: string;
|
||||
strictHostKey: boolean;
|
||||
knownHostsPath: string;
|
||||
@@ -203,6 +204,7 @@ export namespace domain {
|
||||
this.user = source["user"];
|
||||
this.authMethod = source["authMethod"];
|
||||
this.password = source["password"];
|
||||
this.rootDirectory = source["rootDirectory"];
|
||||
this.pathPrefix = source["pathPrefix"];
|
||||
this.strictHostKey = source["strictHostKey"];
|
||||
this.knownHostsPath = source["knownHostsPath"];
|
||||
|
||||
Reference in New Issue
Block a user