优化
This commit is contained in:
@@ -18,7 +18,12 @@ function search(){page.value===1?void load():page.value=1}
|
||||
async function action(row:NotificationTask,type:'cancel'|'retry'){try{await ElMessageBox.confirm(type==='cancel'?'确定取消该消息任务吗?':'确定重试该消息任务吗?',type==='cancel'?'取消任务':'重试任务',{type:'warning',customClass:'admin-density-confirm'});actionId.value=row.id;if(type==='cancel')await cancelTask(row.id);else await retryTask(row.id);ElMessage.success(type==='cancel'?'任务已取消':'任务已提交重试');await load()}catch(e){if(e!=='cancel'&&e!=='close')ElMessage.error(getApiErrorMessage(e,type==='cancel'?'取消失败':'重试失败'))}finally{actionId.value=''}}
|
||||
watch([page,pageSize],load);onMounted(()=>{void load();void loadTemplates()})
|
||||
</script>
|
||||
<template><AdminPage class="admin-density"><ListPageLayout aria-label="消息管理列表"><template #toolbar><QueryToolbar v-model="filters" class="surface-panel" ariaLabel="消息任务筛选" :fields="queryFields" preference-key="notifications-messages-query" @search="search" /></template><template v-if="error" #state><LoadErrorState title="消息任务加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState></template><section v-if="!error" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" preference-key="notifications-messages-table" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息任务"><template #toolbar-actions><el-button v-if="access.can('platform:notification:create')" type="primary" :disabled="!templates.length" @click="composerOpen=true"><Plus :size="16"/>新建消息</el-button></template><template #pagination-left><span>共 {{ result.total }} 个任务</span></template><template #actions="{row}"><div class="density-actions"><el-button class="density-action" data-tone="neutral" @click="openDetail(row as NotificationTask)">查看</el-button><el-button v-if="access.can('platform:notification:task:cancel')&&['CREATED','SCHEDULED'].includes((row as NotificationTask).status)" class="density-action" data-tone="danger" :loading="actionId===(row as NotificationTask).id" @click="action(row as NotificationTask,'cancel')">取消</el-button><el-button v-if="access.can('platform:notification:task:retry')&&['RETRYING','DEAD'].includes((row as NotificationTask).status)" class="density-action" data-tone="neutral" :loading="actionId===(row as NotificationTask).id" @click="action(row as NotificationTask,'retry')">重试</el-button></div></template><template #category="{row}">{{notificationCategoryLabel((row as NotificationTask).category)}}</template><template #scheduledAt="{row}">{{formatDate((row as NotificationTask).scheduledAt)}}</template><template #sentAt="{row}">{{formatDate((row as NotificationTask).sentAt)}}</template><template #status="{row}"><el-tag>{{statusLabel((row as NotificationTask).status)}}</el-tag></template></DataTable></section></ListPageLayout><MessageComposerDialog v-model="composerOpen" :templates="templates" @success="load"/><AppDrawer class="admin-density admin-density-drawer" v-model="detailOpen" title="消息任务详情" size="min(820px, 94vw)" :loading="detailLoading" :show-footer="false" destroy-on-close><LoadErrorState v-if="detailError" title="消息任务详情加载失败" :message="detailError.message" :loading="detailLoading"><template #details><ApiErrorMeta :details="detailError" /></template></LoadErrorState><template v-else-if="detail"><dl class="detail-grid density-fields"><div><dt>任务号</dt><dd>{{detail.taskNo}}</dd></div><div><dt>状态</dt><dd>{{statusLabel(detail.status)}}</dd></div><div><dt>业务分类</dt><dd>{{notificationCategoryLabel(detail.category)}}</dd></div><div><dt>接收人数</dt><dd>{{detail.recipientCount}}</dd></div><div><dt>尝试次数</dt><dd>{{detail.attemptCount}}</dd></div><div><dt>发送时间</dt><dd>{{formatDate(detail.sentAt)}}</dd></div></dl><section v-if="detail.lastError" class="failure-panel" role="alert"><strong>任务失败原因</strong><p>{{detail.lastError}}</p></section><h3 class="recipient-heading">收件人投递明细</h3><el-table :data="detail.recipients" row-key="id" empty-text="暂无收件人明细" size="small"><el-table-column prop="displayName" label="收件人" min-width="150"/><el-table-column label="应用端" width="110"><template #default="{row}">{{notificationAppLabel(row.appCode)}}</template></el-table-column><el-table-column label="投递状态" width="120"><template #default="{row}">{{notificationRecipientStatusLabel(row.status)}}</template></el-table-column><el-table-column label="送达时间" width="180"><template #default="{row}">{{formatDate(row.deliveredAt)}}</template></el-table-column><el-table-column prop="failureReason" label="失败原因" min-width="220"><template #default="{row}">{{row.failureReason||'—'}}</template></el-table-column></el-table></template></AppDrawer></AdminPage></template>
|
||||
<template><AdminPage class="admin-density"><ListPageLayout aria-label="消息管理列表"><section><DataTable appearance="integrated" :stripe="false" column-settings-mode="show" :results-visible="!error" v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" preference-key="notifications-messages-table" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息任务">
|
||||
<template #toolbar-start><h1>消息管理</h1></template>
|
||||
<template #filters><QueryToolbar v-model="filters" ariaLabel="消息任务筛选" :fields="queryFields" preference-key="notifications-messages-query" @search="search" /></template>
|
||||
<template #notices><template v-if="error"><LoadErrorState title="消息任务加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState></template></template>
|
||||
|
||||
<template #toolbar-actions><el-button v-if="access.can('platform:notification:create')" type="primary" :disabled="!templates.length" @click="composerOpen=true"><Plus :size="16"/>新建消息</el-button></template><template #pagination-left><span>共 {{ result.total }} 个任务</span></template><template #actions="{row}"><div class="density-actions row-actions admin-text-actions"><el-button class="density-action" data-tone="neutral" @click="openDetail(row as NotificationTask)">查看</el-button><el-button v-if="access.can('platform:notification:task:cancel')&&['CREATED','SCHEDULED'].includes((row as NotificationTask).status)" class="density-action" data-tone="danger" :loading="actionId===(row as NotificationTask).id" @click="action(row as NotificationTask,'cancel')">取消</el-button><el-button v-if="access.can('platform:notification:task:retry')&&['RETRYING','DEAD'].includes((row as NotificationTask).status)" class="density-action" data-tone="neutral" :loading="actionId===(row as NotificationTask).id" @click="action(row as NotificationTask,'retry')">重试</el-button></div></template><template #category="{row}">{{notificationCategoryLabel((row as NotificationTask).category)}}</template><template #scheduledAt="{row}">{{formatDate((row as NotificationTask).scheduledAt)}}</template><template #sentAt="{row}">{{formatDate((row as NotificationTask).sentAt)}}</template><template #status="{row}"><el-tag>{{statusLabel((row as NotificationTask).status)}}</el-tag></template></DataTable></section></ListPageLayout><MessageComposerDialog v-model="composerOpen" :templates="templates" @success="load"/><AppDrawer class="admin-density admin-density-drawer" v-model="detailOpen" title="消息任务详情" size="min(820px, 94vw)" :loading="detailLoading" :show-footer="false" destroy-on-close><LoadErrorState v-if="detailError" title="消息任务详情加载失败" :message="detailError.message" :loading="detailLoading"><template #details><ApiErrorMeta :details="detailError" /></template></LoadErrorState><template v-else-if="detail"><dl class="detail-grid density-fields"><div><dt>任务号</dt><dd>{{detail.taskNo}}</dd></div><div><dt>状态</dt><dd>{{statusLabel(detail.status)}}</dd></div><div><dt>业务分类</dt><dd>{{notificationCategoryLabel(detail.category)}}</dd></div><div><dt>接收人数</dt><dd>{{detail.recipientCount}}</dd></div><div><dt>尝试次数</dt><dd>{{detail.attemptCount}}</dd></div><div><dt>发送时间</dt><dd>{{formatDate(detail.sentAt)}}</dd></div></dl><section v-if="detail.lastError" class="failure-panel" role="alert"><strong>任务失败原因</strong><p>{{detail.lastError}}</p></section><h3 class="recipient-heading">收件人投递明细</h3><el-table :data="detail.recipients" row-key="id" empty-text="暂无收件人明细" size="small"><el-table-column prop="displayName" label="收件人" min-width="150"/><el-table-column label="应用端" width="110"><template #default="{row}">{{notificationAppLabel(row.appCode)}}</template></el-table-column><el-table-column label="投递状态" width="120"><template #default="{row}">{{notificationRecipientStatusLabel(row.status)}}</template></el-table-column><el-table-column label="送达时间" width="180"><template #default="{row}">{{formatDate(row.deliveredAt)}}</template></el-table-column><el-table-column prop="failureReason" label="失败原因" min-width="220"><template #default="{row}">{{row.failureReason||'—'}}</template></el-table-column></el-table></template></AppDrawer></AdminPage></template>
|
||||
<style scoped>
|
||||
.detail-grid.density-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-bottom: var(--admin-space-6); }
|
||||
.failure-panel { margin-bottom: var(--admin-space-6); padding: var(--admin-space-5); border: 1px solid #f2b8b5; border-radius: var(--admin-radius); background: #fff7f6; color: #9f2d27; }
|
||||
|
||||
@@ -11,4 +11,9 @@ function search(){page.value===1?void load():page.value=1}function create(){edit
|
||||
async function changeStatus(row:NotificationTemplate){const target=row.status==='DRAFT'?'ACTIVE':'DISABLED';try{await ElMessageBox.confirm(target==='ACTIVE'?'激活后模板不可再编辑,确定继续吗?':'禁用后首期不可重新启用,确定继续吗?',target==='ACTIVE'?'激活模板':'禁用模板',{type:'warning',customClass:'admin-density-confirm'});actionId.value=row.id;await changeTemplateStatus(row.id,target,row.version);ElMessage.success(target==='ACTIVE'?'模板已激活':'模板已禁用');await load()}catch(e){if(e!=='cancel'&&e!=='close')ElMessage.error(getApiErrorMessage(e,'模板状态变更失败'))}finally{actionId.value=''}}
|
||||
watch([page,pageSize],load);onMounted(load)
|
||||
</script>
|
||||
<template><AdminPage class="admin-density"><ListPageLayout aria-label="消息模板列表"><template #toolbar><QueryToolbar v-model="filters" class="surface-panel" ariaLabel="消息模板筛选" :fields="queryFields" preference-key="notifications-templates-query" @search="search"/></template><template v-if="error" #state><LoadErrorState title="模板加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error"/></template></LoadErrorState></template><section v-if="!error" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" preference-key="notifications-templates-table" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息模板"><template #toolbar-actions><el-button v-if="access.can('platform:notification:template:create')" type="primary" @click="create"><Plus :size="16"/>新增模板</el-button></template><template #pagination-left><span>共 {{result.total}} 个模板</span></template><template #actions="{row}"><div class="density-actions"><el-button v-if="access.can('platform:notification:template:edit')&&(row as NotificationTemplate).status==='DRAFT'" class="density-action" data-tone="neutral" @click="edit(row as NotificationTemplate)">编辑</el-button><el-button v-if="access.can('platform:notification:template:status')&&(row as NotificationTemplate).status!=='DISABLED'" class="density-action" :data-tone="(row as NotificationTemplate).status==='ACTIVE'?'danger':'success'" :loading="actionId===(row as NotificationTemplate).id" @click="changeStatus(row as NotificationTemplate)">{{(row as NotificationTemplate).status==='DRAFT'?'激活':'禁用'}}</el-button></div></template><template #status="{row}"><el-tag>{{statusLabel((row as NotificationTemplate).status)}}</el-tag></template></DataTable></section></ListPageLayout><TemplateEditorDialog v-model="editorOpen" :template="editing" @success="load"/></AdminPage></template>
|
||||
<template><AdminPage class="admin-density"><ListPageLayout aria-label="消息模板列表"><section><DataTable appearance="integrated" :stripe="false" column-settings-mode="show" :results-visible="!error" v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" preference-key="notifications-templates-table" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息模板">
|
||||
<template #toolbar-start><h1>模板管理</h1></template>
|
||||
<template #filters><QueryToolbar v-model="filters" ariaLabel="消息模板筛选" :fields="queryFields" preference-key="notifications-templates-query" @search="search"/></template>
|
||||
<template #notices><template v-if="error"><LoadErrorState title="模板加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error"/></template></LoadErrorState></template></template>
|
||||
|
||||
<template #toolbar-actions><el-button v-if="access.can('platform:notification:template:create')" type="primary" @click="create"><Plus :size="16"/>新增模板</el-button></template><template #pagination-left><span>共 {{result.total}} 个模板</span></template><template #actions="{row}"><div class="density-actions row-actions admin-text-actions"><el-button v-if="access.can('platform:notification:template:edit')&&(row as NotificationTemplate).status==='DRAFT'" class="density-action" data-tone="neutral" @click="edit(row as NotificationTemplate)">编辑</el-button><el-button v-if="access.can('platform:notification:template:status')&&(row as NotificationTemplate).status!=='DISABLED'" class="density-action" :data-tone="(row as NotificationTemplate).status==='ACTIVE'?'danger':'success'" :loading="actionId===(row as NotificationTemplate).id" @click="changeStatus(row as NotificationTemplate)">{{(row as NotificationTemplate).status==='DRAFT'?'激活':'禁用'}}</el-button></div></template><template #status="{row}"><el-tag>{{statusLabel((row as NotificationTemplate).status)}}</el-tag></template></DataTable></section></ListPageLayout><TemplateEditorDialog v-model="editorOpen" :template="editing" @success="load"/></AdminPage></template>
|
||||
|
||||
@@ -81,18 +81,21 @@ onMounted(() => void load())
|
||||
<template>
|
||||
<AdminPage class="admin-density">
|
||||
<ListPageLayout aria-label="我的消息列表">
|
||||
<template #toolbar><QueryToolbar v-model="filters" class="surface-panel" ariaLabel="我的消息筛选" :fields="queryFields" preference-key="notifications-inbox-query" @search="search" /></template>
|
||||
<template v-if="error" #state><LoadErrorState title="我的消息加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState></template>
|
||||
<section v-if="!error" class="surface-panel table-panel">
|
||||
<DataTable v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息">
|
||||
|
||||
|
||||
<section><DataTable preference-key="notifications-platformnotificationsview" appearance="integrated" :stripe="false" column-settings-mode="show" :results-visible="!error" v-model:page="page" v-model:page-size="pageSize" :data="result.records" :columns="columns" :loading="loading" :total="result.total" row-key="id" empty-text="暂无消息">
|
||||
<template #toolbar-start><h1>我的消息</h1></template>
|
||||
<template #filters><QueryToolbar v-model="filters" ariaLabel="我的消息筛选" :fields="queryFields" preference-key="notifications-inbox-query" @search="search" /></template>
|
||||
<template #notices><template v-if="error"><LoadErrorState title="我的消息加载失败" :message="error.message" :loading="loading" @retry="load"><template #details><ApiErrorMeta :details="error" /></template></LoadErrorState></template></template>
|
||||
|
||||
|
||||
<template #toolbar-actions><el-button v-if="canReadAll && unreadCount" type="primary" plain :disabled="loading" @click="markAllRead"><CheckCheck :size="16" />全部标为已读</el-button></template>
|
||||
<template #pagination-left><span>共 {{ result.total }} 条<span v-if="unreadCount">,未读 {{ unreadCount }} 条</span></span></template>
|
||||
<template #actions="{ row }"><div class="density-actions"><el-button class="density-action" data-tone="neutral" @click="openDetail(row as NotificationInboxItem)">查看</el-button><el-button v-if="canRead && (row as NotificationInboxItem).status === 'UNREAD'" class="density-action" data-tone="neutral" @click="markRead(row as NotificationInboxItem)">标为已读</el-button></div></template>
|
||||
<template #actions="{ row }"><div class="density-actions row-actions admin-text-actions"><el-button class="density-action" data-tone="neutral" @click="openDetail(row as NotificationInboxItem)">查看</el-button><el-button v-if="canRead && (row as NotificationInboxItem).status === 'UNREAD'" class="density-action" data-tone="neutral" @click="markRead(row as NotificationInboxItem)">标为已读</el-button></div></template>
|
||||
<template #category="{ row }">{{ notificationCategoryLabel((row as NotificationInboxItem).category) }}</template>
|
||||
<template #sentAt="{ row }">{{ formatDate((row as NotificationInboxItem).sentAt) }}</template>
|
||||
<template #status="{ row }"><el-tag :type="(row as NotificationInboxItem).status === 'UNREAD' ? 'danger' : 'info'">{{ statusLabel((row as NotificationInboxItem).status) }}</el-tag></template>
|
||||
</DataTable>
|
||||
</section>
|
||||
</DataTable></section>
|
||||
</ListPageLayout>
|
||||
<AppDrawer class="admin-density admin-density-drawer" v-model="detailOpen" title="消息详情" size="min(680px, 94vw)" :loading="detailLoading" :show-footer="false" destroy-on-close>
|
||||
<LoadErrorState v-if="detailError" title="消息详情加载失败" :message="detailError.message" :loading="detailLoading"><template #details><ApiErrorMeta :details="detailError" /></template></LoadErrorState>
|
||||
|
||||
@@ -5,18 +5,18 @@ export const notificationRoutes = [
|
||||
path: 'notifications',
|
||||
name: 'notification-inbox',
|
||||
component: () => import('@/modules/notifications/pages/PlatformNotificationsView.vue'),
|
||||
meta: { title: '我的消息', description: '查看当前平台账号的站内消息', permission: 'platform:notification:view' },
|
||||
meta: { showPageHeading: false, title: '我的消息', description: '查看当前平台账号的站内消息', permission: 'platform:notification:view' },
|
||||
},
|
||||
{
|
||||
path: 'notifications/messages',
|
||||
name: 'notification-messages',
|
||||
component: () => import('@/modules/notifications/pages/MessageManagementView.vue'),
|
||||
meta: { title: '消息管理', description: '创建并管理平台站内消息', permission: 'platform:notification:task:list' },
|
||||
meta: { showPageHeading: false, title: '消息管理', description: '创建并管理平台站内消息', permission: 'platform:notification:task:list' },
|
||||
},
|
||||
{
|
||||
path: 'notifications/templates',
|
||||
name: 'notification-templates',
|
||||
component: () => import('@/modules/notifications/pages/MessageTemplatesView.vue'),
|
||||
meta: { title: '模板管理', description: '维护平台站内消息模板', permission: 'platform:notification:template:list' },
|
||||
meta: { showPageHeading: false, title: '模板管理', description: '维护平台站内消息模板', permission: 'platform:notification:template:list' },
|
||||
},
|
||||
] satisfies RouteRecordRaw[]
|
||||
|
||||
Reference in New Issue
Block a user