🔥 移除旧密码重置审核系统 & 优化存储管理UI

后端改进:
- 移除需要管理员审核的密码重置请求功能
- 简化密码重置流程,直接使用邮件重置
- 删除 password_reset_requests 表及相关代码

前端优化:
- 重新设计存储管理界面,采用现代化渐变风格
- 改进存储方式切换交互,添加动画效果
- 优化视觉层次和信息展示

🤖 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:12:57 +08:00
parent 104d7fe0ef
commit 02f0f3aa24
4 changed files with 138 additions and 297 deletions

View File

@@ -1111,45 +1111,120 @@
<i class="fas fa-database"></i> 存储管理
</h3>
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px;">
<div style="margin-bottom: 15px;">
<span style="font-weight: 600; color: #333;">当前存储方式: </span>
<span style="color: #667eea; font-weight: 600;">{{ storageTypeText }}</span>
<div style="background: linear-gradient(135deg, #f3f5ff 0%, #eef7ff 100%); padding: 22px; border-radius: 14px; box-shadow: 0 10px 30px rgba(102,126,234,0.12); border: 1px solid #e3e9ff;">
<div style="display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;">
<div style="display: flex; align-items: center; gap: 10px;">
<span style="font-weight: 700; color: #334155;">当前模式</span>
<span :style="{
padding: '6px 12px',
borderRadius: '999px',
background: storageType === 'local' ? 'rgba(40,167,69,0.12)' : 'rgba(102,126,234,0.12)',
color: storageType === 'local' ? '#1c7c3d' : '#4b5fc9',
fontWeight: 700,
display: 'inline-flex',
alignItems: 'center',
gap: '6px'
}">
<i :class="storageType === 'local' ? 'fas fa-hard-drive' : 'fas fa-server'"></i>
{{ storageTypeText }}
</span>
</div>
<div v-if="storageSwitching" style="color: #4b5fc9; font-weight: 600; display: inline-flex; align-items: center; gap: 8px;">
<i class="fas fa-sync-alt fa-spin"></i>
正在切换到 {{ storageSwitchTarget === 'sftp' ? 'SFTP 存储' : '本地存储' }}...
</div>
<div v-else style="color: #666; font-size: 13px;">本地存储适合快速读写SFTP 适合独立服务器空间</div>
</div>
<div v-if="storageType === 'local'" style="margin-bottom: 15px;">
<span style="font-weight: 600; color: #333;">配额使用: </span>
<span>{{ localUsedFormatted }} / {{ localQuotaFormatted }} ({{ quotaPercentage }}%)</span>
<div style="margin-top: 8px; width: 100%; height: 18px; background: #e0e0e0; border-radius: 9px; overflow: hidden;">
<div :style="{
width: quotaPercentage + '%',
height: '100%',
background: quotaPercentage > 90 ? '#dc3545' : quotaPercentage > 75 ? '#ffc107' : '#28a745',
transition: 'width 0.3s'
}"></div>
<div style="margin-top: 16px; background: white; border-radius: 12px; padding: 12px; border: 1px solid #e2e8f0;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; align-items: center;">
<button
class="btn"
:class="storageType === 'local' ? 'btn-primary' : 'btn-secondary'"
style="width: 100%; border-radius: 10px; padding: 12px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; transition: all .3s;"
:disabled="storageType === 'local' || storageSwitching"
@click="switchStorage('local')">
<i class="fas fa-hard-drive"></i>
切换到本地
</button>
<div style="height: 4px; background: #e2e8f0; border-radius: 999px; position: relative; overflow: hidden;">
<div :style="{
position: 'absolute',
left: storageType === 'local' ? '6%' : '52%',
width: '42%',
height: '100%',
background: 'linear-gradient(90deg,#667eea,#764ba2)',
borderRadius: '999px',
transition: 'left .35s ease'
}"></div>
</div>
<button
class="btn"
:class="storageType === 'sftp' ? 'btn-primary' : 'btn-secondary'"
style="width: 100%; border-radius: 10px; padding: 12px; display: inline-flex; align-items: center; justify-content: center; gap: 8px; transition: all .3s;"
:disabled="storageType === 'sftp' || storageSwitching"
@click="switchStorage('sftp')">
<i class="fas fa-server"></i>
切换到 SFTP
</button>
</div>
</div>
<div style="display: flex; gap: 15px; flex-wrap: wrap;">
<button
class="btn"
:class="storageType === 'local' ? 'btn-primary' : 'btn-secondary'"
@click="switchStorage('local')"
:disabled="storageType === 'local'">
<i class="fas fa-hard-drive"></i> 本地存储
</button>
<button
class="btn"
:class="storageType === 'sftp' ? 'btn-primary' : 'btn-secondary'"
@click="switchStorage('sftp')"
:disabled="storageType === 'sftp'">
<i class="fas fa-server"></i> SFTP存储
</button>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 14px; margin-top: 14px;">
<div style="background: white; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; box-shadow: 0 6px 20px rgba(0,0,0,0.04);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="font-weight: 700; color: #0f172a; display: flex; gap: 8px; align-items: center;">
<i class="fas fa-hard-drive"></i> 本地存储
</div>
<span v-if="storageType === 'local'" style="font-size: 12px; color: #28a745; background: rgba(40,167,69,0.12); padding: 4px 8px; border-radius: 999px;">当前</span>
</div>
<div style="color: #475569; font-size: 13px; margin-bottom: 10px;">更快的读写,适合日常上传下载。</div>
<div style="margin-bottom: 10px;">
<div style="font-size: 12px; color: #64748b; margin-bottom: 6px;">配额使用</div>
<div style="font-weight: 600; color: #0f172a;">{{ localUsedFormatted }} / {{ localQuotaFormatted }}</div>
<div style="margin-top: 6px; width: 100%; height: 10px; background: #e2e8f0; border-radius: 5px; overflow: hidden;">
<div :style="{
width: quotaPercentage + '%',
height: '100%',
background: quotaPercentage > 90 ? '#dc3545' : quotaPercentage > 75 ? '#ffc107' : '#28a745',
transition: 'width 0.35s ease'
}"></div>
</div>
</div>
<button class="btn btn-primary" style="width: 100%; border-radius: 10px;" :disabled="storageType === 'local' || storageSwitching" @click="switchStorage('local')">
<i class="fas fa-bolt"></i> 用本地存储
</button>
</div>
<div style="background: white; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; box-shadow: 0 6px 20px rgba(0,0,0,0.04);">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
<div style="font-weight: 700; color: #0f172a; display: flex; gap: 8px; align-items: center;">
<i class="fas fa-server"></i> SFTP 存储
</div>
<span v-if="storageType === 'sftp'" style="font-size: 12px; color: #4b5fc9; background: rgba(102,126,234,0.15); padding: 4px 8px; border-radius: 999px;">当前</span>
</div>
<div style="color: #475569; font-size: 13px; margin-bottom: 10px;">使用你自己的服务器空间,独立存储更灵活。</div>
<div v-if="user?.has_ftp_config" style="font-size: 13px; color: #0f172a; margin-bottom: 10px;">
已配置: {{ user.ftp_host }}:{{ user.ftp_port }}
</div>
<div v-else style="font-size: 13px; color: #b45309; background: #fff7ed; border: 1px dashed #fcd34d; padding: 10px; border-radius: 8px; margin-bottom: 10px;">
<i class="fas fa-exclamation-circle"></i> 先填写 SFTP 连接信息再切换
</div>
<button
class="btn"
:class="user?.has_ftp_config ? 'btn-primary' : 'btn-secondary'"
style="width: 100%; border-radius: 10px;"
:disabled="storageType === 'sftp' || storageSwitching"
@click="switchStorage('sftp')">
<i class="fas fa-random"></i>
{{ user?.has_ftp_config ? '切到 SFTP 存储' : '去配置 SFTP' }}
</button>
</div>
</div>
<div style="margin-top: 15px; padding: 10px; background: #fff3cd; border-radius: 6px; font-size: 13px; color: #856404;">
<i class="fas fa-info-circle"></i>
<strong>提示:</strong> 本地存储速度快但配额限制SFTP存储需先配置服务器信息
<div style="margin-top: 12px; padding: 10px 12px; background: #f1f5f9; border-radius: 10px; font-size: 13px; color: #475569;">
<i class="fas fa-info-circle" style="color: #4b5fc9;"></i>
本地存储速度快但配额限制SFTP 需先配置连接,切换过程中可继续查看文件列表。
</div>
</div>
</div>
@@ -1641,39 +1716,6 @@
</div>
</div>
<!-- 密码重置审核区域 -->
<div class="card" style="margin-top: 30px;">
<h3 style="margin-bottom: 20px;">密码重置审核</h3>
<div v-if="passwordResetRequests.length === 0" class="alert alert-info">
暂无待审核的密码重置请求
</div>
<table v-else style="width: 100%; border-collapse: collapse; table-layout: fixed;">
<thead>
<tr style="border-bottom: 2px solid #ddd;">
<th style="padding: 10px; text-align: left;">用户名</th>
<th style="padding: 10px; text-align: left;">邮箱</th>
<th style="padding: 10px; text-align: left;">提交时间</th>
<th style="padding: 10px; text-align: center;">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="req in passwordResetRequests" :key="req.id" style="border-bottom: 1px solid #eee;">
<td style="padding: 10px;">{{ req.username }}</td>
<td style="padding: 10px;">{{ req.email }}</td>
<td style="padding: 10px;">{{ formatDate(req.created_at) }}</td>
<td style="padding: 10px; text-align: center;">
<button class="btn" style="background: #28a745; color: white; margin: 2px;" @click="reviewPasswordReset(req.id, true)">
<i class="fas fa-check"></i> 批准
</button>
<button class="btn" style="background: #dc3545; color: white; margin: 2px;" @click="reviewPasswordReset(req.id, false)">
<i class="fas fa-times"></i> 拒绝
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 上传工具管理区域 -->
<div class="card" style="margin-top: 30px;">
<h3 style="margin-bottom: 20px;">