246 lines
5.5 KiB
Markdown
246 lines
5.5 KiB
Markdown
# 实现用户邀请列表功能
|
||
|
||
## 1. 功能需求
|
||
|
||
1. 在用户列表的操作按钮中添加"邀请列表"按钮
|
||
2. 点击按钮携带用户ID跳转到邀请列表页面
|
||
3. 新建邀请列表页面,初始化调用getUsersInvites API渲染列表
|
||
4. 添加分页功能
|
||
|
||
## 2. 实现步骤
|
||
|
||
### 2.1 修改用户列表组件,添加邀请列表按钮
|
||
|
||
* 在操作按钮区域添加"邀请列表"按钮
|
||
|
||
* 绑定点击事件,携带用户ID跳转到邀请列表页面
|
||
|
||
### 2.2 创建邀请列表页面组件
|
||
|
||
* 新建`AdminUserInvites.vue`文件
|
||
|
||
* 实现页面布局,包括标题、筛选条件、列表和分页
|
||
|
||
* 实现API调用逻辑,获取邀请列表数据
|
||
|
||
* 添加分页功能
|
||
|
||
### 2.3 添加路由配置
|
||
|
||
* 在`router/index.js`中添加邀请列表页面的路由
|
||
|
||
* 配置路由参数,接收用户ID
|
||
|
||
### 2.4 实现邀请列表页面功能
|
||
|
||
* 初始化时调用getUsersInvites API获取数据
|
||
|
||
* 处理分页逻辑
|
||
|
||
* 实现数据渲染
|
||
|
||
* 添加错误处理
|
||
|
||
## 3. 代码修改点
|
||
|
||
### 3.1 修改用户列表组件
|
||
|
||
```vue
|
||
<!-- 在操作按钮区域添加邀请列表按钮 -->
|
||
el-button
|
||
size="small"
|
||
type="info"
|
||
@click="handleInviteList(row)"
|
||
>
|
||
{{ t('admin.users.inviteList') }}
|
||
</el-button>
|
||
|
||
<!-- 添加点击事件处理函数 -->
|
||
const handleInviteList = (row) => {
|
||
router.push({
|
||
name: 'AdminUserInvites',
|
||
params: { id: row.id }
|
||
})
|
||
}
|
||
```
|
||
|
||
### 3.2 添加路由配置
|
||
|
||
```javascript
|
||
// 导入组件
|
||
const AdminUserInvites = () => import('@/views/admin/AdminUsers/AdminUserInvites.vue')
|
||
|
||
// 添加路由
|
||
{
|
||
path: 'users/:id/invites',
|
||
name: 'AdminUserInvites',
|
||
component: AdminUserInvites,
|
||
meta: {
|
||
title: '邀请列表'
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.3 创建邀请列表页面组件
|
||
|
||
```vue
|
||
<template>
|
||
<div class="user-invites">
|
||
<h2>{{ t('admin.users.inviteList') }}</h2>
|
||
|
||
<!-- 列表区域 -->
|
||
<div class="invite-table">
|
||
<el-table
|
||
:data="inviteList"
|
||
stripe
|
||
style="width: 100%"
|
||
v-loading="loading"
|
||
>
|
||
<!-- 列表列定义 -->
|
||
<el-table-column prop="id" label="ID" width="80" />
|
||
<el-table-column prop="nickname" :label="t('admin.users.username')" min-width="120" />
|
||
<el-table-column prop="email" :label="t('admin.users.email')" min-width="180" />
|
||
<el-table-column prop="registerDate" :label="t('admin.users.registerDate')" min-width="160" />
|
||
<el-table-column prop="status" :label="t('admin.users.status')" min-width="100">
|
||
<template #default="{ row }">
|
||
<el-tag :type="getStatusTagType(row.status)">
|
||
{{ t(`admin.users.statusOptions.${row.status}`) }}
|
||
</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</div>
|
||
|
||
<!-- 分页 -->
|
||
<div class="pagination">
|
||
<el-pagination
|
||
v-model:current-page="currentPage"
|
||
v-model:page-size="pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
:total="totalInvites"
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, onMounted } from 'vue'
|
||
import { useRoute, useRouter } from 'vue-router'
|
||
import { useI18n } from 'vue-i18n'
|
||
import { AdminOrders } from './index.js'
|
||
|
||
const route = useRoute()
|
||
const router = useRouter()
|
||
const { t } = useI18n()
|
||
const adminOrders = new AdminOrders()
|
||
|
||
// 响应式数据
|
||
const loading = ref(false)
|
||
const currentPage = ref(1)
|
||
const pageSize = ref(20)
|
||
const totalInvites = ref(0)
|
||
const inviteList = ref([])
|
||
const userId = ref(route.params.id)
|
||
|
||
// 获取状态标签类型
|
||
const getStatusTagType = (status) => {
|
||
const typeMap = {
|
||
active: 'success',
|
||
disable: 'info',
|
||
banned: 'danger'
|
||
}
|
||
return typeMap[status] || 'info'
|
||
}
|
||
|
||
// 获取邀请列表
|
||
const getInviteList = async () => {
|
||
loading.value = true
|
||
try {
|
||
const result = await adminOrders.getUsersInvites({
|
||
id: userId.value,
|
||
pageSize: pageSize.value,
|
||
pageNum: currentPage.value
|
||
})
|
||
inviteList.value = result.rows || []
|
||
totalInvites.value = result.total || 0
|
||
} catch (error) {
|
||
console.error('获取邀请列表失败:', error)
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
// 分页处理
|
||
const handleSizeChange = (size) => {
|
||
pageSize.value = size
|
||
currentPage.value = 1
|
||
getInviteList()
|
||
}
|
||
|
||
const handleCurrentChange = (page) => {
|
||
currentPage.value = page
|
||
getInviteList()
|
||
}
|
||
|
||
// 初始化
|
||
onMounted(() => {
|
||
getInviteList()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* 样式定义 */
|
||
.user-invites {
|
||
padding: 20px;
|
||
}
|
||
|
||
.invite-table {
|
||
background: white;
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||
border: 1px solid #e5e7eb;
|
||
margin-bottom: 24px;
|
||
}
|
||
|
||
.pagination {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
padding: 16px 0;
|
||
}
|
||
</style>
|
||
```
|
||
|
||
### 3.4 添加翻译键
|
||
|
||
在中英文语言包中添加邀请列表相关的翻译键:
|
||
|
||
```javascript
|
||
// 中文
|
||
inviteList: '邀请列表',
|
||
|
||
// 英文
|
||
inviteList: 'Invite List'
|
||
```
|
||
|
||
## 4. 测试要点
|
||
|
||
1. 邀请列表按钮显示正确
|
||
2. 点击按钮能正确跳转到邀请列表页面,并携带用户ID
|
||
3. 邀请列表页面能正确调用API获取数据
|
||
4. 分页功能正常工作
|
||
5. 错误处理正常
|
||
|
||
## 5. 预期效果
|
||
|
||
1. 用户列表中每个用户都有一个"邀请列表"按钮
|
||
2. 点击按钮跳转到邀请列表页面,URL中包含用户ID
|
||
3. 邀请列表页面显示该用户邀请的所有用户
|
||
4. 分页功能正常,能切换页面和调整每页显示数量
|
||
5. 数据加载时有加载状态提示
|
||
6. API调用失败时有错误提示
|
||
|