Spaces:
Runtime error
Runtime error
| <script lang="ts" setup> | |
| import { h, onMounted, reactive, ref } from 'vue' | |
| import { NButton, NDataTable, NModal, NSelect, NTag, useDialog, useMessage } from 'naive-ui' | |
| import { Status, UserInfo, UserRole, userRoleOptions } from './model' | |
| import { fetchGetUsers, fetchUpdateUserRole, fetchUpdateUserStatus } from '@/api' | |
| import { t } from '@/locales' | |
| const ms = useMessage() | |
| const dialog = useDialog() | |
| const loading = ref(false) | |
| const show = ref(false) | |
| const handleSaving = ref(false) | |
| const userRef = ref(new UserInfo([UserRole.User])) | |
| const users = ref([]) | |
| const columns = [ | |
| { | |
| title: 'Email', | |
| key: 'email', | |
| resizable: true, | |
| width: 200, | |
| minWidth: 100, | |
| maxWidth: 200, | |
| }, | |
| { | |
| title: 'Register Time', | |
| key: 'createTime', | |
| width: 220, | |
| }, | |
| { | |
| title: 'Verify Time', | |
| key: 'verifyTime', | |
| width: 220, | |
| }, | |
| { | |
| title: 'Roles', | |
| key: 'status', | |
| width: 200, | |
| render(row: any) { | |
| const roles = row.roles.map((role: UserRole) => { | |
| return h( | |
| NTag, | |
| { | |
| style: { | |
| marginRight: '6px', | |
| }, | |
| type: 'info', | |
| bordered: false, | |
| }, | |
| { | |
| default: () => UserRole[role], | |
| }, | |
| ) | |
| }) | |
| return roles | |
| }, | |
| }, | |
| { | |
| title: 'Status', | |
| key: 'status', | |
| width: 200, | |
| render(row: any) { | |
| return Status[row.status] | |
| }, | |
| }, | |
| { | |
| title: 'Action', | |
| key: '_id', | |
| width: 220, | |
| render(row: any) { | |
| const actions: any[] = [] | |
| actions.push(h( | |
| NButton, | |
| { | |
| size: 'small', | |
| type: 'error', | |
| style: { | |
| marginRight: '6px', | |
| }, | |
| onClick: () => handleUpdateUserStatus(row._id, Status.Deleted), | |
| }, | |
| { default: () => t('chat.deleteUser') }, | |
| )) | |
| if (row.status === Status.Normal) { | |
| actions.push(h( | |
| NButton, | |
| { | |
| size: 'small', | |
| type: 'primary', | |
| style: { | |
| marginRight: '6px', | |
| }, | |
| onClick: () => handleEditUser(row), | |
| }, | |
| { default: () => t('chat.setUserRole') }, | |
| )) | |
| } | |
| if (row.status === Status.PreVerify || row.status === Status.AdminVerify) { | |
| actions.push(h( | |
| NButton, | |
| { | |
| size: 'small', | |
| type: 'info', | |
| onClick: () => handleUpdateUserStatus(row._id, Status.Normal), | |
| }, | |
| { default: () => t('chat.verifiedUser') }, | |
| )) | |
| } | |
| return actions | |
| }, | |
| }, | |
| ] | |
| const pagination = reactive ({ | |
| page: 1, | |
| pageSize: 25, | |
| pageCount: 1, | |
| itemCount: 1, | |
| prefix({ itemCount }: { itemCount: number | undefined }) { | |
| return `Total is ${itemCount}.` | |
| }, | |
| showSizePicker: true, | |
| pageSizes: [25, 50, 100], | |
| onChange: (page: number) => { | |
| pagination.page = page | |
| handleGetUsers(pagination.page) | |
| }, | |
| onUpdatePageSize: (pageSize: number) => { | |
| pagination.pageSize = pageSize | |
| pagination.page = 1 | |
| handleGetUsers(pagination.page) | |
| }, | |
| }) | |
| async function handleGetUsers(page: number) { | |
| if (loading.value) | |
| return | |
| users.value.length = 0 | |
| loading.value = true | |
| const size = pagination.pageSize | |
| const data = (await fetchGetUsers(page, size)).data | |
| data.users.forEach((user: never) => { | |
| users.value.push(user) | |
| }) | |
| pagination.page = page | |
| pagination.pageCount = data.total / size + (data.total % size === 0 ? 0 : 1) | |
| pagination.itemCount = data.total | |
| loading.value = false | |
| } | |
| async function handleUpdateUserStatus(userId: string, status: Status) { | |
| if (status === Status.Deleted) { | |
| dialog.warning({ | |
| title: t('chat.deleteUser'), | |
| content: t('chat.deleteUserConfirm'), | |
| positiveText: t('common.yes'), | |
| negativeText: t('common.no'), | |
| onPositiveClick: async () => { | |
| await fetchUpdateUserStatus(userId, status) | |
| ms.info('OK') | |
| await handleGetUsers(pagination.page) | |
| }, | |
| }) | |
| } | |
| else { | |
| await fetchUpdateUserStatus(userId, status) | |
| ms.info('OK') | |
| await handleGetUsers(pagination.page) | |
| } | |
| } | |
| function handleEditUser(user: UserInfo) { | |
| userRef.value = user | |
| show.value = true | |
| } | |
| async function handleUpdateUserRoles() { | |
| if (!userRef.value._id) { | |
| ms.error('User Error') | |
| return | |
| } | |
| handleSaving.value = true | |
| try { | |
| await fetchUpdateUserRole(userRef.value._id, userRef.value.roles) | |
| await handleGetUsers(pagination.page) | |
| show.value = false | |
| } | |
| catch (error: any) { | |
| ms.error(error.message) | |
| } | |
| handleSaving.value = false | |
| } | |
| onMounted(async () => { | |
| await handleGetUsers(pagination.page) | |
| }) | |
| </script> | |
| <template> | |
| <div class="p-4 space-y-5 min-h-[200px]"> | |
| <div class="space-y-6"> | |
| <NDataTable | |
| ref="table" | |
| remote | |
| :loading="loading" | |
| :row-key="(rowData) => rowData._id" | |
| :columns="columns" | |
| :data="users" | |
| :pagination="pagination" | |
| :max-height="444" | |
| striped | |
| :scroll-x="1260" | |
| @update:page="handleGetUsers" | |
| /> | |
| </div> | |
| </div> | |
| <NModal v-model:show="show" :auto-focus="false" preset="card" style="width:50%;"> | |
| <div class="p-4 space-y-5 min-h-[200px]"> | |
| <div class="space-y-6"> | |
| <div class="flex items-center space-x-4"> | |
| <span class="flex-shrink-0 w-[100px]">{{ $t('setting.userRoles') }}</span> | |
| <div class="flex-1"> | |
| <NSelect | |
| style="width: 100%" | |
| multiple | |
| :value="userRef.roles" | |
| :options="userRoleOptions" | |
| @update-value="value => userRef.roles = value" | |
| /> | |
| </div> | |
| </div> | |
| <div class="flex items-center space-x-4"> | |
| <span class="flex-shrink-0 w-[100px]" /> | |
| <NButton type="primary" :loading="handleSaving" @click="handleUpdateUserRoles()"> | |
| {{ $t('common.save') }} | |
| </NButton> | |
| </div> | |
| </div> | |
| </div> | |
| </NModal> | |
| </template> | |