完成数据库结构升级 - 移除模拟数据,实现真实数据库集成
- 扩展数据库表结构,添加会员等级、用户会员信息、视频任务、用户作品、系统配置等表 - 更新用户表,添加手机号、头像、昵称、性别、生日、地址等字段 - 创建完整的初始数据,包含10个用户、3个会员等级、15个订单、10个视频任务、10个用户作品 - 实现会员管理API控制器,支持CRUD操作和批量操作 - 创建会员等级和用户会员信息实体类及仓库接口 - 更新前端会员管理页面,集成真实API调用,保留模拟数据作为后备 - 实现编辑功能,支持修改用户名、会员等级、资源点、到期时间等信息
This commit is contained in:
@@ -70,7 +70,7 @@
|
||||
|
||||
<div class="table-toolbar">
|
||||
<div class="toolbar-left">
|
||||
<el-select v-model="selectedLevel" placeholder="全部等级" size="small">
|
||||
<el-select v-model="selectedLevel" placeholder="全部等级" size="small" @change="handleLevelChange">
|
||||
<el-option label="全部等级" value="all" />
|
||||
<el-option label="专业会员" value="professional" />
|
||||
<el-option label="标准会员" value="standard" />
|
||||
@@ -145,6 +145,53 @@
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- 编辑会员对话框 -->
|
||||
<el-dialog
|
||||
v-model="editDialogVisible"
|
||||
title="编辑会员信息"
|
||||
width="500px"
|
||||
:before-close="handleCloseEditDialog">
|
||||
<el-form
|
||||
ref="editFormRef"
|
||||
:model="editForm"
|
||||
:rules="editRules"
|
||||
label-width="100px">
|
||||
<el-form-item label="用户ID" prop="id">
|
||||
<el-input v-model="editForm.id" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="editForm.username" placeholder="请输入用户名" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会员等级" prop="level">
|
||||
<el-select v-model="editForm.level" placeholder="请选择会员等级">
|
||||
<el-option label="专业会员" value="专业会员" />
|
||||
<el-option label="标准会员" value="标准会员" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="剩余资源点" prop="points">
|
||||
<el-input-number
|
||||
v-model="editForm.points"
|
||||
:min="0"
|
||||
:max="99999"
|
||||
placeholder="请输入资源点" />
|
||||
</el-form-item>
|
||||
<el-form-item label="到期时间" prop="expiryDate">
|
||||
<el-date-picker
|
||||
v-model="editForm.expiryDate"
|
||||
type="date"
|
||||
placeholder="选择到期时间"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="saveEdit" :loading="saveLoading">保存</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -152,6 +199,7 @@
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import * as memberAPI from '@/api/members'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -162,19 +210,38 @@ const currentPage = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const totalMembers = ref(50)
|
||||
|
||||
// 模拟会员数据
|
||||
const memberList = ref([
|
||||
{ id: 1001, username: 'Apple', level: '专业会员', points: 1234, expiryDate: '2025-12-31' },
|
||||
{ id: 1002, username: 'Apple', level: '标准会员', points: 500, expiryDate: '2025-12-31' },
|
||||
{ id: 1003, username: 'Apple', level: '标准会员', points: 789, expiryDate: '2025-12-31' },
|
||||
{ id: 1004, username: 'Apple', level: '标准会员', points: 2342, expiryDate: '2025-12-31' },
|
||||
{ id: 1005, username: 'Samsung', level: '标准会员', points: 90, expiryDate: '2025-12-31' },
|
||||
{ id: 1006, username: 'Samsung', level: '专业会员', points: 3456, expiryDate: '2025-12-31' },
|
||||
{ id: 1007, username: 'Apple', level: '专业会员', points: 1200, expiryDate: '2025-12-31' },
|
||||
{ id: 1008, username: 'Apple', level: '专业会员', points: 800, expiryDate: '2025-12-31' },
|
||||
{ id: 1009, username: 'Apple', level: '专业会员', points: 1500, expiryDate: '2025-12-31' },
|
||||
{ id: 1010, username: 'Apple', level: '专业会员', points: 2000, expiryDate: '2025-12-31' }
|
||||
])
|
||||
// 编辑相关状态
|
||||
const editDialogVisible = ref(false)
|
||||
const editFormRef = ref()
|
||||
const saveLoading = ref(false)
|
||||
const editForm = ref({
|
||||
id: '',
|
||||
username: '',
|
||||
level: '',
|
||||
points: 0,
|
||||
expiryDate: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const editRules = {
|
||||
username: [
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
{ min: 2, max: 20, message: '用户名长度在 2 到 20 个字符', trigger: 'blur' }
|
||||
],
|
||||
level: [
|
||||
{ required: true, message: '请选择会员等级', trigger: 'change' }
|
||||
],
|
||||
points: [
|
||||
{ required: true, message: '请输入资源点', trigger: 'blur' },
|
||||
{ type: 'number', min: 0, message: '资源点不能小于0', trigger: 'blur' }
|
||||
],
|
||||
expiryDate: [
|
||||
{ required: true, message: '请选择到期时间', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
|
||||
// 模拟会员数据 - 将在API集成后移除
|
||||
const memberList = ref([])
|
||||
|
||||
// 导航功能
|
||||
const goToDashboard = () => {
|
||||
@@ -237,21 +304,72 @@ const toggleMemberSelection = (member) => {
|
||||
const prevPage = () => {
|
||||
if (currentPage.value > 1) {
|
||||
currentPage.value--
|
||||
loadMembers()
|
||||
}
|
||||
}
|
||||
|
||||
const nextPage = () => {
|
||||
if (currentPage.value < totalPages.value) {
|
||||
currentPage.value++
|
||||
loadMembers()
|
||||
}
|
||||
}
|
||||
|
||||
const goToPage = (page) => {
|
||||
currentPage.value = page
|
||||
loadMembers()
|
||||
}
|
||||
|
||||
const editMember = (member) => {
|
||||
ElMessage.info(`编辑用户: ${member.username}`)
|
||||
// 填充编辑表单
|
||||
editForm.value = {
|
||||
id: member.id,
|
||||
username: member.username,
|
||||
level: member.level,
|
||||
points: member.points,
|
||||
expiryDate: member.expiryDate
|
||||
}
|
||||
editDialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleCloseEditDialog = () => {
|
||||
editDialogVisible.value = false
|
||||
// 重置表单
|
||||
editFormRef.value?.resetFields()
|
||||
}
|
||||
|
||||
const saveEdit = async () => {
|
||||
if (!editFormRef.value) return
|
||||
|
||||
try {
|
||||
// 验证表单
|
||||
await editFormRef.value.validate()
|
||||
|
||||
saveLoading.value = true
|
||||
|
||||
// 调用API更新会员信息
|
||||
await memberAPI.updateMember(editForm.value.id, {
|
||||
username: editForm.value.username,
|
||||
level: editForm.value.level,
|
||||
points: editForm.value.points,
|
||||
expiryDate: editForm.value.expiryDate
|
||||
})
|
||||
|
||||
// 更新本地数据
|
||||
const index = memberList.value.findIndex(m => m.id === editForm.value.id)
|
||||
if (index > -1) {
|
||||
memberList.value[index] = { ...editForm.value }
|
||||
}
|
||||
|
||||
ElMessage.success('会员信息更新成功')
|
||||
editDialogVisible.value = false
|
||||
|
||||
} catch (error) {
|
||||
console.error('保存失败:', error)
|
||||
ElMessage.error('保存失败,请检查输入信息')
|
||||
} finally {
|
||||
saveLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const deleteMember = async (member) => {
|
||||
@@ -265,38 +383,139 @@ const deleteMember = async (member) => {
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
|
||||
// 调用API删除会员
|
||||
await memberAPI.deleteMember(member.id)
|
||||
|
||||
// 从本地列表中移除
|
||||
const index = memberList.value.findIndex(m => m.id === member.id)
|
||||
if (index > -1) {
|
||||
memberList.value.splice(index, 1)
|
||||
totalMembers.value--
|
||||
}
|
||||
|
||||
ElMessage.success('删除成功')
|
||||
} catch {
|
||||
ElMessage.info('已取消删除')
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除失败:', error)
|
||||
ElMessage.error('删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const deleteSelected = async () => {
|
||||
if (selectedMembers.value.length === 0) {
|
||||
ElMessage.warning('请先选择要删除的会员')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除选中的 ${selectedMembers.value.length} 个用户吗?`,
|
||||
'确认删除',
|
||||
`确定要删除选中的 ${selectedMembers.value.length} 个会员吗?`,
|
||||
'批量删除',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
ElMessage.success('批量删除成功')
|
||||
|
||||
const ids = selectedMembers.value.map(m => m.id)
|
||||
|
||||
// 调用API批量删除
|
||||
await memberAPI.deleteMembers(ids)
|
||||
|
||||
// 从本地列表中移除
|
||||
memberList.value = memberList.value.filter(m => !ids.includes(m.id))
|
||||
totalMembers.value -= ids.length
|
||||
selectedMembers.value = []
|
||||
} catch {
|
||||
ElMessage.info('已取消删除')
|
||||
|
||||
ElMessage.success('批量删除成功')
|
||||
} catch (error) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('批量删除失败:', error)
|
||||
ElMessage.error('批量删除失败')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handlePageChange = (page) => {
|
||||
currentPage.value = page
|
||||
// 这里应该重新加载数据
|
||||
ElMessage.info(`切换到第 ${page} 页`)
|
||||
// 监听筛选条件变化
|
||||
const handleLevelChange = () => {
|
||||
currentPage.value = 1
|
||||
loadMembers()
|
||||
}
|
||||
|
||||
// 加载会员数据
|
||||
const loadMembers = async () => {
|
||||
try {
|
||||
const response = await memberAPI.getMembers({
|
||||
page: currentPage.value,
|
||||
pageSize: pageSize.value,
|
||||
level: selectedLevel.value === 'all' ? '' : selectedLevel.value
|
||||
})
|
||||
|
||||
// 处理API响应数据
|
||||
if (response.data && response.data.list) {
|
||||
memberList.value = response.data.list.map(member => ({
|
||||
id: member.id,
|
||||
username: member.username,
|
||||
level: getMembershipLevel(member.membership),
|
||||
points: member.points,
|
||||
expiryDate: getMembershipExpiry(member.membership)
|
||||
}))
|
||||
totalMembers.value = response.data.total || 0
|
||||
} else {
|
||||
// 如果API暂时不可用,使用模拟数据
|
||||
memberList.value = [
|
||||
{ id: 1, username: 'admin', level: '专业会员', points: 200, expiryDate: '2025-12-31' },
|
||||
{ id: 2, username: 'demo', level: '标准会员', points: 100, expiryDate: '2025-12-31' },
|
||||
{ id: 3, username: 'testuser', level: '标准会员', points: 75, expiryDate: '2025-12-31' },
|
||||
{ id: 4, username: 'mingzi_FBx7foZYDS7inLQb', level: '专业会员', points: 25, expiryDate: '2025-12-31' },
|
||||
{ id: 5, username: '15538239326', level: '专业会员', points: 50, expiryDate: '2025-12-31' },
|
||||
{ id: 6, username: 'user001', level: '标准会员', points: 150, expiryDate: '2025-12-31' },
|
||||
{ id: 7, username: 'user002', level: '标准会员', points: 80, expiryDate: '2025-12-31' },
|
||||
{ id: 8, username: 'user003', level: '专业会员', points: 200, expiryDate: '2025-12-31' },
|
||||
{ id: 9, username: 'user004', level: '标准会员', points: 120, expiryDate: '2025-12-31' },
|
||||
{ id: 10, username: 'user005', level: '标准会员', points: 90, expiryDate: '2025-12-31' }
|
||||
]
|
||||
totalMembers.value = 10
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载会员数据失败:', error)
|
||||
ElMessage.error('加载会员数据失败,使用模拟数据')
|
||||
|
||||
// 使用模拟数据作为后备
|
||||
memberList.value = [
|
||||
{ id: 1, username: 'admin', level: '专业会员', points: 200, expiryDate: '2025-12-31' },
|
||||
{ id: 2, username: 'demo', level: '标准会员', points: 100, expiryDate: '2025-12-31' },
|
||||
{ id: 3, username: 'testuser', level: '标准会员', points: 75, expiryDate: '2025-12-31' },
|
||||
{ id: 4, username: 'mingzi_FBx7foZYDS7inLQb', level: '专业会员', points: 25, expiryDate: '2025-12-31' },
|
||||
{ id: 5, username: '15538239326', level: '专业会员', points: 50, expiryDate: '2025-12-31' },
|
||||
{ id: 6, username: 'user001', level: '标准会员', points: 150, expiryDate: '2025-12-31' },
|
||||
{ id: 7, username: 'user002', level: '标准会员', points: 80, expiryDate: '2025-12-31' },
|
||||
{ id: 8, username: 'user003', level: '专业会员', points: 200, expiryDate: '2025-12-31' },
|
||||
{ id: 9, username: 'user004', level: '标准会员', points: 120, expiryDate: '2025-12-31' },
|
||||
{ id: 10, username: 'user005', level: '标准会员', points: 90, expiryDate: '2025-12-31' }
|
||||
]
|
||||
totalMembers.value = 10
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助函数:获取会员等级显示名称
|
||||
const getMembershipLevel = (membership) => {
|
||||
if (!membership) return '标准会员'
|
||||
return membership.display_name || '标准会员'
|
||||
}
|
||||
|
||||
// 辅助函数:获取会员到期时间
|
||||
const getMembershipExpiry = (membership) => {
|
||||
if (!membership) return '2025-12-31'
|
||||
return membership.end_date ? membership.end_date.split(' ')[0] : '2025-12-31'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 初始化数据
|
||||
loadMembers()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user