feat(projects): 实现用户管理页面

This commit is contained in:
Soybean
2022-08-07 12:02:00 +08:00
parent 77572855c3
commit 472f93bfc1
11 changed files with 361 additions and 83 deletions

View File

@ -0,0 +1,124 @@
<template>
<n-modal v-model:show="modalVisible" preset="card" :title="title" class="w-700px">
<n-form label-placement="left" :label-width="80" :model="formModel">
<n-grid :cols="24" :x-gap="18">
<n-form-item-grid-item :span="12" label="用户名" path="userName">
<n-input v-model:value="formModel.userName" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="年龄" path="userAge">
<n-input v-model:value="formModel.userAge" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="性别" path="userGender">
<n-input v-model:value="formModel.userGender" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="手机号" path="userPhone">
<n-input v-model:value="formModel.userPhone" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="邮箱" path="userEmail">
<n-input v-model:value="formModel.userEmail" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="角色" path="userRole">
<n-input v-model:value="formModel.userRole" />
</n-form-item-grid-item>
<n-form-item-grid-item :span="12" label="状态" path="disabled">
<n-switch v-model:value="formModel.disabled" />
</n-form-item-grid-item>
</n-grid>
</n-form>
</n-modal>
</template>
<script setup lang="ts">
import { reactive, computed, watch } from 'vue';
defineOptions({ name: 'TableActionModal' });
type ModalType = 'add' | 'edit';
interface Props {
/** 弹窗可见性 */
visible: boolean;
/** 弹窗类型 */
type?: ModalType;
/** 编辑的表格行数据 */
editData?: UserManagement.UserTable | null;
}
const props = withDefaults(defineProps<Props>(), {
type: 'add',
editData: null
});
interface Emits {
(e: 'update:visible', visible: boolean): void;
}
const emit = defineEmits<Emits>();
const modalVisible = computed({
get() {
return props.visible;
},
set(visible) {
emit('update:visible', visible);
}
});
const title = computed(() => {
const titles: Record<ModalType, string> = {
add: '添加用户',
edit: '编辑用户'
};
return titles[props.type];
});
type FormModel = Pick<
UserManagement.UserTable,
'userName' | 'userAge' | 'userGender' | 'userPhone' | 'userEmail' | 'userRole' | 'disabled'
>;
const formModel = reactive<FormModel>(createDefaultFormModel());
function createDefaultFormModel(): FormModel {
return {
userName: '',
userAge: '',
userGender: 'null',
userPhone: '',
userEmail: '',
userRole: 'user',
disabled: true
};
}
function handleUpdateFormModel(model: Partial<FormModel>) {
Object.assign(formModel, model);
}
function handleUpdateFormModelByModalType() {
const handlers: Record<ModalType, () => void> = {
add: () => {
const defaultFormModel = createDefaultFormModel();
handleUpdateFormModel(defaultFormModel);
},
edit: () => {
if (props.editData) {
handleUpdateFormModel(props.editData);
}
}
};
handlers[props.type]();
}
watch(
() => props.visible,
newValue => {
if (newValue) {
handleUpdateFormModelByModalType();
}
}
);
</script>
<style scoped></style>

View File

@ -0,0 +1,3 @@
import TableActionModal from './TableActionModal.vue';
export { TableActionModal };

View File

@ -1,34 +1,42 @@
<template>
<div>
<n-data-table :columns="columns" :data="tableData" :loading="loading" />
</div>
<n-card title="用户管理" :bordered="false" class="rounded-16px shadow-sm">
<n-space class="pb-12px" justify="space-between">
<n-space>
<n-button type="primary" @click="handleAddTable">
<icon-ic-round-plus class="mr-4px text-20px" />
新增
</n-button>
<n-button type="error">
<icon-ic-round-delete class="mr-4px text-20px" />
删除
</n-button>
<n-button type="success">
<icon-uil:export class="mr-4px text-20px" />
导出Excel
</n-button>
</n-space>
<n-space>
<n-switch />
<icon-mdi-refresh class="text-20px" />
</n-space>
</n-space>
<n-data-table :columns="columns" :data="tableData" :loading="loading" :pagination="pagination" />
<table-action-modal v-model:visible="visible" :type="modalType" :edit-data="editData" />
</n-card>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import type { DataTableColumns } from 'naive-ui';
<script setup lang="tsx">
import { ref, reactive } from 'vue';
import { NSwitch, NTag, NSpace, NPopconfirm, NButton } from 'naive-ui';
import type { DataTableColumns, PaginationProps } from 'naive-ui';
import { fetchUserManagementList } from '@/service';
import { useLoading } from '@/hooks';
import { useLoading, useBoolean } from '@/hooks';
import { TableActionModal } from './components';
const { loading, startLoading, endLoading } = useLoading(false);
const columns: DataTableColumns = [
{
key: 'userName',
title: '用户名'
},
{
key: 'userAge',
title: '用户年龄'
},
{
key: 'userGenderLabel',
title: '性别'
}
];
const { bool: visible, setTrue: openModal } = useBoolean();
const tableData = ref<UserManagement.UserTable[]>([]);
function setTableData(data: UserManagement.UserTable[]) {
tableData.value = data;
}
@ -44,6 +52,157 @@ async function getTableData() {
}
}
const columns: DataTableColumns = [
{
type: 'selection',
align: 'center'
},
{
key: 'index',
title: '序号',
align: 'center'
},
{
key: 'userName',
title: '用户名',
align: 'center'
},
{
key: 'userAge',
title: '用户年龄',
align: 'center'
},
{
key: 'userGenderLabel',
title: '性别',
align: 'center',
render: row => {
const rowData = row as unknown as UserManagement.UserTable;
if (rowData.userGender !== 'null') {
const tagType = {
male: 'success',
female: 'warning'
} as const;
return <NTag type={tagType[rowData.userGender]}>{rowData.userGenderLabel}</NTag>;
}
return <span></span>;
}
},
{
key: 'userPhone',
title: '手机号码',
align: 'center'
},
{
key: 'userEmail',
title: '邮箱',
align: 'center'
},
{
key: 'userRole',
title: '角色',
align: 'center',
render: row => {
const rowData = row as unknown as UserManagement.UserTable;
const tagType = {
super: 'primary',
admin: 'warning',
user: 'success'
} as const;
return <NTag type={tagType[rowData.userRole]}>{rowData.userRole}</NTag>;
}
},
{
key: 'disabled',
title: '状态',
align: 'center',
render: row => {
const rowData = row as unknown as UserManagement.UserTable;
return (
<NSwitch value={rowData.disabled} onUpdateValue={disabled => handleUpdateDisabled(disabled, rowData.id)}>
{{ checked: () => '启用', unchecked: () => '禁用' }}
</NSwitch>
);
}
},
{
key: 'actions',
title: '操作',
align: 'center',
render: row => {
const rowData = row as unknown as UserManagement.UserTable;
return (
<NSpace justify={'center'}>
<NButton size={'small'} onClick={() => handleEditTable(rowData.id)}>
编辑
</NButton>
<NPopconfirm onPositiveClick={() => handleDeleteTable(rowData.id)}>
{{
default: () => '确认删除',
trigger: () => <NButton size={'small'}>删除</NButton>
}}
</NPopconfirm>
</NSpace>
);
}
}
];
function handleUpdateDisabled(disabled: boolean, rowId: string) {
const index = tableData.value.findIndex(item => item.id === rowId);
if (index > -1) {
tableData.value[index].disabled = disabled;
}
}
type ModalType = 'add' | 'edit';
const modalType = ref<ModalType>('add');
function setModalType(type: ModalType) {
modalType.value = type;
}
const editData = ref<UserManagement.UserTable | null>(null);
function setEditData(data: UserManagement.UserTable | null) {
editData.value = data;
}
function handleAddTable() {
openModal();
setModalType('add');
}
function handleEditTable(rowId: string) {
const findItem = tableData.value.find(item => item.id === rowId);
if (findItem) {
setEditData(findItem);
}
setModalType('edit');
openModal();
}
function handleDeleteTable(rowId: string) {
window.$message?.info(`点击了删除rowId为${rowId}`);
}
const pagination = reactive<PaginationProps>({
page: 1,
pageSize: 10,
showSizePicker: true,
pageSizes: [10, 15, 20, 25, 30],
onChange: (page: number) => {
pagination.page = page;
},
onUpdatePageSize: (pageSize: number) => {
pagination.pageSize = pageSize;
pagination.page = 1;
}
});
function init() {
getTableData();
}