diff --git a/demo/ORDER_MANAGEMENT_SUMMARY.md b/demo/ORDER_MANAGEMENT_SUMMARY.md
index 2acf0cb..8897abe 100644
--- a/demo/ORDER_MANAGEMENT_SUMMARY.md
+++ b/demo/ORDER_MANAGEMENT_SUMMARY.md
@@ -316,3 +316,6 @@ ALTER TABLE payments ADD FOREIGN KEY (order_id_ref) REFERENCES orders(id);
+
+
+
diff --git a/demo/PasswordChecker.java b/demo/PasswordChecker.java
index b85f34b..6a156bb 100644
--- a/demo/PasswordChecker.java
+++ b/demo/PasswordChecker.java
@@ -23,3 +23,6 @@ public class PasswordChecker {
+
+
+
diff --git a/demo/VUE_FRONTEND_SUMMARY.md b/demo/VUE_FRONTEND_SUMMARY.md
index 721c83a..04c003f 100644
--- a/demo/VUE_FRONTEND_SUMMARY.md
+++ b/demo/VUE_FRONTEND_SUMMARY.md
@@ -280,3 +280,6 @@ Vue.js 前端项目迁移已经完成,实现了:
+
+
+
diff --git a/demo/frontend/README.md b/demo/frontend/README.md
index a522f96..d355a69 100644
--- a/demo/frontend/README.md
+++ b/demo/frontend/README.md
@@ -423,3 +423,6 @@ MIT License
+
+
+
diff --git a/demo/frontend/src/App-backup.vue b/demo/frontend/src/App-backup.vue
index 3a89026..5a530b0 100644
--- a/demo/frontend/src/App-backup.vue
+++ b/demo/frontend/src/App-backup.vue
@@ -19,3 +19,6 @@ console.log('App.vue 加载成功')
+
+
+
diff --git a/demo/frontend/src/api/members.js b/demo/frontend/src/api/members.js
new file mode 100644
index 0000000..d215c3d
--- /dev/null
+++ b/demo/frontend/src/api/members.js
@@ -0,0 +1,44 @@
+import request from './request'
+
+// 获取会员列表
+export const getMembers = (params) => {
+ return request({
+ url: '/members',
+ method: 'get',
+ params
+ })
+}
+
+// 更新会员信息
+export const updateMember = (id, data) => {
+ return request({
+ url: `/members/${id}`,
+ method: 'put',
+ data
+ })
+}
+
+// 删除会员
+export const deleteMember = (id) => {
+ return request({
+ url: `/members/${id}`,
+ method: 'delete'
+ })
+}
+
+// 批量删除会员
+export const deleteMembers = (ids) => {
+ return request({
+ url: '/members/batch',
+ method: 'delete',
+ data: { ids }
+ })
+}
+
+// 获取会员详情
+export const getMemberDetail = (id) => {
+ return request({
+ url: `/members/${id}`,
+ method: 'get'
+ })
+}
diff --git a/demo/frontend/src/api/orders.js b/demo/frontend/src/api/orders.js
index 038cc33..d40f3c5 100644
--- a/demo/frontend/src/api/orders.js
+++ b/demo/frontend/src/api/orders.js
@@ -60,3 +60,6 @@ export const getOrderStats = () => {
+
+
+
diff --git a/demo/frontend/src/components/Footer.vue b/demo/frontend/src/components/Footer.vue
index 2ce168b..372dce1 100644
--- a/demo/frontend/src/components/Footer.vue
+++ b/demo/frontend/src/components/Footer.vue
@@ -82,3 +82,6 @@
+
+
+
diff --git a/demo/frontend/src/views/ImageToVideoCreate.vue b/demo/frontend/src/views/ImageToVideoCreate.vue
index 52bc67f..09b16b0 100644
--- a/demo/frontend/src/views/ImageToVideoCreate.vue
+++ b/demo/frontend/src/views/ImageToVideoCreate.vue
@@ -779,3 +779,6 @@ const startGenerate = () => {
+
+
+
diff --git a/demo/frontend/src/views/MemberManagement.vue b/demo/frontend/src/views/MemberManagement.vue
index b57838d..ac35717 100644
--- a/demo/frontend/src/views/MemberManagement.vue
+++ b/demo/frontend/src/views/MemberManagement.vue
@@ -70,7 +70,7 @@
@@ -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()
})
diff --git a/demo/frontend/src/views/OrderDetail.vue b/demo/frontend/src/views/OrderDetail.vue
index 169dcee..57a5456 100644
--- a/demo/frontend/src/views/OrderDetail.vue
+++ b/demo/frontend/src/views/OrderDetail.vue
@@ -199,3 +199,6 @@ onMounted(async () => {
+
+
+
diff --git a/demo/frontend/src/views/PaymentCreate.vue b/demo/frontend/src/views/PaymentCreate.vue
index f9e2b4b..6069003 100644
--- a/demo/frontend/src/views/PaymentCreate.vue
+++ b/demo/frontend/src/views/PaymentCreate.vue
@@ -252,3 +252,6 @@ const handleSubmit = async () => {
+
+
+
diff --git a/demo/frontend/src/views/SimpleTest.vue b/demo/frontend/src/views/SimpleTest.vue
index c998f06..98d842b 100644
--- a/demo/frontend/src/views/SimpleTest.vue
+++ b/demo/frontend/src/views/SimpleTest.vue
@@ -11,3 +11,6 @@ console.log('测试页面加载成功')
+
+
+
diff --git a/demo/frontend/src/views/StoryboardVideoCreate.vue b/demo/frontend/src/views/StoryboardVideoCreate.vue
index 695bbda..571a0e0 100644
--- a/demo/frontend/src/views/StoryboardVideoCreate.vue
+++ b/demo/frontend/src/views/StoryboardVideoCreate.vue
@@ -730,3 +730,6 @@ const startGenerate = () => {
+
+
+
diff --git a/demo/src/main/java/com/example/demo/controller/MemberApiController.java b/demo/src/main/java/com/example/demo/controller/MemberApiController.java
new file mode 100644
index 0000000..4a6f40c
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/controller/MemberApiController.java
@@ -0,0 +1,263 @@
+package com.example.demo.controller;
+
+import com.example.demo.model.User;
+import com.example.demo.model.UserMembership;
+import com.example.demo.model.MembershipLevel;
+import com.example.demo.repository.UserRepository;
+import com.example.demo.repository.UserMembershipRepository;
+import com.example.demo.repository.MembershipLevelRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/api/members")
+@CrossOrigin(origins = "*")
+public class MemberApiController {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private UserMembershipRepository userMembershipRepository;
+
+ @Autowired
+ private MembershipLevelRepository membershipLevelRepository;
+
+ // 获取会员列表
+ @GetMapping
+ public ResponseEntity