feat(user): 添加用户列表导出功能
- 新增 exportUsers API 接口用于导出用户数据 - 在用户管理页面添加导出按钮,仅超级管理员可见- 实现 handleExport 方法处理导出逻辑 - 使用 xlsx 库生成 Excel 文件并自动下载 - 添加搜索处理方法 handleSearch 优化查询体验 - 引入 computed 属性获取当前登录用户信息 - 更新搜索框事件处理为 handleSearch 方法- 调整导入/导出按钮显示权限控制逻辑
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
VITE_APP_NAME=后台管理(开发环境)
|
||||
VITE_API_URL=http://127.0.0.1:9200/api
|
||||
#VITE_API_URL=http://127.0.0.1:9200/api
|
||||
#VITE_SERVER_API_URL=http://127.0.0.1:8000/api
|
||||
|
||||
|
||||
|
||||
@@ -282,3 +282,17 @@ export async function listAdminsByPhoneAll(params?: UserParam){
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出用户列表
|
||||
*/
|
||||
export async function exportUsers(params?: UserParam) {
|
||||
const res = await request.get<Blob>(
|
||||
SERVER_API_URL + '/system/user/export',
|
||||
{
|
||||
params,
|
||||
responseType: 'blob'
|
||||
}
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
@@ -165,6 +165,15 @@ const columns = ref<ColumnItem[]>([
|
||||
key: 'comments',
|
||||
align: 'left'
|
||||
},
|
||||
{
|
||||
title: '收益基数',
|
||||
dataIndex: 'rate',
|
||||
key: 'rate',
|
||||
align: 'left',
|
||||
customRender: () => {
|
||||
return `0.007`;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '报备人信息',
|
||||
key: 'applicantInfo',
|
||||
|
||||
@@ -54,18 +54,21 @@
|
||||
</template>
|
||||
<span>批量删除</span>
|
||||
</a-button>
|
||||
<template v-if="hasRole('superAdmin')">
|
||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport">
|
||||
<template #icon>
|
||||
<upload-outlined/>
|
||||
</template>
|
||||
<span>导入</span>
|
||||
</a-button>
|
||||
<a-button type="dashed" @click="handleExport">导出xls</a-button>
|
||||
</template>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
v-model:value="searchText"
|
||||
placeholder="请输入关键词"
|
||||
@search="reload"
|
||||
@pressEnter="reload"
|
||||
@search="handleSearch"
|
||||
@pressEnter="handleSearch"
|
||||
/>
|
||||
</a-space>
|
||||
</template>
|
||||
@@ -149,7 +152,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {createVNode, ref, reactive} from 'vue';
|
||||
import {createVNode, ref,computed, reactive} from 'vue';
|
||||
import {message, Modal} from 'ant-design-vue/es';
|
||||
import {
|
||||
PlusOutlined,
|
||||
@@ -177,16 +180,20 @@ import {
|
||||
removeUser,
|
||||
removeUsers,
|
||||
updateUserPassword,
|
||||
updateUser
|
||||
updateUser,
|
||||
listUsers
|
||||
} from '@/api/system/user';
|
||||
import type {User, UserParam} from '@/api/system/user/model';
|
||||
import {toTreeData, uuid} from 'ele-admin-pro';
|
||||
import {utils, writeFile} from 'xlsx';
|
||||
import dayjs from 'dayjs';
|
||||
import {listRoles} from '@/api/system/role';
|
||||
import {listOrganizations} from '@/api/system/organization';
|
||||
import {Organization} from '@/api/system/organization/model';
|
||||
import {hasRole} from '@/utils/permission';
|
||||
import {getPageTitle} from "@/utils/common";
|
||||
import Extra from "./components/Extra.vue";
|
||||
import {useUserStore} from '@/store/modules/user';
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
@@ -208,7 +215,9 @@ const showInfo = ref(false);
|
||||
const showImport = ref(false);
|
||||
const userType = ref<number>();
|
||||
const searchText = ref('');
|
||||
|
||||
const userStore = useUserStore();
|
||||
// 当前用户信息
|
||||
const loginUser = computed(() => userStore.info ?? {});
|
||||
// 加载角色
|
||||
const roles = ref<any[]>([]);
|
||||
const filters = () => {
|
||||
@@ -536,6 +545,107 @@ const updateIsAdmin = (row: User) => {
|
||||
});
|
||||
};
|
||||
|
||||
/* 搜索处理 */
|
||||
const handleSearch = () => {
|
||||
reload();
|
||||
};
|
||||
|
||||
/* 导出功能 */
|
||||
const handleExport = async () => {
|
||||
if (loading.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
message.loading('正在准备导出数据...', 0);
|
||||
|
||||
try {
|
||||
const array: (string | number)[][] = [
|
||||
[
|
||||
'用户ID',
|
||||
'头像',
|
||||
'手机号码',
|
||||
'真实姓名',
|
||||
'昵称',
|
||||
'性别',
|
||||
'邮箱',
|
||||
'可用余额',
|
||||
'可用积分',
|
||||
'注册来源',
|
||||
'注册时间'
|
||||
]
|
||||
];
|
||||
|
||||
// 构建查询参数
|
||||
const queryParams = {
|
||||
keywords: searchText.value
|
||||
};
|
||||
|
||||
// 按搜索结果导出
|
||||
const list = await listUsers(queryParams);
|
||||
|
||||
if (!list || list.length === 0) {
|
||||
message.warning('没有数据可以导出');
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
list.forEach((user: User) => {
|
||||
array.push([
|
||||
`${user.userId || ''}`,
|
||||
`${user.avatar ? '有头像' : '无头像'}`,
|
||||
`${user.phone || ''}`,
|
||||
`${user.realName || ''}`,
|
||||
`${user.nickname || ''}`,
|
||||
`${user.sex === '1' ? '男' : user.sex === '2' ? '女' : ''}`,
|
||||
`${user.email || ''}`,
|
||||
`${user.balance || '0'}`,
|
||||
`${user.points || '0'}`,
|
||||
`${user.platform || ''}`,
|
||||
`${user.createTime || ''}`
|
||||
]);
|
||||
});
|
||||
|
||||
const sheetName = `导出用户列表${dayjs(new Date()).format('YYYYMMDD')}`;
|
||||
const workbook = {
|
||||
SheetNames: [sheetName],
|
||||
Sheets: {}
|
||||
};
|
||||
const sheet = utils.aoa_to_sheet(array);
|
||||
workbook.Sheets[sheetName] = sheet;
|
||||
|
||||
// 设置列宽
|
||||
sheet['!cols'] = [
|
||||
{wch: 10}, // 用户ID
|
||||
{wch: 10}, // 头像
|
||||
{wch: 15}, // 手机号码
|
||||
{wch: 15}, // 真实姓名
|
||||
{wch: 15}, // 昵称
|
||||
{wch: 8}, // 性别
|
||||
{wch: 20}, // 邮箱
|
||||
{wch: 12}, // 可用余额
|
||||
{wch: 12}, // 可用积分
|
||||
{wch: 12}, // 注册来源
|
||||
{wch: 20} // 注册时间
|
||||
];
|
||||
|
||||
message.destroy();
|
||||
message.loading('正在生成Excel文件...', 0);
|
||||
|
||||
setTimeout(() => {
|
||||
writeFile(workbook, `${sheetName}.xlsx`);
|
||||
loading.value = false;
|
||||
message.destroy();
|
||||
message.success(`成功导出 ${list.length} 条记录`);
|
||||
}, 1000);
|
||||
|
||||
} catch (error: any) {
|
||||
loading.value = false;
|
||||
message.destroy();
|
||||
message.error(error.message || '导出失败,请重试');
|
||||
}
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: User) => {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user