优化 SFTP 配置流程和界面

前端优化:
- 重新设计 SFTP 配置引导弹窗,采用渐变色头部
- 新增独立的 SFTP 配置弹窗,支持导入 .inf 配置文件
- 移除 forceSftpConfigVisible 标志,改用弹窗方式
- 简化存储切换逻辑,提升用户体验
- 优化配置表单布局和提示文字

交互改进:
- 支持拖拽导入配置文件
- 优化配置流程,更加直观
- 改进错误提示和操作引导

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-24 19:30:00 +08:00
parent db520f931e
commit 19a6c70d42
2 changed files with 123 additions and 108 deletions

View File

@@ -1104,17 +1104,85 @@
<!-- SFTP 配置引导弹窗 -->
<div v-if="showSftpGuideModal" class="modal-overlay" @mousedown.self="handleModalMouseDown" @mouseup.self="handleModalMouseUp('showSftpGuideModal')">
<div class="modal-content" @click.stop>
<h3 style="margin-bottom: 10px;">切换到 SFTP 存储</h3>
<p style="color: #555; line-height: 1.6; margin-bottom: 16px;">
需要先填写 SFTP 连接信息才能使用 SFTP 存储。是否前往配置?
</p>
<div style="display: flex; gap: 10px; justify-content: flex-end;">
<button class="btn btn-secondary" @click="closeSftpGuideModal">稍后再说</button>
<button class="btn btn-primary" @click="proceedSftpGuide">
<i class="fas fa-tools"></i> 去配置 SFTP
<div class="modal-content" @click.stop style="max-width: 520px; border-radius: 16px; overflow: hidden;">
<div style="background: linear-gradient(135deg,#667eea,#764ba2); color: white; padding: 18px;">
<div style="display: flex; align-items: center; gap: 10px;">
<i class="fas fa-server" style="font-size: 20px;"></i>
<h3 style="margin: 0; font-size: 20px;">切换到 SFTP 存储</h3>
</div>
<p style="margin: 8px 0 0 0; opacity: 0.9; font-size: 14px;">先配置连接信息,再切换到你的专属 SFTP 空间。</p>
</div>
<div style="padding: 18px;">
<p style="color: #4b5563; line-height: 1.6; margin-bottom: 16px;">
我们会在你填写完成后再切换,确保过程平滑无干扰。
</p>
<div style="display: flex; gap: 10px; justify-content: flex-end;">
<button class="btn btn-secondary" @click="closeSftpGuideModal">稍后再说</button>
<button class="btn btn-primary" @click="proceedSftpGuide">
<i class="fas fa-tools"></i> 去配置 SFTP
</button>
</div>
</div>
</div>
</div>
<!-- SFTP 配置弹窗 -->
<div v-if="showSftpConfigModal" class="modal-overlay" @mousedown.self="handleModalMouseDown" @mouseup.self="handleModalMouseUp('showSftpConfigModal')">
<div class="modal-content" @click.stop style="max-width: 720px; border-radius: 16px;">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
<div>
<h3 style="margin: 0 0 6px 0;">配置 SFTP 存储</h3>
<p style="margin: 0; color: #64748b; font-size: 13px;">填写连接信息或导入 .inf 配置,保存后即可切换到 SFTP 模式。</p>
</div>
<button class="btn btn-secondary" style="padding: 6px 10px;" @click="closeSftpConfigModal">
<i class="fas fa-times"></i>
</button>
</div>
<div style="display: grid; grid-template-columns: 1fr; gap: 14px;">
<div style="border: 1px dashed #cbd5e1; border-radius: 12px; padding: 16px; background: #f8fafc; text-align: center; cursor: pointer; transition: all .3s;"
@click="$refs.configFileInput.click()"
@dragover.prevent="$event.currentTarget.style.background='#eef2ff'"
@dragleave.prevent="$event.currentTarget.style.background='#f8fafc'"
@drop.prevent="handleConfigFileDrop">
<i class="fas fa-cloud-upload-alt" style="font-size: 36px; color: #667eea; margin-bottom: 8px;"></i>
<div style="font-weight: 600; color: #1f2937;">导入配置文件</div>
<div style="color: #6b7280; font-size: 13px; margin-top: 4px;">点击选择或拖拽 .inf 文件</div>
<input type="file" accept=".inf" @change="handleConfigFileUpload" ref="configFileInput" style="display: none;">
</div>
<form @submit.prevent="updateFtpConfig" style="display: grid; gap: 12px;">
<div class="form-group">
<label class="form-label">主机地址</label>
<input type="text" class="form-input" v-model="ftpConfigForm.ftp_host" required>
</div>
<div class="form-group">
<label class="form-label">端口</label>
<input type="number" class="form-input" v-model="ftpConfigForm.ftp_port" required>
</div>
<div class="form-group">
<label class="form-label">用户名</label>
<input type="text" class="form-input" v-model="ftpConfigForm.ftp_user" required>
</div>
<div class="form-group">
<label class="form-label">密码 (留空保留现有密码)</label>
<input type="password" class="form-input" v-model="ftpConfigForm.ftp_password" placeholder="留空保留现有密码">
</div>
<div class="form-group">
<label class="form-label">HTTP下载基础URL (可选)</label>
<input type="text" class="form-input" v-model="ftpConfigForm.http_download_base_url" placeholder="例如: http://example.com/files">
<small style="color: #666; font-size: 12px; margin-top: 5px; display: block;">
配置后可通过 HTTP 直接下载,例如: 基础URL/文件路径。
</small>
</div>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px;">
<button type="button" class="btn btn-secondary" @click="closeSftpConfigModal">取消</button>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> 保存配置
</button>
</div>
</form>
</div>
</div>
</div>
@@ -1235,6 +1303,11 @@
<i class="fas fa-random"></i>
{{ user?.has_ftp_config ? '切到 SFTP 存储' : '去配置 SFTP' }}
</button>
<div style="margin-top: 8px; text-align: center;">
<a style="color: #4b5fc9; font-size: 13px; text-decoration: none; cursor: pointer;" @click.prevent="openSftpConfigModal">
<i class="fas fa-tools"></i> 配置 / 修改 SFTP
</a>
</div>
</div>
</div>
@@ -1307,62 +1380,31 @@
</div>
</div>
<!-- SFTP配置 - 仅普通用户且权限允许SFTP -->
<div v-if="user && !user.is_admin && (storagePermission === 'sftp_only' || (storagePermission === 'user_choice' && (storageType === 'sftp' || forceSftpConfigVisible)))" id="sftp-config-section">
<h3 style="margin-bottom: 20px;">SFTP配置</h3>
<div v-if="user && !user.has_ftp_config" class="alert alert-info">
请配置SFTP服务器
</div>
<!-- 上传配置文件 -->
<div style="margin-bottom: 25px;">
<div style="border: 2px dashed #667eea; border-radius: 8px; padding: 20px; text-align: center; background: #f8f9ff; cursor: pointer; transition: all 0.3s;"
@click="$refs.configFileInput.click()"
@dragover.prevent="$event.currentTarget.style.background='#e8ecf7'"
@dragleave.prevent="$event.currentTarget.style.background='#f8f9ff'"
@drop.prevent="handleConfigFileDrop">
<i class="fas fa-cloud-upload-alt" style="font-size: 48px; color: #667eea; margin-bottom: 10px;"></i>
<p style="margin: 10px 0; font-size: 16px; color: #333; font-weight: 500;">
快速导入配置文件
</p>
<p style="margin: 5px 0; font-size: 14px; color: #666;">
点击选择或拖拽 .inf 文件到此处
</p>
<p style="margin: 5px 0; font-size: 12px; color: #999;">
导入后请检查配置信息并点击保存按钮
</p>
<input type="file" accept=".inf" @change="handleConfigFileUpload" ref="configFileInput" style="display: none;">
<!-- SFTP 概览 / 配置入口 -->
<div v-if="user && !user.is_admin && storagePermission === 'sftp_only'" style="margin-bottom: 40px;">
<h3 style="margin-bottom: 20px;">
<i class="fas fa-server"></i> SFTP存储
</h3>
<div style="background: #f8f9fa; padding: 20px; border-radius: 12px; border: 1px solid #e5e7eb;">
<div style="display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px;">
<div>
<div style="font-weight: 700; color: #0f172a; display: flex; gap: 8px; align-items: center;">
<i class="fas fa-shield-alt"></i>
仅 SFTP 模式
</div>
<div style="color: #475569; font-size: 13px; margin-top: 6px;">
{{ user.has_ftp_config ? '已配置服务器,可正常使用 SFTP 存储。' : '还未配置 SFTP请先填写连接信息。' }}
</div>
</div>
<button class="btn btn-primary" @click="openSftpConfigModal()" style="border-radius: 10px;">
<i class="fas fa-tools"></i> 配置 / 修改 SFTP
</button>
</div>
<div style="padding: 10px; background: #eef2ff; border-radius: 10px; color: #374151; font-size: 13px;">
<i class="fas fa-info-circle" style="color: #4b5fc9;"></i>
数据存储在你的 SFTP 服务器上,如需切换回本地请联系管理员调整权限。
</div>
</div>
<form @submit.prevent="updateFtpConfig">
<div class="form-group">
<label class="form-label">主机地址</label>
<input type="text" class="form-input" v-model="ftpConfigForm.ftp_host" required>
</div>
<div class="form-group">
<label class="form-label">端口</label>
<input type="number" class="form-input" v-model="ftpConfigForm.ftp_port" required>
</div>
<div class="form-group">
<label class="form-label">用户名</label>
<input type="text" class="form-input" v-model="ftpConfigForm.ftp_user" required>
</div>
<div class="form-group">
<label class="form-label">密码 (留空保留现有密码)</label>
<input type="password" class="form-input" v-model="ftpConfigForm.ftp_password" placeholder="留空保留现有密码">
</div>
<div class="form-group">
<label class="form-label">HTTP下载基础URL (可选)</label>
<input type="text" class="form-input" v-model="ftpConfigForm.http_download_base_url" placeholder="例如: http://example.com/files">
<small style="color: #666; font-size: 12px; margin-top: 5px; display: block;">
配置后可直接通过HTTP下载文件。URL格式: 基础URL/文件路径,例如: http://example.com/files/test.exe
</small>
</div>
<button type="submit" class="btn btn-primary">
<i class="fas fa-save"></i> 保存SFTP配置
</button>
</form>
</div>
<!-- 账号设置 -->

View File

@@ -209,15 +209,13 @@ createApp({
checkingUploadTool: false, // 是否正在检测上传工具
uploadingTool: false, // 是否正在上传工具
// 强制显示SFTP配置用于本地存储模式下临时显示SFTP配置
forceSftpConfigVisible: false,
// 存储切换状态
storageSwitching: false,
storageSwitchTarget: null,
// SFTP配置引导弹窗
showSftpGuideModal: false
showSftpGuideModal: false,
showSftpConfigModal: false
};
},
@@ -399,6 +397,7 @@ handleDragLeave(e) {
} else {
this.currentView = 'settings';
alert('欢迎请先配置您的SFTP服务器');
this.openSftpConfigModal();
}
} else {
// 默认行为:跳转到文件页面
@@ -530,8 +529,8 @@ handleDragLeave(e) {
}
}
// 重置强制显示标志
this.forceSftpConfigVisible = false;
// 关闭配置弹窗
this.showSftpConfigModal = false;
// 刷新到文件页面
this.currentView = 'files';
@@ -1819,29 +1818,6 @@ handleDragLeave(e) {
// 用户切换存储方式
async switchStorage(type) {
// 检查是否尝试切换到SFTP但未配置
if (type === 'sftp' && !this.user.has_ftp_config) {
const goToSettings = confirm('您还未配置SFTP服务器。\n\n是否现在前往设置页面进行配置配置完成后将自动切换到SFTP存储。');
if (goToSettings) {
// 直接设置视图并加载配置避免switchView的重复检查
this.currentView = 'settings';
// 强制显示SFTP配置区域
this.forceSftpConfigVisible = true;
// 如果是普通用户手动加载SFTP配置
if (this.user && !this.user.is_admin) {
this.loadFtpConfig();
}
// 等待DOM更新后滚动到SFTP配置区域
this.$nextTick(() => {
const sftpSection = document.getElementById('sftp-config-section');
if (sftpSection) {
sftpSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
}
return;
}
if (this.storageSwitching || type === this.storageType) {
return;
}
@@ -1881,17 +1857,7 @@ handleDragLeave(e) {
},
ensureSftpConfigSection() {
this.currentView = 'settings';
this.forceSftpConfigVisible = true;
if (this.user && !this.user.is_admin) {
this.loadFtpConfig();
}
this.$nextTick(() => {
const sftpSection = document.getElementById('sftp-config-section');
if (sftpSection) {
sftpSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
this.openSftpConfigModal();
},
openSftpGuideModal() {
@@ -1907,6 +1873,18 @@ handleDragLeave(e) {
this.ensureSftpConfigSection();
},
openSftpConfigModal() {
this.showSftpGuideModal = false;
this.showSftpConfigModal = true;
if (this.user && !this.user.is_admin) {
this.loadFtpConfig();
}
},
closeSftpConfigModal() {
this.showSftpConfigModal = false;
},
// 切换视图并自动刷新数据
switchView(view) {
// 如果已经在当前视图,不重复刷新
@@ -1916,11 +1894,6 @@ handleDragLeave(e) {
this.currentView = view;
// 离开settings页面时重置强制显示SFTP配置的标志
if (this.currentView !== 'settings') {
this.forceSftpConfigVisible = false;
}
// 根据视图类型自动加载对应数据
switch (view) {
case 'files':