mirror of https://github.com/halo-dev/halo
Optimize comment notification template to support rich text rendering (#7683)
#### What type of PR is this? /area core /area ui /milestone 2.21.x /kind feature #### What this PR does / why we need it: Optimize comment notification template to support rich text rendering #### Does this PR introduce a user-facing change? ```release-note None ```pull/7685/head
parent
eddcb5bc38
commit
2bcfbbc371
|
@ -25,7 +25,7 @@ spec:
|
|||
<a th:href="${postUrl}" target="_blank" th:text="|《${postTitle}》|"></a>
|
||||
<span>,以下是评论的具体内容:</span>
|
||||
</p>
|
||||
<pre class="content" th:text="${content}"></pre>
|
||||
<div class="content" th:utext="${content}"></div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
@ -58,7 +58,7 @@ spec:
|
|||
<a th:href="${pageUrl}" target="_blank" th:text="|《${pageTitle}》|"></a>
|
||||
<span>,以下是评论的具体内容:</span>
|
||||
</p>
|
||||
<pre class="content" th:text="${content}"></pre>
|
||||
<div class="content" th:utext="${content}"></div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
@ -87,15 +87,18 @@ spec:
|
|||
</div>
|
||||
<div class="body">
|
||||
<p>
|
||||
<span th:text="${replier}"></span> 在评论
|
||||
<span th:text="${replier}"></span> 在
|
||||
<a
|
||||
th:href="${commentSubjectUrl}"
|
||||
target="_blank"
|
||||
th:text="|”${isQuoteReply ? quoteContent : commentContent}”|"
|
||||
th:text="|《${commentSubjectTitle}》|"
|
||||
></a>
|
||||
<span>中回复了你,以下是回复的具体内容:</span>
|
||||
<span>中回复了你。</span>
|
||||
</p>
|
||||
<pre class="content" th:text="${content}"></pre>
|
||||
<p>你的评论:</p>
|
||||
<div class="content" th:utext="${isQuoteReply ? quoteContent : commentContent}"></div>
|
||||
<p>回复的内容:</p>
|
||||
<div class="content" th:utext="${content}"></div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
} from "@halo-dev/components";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||
import sanitize from "sanitize-html";
|
||||
|
||||
const { currentUser } = useUserStore();
|
||||
|
||||
|
@ -81,7 +82,12 @@ function handleRouteToNotification(notification: Notification) {
|
|||
<template #start>
|
||||
<VEntityField
|
||||
:title="notification.spec?.title"
|
||||
:description="notification.spec?.rawContent"
|
||||
:description="
|
||||
sanitize(notification.spec?.htmlContent || '', {
|
||||
allowedTags: [],
|
||||
allowedAttributes: {},
|
||||
})
|
||||
"
|
||||
@click="handleRouteToNotification(notification)"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -231,7 +231,9 @@ function handleMarkAllAsRead() {
|
|||
</Transition>
|
||||
</OverlayScrollbarsComponent>
|
||||
</div>
|
||||
<div class="col-span-12 sm:col-span-6 lg:col-span-7 xl:col-span-9">
|
||||
<div
|
||||
class="col-span-12 overflow-auto sm:col-span-6 lg:col-span-7 xl:col-span-9"
|
||||
>
|
||||
<NotificationContent :notification="selectedNotification" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts" setup>
|
||||
import type { Notification } from "@halo-dev/api-client";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
|
||||
import sanitize from "sanitize-html";
|
||||
import { computed } from "vue";
|
||||
|
||||
const props = withDefaults(
|
||||
|
@ -10,34 +11,28 @@ const props = withDefaults(
|
|||
{ notification: undefined }
|
||||
);
|
||||
|
||||
const htmlContent = computed(() => {
|
||||
const styles = `
|
||||
<style>
|
||||
html {
|
||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
|
||||
if (!props.notification?.spec?.htmlContent) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return styles + props.notification?.spec?.htmlContent;
|
||||
const content = computed(() => {
|
||||
return sanitize(props.notification?.spec?.htmlContent || "");
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full w-full overflow-auto">
|
||||
<OverlayScrollbarsComponent
|
||||
element="div"
|
||||
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||
class="h-full w-full"
|
||||
defer
|
||||
>
|
||||
<iframe class="h-full w-full p-2" :srcdoc="htmlContent"></iframe>
|
||||
</OverlayScrollbarsComponent>
|
||||
</div>
|
||||
<OverlayScrollbarsComponent
|
||||
element="div"
|
||||
:options="{ scrollbars: { autoHide: 'scroll' } }"
|
||||
class="h-full w-full"
|
||||
defer
|
||||
>
|
||||
<div class="markdown-body h-full w-full p-2 text-sm" v-html="content"></div>
|
||||
</OverlayScrollbarsComponent>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.markdown-body :deep(ul) {
|
||||
list-style: disc !important;
|
||||
}
|
||||
|
||||
.markdown-body :deep(ol) {
|
||||
list-style: decimal !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -5,7 +5,8 @@ import type { Notification } from "@halo-dev/api-client";
|
|||
import { ucApiClient } from "@halo-dev/api-client";
|
||||
import { Dialog, Toast, VStatusDot } from "@halo-dev/components";
|
||||
import { useMutation, useQueryClient } from "@tanstack/vue-query";
|
||||
import { ref, watch } from "vue";
|
||||
import sanitize from "sanitize-html";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
@ -74,6 +75,14 @@ watch(
|
|||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
const content = computed(() => {
|
||||
// Clean html tags
|
||||
return sanitize(props.notification.spec?.htmlContent || "", {
|
||||
allowedTags: [],
|
||||
allowedAttributes: {},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
|
@ -99,10 +108,10 @@ watch(
|
|||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="notification.spec?.rawContent"
|
||||
class="truncate text-xs text-gray-600"
|
||||
v-if="notification.spec?.htmlContent"
|
||||
class="line-clamp-1 text-xs text-gray-600"
|
||||
>
|
||||
{{ notification.spec.rawContent }}
|
||||
{{ content }}
|
||||
</div>
|
||||
<div class="flex h-6 items-end justify-between">
|
||||
<div class="text-xs text-gray-600">
|
||||
|
|
Loading…
Reference in New Issue