Browse Source

feat: 增加实体变更记录.

pull/1080/head
colin 1 year ago
parent
commit
ac3ed868f4
  1. 2
      apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireFeaturesSimpleStateChecker.ts
  2. 44
      apps/vben5/packages/@abp/core/src/hooks/useFeatures.ts
  3. 7
      apps/vben5/packages/@abp/core/src/hooks/useGlobalFeatures.ts
  4. 50
      apps/vben5/packages/@abp/core/src/hooks/useSettings.ts
  5. 6
      apps/vben5/packages/@abp/core/src/hooks/useSimpleStateCheck.ts
  6. 6
      apps/vben5/packages/@abp/core/src/hooks/useValidation.ts
  7. 6
      apps/vben5/packages/@abp/identity/src/components/claim-types/ClaimTypeTable.vue
  8. 9
      apps/vben5/packages/@abp/identity/src/components/roles/RoleTable.vue
  9. 8
      apps/vben5/packages/@abp/identity/src/components/users/UserTable.vue
  10. 1
      apps/vben5/packages/@abp/openiddict/package.json
  11. 31
      apps/vben5/packages/@abp/openiddict/src/components/applications/ApplicationTable.vue
  12. 89
      apps/vben5/packages/@abp/openiddict/src/components/scopes/ScopeTable.vue

2
apps/vben5/packages/@abp/core/src/hooks/SimpleStateChecking/useRequireFeaturesSimpleStateChecker.ts

@ -50,7 +50,7 @@ export function useRequireFeaturesSimpleStateChecker<
featureNames: string[],
requiresAll: boolean = false,
): ISimpleStateChecker<TState> {
const { featureChecker } = useFeatures();
const featureChecker = useFeatures();
return new RequireFeaturesSimpleStateChecker(
featureChecker,
featureNames,

44
apps/vben5/packages/@abp/core/src/hooks/useFeatures.ts

@ -1,24 +1,40 @@
import type { FeatureValue, IFeatureChecker } from '../types/features';
import { computed } from 'vue';
import { ref, watch } from 'vue';
import { useAbpStore } from '../store/abp';
export function useFeatures() {
export function useFeatures(): IFeatureChecker {
const abpStore = useAbpStore();
const getFeatures = computed(() => {
const fetures = abpStore.application?.features.values ?? {};
const fetureValues = Object.keys(fetures).map((key): FeatureValue => {
return {
name: key,
value: fetures[key] ?? '',
};
});
return fetureValues;
});
const features = ref<FeatureValue[]>([]);
watch(
() => abpStore.application,
(application) => {
if (!application?.features.values) {
features.value = [];
return;
}
const featuresSet: FeatureValue[] = [];
Object.keys(application.features.values).forEach((name) => {
if (application.features.values[name]) {
featuresSet.push({
name,
value: application.features.values[name],
});
}
});
features.value = featuresSet;
},
{
deep: true,
immediate: true,
},
);
function get(name: string): FeatureValue | undefined {
return getFeatures.value.find((feature) => name === feature.name);
return features.value.find((feature) => name === feature.name);
}
function _isEnabled(name: string): boolean {
@ -52,5 +68,5 @@ export function useFeatures() {
},
};
return { featureChecker };
return featureChecker;
}

7
apps/vben5/packages/@abp/core/src/hooks/useGlobalFeatures.ts

@ -4,10 +4,13 @@ import { useAbpStore } from '../store/abp';
import { isNullOrWhiteSpace } from '../utils/string';
export function useGlobalFeatures() {
const abpStore = useAbpStore();
const getGlobalFeatures = computed(() => {
const abpStore = useAbpStore();
if (!abpStore.application) {
return [];
}
const enabledFeatures =
abpStore.application?.globalFeatures.enabledFeatures ?? [];
abpStore.application.globalFeatures.enabledFeatures ?? [];
return enabledFeatures;
});

50
apps/vben5/packages/@abp/core/src/hooks/useSettings.ts

@ -1,37 +1,47 @@
import type { ISettingProvider, SettingValue } from '../types/settings';
import { computed } from 'vue';
import { ref, watch } from 'vue';
import { useAbpStore } from '../store';
export function useSettings(): ISettingProvider {
const abpStore = useAbpStore();
const getSettings = computed(() => {
if (!abpStore.application) {
return [];
}
const { values: settings } = abpStore.application.setting;
const settingValues = Object.keys(settings).map((key): SettingValue => {
return {
name: key,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
value: settings[key]!,
};
});
return settingValues;
});
const settings = ref<SettingValue[]>([]);
watch(
() => abpStore.application,
(application) => {
if (!application?.setting.values) {
settings.value = [];
return;
}
const settingsSet: SettingValue[] = [];
Object.keys(application.setting.values).forEach((name) => {
if (application.setting.values[name]) {
settingsSet.push({
name,
value: application.setting.values[name],
});
}
});
settings.value = settingsSet;
},
{
deep: true,
immediate: true,
},
);
function get(name: string): SettingValue | undefined {
return getSettings.value.find((setting) => name === setting.name);
return settings.value.find((setting) => name === setting.name);
}
function getAll(...names: string[]): SettingValue[] {
if (names) {
return getSettings.value.filter((setting) =>
names.includes(setting.name),
);
return settings.value.filter((setting) => names.includes(setting.name));
}
return getSettings.value;
return settings.value;
}
function getOrDefault<T>(name: string, defaultValue: T): string | T {

6
apps/vben5/packages/@abp/core/src/hooks/useSimpleStateCheck.ts

@ -128,8 +128,6 @@ class SimpleStateCheckerSerializer implements ISimpleStateCheckerSerializer {
export function useSimpleStateCheck<
TState extends IHasSimpleStateCheckers<TState>,
>() {
return {
serializer: new SimpleStateCheckerSerializer(),
};
>(): ISimpleStateCheckerSerializer {
return new SimpleStateCheckerSerializer();
}

6
apps/vben5/packages/@abp/core/src/hooks/useValidation.ts

@ -17,7 +17,7 @@ import { ValidationEnum } from '../constants';
import { isEmail, isPhone } from '../utils/regex';
import { useLocalization } from './useLocalization';
export function useValidation() {
export function useValidation(): RuleCreator {
const { L } = useLocalization(['AbpValidation']);
function _getFieldName(field: Field) {
return __getFieldName(
@ -399,7 +399,5 @@ export function useValidation() {
},
};
return {
ruleCreator,
};
return ruleCreator;
}

6
apps/vben5/packages/@abp/identity/src/components/claim-types/ClaimTypeTable.vue

@ -12,6 +12,7 @@ import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing';
import { useFeatures } from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import {
DeleteOutlined,
@ -36,6 +37,7 @@ const CheckIcon = createIconifyIcon('ant-design:check-outlined');
const CloseIcon = createIconifyIcon('ant-design:close-outlined');
const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit');
const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess();
const { cancel, deleteApi, getPagedListApi } = useClaimTypesApi();
@ -194,7 +196,7 @@ const onMenuClick = (row: IdentityClaimTypeDto, info: MenuInfo) => {
case 'entity-changes': {
roleChangeDrawerApi.setData({
entityId: row.id,
entityTypeFullName: 'Volo.Abp.Identity.IdentityRole',
entityTypeFullName: 'Volo.Abp.Identity.IdentityClaimType',
subject: row.name,
});
roleChangeDrawerApi.open();
@ -249,7 +251,7 @@ const onMenuClick = (row: IdentityClaimTypeDto, info: MenuInfo) => {
>
{{ $t('AbpUi.Delete') }}
</Button>
<Dropdown>
<Dropdown v-if="isEnabled('AbpAuditing.Logging.AuditLog')">
<template #overlay>
<Menu @click="(info) => onMenuClick(row, info)">
<MenuItem

9
apps/vben5/packages/@abp/identity/src/components/roles/RoleTable.vue

@ -12,7 +12,7 @@ import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing';
import { useAbpStore } from '@abp/core';
import { useAbpStore, useFeatures } from '@abp/core';
import { PermissionModal } from '@abp/permissions';
import { useVbenVxeGrid } from '@abp/ui';
import {
@ -37,7 +37,9 @@ const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit');
const RoleModal = defineAsyncComponent(() => import('./RoleModal.vue'));
const ClaimModal = defineAsyncComponent(() => import('./RoleClaimModal.vue'));
const abpStore = useAbpStore();
const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess();
const { cancel, deleteApi, getPagedListApi } = useRolesApi();
@ -251,7 +253,10 @@ const handleMenuClick = async (row: IdentityRoleDto, info: MenuInfo) => {
{{ $t('AppPlatform.Menu:Manage') }}
</MenuItem>
<MenuItem
v-if="hasAccessByCodes([AuditLogPermissions.Default])"
v-if="
isEnabled('AbpAuditing.Logging.AuditLog') &&
hasAccessByCodes([AuditLogPermissions.Default])
"
key="entity-changes"
:icon="h(AuditLogIcon)"
>

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

@ -12,7 +12,7 @@ import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing';
import { formatToDateTime, useAbpStore } from '@abp/core';
import { formatToDateTime, useAbpStore, useFeatures } from '@abp/core';
import { PermissionModal } from '@abp/permissions';
import { useVbenVxeGrid } from '@abp/ui';
import {
@ -63,6 +63,7 @@ const getLockEnd = computed(() => {
});
const abpStore = useAbpStore();
const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess();
const { cancel, deleteApi, getPagedListApi, unLockApi } = useUsersApi();
@ -353,7 +354,10 @@ const handleMenuClick = async (row: IdentityUserDto, info: MenuInfo) => {
{{ $t('AppPlatform.Menu:Manage') }}
</MenuItem>
<MenuItem
v-if="hasAccessByCodes([AuditLogPermissions.Default])"
v-if="
isEnabled('AbpAuditing.Logging.AuditLog') &&
hasAccessByCodes([AuditLogPermissions.Default])
"
key="entity-changes"
:icon="h(AuditLogIcon)"
>

1
apps/vben5/packages/@abp/openiddict/package.json

@ -20,6 +20,7 @@
}
},
"dependencies": {
"@abp/auditing": "workspace:*",
"@abp/core": "workspace:*",
"@abp/identity": "workspace:*",
"@abp/permissions": "workspace:*",

31
apps/vben5/packages/@abp/openiddict/src/components/applications/ApplicationTable.vue

@ -7,10 +7,12 @@ import type { OpenIddictApplicationDto } from '../../types/applications';
import { defineAsyncComponent, h } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal } from '@vben/common-ui';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing';
import { useFeatures } from '@abp/core';
import { PermissionModal } from '@abp/permissions';
import { useVbenVxeGrid } from '@abp/ui';
import {
@ -29,11 +31,14 @@ defineOptions({
});
const MenuItem = Menu.Item;
const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit');
const CheckIcon = createIconifyIcon('ant-design:check-outlined');
const CloseIcon = createIconifyIcon('ant-design:close-outlined');
const SecretIcon = createIconifyIcon('codicon:gist-secret');
const PermissionsOutlined = createIconifyIcon('icon-park-outline:permissions');
const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess();
const { deleteApi, getPagedListApi } = useApplicationsApi();
@ -148,6 +153,9 @@ const [ApplicationSecretModal, secretModalApi] = useVbenModal({
const [ApplicationPermissionModal, permissionModalApi] = useVbenModal({
connectedComponent: PermissionModal,
});
const [ApplicationChangeDrawer, applicationChangeDrawerApi] = useVbenDrawer({
connectedComponent: EntityChangeDrawer,
});
const [Grid, { query }] = useVbenVxeGrid({
formOptions,
@ -179,6 +187,16 @@ const onDelete = (row: OpenIddictApplicationDto) => {
const onMenuClick = (row: OpenIddictApplicationDto, info: MenuInfo) => {
switch (info.key) {
case 'entity-changes': {
applicationChangeDrawerApi.setData({
entityId: row.id,
entityTypeFullName:
'Volo.Abp.OpenIddict.Applications.OpenIddictApplication',
subject: row.clientId,
});
applicationChangeDrawerApi.open();
break;
}
case 'permissions': {
permissionModalApi.setData({
displayName: row.clientId,
@ -271,6 +289,16 @@ const onMenuClick = (row: OpenIddictApplicationDto, info: MenuInfo) => {
>
{{ $t('AbpOpenIddict.ManagePermissions') }}
</MenuItem>
<MenuItem
v-if="
isEnabled('AbpAuditing.Logging.AuditLog') &&
hasAccessByCodes([AuditLogPermissions.Default])
"
key="entity-changes"
:icon="h(AuditLogIcon)"
>
{{ $t('AbpAuditLogging.EntitiesChanged') }}
</MenuItem>
</Menu>
</template>
<Button :icon="h(EllipsisOutlined)" type="link" />
@ -282,6 +310,7 @@ const onMenuClick = (row: OpenIddictApplicationDto, info: MenuInfo) => {
<ApplicationModal @change="() => query()" />
<ApplicationSecretModal @change="() => query()" />
<ApplicationPermissionModal />
<ApplicationChangeDrawer />
</template>
<style lang="scss" scoped></style>

89
apps/vben5/packages/@abp/openiddict/src/components/scopes/ScopeTable.vue

@ -1,22 +1,26 @@
<script setup lang="ts">
import type { VbenFormProps, VxeGridProps } from '@abp/ui';
import type { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import type { OpenIddictScopeDto } from '../../types/scopes';
import { defineAsyncComponent, h } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { useAccess } from '@vben/access';
import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { formatToDateTime } from '@abp/core';
import { AuditLogPermissions, EntityChangeDrawer } from '@abp/auditing';
import { formatToDateTime, useFeatures } from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import {
DeleteOutlined,
EditOutlined,
EllipsisOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import { Button, message, Modal } from 'ant-design-vue';
import { Button, Dropdown, Menu, message, Modal } from 'ant-design-vue';
import { useScopesApi } from '../../api/useScopesApi';
import { ScopesPermissions } from '../../constants/permissions';
@ -25,9 +29,14 @@ defineOptions({
name: 'ScopeTable',
});
const MenuItem = Menu.Item;
const AuditLogIcon = createIconifyIcon('fluent-mdl2:compliance-audit');
const CheckIcon = createIconifyIcon('ant-design:check-outlined');
const CloseIcon = createIconifyIcon('ant-design:close-outlined');
const { isEnabled } = useFeatures();
const { hasAccessByCodes } = useAccess();
const { deleteApi, getPagedListApi } = useScopesApi();
const formOptions: VbenFormProps = {
@ -109,9 +118,13 @@ const gridOptions: VxeGridProps<OpenIddictScopeDto> = {
zoom: true,
},
};
const [ScopeModal, modalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(() => import('./ScopeModal.vue')),
});
const [ScopeChangeDrawer, scopeChangeDrawerApi] = useVbenDrawer({
connectedComponent: EntityChangeDrawer,
});
const [Grid, { query }] = useVbenVxeGrid({
formOptions,
gridOptions,
@ -139,6 +152,19 @@ const onDelete = (row: OpenIddictScopeDto) => {
title: $t('AbpUi.AreYouSure'),
});
};
const onMenuClick = (row: OpenIddictScopeDto, info: MenuInfo) => {
switch (info.key) {
case 'entity-changes': {
scopeChangeDrawerApi.setData({
entityId: row.id,
entityTypeFullName: 'Volo.Abp.OpenIddict.Scopes.OpenIddictScope',
subject: row.name,
});
scopeChangeDrawerApi.open();
break;
}
}
};
</script>
<template>
@ -167,33 +193,44 @@ const onDelete = (row: OpenIddictScopeDto) => {
</template>
<template #action="{ row }">
<div class="flex flex-row">
<div class="basis-1/3">
<Button
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[ScopesPermissions.Update]"
@click="onUpdate(row)"
>
{{ $t('AbpUi.Edit') }}
</Button>
</div>
<div class="basis-1/3">
<Button
:icon="h(DeleteOutlined)"
block
danger
type="link"
v-access:code="[ScopesPermissions.Delete]"
@click="onDelete(row)"
>
{{ $t('AbpUi.Delete') }}
</Button>
</div>
<Button
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[ScopesPermissions.Update]"
@click="onUpdate(row)"
>
{{ $t('AbpUi.Edit') }}
</Button>
<Button
:icon="h(DeleteOutlined)"
block
danger
type="link"
v-access:code="[ScopesPermissions.Delete]"
@click="onDelete(row)"
>
{{ $t('AbpUi.Delete') }}
</Button>
<Dropdown v-if="isEnabled('AbpAuditing.Logging.AuditLog')">
<template #overlay>
<Menu @click="(info) => onMenuClick(row, info)">
<MenuItem
v-if="hasAccessByCodes([AuditLogPermissions.Default])"
key="entity-changes"
:icon="h(AuditLogIcon)"
>
{{ $t('AbpAuditLogging.EntitiesChanged') }}
</MenuItem>
</Menu>
</template>
<Button :icon="h(EllipsisOutlined)" type="link" />
</Dropdown>
</div>
</template>
</Grid>
<ScopeModal @change="() => query()" />
<ScopeChangeDrawer />
</template>
<style lang="scss" scoped></style>

Loading…
Cancel
Save