Browse Source

Merge pull request #1138 from colinin/vben5-notifications

Vben5 notifications
pull/1149/head
yx lin 1 year ago
committed by GitHub
parent
commit
4ab41a4336
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json
  2. 4
      apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json
  3. 20
      apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts
  4. 15
      apps/vben5/apps/app-antd/src/views/notifications/definitions/index.vue
  5. 15
      apps/vben5/apps/app-antd/src/views/notifications/groups/index.vue
  6. 3
      apps/vben5/packages/@abp/notifications/package.json
  7. 2
      apps/vben5/packages/@abp/notifications/src/api/index.ts
  8. 100
      apps/vben5/packages/@abp/notifications/src/api/useNotificationDefinitionsApi.ts
  9. 100
      apps/vben5/packages/@abp/notifications/src/api/useNotificationGroupDefinitionsApi.ts
  10. 16
      apps/vben5/packages/@abp/notifications/src/api/useNotificationsApi.ts
  11. 172
      apps/vben5/packages/@abp/notifications/src/components/definitions/groups/NotificationGroupDefinitionModal.vue
  12. 262
      apps/vben5/packages/@abp/notifications/src/components/definitions/groups/NotificationGroupDefinitionTable.vue
  13. 311
      apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationDefinitionModal.vue
  14. 418
      apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationDefinitionTable.vue
  15. 143
      apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationSendModal.vue
  16. 123
      apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/useEnumMaps.ts
  17. 2
      apps/vben5/packages/@abp/notifications/src/components/index.ts
  18. 28
      apps/vben5/packages/@abp/notifications/src/constants/permissions.ts
  19. 12
      apps/vben5/packages/@abp/notifications/src/hooks/useNotifications.ts
  20. 66
      apps/vben5/packages/@abp/notifications/src/types/definitions.ts
  21. 35
      apps/vben5/packages/@abp/notifications/src/types/groups.ts
  22. 1
      apps/vben5/packages/@abp/notifications/src/types/index.ts

4
apps/vben5/apps/app-antd/src/locales/langs/en-US/abp.json

@ -42,7 +42,9 @@
},
"notifications": {
"title": "Notifications",
"myNotifilers": "My Notifilers"
"myNotifilers": "My Notifilers",
"groups": "Groups",
"definitions": "Definitions"
}
},
"openiddict": {

4
apps/vben5/apps/app-antd/src/locales/langs/zh-CN/abp.json

@ -42,7 +42,9 @@
},
"notifications": {
"title": "通知管理",
"myNotifilers": "我的通知"
"myNotifilers": "我的通知",
"groups": "通知分组",
"definitions": "通知定义"
}
},
"openiddict": {

20
apps/vben5/apps/app-antd/src/router/routes/modules/abp.ts

@ -202,6 +202,26 @@ const routes: RouteRecordRaw[] = [
component: () =>
import('#/views/notifications/my-notifilers/index.vue'),
},
{
meta: {
title: $t('abp.manage.notifications.groups'),
icon: 'lucide:group',
},
name: 'NotificationGroupDefinitions',
path: '/manage/notifications/groups',
component: () =>
import('#/views/notifications/groups/index.vue'),
},
{
meta: {
title: $t('abp.manage.notifications.definitions'),
icon: 'nimbus:notification',
},
name: 'NotificationDefinitions',
path: '/manage/notifications/definitions',
component: () =>
import('#/views/notifications/definitions/index.vue'),
},
],
},
],

15
apps/vben5/apps/app-antd/src/views/notifications/definitions/index.vue

@ -0,0 +1,15 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import { NotificationDefinitionTable } from '@abp/notifications';
defineOptions({
name: 'NotificationDefinitions',
});
</script>
<template>
<Page>
<NotificationDefinitionTable />
</Page>
</template>

15
apps/vben5/apps/app-antd/src/views/notifications/groups/index.vue

@ -0,0 +1,15 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import { NotificationGroupDefinitionTable } from '@abp/notifications';
defineOptions({
name: 'NotificationGroupDefinitions',
});
</script>
<template>
<Page>
<NotificationGroupDefinitionTable />
</Page>
</template>

3
apps/vben5/packages/@abp/notifications/package.json

@ -34,6 +34,7 @@
"@vben/locales": "workspace:*",
"ant-design-vue": "catalog:",
"dayjs": "catalog:",
"vue": "catalog:*"
"vue": "catalog:*",
"vxe-table": "catalog:"
}
}

2
apps/vben5/packages/@abp/notifications/src/api/index.ts

@ -1,3 +1,5 @@
export { useMyNotifilersApi } from './useMyNotifilersApi';
export { useMySubscribesApi } from './useMySubscribesApi';
export { useNotificationDefinitionsApi } from './useNotificationDefinitionsApi';
export { useNotificationGroupDefinitionsApi } from './useNotificationGroupDefinitionsApi';
export { useNotificationsApi } from './useNotificationsApi';

100
apps/vben5/packages/@abp/notifications/src/api/useNotificationDefinitionsApi.ts

@ -0,0 +1,100 @@
import type { ListResultDto } from '@abp/core';
import type {
NotificationDefinitionCreateDto,
NotificationDefinitionDto,
NotificationDefinitionGetListInput,
NotificationDefinitionUpdateDto,
} from '../types/definitions';
import { useRequest } from '@abp/request';
export function useNotificationDefinitionsApi() {
const { cancel, request } = useRequest();
/**
*
* @param name
*/
function deleteApi(name: string): Promise<void> {
return request(`/api/notifications/definitions/notifications/${name}`, {
method: 'DELETE',
});
}
/**
*
* @param name
* @returns
*/
function getApi(name: string): Promise<NotificationDefinitionDto> {
return request<NotificationDefinitionDto>(
`/api/notifications/definitions/notifications/${name}`,
{
method: 'GET',
},
);
}
/**
*
* @param input
* @returns
*/
function getListApi(
input?: NotificationDefinitionGetListInput,
): Promise<ListResultDto<NotificationDefinitionDto>> {
return request<ListResultDto<NotificationDefinitionDto>>(
`/api/notifications/definitions/notifications`,
{
method: 'GET',
params: input,
},
);
}
/**
*
* @param input
* @returns
*/
function createApi(
input: NotificationDefinitionCreateDto,
): Promise<NotificationDefinitionDto> {
return request<NotificationDefinitionDto>(
'/api/notifications/definitions/notifications',
{
data: input,
method: 'POST',
},
);
}
/**
*
* @param name
* @param input
* @returns
*/
function updateApi(
name: string,
input: NotificationDefinitionUpdateDto,
): Promise<NotificationDefinitionDto> {
return request<NotificationDefinitionDto>(
`/api/notifications/definitions/notifications/${name}`,
{
data: input,
method: 'PUT',
},
);
}
return {
cancel,
createApi,
deleteApi,
getApi,
getListApi,
updateApi,
};
}

100
apps/vben5/packages/@abp/notifications/src/api/useNotificationGroupDefinitionsApi.ts

@ -0,0 +1,100 @@
import type { ListResultDto } from '@abp/core';
import type {
NotificationGroupDefinitionCreateDto,
NotificationGroupDefinitionDto,
NotificationGroupDefinitionGetListInput,
NotificationGroupDefinitionUpdateDto,
} from '../types';
import { useRequest } from '@abp/request';
export function useNotificationGroupDefinitionsApi() {
const { cancel, request } = useRequest();
/**
*
* @param name
*/
function deleteApi(name: string): Promise<void> {
return request(`/api/notifications/definitions/groups/${name}`, {
method: 'DELETE',
});
}
/**
*
* @param name
* @returns
*/
function getApi(name: string): Promise<NotificationGroupDefinitionDto> {
return request<NotificationGroupDefinitionDto>(
`/api/notifications/definitions/groups/${name}`,
{
method: 'GET',
},
);
}
/**
*
* @param input
* @returns
*/
function getListApi(
input?: NotificationGroupDefinitionGetListInput,
): Promise<ListResultDto<NotificationGroupDefinitionDto>> {
return request<ListResultDto<NotificationGroupDefinitionDto>>(
`/api/notifications/definitions/groups`,
{
method: 'GET',
params: input,
},
);
}
/**
*
* @param input
* @returns
*/
function createApi(
input: NotificationGroupDefinitionCreateDto,
): Promise<NotificationGroupDefinitionDto> {
return request<NotificationGroupDefinitionDto>(
'/api/notifications/definitions/groups',
{
data: input,
method: 'POST',
},
);
}
/**
*
* @param name
* @param input
* @returns
*/
function updateApi(
name: string,
input: NotificationGroupDefinitionUpdateDto,
): Promise<NotificationGroupDefinitionDto> {
return request<NotificationGroupDefinitionDto>(
`/api/notifications/definitions/groups/${name}`,
{
data: input,
method: 'PUT',
},
);
}
return {
cancel,
createApi,
deleteApi,
getApi,
getListApi,
updateApi,
};
}

16
apps/vben5/packages/@abp/notifications/src/api/useNotificationsApi.ts

@ -2,6 +2,7 @@ import type { ListResultDto } from '@abp/core';
import type {
NotificationGroupDto,
NotificationProviderDto,
NotificationTemplateDto,
} from '../types/definitions';
import type {
@ -13,6 +14,20 @@ import { useRequest } from '@abp/request';
export function useNotificationsApi() {
const { cancel, request } = useRequest();
/**
*
* @returns {Promise<ListResultDto<NotificationProviderDto>>}
*/
function getAssignableProvidersApi(): Promise<
ListResultDto<NotificationProviderDto>
> {
return request<ListResultDto<NotificationProviderDto>>(
'/api/notifications/assignable-providers',
{
method: 'GET',
},
);
}
/**
*
* @returns {Promise<ListResultDto<NotificationGroupDto>>}
@ -69,6 +84,7 @@ export function useNotificationsApi() {
return {
cancel,
getAssignableNotifiersApi,
getAssignableProvidersApi,
getAssignableTemplatesApi,
sendNotiferApi,
sendTemplateNotiferApi,

172
apps/vben5/packages/@abp/notifications/src/components/definitions/groups/NotificationGroupDefinitionModal.vue

@ -0,0 +1,172 @@
<script setup lang="ts">
import type { PropertyInfo } from '@abp/ui';
import type { FormInstance } from 'ant-design-vue';
import type { NotificationGroupDefinitionDto } from '../../../types/groups';
import { defineEmits, defineOptions, ref, toValue, useTemplateRef } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { LocalizableInput, PropertyTable } from '@abp/ui';
import { Checkbox, Form, Input, message, Tabs } from 'ant-design-vue';
import { useNotificationGroupDefinitionsApi } from '../../../api/useNotificationGroupDefinitionsApi';
defineOptions({
name: 'NotificationGroupDefinitionModal',
});
const emits = defineEmits<{
(event: 'change', data: NotificationGroupDefinitionDto): void;
}>();
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
type TabKeys = 'basic' | 'props';
const defaultModel = {} as NotificationGroupDefinitionDto;
const isEditModel = ref(false);
const activeTab = ref<TabKeys>('basic');
const form = useTemplateRef<FormInstance>('form');
const formModel = ref<NotificationGroupDefinitionDto>({ ...defaultModel });
const { cancel, createApi, getApi, updateApi } =
useNotificationGroupDefinitionsApi();
const [Modal, modalApi] = useVbenModal({
class: 'w-1/2',
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
onClosed() {
cancel('NotificationGroupDefinitionModal has closed!');
},
onConfirm: async () => {
await form.value?.validate();
const input = toValue(formModel);
const api = isEditModel.value
? updateApi(formModel.value.name, input)
: createApi(input);
modalApi.setState({ confirmLoading: true, loading: true });
api
.then((res) => {
message.success($t('AbpUi.SavedSuccessfully'));
emits('change', res);
modalApi.close();
})
.finally(() => {
modalApi.setState({ confirmLoading: false, loading: false });
});
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
isEditModel.value = false;
activeTab.value = 'basic';
formModel.value = { ...defaultModel };
modalApi.setState({
showConfirmButton: true,
title: $t('Notifications.GroupDefinitions:AddNew'),
});
try {
modalApi.setState({ loading: true });
const { name } = modalApi.getData<NotificationGroupDefinitionDto>();
name && (await onGet(name));
} finally {
modalApi.setState({ loading: false });
}
}
},
title: $t('Notifications.GroupDefinitions:AddNew'),
});
async function onGet(name: string) {
isEditModel.value = true;
const dto = await getApi(name);
formModel.value = dto;
modalApi.setState({
showConfirmButton: !dto.isStatic,
title: `${$t('Notifications.GroupDefinitions')} - ${dto.name}`,
});
}
function onPropChange(prop: PropertyInfo) {
formModel.value.extraProperties ??= {};
formModel.value.extraProperties[prop.key] = prop.value;
}
function onPropDelete(prop: PropertyInfo) {
formModel.value.extraProperties ??= {};
delete formModel.value.extraProperties[prop.key];
}
</script>
<template>
<Modal>
<Form
ref="form"
:label-col="{ span: 6 }"
:model="formModel"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:active-key="activeTab">
<!-- 基本信息 -->
<TabPane key="basic" :tab="$t('Notifications.BasicInfo')">
<FormItem
:label="$t('Notifications.DisplayName:Name')"
name="name"
required
>
<Input
v-model:value="formModel.name"
:disabled="formModel.isStatic"
autocomplete="off"
/>
</FormItem>
<FormItem
:label="$t('Notifications.DisplayName:DisplayName')"
name="displayName"
required
>
<LocalizableInput
v-model:value="formModel.displayName"
:disabled="formModel.isStatic"
/>
</FormItem>
<FormItem
:label="$t('Notifications.DisplayName:Description')"
name="description"
>
<LocalizableInput
v-model:value="formModel.description"
:disabled="formModel.isStatic"
/>
</FormItem>
<FormItem
name="allowSubscriptionToClients"
:label="$t('Notifications.DisplayName:AllowSubscriptionToClients')"
:extra="$t('Notifications.Description:AllowSubscriptionToClients')"
>
<Checkbox
:disabled="formModel.isStatic"
v-model:checked="formModel.allowSubscriptionToClients"
>
{{ $t('Notifications.DisplayName:AllowSubscriptionToClients') }}
</Checkbox>
</FormItem>
</TabPane>
<!-- 属性 -->
<TabPane key="props" :tab="$t('Notifications.Properties')">
<PropertyTable
:data="formModel.extraProperties"
:disabled="formModel.isStatic"
@change="onPropChange"
@delete="onPropDelete"
/>
</TabPane>
</Tabs>
</Form>
</Modal>
</template>
<style scoped></style>

262
apps/vben5/packages/@abp/notifications/src/components/definitions/groups/NotificationGroupDefinitionTable.vue

@ -0,0 +1,262 @@
<script setup lang="ts">
import type { VbenFormProps, VxeGridListeners, VxeGridProps } from '@abp/ui';
import type { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import type { NotificationGroupDefinitionDto } from '../../../types/groups';
import { defineAsyncComponent, h, onMounted, reactive, ref } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal } from '@vben/common-ui';
import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import { useLocalization, useLocalizationSerializer } from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import {
DeleteOutlined,
EditOutlined,
EllipsisOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import { Button, Dropdown, Menu, message, Modal } from 'ant-design-vue';
import { useNotificationGroupDefinitionsApi } from '../../../api/useNotificationGroupDefinitionsApi';
import {
GroupDefinitionsPermissions,
NotificationDefinitionsPermissions,
} from '../../../constants/permissions';
defineOptions({
name: 'NotificationGroupDefinitionTable',
});
const MenuItem = Menu.Item;
const DefinitionIcon = createIconifyIcon('nimbus:notification');
const permissionGroups = ref<NotificationGroupDefinitionDto[]>([]);
const pageState = reactive({
current: 1,
size: 10,
total: 0,
});
const { Lr } = useLocalization();
const { hasAccessByCodes } = useAccess();
const { deserialize } = useLocalizationSerializer();
const { deleteApi, getListApi } = useNotificationGroupDefinitionsApi();
const formOptions: VbenFormProps = {
//
collapsed: false,
handleReset: onReset,
async handleSubmit(params) {
pageState.current = 1;
await onGet(params);
},
schema: [
{
component: 'Input',
fieldName: 'filter',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpUi.Search'),
},
],
//
showCollapseButton: true,
//
submitOnEnter: true,
};
const gridOptions: VxeGridProps<NotificationGroupDefinitionDto> = {
columns: [
{
align: 'left',
field: 'name',
minWidth: 150,
title: $t('Notifications.DisplayName:Name'),
},
{
align: 'left',
field: 'displayName',
minWidth: 150,
title: $t('Notifications.DisplayName:DisplayName'),
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: $t('AbpUi.Actions'),
width: 220,
},
],
exportConfig: {},
keepSource: true,
toolbarConfig: {
custom: true,
export: true,
refresh: false,
zoom: true,
},
};
const gridEvents: VxeGridListeners<NotificationGroupDefinitionDto> = {
pageChange(params) {
pageState.current = params.currentPage;
pageState.size = params.pageSize;
onPageChange();
},
};
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridEvents,
gridOptions,
});
const [NotificationGroupDefinitionModal, groupModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./NotificationGroupDefinitionModal.vue'),
),
});
const [NotificationDefinitionModal, defineModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('../notifications/NotificationDefinitionModal.vue'),
),
});
async function onGet(input?: Record<string, string>) {
try {
gridApi.setLoading(true);
const { items } = await getListApi(input);
pageState.total = items.length;
permissionGroups.value = items.map((item) => {
const localizableString = deserialize(item.displayName);
return {
...item,
displayName: Lr(localizableString.resourceName, localizableString.name),
};
});
onPageChange();
} finally {
gridApi.setLoading(false);
}
}
async function onReset() {
await gridApi.formApi.resetForm();
const input = await gridApi.formApi.getValues();
await onGet(input);
}
function onPageChange() {
const items = permissionGroups.value.slice(
(pageState.current - 1) * pageState.size,
pageState.current * pageState.size,
);
gridApi.setGridOptions({
data: items,
pagerConfig: {
currentPage: pageState.current,
pageSize: pageState.size,
total: pageState.total,
},
});
}
function onCreate() {
groupModalApi.setData({});
groupModalApi.open();
}
function onUpdate(row: NotificationGroupDefinitionDto) {
groupModalApi.setData(row);
groupModalApi.open();
}
function onDelete(row: NotificationGroupDefinitionDto) {
Modal.confirm({
centered: true,
content: `${$t('AbpUi.ItemWillBeDeletedMessageWithFormat', [row.name])}`,
onOk: async () => {
await deleteApi(row.name);
message.success($t('AbpUi.SuccessfullyDeleted'));
onGet();
},
title: $t('AbpUi.AreYouSure'),
});
}
function onMenuClick(row: NotificationGroupDefinitionDto, info: MenuInfo) {
switch (info.key) {
case 'definitions': {
defineModalApi.setData({
groupName: row.name,
});
defineModalApi.open();
break;
}
}
}
onMounted(onGet);
</script>
<template>
<Grid :table-title="$t('Notifications.GroupDefinitions')">
<template #toolbar-tools>
<Button
:icon="h(PlusOutlined)"
type="primary"
v-access:code="[GroupDefinitionsPermissions.Create]"
@click="onCreate"
>
{{ $t('Notifications.GroupDefinitions:AddNew') }}
</Button>
</template>
<template #action="{ row }">
<div class="flex flex-row">
<Button
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[GroupDefinitionsPermissions.Update]"
@click="onUpdate(row)"
>
{{ $t('AbpUi.Edit') }}
</Button>
<Button
v-if="!row.isStatic"
:icon="h(DeleteOutlined)"
block
danger
type="link"
v-access:code="[GroupDefinitionsPermissions.Delete]"
@click="onDelete(row)"
>
{{ $t('AbpUi.Delete') }}
</Button>
<Dropdown v-if="!row.isStatic">
<template #overlay>
<Menu @click="(info) => onMenuClick(row, info)">
<MenuItem
v-if="
hasAccessByCodes([NotificationDefinitionsPermissions.Create])
"
key="definitions"
:icon="h(DefinitionIcon)"
>
{{ $t('Notifications.NotificationDefinitions:AddNew') }}
</MenuItem>
</Menu>
</template>
<Button :icon="h(EllipsisOutlined)" type="link" />
</Dropdown>
</div>
</template>
</Grid>
<NotificationGroupDefinitionModal @change="() => onGet()" />
<NotificationDefinitionModal />
</template>
<style scoped></style>

311
apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationDefinitionModal.vue

@ -0,0 +1,311 @@
<script setup lang="ts">
import type { PropertyInfo } from '@abp/ui';
import type { FormInstance } from 'ant-design-vue';
import type { NotificationGroupDefinitionDto } from '../../../types';
import type {
NotificationDefinitionDto,
NotificationProviderDto,
NotificationTemplateDto,
} from '../../../types/definitions';
import { defineEmits, defineOptions, ref, toValue, useTemplateRef } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { useLocalization, useLocalizationSerializer } from '@abp/core';
import { LocalizableInput, PropertyTable } from '@abp/ui';
import { Checkbox, Form, Input, message, Select, Tabs } from 'ant-design-vue';
import {
useNotificationGroupDefinitionsApi,
useNotificationsApi,
} from '../../../api';
import { useNotificationDefinitionsApi } from '../../../api/useNotificationDefinitionsApi';
import {
NotificationContentType,
NotificationLifetime,
NotificationType,
} from '../../../types';
import { useEnumMaps } from './useEnumMaps';
defineOptions({
name: 'NotificationDefinitionModal',
});
const emits = defineEmits<{
(event: 'change', data: NotificationDefinitionDto): void;
}>();
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
type TabKeys = 'basic' | 'props';
const defaultModel: NotificationDefinitionDto = {
allowSubscriptionToClients: false,
contentType: NotificationContentType.Text,
displayName: '',
extraProperties: {},
groupName: '',
isStatic: false,
name: '',
notificationLifetime: NotificationLifetime.Persistent,
notificationType: NotificationType.Application,
};
const isEditModel = ref(false);
const activeTab = ref<TabKeys>('basic');
const form = useTemplateRef<FormInstance>('form');
const formModel = ref<NotificationDefinitionDto>({ ...defaultModel });
const assignableProviders = ref<NotificationProviderDto[]>([]);
const assignableTemplates = ref<NotificationTemplateDto[]>([]);
const notificationGroups = ref<NotificationGroupDefinitionDto[]>([]);
const {
notificationContentTypeOptions,
notificationLifetimeOptions,
notificationTypeOptions,
} = useEnumMaps();
const { cancel, createApi, getApi, updateApi } =
useNotificationDefinitionsApi();
const { getAssignableProvidersApi, getAssignableTemplatesApi } =
useNotificationsApi();
const { getListApi: getGroupDefinitionsApi } =
useNotificationGroupDefinitionsApi();
const { Lr } = useLocalization();
const { deserialize } = useLocalizationSerializer();
const [Modal, modalApi] = useVbenModal({
class: 'w-1/2',
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
onClosed() {
cancel('Notifications.NotificationDefinitionModal has closed!');
},
onConfirm: async () => {
await form.value?.validate();
const input = toValue(formModel);
const api = isEditModel.value
? updateApi(formModel.value.name, input)
: createApi(input);
try {
modalApi.setState({ submitting: true });
const res = await api;
emits('change', res);
message.success($t('AbpUi.SavedSuccessfully'));
modalApi.close();
} finally {
modalApi.setState({ submitting: false });
}
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
isEditModel.value = false;
activeTab.value = 'basic';
formModel.value = { ...defaultModel };
modalApi.setState({
loading: true,
showConfirmButton: true,
title: $t('Notifications.NotificationDefinitions:AddNew'),
});
try {
const { groupName, name } =
modalApi.getData<NotificationDefinitionDto>();
await onInit(groupName);
name && (await onGet(name));
} finally {
modalApi.setState({ loading: false });
}
}
},
title: $t('Notifications.NotificationDefinitions:AddNew'),
});
async function onGet(name: string) {
isEditModel.value = true;
const dto = await getApi(name);
formModel.value = dto;
modalApi.setState({
showConfirmButton: !dto.isStatic,
title: `${$t('Notifications.NotificationDefinitions')} - ${dto.name}`,
});
}
async function onInit(groupName?: string) {
const [getGroupsRes, getTemplateRes, getProviderRes] = await Promise.all([
getGroupDefinitionsApi({ filter: groupName }),
getAssignableTemplatesApi(),
getAssignableProvidersApi(),
]);
assignableProviders.value = getProviderRes.items;
assignableTemplates.value = getTemplateRes.items;
notificationGroups.value = getGroupsRes.items.map((group) => {
const displayName = deserialize(group.displayName);
const description = deserialize(group.description);
return {
...group,
description: Lr(description.resourceName, description.name),
displayName: Lr(displayName.resourceName, displayName.name),
};
});
if (getGroupsRes.items.length === 1) {
formModel.value.groupName = getGroupsRes.items[0]!.name;
}
}
function onPropChange(prop: PropertyInfo) {
formModel.value.extraProperties ??= {};
formModel.value.extraProperties[prop.key] = prop.value;
}
function onPropDelete(prop: PropertyInfo) {
formModel.value.extraProperties ??= {};
delete formModel.value.extraProperties[prop.key];
}
</script>
<template>
<Modal>
<Form
ref="form"
:label-col="{ span: 6 }"
:model="formModel"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:active-key="activeTab">
<!-- 基本信息 -->
<TabPane key="basic" :tab="$t('Notifications.BasicInfo')">
<FormItem
name="groupName"
:label="$t('Notifications.DisplayName:GroupName')"
required
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.groupName"
:options="notificationGroups"
:field-names="{ label: 'displayName', value: 'name' }"
/>
</FormItem>
<FormItem
:label="$t('Notifications.DisplayName:Name')"
name="name"
required
>
<Input
v-model:value="formModel.name"
:disabled="formModel.isStatic"
autocomplete="off"
/>
</FormItem>
<FormItem
:label="$t('Notifications.DisplayName:DisplayName')"
name="displayName"
required
>
<LocalizableInput
v-model:value="formModel.displayName"
:disabled="formModel.isStatic"
/>
</FormItem>
<FormItem
name="description"
:label="$t('Notifications.DisplayName:Description')"
>
<LocalizableInput
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.description"
/>
</FormItem>
<FormItem
name="allowSubscriptionToClients"
:label="$t('Notifications.DisplayName:AllowSubscriptionToClients')"
:extra="$t('Notifications.Description:AllowSubscriptionToClients')"
>
<Checkbox
:disabled="formModel.isStatic"
v-model:checked="formModel.allowSubscriptionToClients"
>
{{ $t('Notifications.DisplayName:AllowSubscriptionToClients') }}
</Checkbox>
</FormItem>
<FormItem
name="notificationType"
:label="$t('Notifications.DisplayName:NotificationType')"
:extra="$t('Notifications.Description:NotificationType')"
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.notificationType"
:options="notificationTypeOptions"
/>
</FormItem>
<FormItem
name="notificationLifetime"
:label="$t('Notifications.DisplayName:NotificationLifetime')"
:extra="$t('Notifications.Description:NotificationLifetime')"
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.notificationLifetime"
:options="notificationLifetimeOptions"
/>
</FormItem>
<FormItem
name="contentType"
:label="$t('Notifications.DisplayName:ContentType')"
:extra="$t('Notifications.Description:ContentType')"
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.contentType"
:options="notificationContentTypeOptions"
/>
</FormItem>
<FormItem
name="providers"
:label="$t('Notifications.DisplayName:Providers')"
:extra="$t('Notifications.Description:Providers')"
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
mode="multiple"
v-model:value="formModel.providers"
:options="assignableProviders"
:field-names="{ label: 'name', value: 'name' }"
/>
</FormItem>
<FormItem
name="template"
:label="$t('Notifications.DisplayName:Template')"
:extra="$t('Notifications.Description:Template')"
>
<Select
:disabled="formModel.isStatic"
:allow-clear="true"
v-model:value="formModel.template"
:options="assignableTemplates"
:field-names="{ label: 'name', value: 'name' }"
/>
</FormItem>
</TabPane>
<!-- 属性 -->
<TabPane key="props" :tab="$t('Notifications.Properties')">
<PropertyTable
:data="formModel.extraProperties"
:disabled="formModel.isStatic"
@change="onPropChange"
@delete="onPropDelete"
/>
</TabPane>
</Tabs>
</Form>
</Modal>
</template>
<style scoped></style>

418
apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationDefinitionTable.vue

@ -0,0 +1,418 @@
<script setup lang="ts">
import type { VbenFormProps, VxeGridListeners, VxeGridProps } from '@abp/ui';
import type { MenuInfo } from 'ant-design-vue/es/menu/src/interface';
import type { NotificationDefinitionDto } from '../../../types/definitions';
import type { NotificationGroupDefinitionDto } from '../../../types/groups';
import { defineAsyncComponent, h, onMounted, reactive, ref } from 'vue';
import { useAccess } from '@vben/access';
import { useVbenModal } from '@vben/common-ui';
import { createIconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
import {
listToTree,
useLocalization,
useLocalizationSerializer,
} from '@abp/core';
import { useVbenVxeGrid } from '@abp/ui';
import {
CheckOutlined,
CloseOutlined,
DeleteOutlined,
EditOutlined,
EllipsisOutlined,
PlusOutlined,
} from '@ant-design/icons-vue';
import { Button, Dropdown, Menu, message, Modal, Tag } from 'ant-design-vue';
import { VxeGrid } from 'vxe-table';
import { useNotificationDefinitionsApi } from '../../../api/useNotificationDefinitionsApi';
import { useNotificationGroupDefinitionsApi } from '../../../api/useNotificationGroupDefinitionsApi';
import {
NotificationDefinitionsPermissions,
NotificationPermissions,
} from '../../../constants/permissions';
import { useEnumMaps } from './useEnumMaps';
defineOptions({
name: 'NotificationDefinitionTable',
});
interface DefinitionItem {
allowSubscriptionToClients: boolean;
children: DefinitionItem[];
contentType: string;
description?: string;
displayName: string;
groupName: string;
isStatic: boolean;
name: string;
notificationLifetime: string;
notificationType: string;
providers?: string[];
template?: string;
}
interface DefinitionGroup {
displayName: string;
items: DefinitionItem[];
name: string;
}
const MenuItem = Menu.Item;
const SendIcon = createIconifyIcon('ant-design:send-outlined');
const { Lr } = useLocalization();
const { hasAccessByCodes } = useAccess();
const { deserialize } = useLocalizationSerializer();
const {
notificationContentTypeMap,
notificationLifetimeMap,
notificationTypeMap,
} = useEnumMaps();
const { getListApi: getGroupsApi } = useNotificationGroupDefinitionsApi();
const { deleteApi, getListApi: getDefinitionsApi } =
useNotificationDefinitionsApi();
const definitionGroups = ref<DefinitionGroup[]>([]);
const pageState = reactive({
current: 1,
size: 10,
total: 0,
});
const formOptions: VbenFormProps = {
//
collapsed: false,
handleReset: onReset,
async handleSubmit(params) {
pageState.current = 1;
await onGet(params);
},
schema: [
{
component: 'Input',
fieldName: 'filter',
formItemClass: 'col-span-2 items-baseline',
label: $t('AbpUi.Search'),
},
],
//
showCollapseButton: true,
//
submitOnEnter: true,
};
const gridOptions: VxeGridProps<NotificationGroupDefinitionDto> = {
columns: [
{
align: 'center',
type: 'seq',
width: 50,
},
{
align: 'left',
field: 'group',
slots: { content: 'group' },
type: 'expand',
width: 50,
},
{
align: 'left',
field: 'name',
minWidth: 150,
title: $t('Notifications.DisplayName:Name'),
},
{
align: 'left',
field: 'displayName',
minWidth: 150,
title: $t('Notifications.DisplayName:DisplayName'),
},
],
expandConfig: {
padding: true,
trigger: 'row',
},
exportConfig: {},
keepSource: true,
toolbarConfig: {
custom: true,
export: true,
refresh: false,
zoom: true,
},
};
const subGridColumns: VxeGridProps<NotificationDefinitionDto>['columns'] = [
{
align: 'center',
type: 'seq',
width: 50,
},
{
align: 'left',
field: 'name',
minWidth: 150,
title: $t('Notifications.DisplayName:Name'),
treeNode: true,
},
{
align: 'left',
field: 'displayName',
minWidth: 120,
title: $t('Notifications.DisplayName:DisplayName'),
},
{
align: 'left',
field: 'description',
minWidth: 120,
title: $t('Notifications.DisplayName:Description'),
},
{
align: 'left',
field: 'allowSubscriptionToClients',
minWidth: 120,
slots: { default: 'allowSubscriptionToClients' },
title: $t('Notifications.DisplayName:AllowSubscriptionToClients'),
},
{
align: 'left',
field: 'template',
minWidth: 150,
title: $t('Notifications.DisplayName:Template'),
},
{
align: 'left',
field: 'notificationLifetime',
minWidth: 150,
title: $t('Notifications.DisplayName:NotificationLifetime'),
},
{
align: 'left',
field: 'notificationType',
minWidth: 150,
title: $t('Notifications.DisplayName:NotificationType'),
},
{
align: 'left',
field: 'contentType',
minWidth: 150,
title: $t('Notifications.DisplayName:ContentType'),
},
{
align: 'left',
field: 'providers',
minWidth: 150,
slots: { default: 'providers' },
title: $t('Notifications.DisplayName:Providers'),
},
{
field: 'action',
fixed: 'right',
slots: { default: 'action' },
title: $t('AbpUi.Actions'),
width: 220,
},
];
const gridEvents: VxeGridListeners<NotificationGroupDefinitionDto> = {
pageChange(params) {
pageState.current = params.currentPage;
pageState.size = params.pageSize;
onPageChange();
},
};
const [GroupGrid, gridApi] = useVbenVxeGrid({
formOptions,
gridEvents,
gridOptions,
});
const [NotificationDefinitionModal, modalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./NotificationDefinitionModal.vue'),
),
});
const [NotificationSendModal, sendModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./NotificationSendModal.vue'),
),
});
async function onGet(input?: Record<string, string>) {
try {
gridApi.setLoading(true);
const groupRes = await getGroupsApi(input);
const definitionRes = await getDefinitionsApi(input);
pageState.total = groupRes.items.length;
definitionGroups.value = groupRes.items.map((group) => {
const localizableGroup = deserialize(group.displayName);
const definitions = definitionRes.items
.filter((definition) => definition.groupName === group.name)
.map((definition) => {
const displayName = deserialize(definition.displayName);
const description = deserialize(definition.displayName);
return {
...definition,
contentType: notificationContentTypeMap[definition.contentType],
description: Lr(description.resourceName, description.name),
displayName: Lr(displayName.resourceName, displayName.name),
notificationLifetime:
notificationLifetimeMap[definition.notificationLifetime],
notificationType: notificationTypeMap[definition.notificationType],
};
});
return {
...group,
displayName: Lr(localizableGroup.resourceName, localizableGroup.name),
items: listToTree(definitions, {
id: 'name',
pid: 'parentName',
}),
};
});
onPageChange();
} finally {
gridApi.setLoading(false);
}
}
async function onReset() {
await gridApi.formApi.resetForm();
const input = await gridApi.formApi.getValues();
await onGet(input);
}
function onPageChange() {
const items = definitionGroups.value.slice(
(pageState.current - 1) * pageState.size,
pageState.current * pageState.size,
);
gridApi.setGridOptions({
data: items,
pagerConfig: {
currentPage: pageState.current,
pageSize: pageState.size,
total: pageState.total,
},
});
}
function onCreate() {
modalApi.setData({});
modalApi.open();
}
function onUpdate(row: NotificationDefinitionDto) {
modalApi.setData(row);
modalApi.open();
}
function onDelete(row: NotificationDefinitionDto) {
Modal.confirm({
centered: true,
content: `${$t('AbpUi.ItemWillBeDeletedMessageWithFormat', [row.name])}`,
onOk: async () => {
await deleteApi(row.name);
message.success($t('AbpUi.SuccessfullyDeleted'));
onGet();
},
title: $t('AbpUi.AreYouSure'),
});
}
function onMenuClick(row: NotificationDefinitionDto, info: MenuInfo) {
switch (info.key) {
case 'send': {
sendModalApi.setData(row);
sendModalApi.open();
}
}
}
onMounted(onGet);
</script>
<template>
<GroupGrid :table-title="$t('Notifications.NotificationDefinitions')">
<template #toolbar-tools>
<Button
:icon="h(PlusOutlined)"
type="primary"
v-access:code="[NotificationDefinitionsPermissions.Create]"
@click="onCreate"
>
{{ $t('Notifications.NotificationDefinitions:AddNew') }}
</Button>
</template>
<template #group="{ row: group }">
<VxeGrid
:columns="subGridColumns"
:data="group.items"
:tree-config="{
trigger: 'row',
rowField: 'name',
childrenField: 'children',
}"
>
<template #allowSubscriptionToClients="{ row }">
<div class="flex flex-row justify-center">
<CheckOutlined
v-if="row.allowSubscriptionToClients"
class="text-green-500"
/>
<CloseOutlined v-else class="text-red-500" />
</div>
</template>
<template #providers="{ row }">
<div class="flex flex-row justify-center gap-1">
<template v-for="provider in row.providers" :key="provider">
<Tag color="blue">{{ provider }}</Tag>
</template>
</div>
</template>
<template #action="{ row: definition }">
<div class="flex flex-row">
<Button
:icon="h(EditOutlined)"
block
type="link"
v-access:code="[NotificationDefinitionsPermissions.Update]"
@click="onUpdate(definition)"
>
{{ $t('AbpUi.Edit') }}
</Button>
<Button
v-if="!definition.isStatic"
:icon="h(DeleteOutlined)"
block
danger
type="link"
v-access:code="[NotificationDefinitionsPermissions.Delete]"
@click="onDelete(definition)"
>
{{ $t('AbpUi.Delete') }}
</Button>
<Dropdown v-if="hasAccessByCodes([NotificationPermissions.Create])">
<template #overlay>
<Menu @click="(info) => onMenuClick(definition, info)">
<MenuItem key="send" :icon="h(SendIcon)">
{{ $t('Notifications.Notifications:Send') }}
</MenuItem>
</Menu>
</template>
<Button :icon="h(EllipsisOutlined)" type="link" />
</Dropdown>
</div>
</template>
</VxeGrid>
</template>
</GroupGrid>
<NotificationDefinitionModal @change="() => onGet()" />
<NotificationSendModal />
</template>
<style scoped></style>

143
apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/NotificationSendModal.vue

@ -0,0 +1,143 @@
<script setup lang="ts">
import type { FormInstance } from 'ant-design-vue';
import type {
NotificationDefinitionDto,
NotificationSeverity,
} from '../../../types';
import { ref, toValue, useTemplateRef } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { PropertyTable } from '@abp/ui';
import { Form, Input, message, Select, Tabs, Textarea } from 'ant-design-vue';
import { useNotificationsApi } from '../../../api/useNotificationsApi';
import { useEnumMaps } from './useEnumMaps';
const FormItem = Form.Item;
const TabPane = Tabs.TabPane;
const defaultModel: {
culture?: string;
data: Record<string, any>;
description?: string;
message: string;
name: string;
severity?: NotificationSeverity;
title: string;
} = {
data: {},
message: '',
name: '',
title: '',
};
const activeTabKey = ref('basic');
const formModel = ref({ ...defaultModel });
const form = useTemplateRef<FormInstance>('form');
const notification = ref<NotificationDefinitionDto>();
const { notificationSeverityOptions } = useEnumMaps();
const { sendNotiferApi } = useNotificationsApi();
const [Modal, modalApi] = useVbenModal({
class: 'w-1/2',
draggable: true,
fullscreenButton: false,
onConfirm: onSubmit,
async onOpenChange(isOpen) {
if (isOpen) {
formModel.value = { ...defaultModel };
await onInit();
}
},
});
async function onInit() {
const dto = modalApi.getData<NotificationDefinitionDto>();
notification.value = dto;
formModel.value.name = dto.name;
}
async function onSubmit() {
await form.value?.validate();
try {
modalApi.setState({ submitting: true });
const input = toValue(formModel);
await sendNotiferApi({
culture: input.culture,
data: {
description: input.description,
message: input.message,
title: input.title,
},
name: input.name,
severity: input.severity,
});
message.success($t('Notifications.SendSuccessfully'));
modalApi.close();
} finally {
modalApi.setState({ submitting: false });
}
}
</script>
<template>
<Modal :title="$t('Notifications.Notifications:Send')">
<Form
ref="form"
:label-col="{ span: 6 }"
:model="formModel"
:wrapper-col="{ span: 18 }"
>
<Tabs v-model:active-key="activeTabKey">
<TabPane key="basic" :tab="$t('Notifications.BasicInfo')">
<FormItem name="name" :label="$t('Notifications.DisplayName:Name')">
<Input disabled :value="notification?.displayName" />
</FormItem>
<FormItem
v-if="!notification?.template"
name="title"
:label="$t('Notifications.Notifications:Title')"
required
>
<Textarea v-model:value="formModel.title" />
</FormItem>
<FormItem
v-if="!notification?.template"
name="message"
:label="$t('Notifications.Notifications:Message')"
required
>
<Textarea v-model:value="formModel.message" />
</FormItem>
<FormItem
v-if="!notification?.template"
name="description"
:label="$t('Notifications.Notifications:Description')"
>
<Textarea v-model:value="formModel.description" />
</FormItem>
<FormItem
name="severity"
:label="$t('Notifications.Notifications:Severity')"
>
<Select
allow-clear
v-model:value="formModel.severity"
:options="notificationSeverityOptions"
/>
</FormItem>
</TabPane>
<TabPane key="props" :tab="$t('Notifications.Properties')">
<PropertyTable :data="formModel.data" />
</TabPane>
</Tabs>
</Form>
</Modal>
</template>
<style scoped></style>

123
apps/vben5/packages/@abp/notifications/src/components/definitions/notifications/useEnumMaps.ts

@ -0,0 +1,123 @@
import { reactive } from 'vue';
import { $t } from '@vben/locales';
import {
NotificationContentType,
NotificationLifetime,
NotificationSeverity,
NotificationType,
} from '../../../types/notifications';
export function useEnumMaps() {
const notificationTypeOptions = reactive([
{
label: $t('Notifications.NotificationType:User'),
value: NotificationType.User,
},
{
label: $t('Notifications.NotificationType:System'),
value: NotificationType.System,
},
{
label: $t('Notifications.NotificationType:Application'),
value: NotificationType.Application,
},
{
label: $t('Notifications.NotificationType:ServiceCallback'),
value: NotificationType.ServiceCallback,
},
]);
const notificationTypeMap = reactive({
[NotificationType.Application]: $t(
'Notifications.NotificationType:Application',
),
[NotificationType.ServiceCallback]: $t(
'Notifications.NotificationType:ServiceCallback',
),
[NotificationType.System]: $t('Notifications.NotificationType:System'),
[NotificationType.User]: $t('Notifications.NotificationType:User'),
});
const notificationLifetimeOptions = reactive([
{
label: $t('Notifications.NotificationLifetime:OnlyOne'),
value: NotificationLifetime.OnlyOne,
},
{
label: $t('Notifications.NotificationLifetime:Persistent'),
value: NotificationLifetime.Persistent,
},
]);
const notificationLifetimeMap = reactive({
[NotificationLifetime.OnlyOne]: $t(
'Notifications.NotificationLifetime:OnlyOne',
),
[NotificationLifetime.Persistent]: $t(
'Notifications.NotificationLifetime:Persistent',
),
});
const notificationContentTypeOptions = reactive([
{
label: $t('Notifications.NotificationContentType:Text'),
value: NotificationContentType.Text,
},
{
label: $t('Notifications.NotificationContentType:Json'),
value: NotificationContentType.Json,
},
{
label: $t('Notifications.NotificationContentType:Html'),
value: NotificationContentType.Html,
},
{
label: $t('Notifications.NotificationContentType:Markdown'),
value: NotificationContentType.Markdown,
},
]);
const notificationContentTypeMap = reactive({
[NotificationContentType.Html]: $t(
'Notifications.NotificationContentType:Html',
),
[NotificationContentType.Json]: $t(
'Notifications.NotificationContentType:Json',
),
[NotificationContentType.Markdown]: $t(
'Notifications.NotificationContentType:Markdown',
),
[NotificationContentType.Text]: $t(
'Notifications.NotificationContentType:Text',
),
});
const notificationSeverityOptions = reactive([
{
label: $t('Notifications.NotificationSeverity:Success'),
value: NotificationSeverity.Success,
},
{
label: $t('Notifications.NotificationSeverity:Info'),
value: NotificationSeverity.Info,
},
{
label: $t('Notifications.NotificationSeverity:Warn'),
value: NotificationSeverity.Warn,
},
{
label: $t('Notifications.NotificationSeverity:Fatal'),
value: NotificationSeverity.Fatal,
},
{
label: $t('Notifications.NotificationSeverity:Error'),
value: NotificationSeverity.Error,
},
]);
return {
notificationContentTypeMap,
notificationContentTypeOptions,
notificationLifetimeMap,
notificationLifetimeOptions,
notificationSeverityOptions,
notificationTypeMap,
notificationTypeOptions,
};
}

2
apps/vben5/packages/@abp/notifications/src/components/index.ts

@ -1 +1,3 @@
export { default as NotificationGroupDefinitionTable } from './definitions/groups/NotificationGroupDefinitionTable.vue';
export { default as NotificationDefinitionTable } from './definitions/notifications/NotificationDefinitionTable.vue';
export { default as MyNotificationTable } from './my-notifilers/MyNotificationTable.vue';

28
apps/vben5/packages/@abp/notifications/src/constants/permissions.ts

@ -0,0 +1,28 @@
/** 分组权限 */
export const GroupDefinitionsPermissions = {
/** 新增 */
Create: 'Notifications.GroupDefinitions.Create',
Default: 'Notifications.GroupDefinitions',
/** 删除 */
Delete: 'Notifications.GroupDefinitions.Delete',
/** 更新 */
Update: 'Notifications.GroupDefinitions.Update',
};
/** 通知定义权限 */
export const NotificationDefinitionsPermissions = {
/** 新增 */
Create: 'Notifications.Definitions.Create',
Default: 'Notifications.Definitions',
/** 删除 */
Delete: 'Notifications.Definitions.Delete',
/** 更新 */
Update: 'Notifications.Definitions.Update',
};
/** 通知权限 */
export const NotificationPermissions = {
/** 发送通知 */
Create: 'Notifications.Notification.Send',
Default: 'Notifications.Notification',
/** 删除 */
Delete: 'Notifications.Notification.Delete',
};

12
apps/vben5/packages/@abp/notifications/src/hooks/useNotifications.ts

@ -61,16 +61,12 @@ export function useNotifications() {
/** 通知推送 */
function _notification(notifier: Notification) {
let message = notifier.description;
let message = notifier.message;
switch (notifier.contentType) {
case NotificationContentType.Html:
case NotificationContentType.Json:
case NotificationContentType.Markdown: {
message = notifier.title;
break;
}
case NotificationContentType.Text: {
message = notifier.description;
if (notifier.description) {
message = notifier.description;
}
}
}
switch (notifier.severity) {

66
apps/vben5/packages/@abp/notifications/src/types/definitions.ts

@ -1,4 +1,10 @@
import type { NotificationLifetime, NotificationType } from './notifications';
import type { ExtensibleObject, IHasExtraProperties } from '@abp/core';
import type {
NotificationContentType,
NotificationLifetime,
NotificationType,
} from './notifications';
interface NotificationDto {
description: string;
@ -14,6 +20,10 @@ interface NotificationGroupDto {
notifications: NotificationDto[];
}
interface NotificationProviderDto {
name: string;
}
interface NotificationTemplateDto {
content?: string;
culture?: string;
@ -22,4 +32,56 @@ interface NotificationTemplateDto {
title: string;
}
export type { NotificationDto, NotificationGroupDto, NotificationTemplateDto };
interface NotificationDefinitionDto extends ExtensibleObject {
allowSubscriptionToClients: boolean;
contentType: NotificationContentType;
description?: string;
displayName: string;
groupName: string;
isStatic: boolean;
name: string;
notificationLifetime: NotificationLifetime;
notificationType: NotificationType;
providers?: string[];
template?: string;
}
interface NotificationDefinitionGetListInput {
allowSubscriptionToClients?: boolean;
contentType?: NotificationContentType;
filter?: string;
groupName?: string;
notificationLifetime?: NotificationLifetime;
notificationType?: NotificationType;
template?: string;
}
interface NotificationDefinitionCreateOrUpdateDto extends IHasExtraProperties {
allowSubscriptionToClients?: boolean;
contentType?: NotificationContentType;
description?: string;
displayName: string;
notificationLifetime?: NotificationLifetime;
notificationType?: NotificationType;
providers?: string[];
template?: string;
}
type NotificationDefinitionUpdateDto = NotificationDefinitionCreateOrUpdateDto;
interface NotificationDefinitionCreateDto
extends NotificationDefinitionCreateOrUpdateDto {
groupName?: string;
name: string;
}
export type {
NotificationDefinitionCreateDto,
NotificationDefinitionDto,
NotificationDefinitionGetListInput,
NotificationDefinitionUpdateDto,
NotificationDto,
NotificationGroupDto,
NotificationProviderDto,
NotificationTemplateDto,
};

35
apps/vben5/packages/@abp/notifications/src/types/groups.ts

@ -0,0 +1,35 @@
import type { ExtensibleObject, IHasExtraProperties } from '@abp/core';
interface NotificationGroupDefinitionDto extends ExtensibleObject {
allowSubscriptionToClients: boolean;
description?: string;
displayName: string;
isStatic: boolean;
name: string;
}
interface NotificationGroupDefinitionGetListInput {
filter?: string;
}
interface NotificationGroupDefinitionCreateOrUpdateDto
extends IHasExtraProperties {
allowSubscriptionToClients: boolean;
description?: string;
displayName: string;
}
interface NotificationGroupDefinitionCreateDto
extends NotificationGroupDefinitionCreateOrUpdateDto {
name: string;
}
type NotificationGroupDefinitionUpdateDto =
NotificationGroupDefinitionCreateOrUpdateDto;
export type {
NotificationGroupDefinitionCreateDto,
NotificationGroupDefinitionDto,
NotificationGroupDefinitionGetListInput,
NotificationGroupDefinitionUpdateDto,
};

1
apps/vben5/packages/@abp/notifications/src/types/index.ts

@ -1,4 +1,5 @@
export * from './definitions';
export * from './groups';
export * from './my-notifilers';
export * from './notifications';
export * from './subscribes';

Loading…
Cancel
Save