feat(user): 添加用户列表导出功能
- 新增 exportUsers API 接口用于导出用户数据 - 在用户管理页面添加导出按钮,仅超级管理员可见- 实现 handleExport 方法处理导出逻辑 - 使用 xlsx 库生成 Excel 文件并自动下载 - 添加搜索处理方法 handleSearch 优化查询体验 - 引入 computed 属性获取当前登录用户信息 - 更新搜索框事件处理为 handleSearch 方法- 调整导入/导出按钮显示权限控制逻辑
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
VITE_APP_NAME=后台管理(开发环境)
|
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
|
#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));
|
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',
|
key: 'comments',
|
||||||
align: 'left'
|
align: 'left'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '收益基数',
|
||||||
|
dataIndex: 'rate',
|
||||||
|
key: 'rate',
|
||||||
|
align: 'left',
|
||||||
|
customRender: () => {
|
||||||
|
return `0.007`;
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '报备人信息',
|
title: '报备人信息',
|
||||||
key: 'applicantInfo',
|
key: 'applicantInfo',
|
||||||
|
|||||||
@@ -54,18 +54,21 @@
|
|||||||
</template>
|
</template>
|
||||||
<span>批量删除</span>
|
<span>批量删除</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<template v-if="hasRole('superAdmin')">
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="openImport">
|
<a-button type="dashed" class="ele-btn-icon" @click="openImport">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<upload-outlined/>
|
<upload-outlined/>
|
||||||
</template>
|
</template>
|
||||||
<span>导入</span>
|
<span>导入</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button type="dashed" @click="handleExport">导出xls</a-button>
|
||||||
|
</template>
|
||||||
<a-input-search
|
<a-input-search
|
||||||
allow-clear
|
allow-clear
|
||||||
v-model:value="searchText"
|
v-model:value="searchText"
|
||||||
placeholder="请输入关键词"
|
placeholder="请输入关键词"
|
||||||
@search="reload"
|
@search="handleSearch"
|
||||||
@pressEnter="reload"
|
@pressEnter="handleSearch"
|
||||||
/>
|
/>
|
||||||
</a-space>
|
</a-space>
|
||||||
</template>
|
</template>
|
||||||
@@ -149,7 +152,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<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 {message, Modal} from 'ant-design-vue/es';
|
||||||
import {
|
import {
|
||||||
PlusOutlined,
|
PlusOutlined,
|
||||||
@@ -177,16 +180,20 @@ import {
|
|||||||
removeUser,
|
removeUser,
|
||||||
removeUsers,
|
removeUsers,
|
||||||
updateUserPassword,
|
updateUserPassword,
|
||||||
updateUser
|
updateUser,
|
||||||
|
listUsers
|
||||||
} from '@/api/system/user';
|
} from '@/api/system/user';
|
||||||
import type {User, UserParam} from '@/api/system/user/model';
|
import type {User, UserParam} from '@/api/system/user/model';
|
||||||
import {toTreeData, uuid} from 'ele-admin-pro';
|
import {toTreeData, uuid} from 'ele-admin-pro';
|
||||||
|
import {utils, writeFile} from 'xlsx';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import {listRoles} from '@/api/system/role';
|
import {listRoles} from '@/api/system/role';
|
||||||
import {listOrganizations} from '@/api/system/organization';
|
import {listOrganizations} from '@/api/system/organization';
|
||||||
import {Organization} from '@/api/system/organization/model';
|
import {Organization} from '@/api/system/organization/model';
|
||||||
import {hasRole} from '@/utils/permission';
|
import {hasRole} from '@/utils/permission';
|
||||||
import {getPageTitle} from "@/utils/common";
|
import {getPageTitle} from "@/utils/common";
|
||||||
import Extra from "./components/Extra.vue";
|
import Extra from "./components/Extra.vue";
|
||||||
|
import {useUserStore} from '@/store/modules/user';
|
||||||
|
|
||||||
// 加载状态
|
// 加载状态
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -208,7 +215,9 @@ const showInfo = ref(false);
|
|||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
const userType = ref<number>();
|
const userType = ref<number>();
|
||||||
const searchText = ref('');
|
const searchText = ref('');
|
||||||
|
const userStore = useUserStore();
|
||||||
|
// 当前用户信息
|
||||||
|
const loginUser = computed(() => userStore.info ?? {});
|
||||||
// 加载角色
|
// 加载角色
|
||||||
const roles = ref<any[]>([]);
|
const roles = ref<any[]>([]);
|
||||||
const filters = () => {
|
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) => {
|
const customRow = (record: User) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user