优化会员管理页面样式 - 使用原生表格替代Element Plus表格,实现更简洁的设计

This commit is contained in:
AIGC Developer
2025-10-22 09:40:33 +08:00
parent 4b7604f20c
commit 9f167aa20f

View File

@@ -85,53 +85,63 @@
</div> </div>
<div class="table-container"> <div class="table-container">
<el-table <table class="member-table">
:data="memberList" <thead>
@selection-change="handleSelectionChange" <tr>
class="member-table"> <th class="checkbox-col">
<el-table-column type="selection" width="55" /> <input type="checkbox" @change="toggleAllSelection" :checked="isAllSelected" />
<el-table-column prop="id" label="用户ID" width="100" /> </th>
<el-table-column prop="username" label="用户名" width="120" /> <th>用户ID</th>
<el-table-column prop="level" label="会员等级" width="120"> <th>用户名</th>
<template #default="{ row }"> <th>会员等级</th>
<el-tag :type="row.level === '专业会员' ? 'danger' : 'primary'" size="small"> <th>剩余资源点</th>
{{ row.level }} <th>到期时间</th>
</el-tag> <th>编辑</th>
</template> <th>删除</th>
</el-table-column> </tr>
<el-table-column prop="points" label="剩余资源点" width="140"> </thead>
<template #default="{ row }"> <tbody>
{{ row.points.toLocaleString() }} <tr v-for="member in memberList" :key="member.id" class="table-row">
</template> <td class="checkbox-col">
</el-table-column> <input
<el-table-column prop="expiryDate" label="到期时间" width="120" /> type="checkbox"
<el-table-column label="编辑" width="80"> :checked="selectedMembers.some(m => m.id === member.id)"
<template #default="{ row }"> @change="toggleMemberSelection(member)" />
<el-button type="primary" text size="small" @click="editMember(row)"> </td>
编辑 <td>{{ member.id }}</td>
</el-button> <td>{{ member.username }}</td>
</template> <td>
</el-table-column> <span class="level-tag" :class="member.level === '专业会员' ? 'professional' : 'standard'">
<el-table-column label="删除" width="80"> {{ member.level }}
<template #default="{ row }"> </span>
<el-button type="danger" text size="small" @click="deleteMember(row)"> </td>
删除 <td>{{ member.points.toLocaleString() }}</td>
</el-button> <td>{{ member.expiryDate }}</td>
</template> <td>
</el-table-column> <button class="action-btn edit-btn" @click="editMember(member)">编辑</button>
</el-table> </td>
<td>
<button class="action-btn delete-btn" @click="deleteMember(member)">删除</button>
</td>
</tr>
</tbody>
</table>
</div> </div>
<!-- 分页 --> <!-- 分页 -->
<div class="pagination-container"> <div class="pagination-container">
<el-pagination <div class="pagination">
v-model:current-page="currentPage" <button class="page-btn" @click="prevPage" :disabled="currentPage === 1"></button>
:page-size="pageSize" <button
:total="totalMembers" v-for="page in visiblePages"
layout="prev, pager, next" :key="page"
:pager-count="5" class="page-btn"
@current-change="handlePageChange" :class="{ active: page === currentPage }"
/> @click="goToPage(page)">
{{ page }}
</button>
<button class="page-btn" @click="nextPage" :disabled="currentPage === totalPages"></button>
</div>
</div> </div>
</section> </section>
</main> </main>
@@ -188,8 +198,56 @@ const goToSettings = () => {
} }
// 表格操作 // 表格操作
const handleSelectionChange = (selection) => { const isAllSelected = computed(() => {
selectedMembers.value = selection return memberList.value.length > 0 && selectedMembers.value.length === memberList.value.length
})
const totalPages = computed(() => {
return Math.ceil(totalMembers.value / pageSize.value)
})
const visiblePages = computed(() => {
const pages = []
const start = Math.max(1, currentPage.value - 2)
const end = Math.min(totalPages.value, start + 4)
for (let i = start; i <= end; i++) {
pages.push(i)
}
return pages
})
const toggleAllSelection = () => {
if (isAllSelected.value) {
selectedMembers.value = []
} else {
selectedMembers.value = [...memberList.value]
}
}
const toggleMemberSelection = (member) => {
const index = selectedMembers.value.findIndex(m => m.id === member.id)
if (index > -1) {
selectedMembers.value.splice(index, 1)
} else {
selectedMembers.value.push(member)
}
}
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--
}
}
const nextPage = () => {
if (currentPage.value < totalPages.value) {
currentPage.value++
}
}
const goToPage = (page) => {
currentPage.value = page
} }
const editMember = (member) => { const editMember = (member) => {
@@ -456,13 +514,92 @@ onMounted(() => {
.table-container { .table-container {
background: white; background: white;
border-radius: 12px; border-radius: 8px;
overflow: hidden; overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
margin-bottom: 24px;
} }
.member-table { .member-table {
width: 100%; width: 100%;
border-collapse: collapse;
font-size: 14px;
}
.member-table thead {
background: #f8fafc;
}
.member-table th {
padding: 12px 16px;
text-align: left;
font-weight: 600;
color: #374151;
border-bottom: 1px solid #e5e7eb;
}
.member-table td {
padding: 12px 16px;
border-bottom: 1px solid #f3f4f6;
color: #374151;
}
.table-row:hover {
background: #f9fafb;
}
.checkbox-col {
width: 50px;
text-align: center;
}
.checkbox-col input[type="checkbox"] {
width: 16px;
height: 16px;
cursor: pointer;
}
.level-tag {
display: inline-block;
padding: 4px 12px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
color: white;
}
.level-tag.professional {
background: #ec4899;
}
.level-tag.standard {
background: #3b82f6;
}
.action-btn {
background: none;
border: none;
cursor: pointer;
font-size: 14px;
padding: 4px 8px;
border-radius: 4px;
transition: all 0.2s ease;
}
.edit-btn {
color: #3b82f6;
}
.edit-btn:hover {
background: #eff6ff;
}
.delete-btn {
color: #dc2626;
}
.delete-btn:hover {
background: #fef2f2;
} }
.pagination-container { .pagination-container {
@@ -471,6 +608,39 @@ onMounted(() => {
margin-top: 24px; margin-top: 24px;
} }
.pagination {
display: flex;
align-items: center;
gap: 8px;
}
.page-btn {
padding: 8px 12px;
border: 1px solid #d1d5db;
background: white;
color: #374151;
cursor: pointer;
border-radius: 4px;
font-size: 14px;
transition: all 0.2s ease;
}
.page-btn:hover:not(:disabled) {
background: #f3f4f6;
border-color: #9ca3af;
}
.page-btn.active {
background: #3b82f6;
color: white;
border-color: #3b82f6;
}
.page-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* 响应式设计 */ /* 响应式设计 */
@media (max-width: 1024px) { @media (max-width: 1024px) {
.member-management { .member-management {