Browse Source

feat(users): 增加用户锁定

pull/1051/head
colin 1 year ago
parent
commit
a6aef1f101
  1. 17
      apps/vben5/packages/@abp/identity/src/api/users.ts
  2. 117
      apps/vben5/packages/@abp/identity/src/components/users/UserLockModal.vue
  3. 65
      apps/vben5/packages/@abp/identity/src/components/users/UserTable.vue

17
apps/vben5/packages/@abp/identity/src/api/users.ts

@ -78,3 +78,20 @@ export function removeOrganizationUnit(
`/api/identity/users/${id}/organization-units/${ouId}`,
);
}
/**
*
* @param id id
* @param seconds ()
*/
export function lockApi(id: string, seconds: number): Promise<void> {
return requestClient.put(`/api/identity/users/${id}/lock/${seconds}`);
}
/**
*
* @param id id
*/
export function unLockApi(id: string): Promise<void> {
return requestClient.put(`/api/identity/users/${id}/unlock`);
}

117
apps/vben5/packages/@abp/identity/src/components/users/UserLockModal.vue

@ -0,0 +1,117 @@
<!-- eslint-disable no-unused-vars -->
<script setup lang="ts">
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { useVbenForm } from '@abp/ui';
import { lockApi } from '../../api/users';
defineOptions({
name: 'UserLockModal',
});
const emits = defineEmits<{
(event: 'change'): void;
}>();
enum LockType {
Days = 86_400,
Hours = 3600,
Minutes = 60,
Months = 2_678_400, // 31
Seconds = 1,
Years = 32_140_800, // 31*12
}
const [Form, formApi] = useVbenForm({
commonConfig: {
//
componentProps: {
class: 'w-full',
},
},
handleSubmit: onSubmit,
schema: [
{
component: 'Input',
componentProps: {
style: {
display: 'none',
},
},
fieldName: 'userId',
},
{
component: 'InputNumber',
fieldName: 'seconds',
label: $t('AbpIdentity.LockTime'),
rules: 'required',
},
{
component: 'Select',
componentProps: {
options: [
// TODO:
{ label: $t('LockType:Seconds'), value: LockType.Seconds },
{ label: $t('LockType:Minutes'), value: LockType.Minutes },
{ label: $t('LockType:Hours'), value: LockType.Hours },
{ label: $t('LockType:Days'), value: LockType.Days },
{ label: $t('LockType:Months'), value: LockType.Months },
{ label: $t('LockType:Years'), value: LockType.Years },
],
},
defaultValue: LockType.Seconds,
fieldName: 'type',
label: $t('AbpIdentity.LockType'),
rules: 'required',
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
closeOnClickModal: false,
closeOnPressEscape: false,
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
onConfirm: async () => {
await formApi.validateAndSubmitForm();
},
async onOpenChange(isOpen: boolean) {
if (isOpen) {
const { id } = modalApi.getData<Record<string, any>>();
formApi.setValues({
userId: id,
});
}
},
title: $t('AbpIdentity.Lock'),
});
async function onSubmit(input: Record<string, any>) {
try {
modalApi.setState({
confirmLoading: true,
});
const lockSeconds = input.type * input.seconds;
await lockApi(input.userId, lockSeconds);
emits('change');
modalApi.close();
} finally {
modalApi.setState({
confirmLoading: false,
});
}
}
</script>
<template>
<Modal>
<Form />
</Modal>
</template>
<style scoped></style>

65
apps/vben5/packages/@abp/identity/src/components/users/UserTable.vue

@ -4,7 +4,7 @@ import type { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import type { IdentityUserDto } from '../../types/users';
import { defineAsyncComponent, h } from 'vue';
import { computed, defineAsyncComponent, h } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal } from '@vben/common-ui';
@ -18,10 +18,12 @@ import {
DeleteOutlined,
EditOutlined,
EllipsisOutlined,
LockOutlined,
UnlockOutlined,
} from '@ant-design/icons-vue';
import { Button, Dropdown, Menu, Modal } from 'ant-design-vue';
import { deleteApi, getPagedListApi } from '../../api/users';
import { deleteApi, getPagedListApi, unLockApi } from '../../api/users';
import { IdentityUserPermissions } from '../../constants/permissions';
defineOptions({
@ -29,6 +31,7 @@ defineOptions({
});
const UserModal = defineAsyncComponent(() => import('./UserModal.vue'));
const LockModal = defineAsyncComponent(() => import('./UserLockModal.vue'));
const MenuItem = Menu.Item;
const CheckIcon = createIconifyIcon('ant-design:check-outlined');
@ -36,8 +39,19 @@ const CloseIcon = createIconifyIcon('ant-design:close-outlined');
const MenuOutlined = createIconifyIcon('heroicons-outline:menu-alt-3');
const ClaimOutlined = createIconifyIcon('la:id-card-solid');
const PermissionsOutlined = createIconifyIcon('icon-park-outline:permissions');
const [UserPermissionModal, permissionModalApi] = useVbenModal({
connectedComponent: PermissionModal,
const getLockEnd = computed(() => {
return (row: IdentityUserDto) => {
if (row.lockoutEnd) {
const lockTime = new Date(row.lockoutEnd);
if (lockTime) {
//
const nowTime = new Date();
return lockTime < nowTime;
}
}
return true;
};
});
const abpStore = useAbpStore();
@ -127,6 +141,12 @@ const gridEvents: VxeGridListeners<IdentityUserDto> = {
const [UserEditModal, userModalApi] = useVbenModal({
connectedComponent: UserModal,
});
const [UserLockModal, lockModalApi] = useVbenModal({
connectedComponent: LockModal,
});
const [UserPermissionModal, permissionModalApi] = useVbenModal({
connectedComponent: PermissionModal,
});
const [Grid, { query }] = useVbenVxeGrid({
formOptions,
gridEvents,
@ -156,8 +176,18 @@ const handleDelete = (row: IdentityUserDto) => {
});
};
const handleUnlock = async (row: IdentityUserDto) => {
await unLockApi(row.id);
await query();
};
const handleMenuClick = async (row: IdentityUserDto, info: MenuInfo) => {
switch (info.key) {
case 'lock': {
lockModalApi.setData(row);
lockModalApi.open();
break;
}
case 'permissions': {
const userId = abpStore.application?.currentUser.id;
permissionModalApi.setData({
@ -169,6 +199,10 @@ const handleMenuClick = async (row: IdentityUserDto, info: MenuInfo) => {
permissionModalApi.open();
break;
}
case 'unlock': {
handleUnlock(row);
break;
}
}
};
</script>
@ -221,6 +255,28 @@ const handleMenuClick = async (row: IdentityUserDto, info: MenuInfo) => {
<Dropdown>
<template #overlay>
<Menu @click="(info) => handleMenuClick(row, info)">
<MenuItem
v-if="
hasAccessByCodes([IdentityUserPermissions.Update]) &&
row.isActive &&
getLockEnd(row)
"
key="lock"
:icon="h(LockOutlined)"
>
{{ $t('AbpIdentity.Lock') }}
</MenuItem>
<MenuItem
v-if="
hasAccessByCodes([IdentityUserPermissions.Update]) &&
row.isActive &&
!getLockEnd(row)
"
key="unlock"
:icon="h(UnlockOutlined)"
>
{{ $t('AbpIdentity.UnLock') }}
</MenuItem>
<MenuItem
v-if="
hasAccessByCodes([
@ -256,6 +312,7 @@ const handleMenuClick = async (row: IdentityUserDto, info: MenuInfo) => {
</div>
</template>
</Grid>
<UserLockModal @change="query" />
<UserEditModal @change="() => query()" />
<UserPermissionModal />
</template>

Loading…
Cancel
Save