重新设计分享管理页面

- 添加搜索/筛选功能(关键字、类型、状态、排序)
- 重新设计卡片视图,展示更多信息(状态、类型、加密、存储来源等)
- 添加filteredShares计算属性实现筛选和排序
- 添加辅助方法:getShareTypeLabel、getShareStatus、getShareProtection等
- 优化分享卡片样式,支持深色/浅色主题

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-30 12:57:35 +08:00
parent 7d5a230007
commit 2b25f18137
2 changed files with 284 additions and 20 deletions

View File

@@ -1028,6 +1028,109 @@
::-webkit-scrollbar-thumb:hover {
background: rgba(255, 255, 255, 0.15);
}
/* 分享卡片布局 */
.share-card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 14px;
}
.share-card {
background: var(--bg-card);
border: 1px solid var(--glass-border);
border-radius: 12px;
padding: 14px;
box-shadow: 0 10px 30px rgba(0,0,0,0.12);
transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.share-card:hover {
transform: translateY(-2px);
border-color: var(--glass-border-hover);
box-shadow: 0 14px 36px rgba(0,0,0,0.18);
}
.share-card__title {
display: flex;
align-items: center;
gap: 10px;
font-weight: 600;
font-size: 15px;
color: var(--text-primary);
margin-bottom: 8px;
word-break: break-all;
}
.share-card__chips {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 10px;
}
.share-chip {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
border-radius: 999px;
font-size: 12px;
border: 1px solid var(--glass-border);
background: rgba(255,255,255,0.04);
color: var(--text-secondary);
}
.share-chip.success { color: #22c55e; background: rgba(34,197,94,0.12); border-color: rgba(34,197,94,0.25); }
.share-chip.warn { color: #f59e0b; background: rgba(245,158,11,0.14); border-color: rgba(245,158,11,0.25); }
.share-chip.danger { color: #ef4444; background: rgba(239,68,68,0.14); border-color: rgba(239,68,68,0.25); }
.share-chip.info { color: var(--accent-1); background: rgba(102,126,234,0.14); border-color: rgba(102,126,234,0.25); }
.share-card__meta {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
gap: 10px;
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 12px;
}
.share-card__meta span {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.share-card__actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.share-card__actions .btn {
padding: 8px 12px;
font-size: 13px;
}
.share-toolbar {
display: flex;
gap: 10px;
flex-wrap: wrap;
align-items: center;
}
.share-toolbar input,
.share-toolbar select {
background: rgba(255,255,255,0.05);
border: 1px solid var(--glass-border);
border-radius: 8px;
padding: 8px 12px;
color: var(--text-primary);
}
.share-toolbar input::placeholder {
color: var(--text-secondary);
}
.share-toolbar select {
min-width: 140px;
cursor: pointer;
}
body.light-theme .share-card {
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
}
body.light-theme .share-card:hover {
box-shadow: 0 14px 36px rgba(0,0,0,0.12);
}
</style>
</head>
<body>
@@ -1919,46 +2022,108 @@
</div>
</div>
<!-- 分享视图 -->
<!-- 分享视图 -->
<div v-if="isLoggedIn && currentView === 'shares'" class="main-container">
<div class="card">
<!-- 标题和工具栏 -->
<div style="margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center;">
<h3 style="margin: 0;">我的分享</h3>
<div style="display: flex; gap: 10px;">
<div style="margin-bottom: 16px; display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap;">
<h3 style="margin: 0; display: flex; align-items: center; gap: 8px;">
<i class="fas fa-share-alt"></i> 我的分享
</h3>
<div style="display: flex; gap: 8px;">
<button class="btn" :class="shareViewMode === 'grid' ? 'btn-primary' : 'btn-secondary'" @click="shareViewMode = 'grid'">
<i class="fas fa-th-large"></i> 大图标
<i class="fas fa-th-large"></i> 卡片
</button>
<button class="btn" :class="shareViewMode === 'list' ? 'btn-primary' : 'btn-secondary'" @click="shareViewMode = 'list'">
<i class="fas fa-list"></i> 列表
</button>
<button class="btn btn-secondary" @click="loadShares">
<i class="fas fa-sync-alt"></i> 刷新
</button>
</div>
</div>
<!-- 筛选/搜索 -->
<div class="share-toolbar" style="margin-bottom: 14px;">
<input type="text" v-model="shareFilters.keyword" placeholder="搜索路径 / 链接 / 分享码" style="flex: 1; min-width: 180px;">
<select v-model="shareFilters.type">
<option value="all">全部类型</option>
<option value="file">文件</option>
<option value="directory">文件夹</option>
<option value="all_files">全部文件</option>
</select>
<select v-model="shareFilters.status">
<option value="all">全部状态</option>
<option value="active">有效</option>
<option value="expiring">即将到期</option>
<option value="expired">已过期</option>
<option value="protected">已加密</option>
<option value="public">公开</option>
</select>
<select v-model="shareFilters.sort">
<option value="created_desc">最新创建</option>
<option value="created_asc">最早创建</option>
<option value="views_desc">访问最多</option>
<option value="downloads_desc">下载最多</option>
<option value="expire_asc">最早到期</option>
</select>
</div>
<!-- 空状态 -->
<div v-if="shares.length === 0" class="alert alert-info">
还没有创建任何分享
</div>
<div v-else-if="filteredShares.length === 0" class="alert alert-warning">
没有符合筛选条件的分享,试试清空搜索/筛选。
</div>
<!-- 大图标视图 -->
<div v-else-if="shareViewMode === 'grid'" class="file-grid">
<div v-for="share in shares" :key="share.id" class="file-grid-item">
<div class="file-icon">
<i class="fas fa-share-alt" style="font-size: 64px; color: #667eea;"></i>
<div v-else-if="shareViewMode === 'grid'" class="share-card-grid">
<div v-for="share in filteredShares" :key="share.id" class="share-card">
<div class="share-card__title">
<i class="fas" :class="{
'fa-file-alt': share.share_type === 'file',
'fa-folder': share.share_type === 'directory',
'fa-layer-group': share.share_type === 'all'
}" style="color: var(--accent-1);"></i>
<span :title="share.share_path">{{ share.share_path }}</span>
</div>
<div class="file-name" :title="share.share_path">{{ share.share_path }}</div>
<div class="file-size" style="font-size: 12px; color: var(--text-secondary);">
访问: {{ share.view_count }} | 下载: {{ share.download_count }}
<div class="share-card__chips">
<span :class="['share-chip', getShareStatus(share).class]">
<i class="fas" :class="getShareStatus(share).icon"></i> {{ getShareStatus(share).text }}
</span>
<span class="share-chip info">
<i class="fas fa-tag"></i> {{ getShareTypeLabel(share.share_type) }}
</span>
<span class="share-chip info">
<i class="fas" :class="getShareProtection(share).icon"></i> {{ getShareProtection(share).text }}
</span>
<span class="share-chip info" v-if="share.storage_type">
<i class="fas fa-hdd"></i> {{ getStorageLabel(share.storage_type) }}
</span>
<span class="share-chip info">
<i class="fas fa-barcode"></i> {{ share.share_code }}
</span>
</div>
<div class="file-actions">
<button class="btn-icon" @click.stop="window.open(share.share_url, '_blank')" title="打开分享">
<i class="fas fa-external-link-alt"></i>
<div style="font-size: 13px; color: var(--text-secondary); margin-bottom: 10px; word-break: break-all;">
<i class="fas fa-link"></i>
<a :href="share.share_url" target="_blank" style="color: var(--accent-1); word-break: break-all;">{{ share.share_url }}</a>
</div>
<div class="share-card__meta">
<span><i class="fas fa-eye"></i> 访问 {{ share.view_count }}</span>
<span><i class="fas fa-download"></i> 下载 {{ share.download_count }}</span>
<span><i class="fas fa-clock"></i> {{ share.expires_at ? formatExpireTime(share.expires_at) : '永久有效' }}</span>
<span><i class="fas fa-calendar-alt"></i> 创建 {{ formatDateTime(share.created_at) }}</span>
</div>
<div class="share-card__actions">
<button class="btn btn-secondary" @click.stop="window.open(share.share_url, '_blank')">
<i class="fas fa-external-link-alt"></i> 打开
</button>
<button class="btn-icon" @click.stop="copyShareLink(share.share_url)" title="复制链接">
<i class="fas fa-copy"></i>
<button class="btn btn-secondary" @click.stop="copyShareLink(share.share_url)">
<i class="fas fa-copy"></i> 复制链接
</button>
<button class="btn-icon" style="color: #ef4444;" @click.stop="deleteShare(share.id)" title="删除">
<i class="fas fa-trash"></i>
<button class="btn" style="background: #ef4444; color: white;" @click.stop="deleteShare(share.id)">
<i class="fas fa-trash"></i> 删除
</button>
</div>
</div>
@@ -1977,7 +2142,7 @@
</tr>
</thead>
<tbody>
<tr v-for="share in shares" :key="share.id" style="border-bottom: 1px solid #eee;">
<tr v-for="share in filteredShares" :key="share.id" style="border-bottom: 1px solid #eee;">
<td style="padding: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" :title="share.share_path">{{ share.share_path }}</td>
<td style="padding: 10px; overflow: hidden;">
<a :href="share.share_url" target="_blank" style="color: #667eea; display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;" :title="share.share_url">{{ share.share_url }}</a>