feat: 优化站内信通知面板
This commit is contained in:
parent
15e588f80e
commit
60ac59c628
@ -44,6 +44,10 @@ pnpm run build:antdv-next
|
|||||||
|
|
||||||
真实环境变量不提交,示例配置以 `.env.example` 为准。
|
真实环境变量不提交,示例配置以 `.env.example` 为准。
|
||||||
|
|
||||||
|
## 业务页面
|
||||||
|
|
||||||
|
- 系统管理 / 站内信是日志级通知列表,只展示 API 错误、QQBot 下线、NapCat 离线等后端自动捕获事件;页面提供筛选、处理/重新打开、置顶和删除,不提供人工新增或编辑。
|
||||||
|
|
||||||
## 部署说明
|
## 部署说明
|
||||||
|
|
||||||
Jenkins 使用 `Jenkinsfile` 执行:
|
Jenkins 使用 `Jenkinsfile` 执行:
|
||||||
|
|||||||
@ -70,7 +70,6 @@ const SUPPORTED_ADMIN_MENU_NAMES = new Set([
|
|||||||
'SystemMenuDelete',
|
'SystemMenuDelete',
|
||||||
'SystemMenuEdit',
|
'SystemMenuEdit',
|
||||||
'SystemNotice',
|
'SystemNotice',
|
||||||
'SystemNoticeCreate',
|
|
||||||
'SystemNoticeDelete',
|
'SystemNoticeDelete',
|
||||||
'SystemNoticeEdit',
|
'SystemNoticeEdit',
|
||||||
'SystemRole',
|
'SystemRole',
|
||||||
|
|||||||
@ -8,37 +8,39 @@ export namespace SystemNoticeApi {
|
|||||||
content: string;
|
content: string;
|
||||||
createTime?: string;
|
createTime?: string;
|
||||||
createdBy?: string;
|
createdBy?: string;
|
||||||
|
dedupeKey?: string;
|
||||||
|
eventType?: string;
|
||||||
|
firstSeenAt?: string;
|
||||||
id: string;
|
id: string;
|
||||||
isDeleted: boolean;
|
isDeleted: boolean;
|
||||||
isTop: boolean;
|
isTop: boolean;
|
||||||
|
lastSeenAt?: string;
|
||||||
level: number;
|
level: number;
|
||||||
|
metadata?: Recordable<any> | string;
|
||||||
notifyUsers?: string;
|
notifyUsers?: string;
|
||||||
|
notifyRoleCode?: string;
|
||||||
|
occurrenceCount?: number;
|
||||||
|
severity?: 'error' | 'fatal' | 'info' | 'warn';
|
||||||
|
source?: string;
|
||||||
status: 0 | 1;
|
status: 0 | 1;
|
||||||
summary?: string;
|
summary?: string;
|
||||||
title: string;
|
title: string;
|
||||||
updateTime?: string;
|
updateTime?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NoticeInput {
|
|
||||||
content: string;
|
|
||||||
id?: string;
|
|
||||||
isTop?: boolean;
|
|
||||||
level?: number;
|
|
||||||
notifyUsers?: string;
|
|
||||||
status?: 0 | 1;
|
|
||||||
summary?: string;
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NoticeQuery {
|
export interface NoticeQuery {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
|
eventType?: string;
|
||||||
isTop?: boolean | number | string;
|
isTop?: boolean | number | string;
|
||||||
keyword?: string;
|
keyword?: string;
|
||||||
level?: number | string;
|
level?: number | string;
|
||||||
notifyUsers?: string;
|
notifyUsers?: string;
|
||||||
|
notifyRoleCode?: string;
|
||||||
page?: number;
|
page?: number;
|
||||||
pageNo?: number;
|
pageNo?: number;
|
||||||
pageSize?: number;
|
pageSize?: number;
|
||||||
|
severity?: string;
|
||||||
|
source?: string;
|
||||||
status?: 0 | 1 | number | string;
|
status?: 0 | 1 | number | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,17 +62,6 @@ async function getNoticeDetail(id: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNotice(data: SystemNoticeApi.NoticeInput) {
|
|
||||||
return requestClient.post<string>('/system/notice/save', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateNotice(id: string, data: SystemNoticeApi.NoticeInput) {
|
|
||||||
return requestClient.post('/system/notice/update', {
|
|
||||||
...data,
|
|
||||||
id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteNotice(id: string) {
|
async function deleteNotice(id: string) {
|
||||||
return requestClient.delete(`/system/notice/${id}`);
|
return requestClient.delete(`/system/notice/${id}`);
|
||||||
}
|
}
|
||||||
@ -97,11 +88,9 @@ async function toggleNoticeTop(id: string, isTop: boolean) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
createNotice,
|
|
||||||
deleteNotice,
|
deleteNotice,
|
||||||
getNoticeDetail,
|
getNoticeDetail,
|
||||||
getNoticeList,
|
getNoticeList,
|
||||||
toggleNoticeStatus,
|
toggleNoticeStatus,
|
||||||
toggleNoticeTop,
|
toggleNoticeTop,
|
||||||
updateNotice,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -112,28 +112,45 @@
|
|||||||
"unconfigured": "Loki Not Configured"
|
"unconfigured": "Loki Not Configured"
|
||||||
},
|
},
|
||||||
"notice": {
|
"notice": {
|
||||||
|
"cancelTop": "Unpin",
|
||||||
|
"cancelTopSuccess": "Unpinned",
|
||||||
"content": "Content",
|
"content": "Content",
|
||||||
"createTime": "Create Time",
|
"createTime": "Create Time",
|
||||||
"deleteConfirm": "Confirm deleting \"{0}\"?",
|
"deleteConfirm": "Confirm deleting \"{0}\"?",
|
||||||
"disableSuccess": "Notice disabled",
|
"eventTitle": "Event Title",
|
||||||
"enableSuccess": "Notice enabled",
|
"eventType": "Event Type",
|
||||||
|
"firstSeenAt": "First Seen",
|
||||||
|
"handleConfirm": "Mark \"{0}\" as handled?",
|
||||||
|
"handleSuccess": "Marked as handled",
|
||||||
"isTop": "Top",
|
"isTop": "Top",
|
||||||
"keyword": "Keyword",
|
"keyword": "Keyword",
|
||||||
|
"lastSeenAt": "Last Seen",
|
||||||
"level": "Level",
|
"level": "Level",
|
||||||
"levelText": "Level {level}",
|
"markHandled": "Handle",
|
||||||
|
"markTop": "Pin",
|
||||||
"name": "Notice",
|
"name": "Notice",
|
||||||
"notifyUsers": "Notify Users",
|
"notifyUsers": "Notify Users",
|
||||||
|
"occurrenceCount": "Count",
|
||||||
|
"reopen": "Reopen",
|
||||||
|
"reopenConfirm": "Reopen \"{0}\"?",
|
||||||
|
"reopenSuccess": "Reopened",
|
||||||
|
"severity": "Severity",
|
||||||
|
"severityError": "Error",
|
||||||
|
"severityFatal": "Fatal",
|
||||||
|
"severityInfo": "Info",
|
||||||
|
"severityWarn": "Warning",
|
||||||
|
"source": "Source",
|
||||||
|
"sourceApi": "API",
|
||||||
|
"sourceQqbot": "QQBot",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
|
"statusHandled": "Handled",
|
||||||
|
"statusUnhandled": "Unhandled",
|
||||||
"summary": "Summary",
|
"summary": "Summary",
|
||||||
"title": "Notices",
|
"title": "Notices",
|
||||||
"top": "Pinned",
|
"top": "Pinned",
|
||||||
|
"topSuccess": "Pinned",
|
||||||
"topNo": "No",
|
"topNo": "No",
|
||||||
"topYes": "Yes",
|
"topYes": "Yes",
|
||||||
"topSuccess": "Pinned",
|
|
||||||
"cancelTopSuccess": "Unpinned",
|
|
||||||
"toggle": "Toggle",
|
|
||||||
"toggleStatusConfirm": "Confirm toggling \"{0}\" status?",
|
|
||||||
"topToggle": "Pin Toggle",
|
|
||||||
"toggleTopConfirm": "Confirm toggling \"{0}\" pin state?"
|
"toggleTopConfirm": "Confirm toggling \"{0}\" pin state?"
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
|
|||||||
@ -114,28 +114,45 @@
|
|||||||
"unconfigured": "Loki 未配置"
|
"unconfigured": "Loki 未配置"
|
||||||
},
|
},
|
||||||
"notice": {
|
"notice": {
|
||||||
|
"cancelTop": "取消置顶",
|
||||||
|
"cancelTopSuccess": "取消置顶成功",
|
||||||
"content": "内容",
|
"content": "内容",
|
||||||
"createTime": "创建时间",
|
"createTime": "创建时间",
|
||||||
"deleteConfirm": "确认删除「{0}」吗?",
|
"deleteConfirm": "确认删除「{0}」吗?",
|
||||||
"disableSuccess": "已停用站内信",
|
"eventTitle": "事件标题",
|
||||||
"enableSuccess": "已启用站内信",
|
"eventType": "事件类型",
|
||||||
|
"firstSeenAt": "首次发生",
|
||||||
|
"handleConfirm": "确认将「{0}」标记为已处理吗?",
|
||||||
|
"handleSuccess": "已标记为已处理",
|
||||||
"isTop": "置顶",
|
"isTop": "置顶",
|
||||||
"keyword": "关键字",
|
"keyword": "关键字",
|
||||||
|
"lastSeenAt": "最后发生",
|
||||||
"level": "等级",
|
"level": "等级",
|
||||||
"levelText": "等级 {level}",
|
"markHandled": "标记处理",
|
||||||
|
"markTop": "置顶",
|
||||||
"name": "站内信",
|
"name": "站内信",
|
||||||
"notifyUsers": "通知用户",
|
"notifyUsers": "通知用户",
|
||||||
|
"occurrenceCount": "次数",
|
||||||
|
"reopen": "重新打开",
|
||||||
|
"reopenConfirm": "确认重新打开「{0}」吗?",
|
||||||
|
"reopenSuccess": "已重新打开",
|
||||||
|
"severity": "级别",
|
||||||
|
"severityError": "错误",
|
||||||
|
"severityFatal": "致命",
|
||||||
|
"severityInfo": "信息",
|
||||||
|
"severityWarn": "警告",
|
||||||
|
"source": "来源",
|
||||||
|
"sourceApi": "接口",
|
||||||
|
"sourceQqbot": "QQBot",
|
||||||
"status": "状态",
|
"status": "状态",
|
||||||
|
"statusHandled": "已处理",
|
||||||
|
"statusUnhandled": "未处理",
|
||||||
"summary": "摘要",
|
"summary": "摘要",
|
||||||
"title": "站内信管理",
|
"title": "站内信管理",
|
||||||
"top": "置顶",
|
"top": "置顶",
|
||||||
|
"topSuccess": "置顶成功",
|
||||||
"topNo": "否",
|
"topNo": "否",
|
||||||
"topYes": "是",
|
"topYes": "是",
|
||||||
"topSuccess": "置顶成功",
|
|
||||||
"cancelTopSuccess": "取消置顶成功",
|
|
||||||
"toggle": "启停",
|
|
||||||
"toggleStatusConfirm": "确认切换「{0}」启停状态吗?",
|
|
||||||
"topToggle": "置顶切换",
|
|
||||||
"toggleTopConfirm": "确认切换「{0}」置顶状态吗?"
|
"toggleTopConfirm": "确认切换「{0}」置顶状态吗?"
|
||||||
},
|
},
|
||||||
"role": {
|
"role": {
|
||||||
|
|||||||
@ -1,19 +1,32 @@
|
|||||||
import type { VbenFormSchema } from '#/adapter/form';
|
import type { VbenFormSchema } from '#/adapter/form';
|
||||||
|
|
||||||
import { z } from '#/adapter/form';
|
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
export const NOTICE_LEVEL_OPTIONS = [
|
export const NOTICE_SEVERITY_OPTIONS = [
|
||||||
{ label: '普通', value: 1 },
|
{ color: 'blue', label: $t('system.notice.severityInfo'), value: 'info' },
|
||||||
{ label: '重要', value: 2 },
|
{ color: 'orange', label: $t('system.notice.severityWarn'), value: 'warn' },
|
||||||
{ label: '紧急', value: 3 },
|
{ color: 'red', label: $t('system.notice.severityError'), value: 'error' },
|
||||||
|
{ color: 'purple', label: $t('system.notice.severityFatal'), value: 'fatal' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const NOTICE_SOURCE_OPTIONS = [
|
||||||
|
{ color: 'geekblue', label: $t('system.notice.sourceApi'), value: 'api' },
|
||||||
|
{ color: 'cyan', label: $t('system.notice.sourceQqbot'), value: 'qqbot' },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const NOTICE_STATUS_OPTIONS = [
|
export const NOTICE_STATUS_OPTIONS = [
|
||||||
{ color: 'success', label: $t('common.enabled'), value: 1 },
|
{ color: 'error', label: $t('system.notice.statusUnhandled'), value: 1 },
|
||||||
{ color: 'default', label: $t('common.disabled'), value: 0 },
|
{ color: 'default', label: $t('system.notice.statusHandled'), value: 0 },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export function getNoticeSeverityOptions() {
|
||||||
|
return NOTICE_SEVERITY_OPTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNoticeSourceOptions() {
|
||||||
|
return NOTICE_SOURCE_OPTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
export function getNoticeStatusOptions() {
|
export function getNoticeStatusOptions() {
|
||||||
return NOTICE_STATUS_OPTIONS;
|
return NOTICE_STATUS_OPTIONS;
|
||||||
}
|
}
|
||||||
@ -32,10 +45,10 @@ export function useSearchSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
options: NOTICE_LEVEL_OPTIONS,
|
options: NOTICE_SEVERITY_OPTIONS,
|
||||||
},
|
},
|
||||||
fieldName: 'level',
|
fieldName: 'severity',
|
||||||
label: $t('system.notice.level'),
|
label: $t('system.notice.severity'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
component: 'Select',
|
component: 'Select',
|
||||||
@ -50,113 +63,18 @@ export function useSearchSchema(): VbenFormSchema[] {
|
|||||||
component: 'Select',
|
component: 'Select',
|
||||||
componentProps: {
|
componentProps: {
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
options: [
|
options: NOTICE_SOURCE_OPTIONS,
|
||||||
{ label: $t('common.no'), value: 0 },
|
|
||||||
{ label: $t('common.yes'), value: 1 },
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
fieldName: 'isTop',
|
fieldName: 'source',
|
||||||
label: $t('system.notice.top'),
|
label: $t('system.notice.source'),
|
||||||
},
|
},
|
||||||
];
|
{
|
||||||
}
|
component: 'Input',
|
||||||
|
componentProps: {
|
||||||
export function useFormSchema(): VbenFormSchema[] {
|
allowClear: true,
|
||||||
return [
|
},
|
||||||
{
|
fieldName: 'eventType',
|
||||||
component: 'Input',
|
label: $t('system.notice.eventType'),
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
placeholder: '如 系统公告',
|
|
||||||
},
|
|
||||||
fieldName: 'title',
|
|
||||||
label: $t('system.notice.title'),
|
|
||||||
rules: z
|
|
||||||
.string()
|
|
||||||
.min(1, $t('ui.formRules.required', [$t('system.notice.title')]))
|
|
||||||
.max(
|
|
||||||
120,
|
|
||||||
$t('ui.formRules.maxLength', [$t('system.notice.title'), 120]),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
placeholder: '如 站内信内容概要',
|
|
||||||
},
|
|
||||||
fieldName: 'summary',
|
|
||||||
label: $t('system.notice.summary'),
|
|
||||||
rules: z
|
|
||||||
.string()
|
|
||||||
.max(
|
|
||||||
200,
|
|
||||||
$t('ui.formRules.maxLength', [$t('system.notice.summary'), 200]),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'TextArea',
|
|
||||||
componentProps: {
|
|
||||||
autoSize: {
|
|
||||||
maxRows: 10,
|
|
||||||
minRows: 4,
|
|
||||||
},
|
|
||||||
allowClear: true,
|
|
||||||
placeholder: '请输入完整内容',
|
|
||||||
},
|
|
||||||
fieldName: 'content',
|
|
||||||
label: $t('system.notice.content'),
|
|
||||||
rules: z
|
|
||||||
.string()
|
|
||||||
.min(1, $t('ui.formRules.required', [$t('system.notice.content')])),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Select',
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
options: NOTICE_LEVEL_OPTIONS,
|
|
||||||
},
|
|
||||||
fieldName: 'level',
|
|
||||||
label: $t('system.notice.level'),
|
|
||||||
defaultValue: 1,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'Input',
|
|
||||||
componentProps: {
|
|
||||||
allowClear: true,
|
|
||||||
placeholder: '逗号分隔,如:10001,10002,留空表示全部用户可见',
|
|
||||||
},
|
|
||||||
fieldName: 'notifyUsers',
|
|
||||||
label: $t('system.notice.notifyUsers'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'RadioGroup',
|
|
||||||
componentProps: {
|
|
||||||
buttonStyle: 'solid',
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: $t('system.notice.topNo'),
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: $t('system.notice.topYes'),
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
defaultValue: false,
|
|
||||||
fieldName: 'isTop',
|
|
||||||
label: $t('system.notice.top'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: 'RadioGroup',
|
|
||||||
componentProps: {
|
|
||||||
buttonStyle: 'solid',
|
|
||||||
options: NOTICE_STATUS_OPTIONS,
|
|
||||||
},
|
|
||||||
defaultValue: 1,
|
|
||||||
fieldName: 'status',
|
|
||||||
label: $t('system.notice.status'),
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,15 +4,11 @@ import type { TableColumnType } from 'antdv-next';
|
|||||||
import type { SystemNoticeApi } from '#/api/system/notice';
|
import type { SystemNoticeApi } from '#/api/system/notice';
|
||||||
import type {
|
import type {
|
||||||
KtTableApi,
|
KtTableApi,
|
||||||
KtTableButton,
|
|
||||||
KtTableContext,
|
KtTableContext,
|
||||||
KtTableRowAction,
|
KtTableRowAction,
|
||||||
} from '#/components/ktTable';
|
} from '#/components/ktTable';
|
||||||
|
|
||||||
import { h } from 'vue';
|
import { Page } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Page, useVbenModal } from '@vben/common-ui';
|
|
||||||
import { Plus } from '@vben/icons';
|
|
||||||
|
|
||||||
import { message, Tag } from 'antdv-next';
|
import { message, Tag } from 'antdv-next';
|
||||||
|
|
||||||
@ -25,14 +21,15 @@ import {
|
|||||||
import { KtTable, useKtTable } from '#/components/ktTable';
|
import { KtTable, useKtTable } from '#/components/ktTable';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
import { getNoticeStatusOptions, useSearchSchema } from './data';
|
import {
|
||||||
import Form from './modules/form.vue';
|
getNoticeSeverityOptions,
|
||||||
|
getNoticeSourceOptions,
|
||||||
const [FormModal, formModalApi] = useVbenModal({
|
getNoticeStatusOptions,
|
||||||
connectedComponent: Form,
|
useSearchSchema,
|
||||||
destroyOnClose: true,
|
} from './data';
|
||||||
});
|
|
||||||
|
|
||||||
|
const noticeSeverityOptions = getNoticeSeverityOptions();
|
||||||
|
const noticeSourceOptions = getNoticeSourceOptions();
|
||||||
const noticeStatusOptions = getNoticeStatusOptions();
|
const noticeStatusOptions = getNoticeStatusOptions();
|
||||||
|
|
||||||
const columns: Array<TableColumnType<SystemNoticeApi.NoticeItem>> = [
|
const columns: Array<TableColumnType<SystemNoticeApi.NoticeItem>> = [
|
||||||
@ -41,37 +38,49 @@ const columns: Array<TableColumnType<SystemNoticeApi.NoticeItem>> = [
|
|||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
key: 'isTop',
|
key: 'isTop',
|
||||||
title: $t('system.notice.top'),
|
title: $t('system.notice.top'),
|
||||||
width: 90,
|
width: 82,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'title',
|
dataIndex: 'severity',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
key: 'title',
|
key: 'severity',
|
||||||
title: $t('system.notice.title'),
|
title: $t('system.notice.severity'),
|
||||||
width: 260,
|
width: 96,
|
||||||
},
|
|
||||||
{
|
|
||||||
dataIndex: 'level',
|
|
||||||
key: 'level',
|
|
||||||
title: $t('system.notice.level'),
|
|
||||||
width: 100,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
title: $t('system.notice.status'),
|
title: $t('system.notice.status'),
|
||||||
width: 100,
|
width: 96,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'notifyUsers',
|
dataIndex: 'title',
|
||||||
key: 'notifyUsers',
|
key: 'title',
|
||||||
title: $t('system.notice.notifyUsers'),
|
title: $t('system.notice.eventTitle'),
|
||||||
|
width: 260,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: 'source',
|
||||||
|
key: 'source',
|
||||||
|
title: $t('system.notice.source'),
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: 'eventType',
|
||||||
|
key: 'eventType',
|
||||||
|
title: $t('system.notice.eventType'),
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
dataIndex: 'createTime',
|
dataIndex: 'occurrenceCount',
|
||||||
key: 'createTime',
|
key: 'occurrenceCount',
|
||||||
title: $t('system.notice.createTime'),
|
title: $t('system.notice.occurrenceCount'),
|
||||||
|
width: 110,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: 'lastSeenAt',
|
||||||
|
key: 'lastSeenAt',
|
||||||
|
title: $t('system.notice.lastSeenAt'),
|
||||||
width: 190,
|
width: 190,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -79,7 +88,7 @@ const columns: Array<TableColumnType<SystemNoticeApi.NoticeItem>> = [
|
|||||||
dataIndex: 'summary',
|
dataIndex: 'summary',
|
||||||
key: 'summary',
|
key: 'summary',
|
||||||
title: $t('system.notice.summary'),
|
title: $t('system.notice.summary'),
|
||||||
width: 280,
|
width: 320,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -87,37 +96,38 @@ const api: KtTableApi<SystemNoticeApi.NoticeItem> = {
|
|||||||
list: async (params) => await getNoticeList(params),
|
list: async (params) => await getNoticeList(params),
|
||||||
};
|
};
|
||||||
|
|
||||||
const buttons: Array<KtTableButton<SystemNoticeApi.NoticeItem>> = [
|
|
||||||
{
|
|
||||||
icon: () => h(Plus, { class: 'kt-table__button-icon' }),
|
|
||||||
key: 'create',
|
|
||||||
label: $t('ui.actionTitle.create', [$t('system.notice.name')]),
|
|
||||||
onClick: onCreate,
|
|
||||||
permissionCodes: ['System:Notice:Create'],
|
|
||||||
type: 'primary',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const rowActions: Array<KtTableRowAction<SystemNoticeApi.NoticeItem>> = [
|
const rowActions: Array<KtTableRowAction<SystemNoticeApi.NoticeItem>> = [
|
||||||
{
|
{
|
||||||
key: 'edit',
|
confirm: (row) => $t('system.notice.handleConfirm', [row.title]),
|
||||||
label: $t('common.edit'),
|
key: 'handle',
|
||||||
onClick: onEdit,
|
label: $t('system.notice.markHandled'),
|
||||||
permissionCodes: ['System:Notice:Edit'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
confirm: (row) => $t('system.notice.toggleStatusConfirm', [row.title]),
|
|
||||||
key: 'toggle',
|
|
||||||
label: $t('system.notice.toggle'),
|
|
||||||
onClick: onToggleStatus,
|
onClick: onToggleStatus,
|
||||||
permissionCodes: ['System:Notice:Edit'],
|
permissionCodes: ['System:Notice:Edit'],
|
||||||
|
rowVisible: (row) => row.status === 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
confirm: (row) => $t('system.notice.reopenConfirm', [row.title]),
|
||||||
|
key: 'reopen',
|
||||||
|
label: $t('system.notice.reopen'),
|
||||||
|
onClick: onToggleStatus,
|
||||||
|
permissionCodes: ['System:Notice:Edit'],
|
||||||
|
rowVisible: (row) => row.status !== 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
confirm: (row) => $t('system.notice.toggleTopConfirm', [row.title]),
|
confirm: (row) => $t('system.notice.toggleTopConfirm', [row.title]),
|
||||||
key: 'top',
|
key: 'markTop',
|
||||||
label: $t('system.notice.topToggle'),
|
label: $t('system.notice.markTop'),
|
||||||
onClick: onToggleTop,
|
onClick: onToggleTop,
|
||||||
permissionCodes: ['System:Notice:Edit'],
|
permissionCodes: ['System:Notice:Edit'],
|
||||||
|
rowVisible: (row) => !row.isTop,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
confirm: (row) => $t('system.notice.toggleTopConfirm', [row.title]),
|
||||||
|
key: 'cancelTop',
|
||||||
|
label: $t('system.notice.cancelTop'),
|
||||||
|
onClick: onToggleTop,
|
||||||
|
permissionCodes: ['System:Notice:Edit'],
|
||||||
|
rowVisible: (row) => row.isTop,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
confirm: (row) => $t('system.notice.deleteConfirm', [row.title]),
|
confirm: (row) => $t('system.notice.deleteConfirm', [row.title]),
|
||||||
@ -129,19 +139,22 @@ const rowActions: Array<KtTableRowAction<SystemNoticeApi.NoticeItem>> = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function getNoticeSeverityOption(
|
||||||
|
severity: SystemNoticeApi.NoticeItem['severity'],
|
||||||
|
) {
|
||||||
|
return noticeSeverityOptions.find((item) => item.value === severity);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNoticeSourceOption(source?: string) {
|
||||||
|
return noticeSourceOptions.find((item) => item.value === source);
|
||||||
|
}
|
||||||
|
|
||||||
function getNoticeStatusOption(status: SystemNoticeApi.NoticeItem['status']) {
|
function getNoticeStatusOption(status: SystemNoticeApi.NoticeItem['status']) {
|
||||||
return noticeStatusOptions.find((item) => item.value === status);
|
return noticeStatusOptions.find((item) => item.value === status);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNoticeLevelColor(level: SystemNoticeApi.NoticeItem['level']) {
|
|
||||||
if (level === 3) return 'red';
|
|
||||||
if (level === 2) return 'orange';
|
|
||||||
return 'blue';
|
|
||||||
}
|
|
||||||
|
|
||||||
const [registerTable, tableApi] = useKtTable<SystemNoticeApi.NoticeItem>({
|
const [registerTable, tableApi] = useKtTable<SystemNoticeApi.NoticeItem>({
|
||||||
api,
|
api,
|
||||||
buttons,
|
|
||||||
columns,
|
columns,
|
||||||
formOptions: {
|
formOptions: {
|
||||||
schema: useSearchSchema(),
|
schema: useSearchSchema(),
|
||||||
@ -152,14 +165,6 @@ const [registerTable, tableApi] = useKtTable<SystemNoticeApi.NoticeItem>({
|
|||||||
tableTitle: $t('system.notice.title'),
|
tableTitle: $t('system.notice.title'),
|
||||||
});
|
});
|
||||||
|
|
||||||
function onCreate() {
|
|
||||||
formModalApi.setData(undefined).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEdit(row: SystemNoticeApi.NoticeItem) {
|
|
||||||
formModalApi.setData(row).open();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onToggleStatus(
|
async function onToggleStatus(
|
||||||
row: SystemNoticeApi.NoticeItem,
|
row: SystemNoticeApi.NoticeItem,
|
||||||
context: KtTableContext<SystemNoticeApi.NoticeItem>,
|
context: KtTableContext<SystemNoticeApi.NoticeItem>,
|
||||||
@ -167,9 +172,9 @@ async function onToggleStatus(
|
|||||||
const nextStatus = row.status === 1 ? 0 : 1;
|
const nextStatus = row.status === 1 ? 0 : 1;
|
||||||
await toggleNoticeStatus(row.id, nextStatus);
|
await toggleNoticeStatus(row.id, nextStatus);
|
||||||
message.success(
|
message.success(
|
||||||
nextStatus === 1
|
nextStatus === 0
|
||||||
? $t('system.notice.enableSuccess')
|
? $t('system.notice.handleSuccess')
|
||||||
: $t('system.notice.disableSuccess'),
|
: $t('system.notice.reopenSuccess'),
|
||||||
);
|
);
|
||||||
await context.reload();
|
await context.reload();
|
||||||
}
|
}
|
||||||
@ -208,15 +213,10 @@ async function onDelete(
|
|||||||
hideLoading();
|
hideLoading();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRefresh() {
|
|
||||||
tableApi.reload();
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Page auto-content-height>
|
<Page auto-content-height>
|
||||||
<FormModal @success="onRefresh" />
|
|
||||||
<KtTable @register="registerTable">
|
<KtTable @register="registerTable">
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
<template v-if="column.key === 'isTop'">
|
<template v-if="column.key === 'isTop'">
|
||||||
@ -228,9 +228,26 @@ function onRefresh() {
|
|||||||
}}
|
}}
|
||||||
</Tag>
|
</Tag>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'level'">
|
<template v-else-if="column.key === 'severity'">
|
||||||
<Tag :color="getNoticeLevelColor(record.level)">
|
<Tag
|
||||||
{{ $t('system.notice.levelText', { level: record.level }) }}
|
:color="
|
||||||
|
getNoticeSeverityOption(record.severity)?.color || 'default'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
getNoticeSeverityOption(record.severity)?.label ||
|
||||||
|
record.severity ||
|
||||||
|
'-'
|
||||||
|
}}
|
||||||
|
</Tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'source'">
|
||||||
|
<Tag :color="getNoticeSourceOption(record.source)?.color || 'blue'">
|
||||||
|
{{
|
||||||
|
getNoticeSourceOption(record.source)?.label ||
|
||||||
|
record.source ||
|
||||||
|
'-'
|
||||||
|
}}
|
||||||
</Tag>
|
</Tag>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="column.key === 'status'">
|
<template v-else-if="column.key === 'status'">
|
||||||
@ -240,6 +257,12 @@ function onRefresh() {
|
|||||||
{{ getNoticeStatusOption(record.status)?.label || record.status }}
|
{{ getNoticeStatusOption(record.status)?.label || record.status }}
|
||||||
</Tag>
|
</Tag>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="column.key === 'occurrenceCount'">
|
||||||
|
{{ record.occurrenceCount || 1 }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'summary'">
|
||||||
|
{{ record.summary || record.content || '-' }}
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</KtTable>
|
</KtTable>
|
||||||
</Page>
|
</Page>
|
||||||
|
|||||||
@ -1,87 +0,0 @@
|
|||||||
<script lang="ts" setup>
|
|
||||||
import type { SystemNoticeApi } from '#/api/system/notice';
|
|
||||||
|
|
||||||
import { computed, ref } from 'vue';
|
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
|
||||||
|
|
||||||
import { Button } from 'antdv-next';
|
|
||||||
|
|
||||||
import { useVbenForm } from '#/adapter/form';
|
|
||||||
import { createNotice, updateNotice } from '#/api/system/notice';
|
|
||||||
import { $t } from '#/locales';
|
|
||||||
|
|
||||||
import { useFormSchema } from '../data';
|
|
||||||
|
|
||||||
const emit = defineEmits<{
|
|
||||||
success: [];
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const formData = ref<Partial<SystemNoticeApi.NoticeItem>>();
|
|
||||||
const getTitle = computed(() => {
|
|
||||||
return formData.value?.id
|
|
||||||
? $t('ui.actionTitle.edit', [$t('system.notice.name')])
|
|
||||||
: $t('ui.actionTitle.create', [$t('system.notice.name')]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const [Form, formApi] = useVbenForm({
|
|
||||||
layout: 'vertical',
|
|
||||||
schema: useFormSchema(),
|
|
||||||
showDefaultActions: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
|
||||||
async onConfirm() {
|
|
||||||
const { valid } = await formApi.validate();
|
|
||||||
if (!valid) return;
|
|
||||||
|
|
||||||
modalApi.lock();
|
|
||||||
const data = (await formApi.getValues()) as SystemNoticeApi.NoticeInput;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const currentId = formData.value?.id;
|
|
||||||
await (currentId ? updateNotice(currentId, data) : createNotice(data));
|
|
||||||
modalApi.close();
|
|
||||||
emit('success');
|
|
||||||
} finally {
|
|
||||||
modalApi.lock(false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onOpenChange(isOpen) {
|
|
||||||
if (!isOpen) return;
|
|
||||||
const data = modalApi.getData<Partial<SystemNoticeApi.NoticeItem>>();
|
|
||||||
formData.value = data || undefined;
|
|
||||||
resetForm();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function getFormValues() {
|
|
||||||
return {
|
|
||||||
content: formData.value?.content || '',
|
|
||||||
isTop: formData.value?.isTop ?? false,
|
|
||||||
level: formData.value?.level ?? 1,
|
|
||||||
notifyUsers: formData.value?.notifyUsers || '',
|
|
||||||
status: formData.value?.status ?? 1,
|
|
||||||
summary: formData.value?.summary || '',
|
|
||||||
title: formData.value?.title || '',
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetForm() {
|
|
||||||
formApi.resetForm();
|
|
||||||
formApi.setValues(getFormValues());
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Modal :title="getTitle">
|
|
||||||
<Form class="mx-4" />
|
|
||||||
<template #prepend-footer>
|
|
||||||
<div class="flex-auto">
|
|
||||||
<Button type="primary" danger @click="resetForm">
|
|
||||||
{{ $t('common.reset') }}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</Modal>
|
|
||||||
</template>
|
|
||||||
Loading…
Reference in New Issue
Block a user