mirror of
https://github.com/soybeanjs/soybean-admin.git
synced 2025-09-21 11:06:38 +08:00
199 lines
4.9 KiB
Vue
199 lines
4.9 KiB
Vue
<script setup lang="tsx">
|
|
import { reactive } from 'vue';
|
|
import { NButton, NTag } from 'naive-ui';
|
|
import { utils, writeFile } from 'xlsx';
|
|
import { enableStatusRecord, userGenderRecord } from '@/constants/business';
|
|
import { fetchGetUserList } from '@/service/api';
|
|
import { useAppStore } from '@/store/modules/app';
|
|
import { isTableColumnHasKey, useNaiveTable } from '@/hooks/common/table';
|
|
import { $t } from '@/locales';
|
|
|
|
const appStore = useAppStore();
|
|
|
|
const searchParams: Api.SystemManage.UserSearchParams = reactive({
|
|
current: 1,
|
|
size: 999,
|
|
status: null,
|
|
userName: null,
|
|
userGender: null,
|
|
nickName: null,
|
|
userPhone: null,
|
|
userEmail: null
|
|
});
|
|
|
|
const { columns, data, loading } = useNaiveTable({
|
|
api: () => fetchGetUserList(searchParams),
|
|
transform: response => {
|
|
const { data: list, error } = response;
|
|
|
|
if (!error) {
|
|
return list.records;
|
|
}
|
|
|
|
return [];
|
|
},
|
|
columns: () => [
|
|
{
|
|
type: 'selection',
|
|
align: 'center',
|
|
width: 48
|
|
},
|
|
{
|
|
key: 'index',
|
|
title: $t('common.index'),
|
|
align: 'center',
|
|
width: 64,
|
|
render: (_, index) => index + 1
|
|
},
|
|
{
|
|
key: 'userName',
|
|
title: $t('page.manage.user.userName'),
|
|
align: 'center',
|
|
minWidth: 100
|
|
},
|
|
{
|
|
key: 'userGender',
|
|
title: $t('page.manage.user.userGender'),
|
|
align: 'center',
|
|
width: 100,
|
|
render: row => {
|
|
if (row.userGender === null) {
|
|
return null;
|
|
}
|
|
|
|
const tagMap: Record<Api.SystemManage.UserGender, NaiveUI.ThemeColor> = {
|
|
1: 'primary',
|
|
2: 'error'
|
|
};
|
|
|
|
const label = $t(userGenderRecord[row.userGender]);
|
|
|
|
return <NTag type={tagMap[row.userGender]}>{label}</NTag>;
|
|
}
|
|
},
|
|
{
|
|
key: 'nickName',
|
|
title: $t('page.manage.user.nickName'),
|
|
align: 'center',
|
|
minWidth: 100
|
|
},
|
|
{
|
|
key: 'userPhone',
|
|
title: $t('page.manage.user.userPhone'),
|
|
align: 'center',
|
|
width: 120
|
|
},
|
|
{
|
|
key: 'userEmail',
|
|
title: $t('page.manage.user.userEmail'),
|
|
align: 'center',
|
|
minWidth: 200
|
|
},
|
|
{
|
|
key: 'status',
|
|
title: $t('page.manage.user.userStatus'),
|
|
align: 'center',
|
|
width: 100,
|
|
render: row => {
|
|
if (row.status === null) {
|
|
return null;
|
|
}
|
|
|
|
const tagMap: Record<Api.Common.EnableStatus, NaiveUI.ThemeColor> = {
|
|
1: 'success',
|
|
2: 'warning'
|
|
};
|
|
|
|
const label = $t(enableStatusRecord[row.status]);
|
|
|
|
return <NTag type={tagMap[row.status]}>{label}</NTag>;
|
|
}
|
|
}
|
|
]
|
|
});
|
|
|
|
function exportExcel() {
|
|
const exportColumns = columns.value.slice(2);
|
|
|
|
const excelList = data.value.map(item => exportColumns.map(col => getTableValue(col, item)));
|
|
|
|
const titleList = exportColumns.map(col => (isTableColumnHasTitle(col) && col.title) || null);
|
|
|
|
excelList.unshift(titleList);
|
|
|
|
const workBook = utils.book_new();
|
|
|
|
const workSheet = utils.aoa_to_sheet(excelList);
|
|
|
|
workSheet['!cols'] = exportColumns.map(item => ({
|
|
width: Math.round(Number(item.width) / 10 || 20)
|
|
}));
|
|
|
|
utils.book_append_sheet(workBook, workSheet, '用户列表');
|
|
|
|
writeFile(workBook, '用户数据.xlsx');
|
|
}
|
|
|
|
function getTableValue(col: NaiveUI.TableColumn<Api.SystemManage.User>, item: Api.SystemManage.User) {
|
|
if (!isTableColumnHasKey(col)) {
|
|
return null;
|
|
}
|
|
|
|
const { key } = col;
|
|
|
|
if (key === 'userRoles') {
|
|
return item.userRoles.map(role => role).join(',');
|
|
}
|
|
|
|
if (key === 'status') {
|
|
return (item.status && $t(enableStatusRecord[item.status])) || null;
|
|
}
|
|
|
|
if (key === 'userGender') {
|
|
return (item.userGender && $t(userGenderRecord[item.userGender])) || null;
|
|
}
|
|
|
|
// @ts-expect-error the key is not in the type of Api.SystemManage.User
|
|
return item[key] || null;
|
|
}
|
|
|
|
function isTableColumnHasTitle<T>(column: NaiveUI.TableColumn<T>): column is NaiveUI.TableColumnWithKey<T> & {
|
|
title: string;
|
|
} {
|
|
return Boolean((column as NaiveUI.TableColumnWithKey<T>).title);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="min-h-500px flex-col-stretch gap-16px overflow-hidden lt-sm:overflow-auto">
|
|
<NCard title="Excel导出" :bordered="false" size="small" class="card-wrapper sm:flex-1-hidden">
|
|
<template #header-extra>
|
|
<NSpace align="end" wrap justify="end" class="lt-sm:w-200px">
|
|
<NButton size="small" ghost type="primary" @click="exportExcel">
|
|
<template #icon>
|
|
<icon-file-icons:microsoft-excel class="text-icon" />
|
|
</template>
|
|
导出excel
|
|
</NButton>
|
|
</NSpace>
|
|
</template>
|
|
|
|
<NDataTable
|
|
:columns="columns"
|
|
:data="data"
|
|
size="small"
|
|
:flex-height="!appStore.isMobile"
|
|
:scroll-x="962"
|
|
:loading="loading"
|
|
remote
|
|
:row-key="row => row.id"
|
|
:pagination="false"
|
|
:virtual-scroll="true"
|
|
class="sm:h-full"
|
|
/>
|
|
</NCard>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|