update 优化 通知公告页面增加查看详情功能 支持预览已经编辑好的富文本内容
update 优化 消息盒子相关消息可直接跳转到详情页展示富文本内容
This commit is contained in:
@@ -70,10 +70,7 @@ const onNewsClick = async (item: any) => {
|
|||||||
currentNewsList.value[item].read = true;
|
currentNewsList.value[item].read = true;
|
||||||
const current = currentNewsList.value[item];
|
const current = currentNewsList.value[item];
|
||||||
if (current?.path) {
|
if (current?.path) {
|
||||||
await router.push({
|
await router.push(current.path);
|
||||||
path: current.path,
|
|
||||||
query: current.query || undefined
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ export interface NoticeItem {
|
|||||||
content?: string;
|
content?: string;
|
||||||
data?: Record<string, any> | null;
|
data?: Record<string, any> | null;
|
||||||
path?: string;
|
path?: string;
|
||||||
query?: Record<string, any> | null;
|
|
||||||
time: string;
|
time: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export interface PushMessagePayload {
|
|||||||
message?: string;
|
message?: string;
|
||||||
data?: Record<string, any> | null;
|
data?: Record<string, any> | null;
|
||||||
path?: string;
|
path?: string;
|
||||||
query?: Record<string, any> | null;
|
|
||||||
timestamp?: number;
|
timestamp?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +39,6 @@ export const parsePushMessage = (raw: string): PushMessagePayload => {
|
|||||||
message: payload.message ?? '',
|
message: payload.message ?? '',
|
||||||
data: payload.data ?? null,
|
data: payload.data ?? null,
|
||||||
path: payload.path,
|
path: payload.path,
|
||||||
query: payload.query ?? null,
|
|
||||||
timestamp: payload.timestamp ?? Date.now()
|
timestamp: payload.timestamp ?? Date.now()
|
||||||
};
|
};
|
||||||
} catch {
|
} catch {
|
||||||
@@ -50,7 +48,6 @@ export const parsePushMessage = (raw: string): PushMessagePayload => {
|
|||||||
message: raw,
|
message: raw,
|
||||||
data: null,
|
data: null,
|
||||||
path: undefined,
|
path: undefined,
|
||||||
query: null,
|
|
||||||
timestamp: Date.now()
|
timestamp: Date.now()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const appendNotice = (raw: string) => {
|
|||||||
content: payload.data?.noticeContent,
|
content: payload.data?.noticeContent,
|
||||||
data: payload.data,
|
data: payload.data,
|
||||||
path: payload.path,
|
path: payload.path,
|
||||||
query: payload.query,
|
|
||||||
read: false,
|
read: false,
|
||||||
time: new Date(payload.timestamp ?? Date.now()).toLocaleString()
|
time: new Date(payload.timestamp ?? Date.now()).toLocaleString()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -73,6 +73,9 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
|
<el-tooltip content="详情" placement="top">
|
||||||
|
<el-button link type="primary" icon="View" @click="handleDetail(scope.row)"></el-button>
|
||||||
|
</el-tooltip>
|
||||||
<el-tooltip content="修改" placement="top">
|
<el-tooltip content="修改" placement="top">
|
||||||
<el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
|
<el-button v-hasPermi="['system:notice:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
@@ -122,6 +125,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog v-model="detailDialog.visible" title="公告详情" width="820px" append-to-body @closed="handleDetailDialogClosed">
|
||||||
|
<div class="notice-detail">
|
||||||
|
<div class="notice-detail__header">
|
||||||
|
<div class="notice-detail__title">{{ detailForm.noticeTitle || '-' }}</div>
|
||||||
|
<div class="notice-detail__meta">
|
||||||
|
<div class="notice-detail__meta-item">
|
||||||
|
<span class="notice-detail__meta-label">类型:</span>
|
||||||
|
<dict-tag :options="sys_notice_type" :value="detailForm.noticeType" />
|
||||||
|
</div>
|
||||||
|
<div class="notice-detail__meta-item">
|
||||||
|
<span class="notice-detail__meta-label">状态:</span>
|
||||||
|
<dict-tag :options="sys_notice_status" :value="detailForm.status" />
|
||||||
|
</div>
|
||||||
|
<div class="notice-detail__meta-item">
|
||||||
|
<span class="notice-detail__meta-label">创建者:</span>
|
||||||
|
<span>{{ detailForm.createByName || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="notice-detail__meta-item">
|
||||||
|
<span class="notice-detail__meta-label">创建时间:</span>
|
||||||
|
<span>{{ proxy.parseTime(detailForm.createTime, '{y}-{m}-{d} {h}:{i}:{s}') || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="notice-detail__content" v-html="detailForm.noticeContent || '<p>暂无公告内容</p>'"></div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -131,6 +162,8 @@ import { NoticeForm, NoticeQuery, NoticeVO } from '@/api/system/notice/types';
|
|||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict('sys_notice_status', 'sys_notice_type'));
|
const { sys_notice_status, sys_notice_type } = toRefs<any>(proxy?.useDict('sys_notice_status', 'sys_notice_type'));
|
||||||
|
const route = useRoute();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const noticeList = ref<NoticeVO[]>([]);
|
const noticeList = ref<NoticeVO[]>([]);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
@@ -147,6 +180,10 @@ const dialog = reactive<DialogOption>({
|
|||||||
visible: false,
|
visible: false,
|
||||||
title: ''
|
title: ''
|
||||||
});
|
});
|
||||||
|
const detailDialog = reactive({
|
||||||
|
visible: false
|
||||||
|
});
|
||||||
|
const routeDetailSyncing = ref(false);
|
||||||
|
|
||||||
const initFormData: NoticeForm = {
|
const initFormData: NoticeForm = {
|
||||||
noticeId: undefined,
|
noticeId: undefined,
|
||||||
@@ -157,6 +194,7 @@ const initFormData: NoticeForm = {
|
|||||||
remark: '',
|
remark: '',
|
||||||
createByName: ''
|
createByName: ''
|
||||||
};
|
};
|
||||||
|
const detailForm = ref<NoticeVO>({} as NoticeVO);
|
||||||
const data = reactive<PageData<NoticeForm, NoticeQuery>>({
|
const data = reactive<PageData<NoticeForm, NoticeQuery>>({
|
||||||
form: { ...initFormData },
|
form: { ...initFormData },
|
||||||
queryParams: {
|
queryParams: {
|
||||||
@@ -227,6 +265,31 @@ const handleUpdate = async (row?: NoticeVO) => {
|
|||||||
dialog.visible = true;
|
dialog.visible = true;
|
||||||
dialog.title = '修改公告';
|
dialog.title = '修改公告';
|
||||||
};
|
};
|
||||||
|
/** 详情按钮操作 */
|
||||||
|
const handleDetail = async (row: NoticeVO) => {
|
||||||
|
await openDetail(row.noticeId);
|
||||||
|
};
|
||||||
|
/** 打开详情 */
|
||||||
|
const openDetail = async (noticeId: string | number) => {
|
||||||
|
const { data } = await getNotice(noticeId);
|
||||||
|
detailForm.value = data;
|
||||||
|
detailDialog.visible = true;
|
||||||
|
};
|
||||||
|
/** 详情弹窗关闭后移除路由参数 */
|
||||||
|
const handleDetailDialogClosed = async () => {
|
||||||
|
if (!route.query.noticeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
routeDetailSyncing.value = true;
|
||||||
|
await router.replace({
|
||||||
|
path: route.path,
|
||||||
|
query: {
|
||||||
|
...route.query,
|
||||||
|
noticeId: undefined
|
||||||
|
}
|
||||||
|
});
|
||||||
|
routeDetailSyncing.value = false;
|
||||||
|
};
|
||||||
/** 提交按钮 */
|
/** 提交按钮 */
|
||||||
const submitForm = () => {
|
const submitForm = () => {
|
||||||
noticeFormRef.value?.validate(async (valid: boolean) => {
|
noticeFormRef.value?.validate(async (valid: boolean) => {
|
||||||
@@ -250,10 +313,69 @@ const handleDelete = async (row?: NoticeVO) => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.query.noticeId,
|
||||||
|
async (noticeId) => {
|
||||||
|
if (routeDetailSyncing.value || !noticeId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await openDetail(String(noticeId));
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@use '@/assets/styles/components/page-shell' as pageShell;
|
@use '@/assets/styles/components/page-shell' as pageShell;
|
||||||
|
|
||||||
@include pageShell.table-crud-page;
|
@include pageShell.table-crud-page;
|
||||||
|
|
||||||
|
.notice-detail {
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12px 20px;
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta-item {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta-label {
|
||||||
|
color: var(--el-text-color-secondary);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
max-height: 60vh;
|
||||||
|
overflow: auto;
|
||||||
|
color: var(--el-text-color-primary);
|
||||||
|
line-height: 1.8;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.notice-detail__meta-item > div) {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user