431 lines
12 KiB
Vue
431 lines
12 KiB
Vue
<template>
|
|
<div v-if="previewMode">
|
|
<component :is="'style'" v-html="styles" />
|
|
<div
|
|
class="container py-6"
|
|
:style="{
|
|
minHeight: '100%',
|
|
backgroundColor: 'hsl(0, 0%, 97%)',
|
|
fontFamily: '-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, sans-serif',
|
|
}"
|
|
>
|
|
<table
|
|
role="presentation"
|
|
cellspacing="0"
|
|
cellpadding="0"
|
|
border="0"
|
|
:style="{
|
|
width: '100%',
|
|
maxWidth: '100%',
|
|
margin: '0 auto',
|
|
}"
|
|
>
|
|
<tbody>
|
|
<tr>
|
|
<td>
|
|
<table
|
|
role="presentation"
|
|
class="email-container gmail-fix"
|
|
cellspacing="0"
|
|
cellpadding="0"
|
|
border="0"
|
|
:style="{
|
|
margin: '0 auto',
|
|
width: '100%',
|
|
maxWidth: '680px',
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: '16px',
|
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)',
|
|
overflow: 'hidden',
|
|
}"
|
|
>
|
|
<tbody>
|
|
<tr class="header-row">
|
|
<td :style="{ padding: '0' }">
|
|
<div
|
|
class="header-image"
|
|
:style="{
|
|
background: '#f3f4f6',
|
|
position: 'relative',
|
|
width: '100%',
|
|
height: '425px',
|
|
overflow: 'hidden',
|
|
}"
|
|
>
|
|
<img
|
|
v-if="hasValidImage"
|
|
:src="content.imageUrl"
|
|
alt="image"
|
|
:style="{
|
|
width: '100%',
|
|
height: '100%',
|
|
objectFit: 'cover',
|
|
display: 'block',
|
|
}"
|
|
/>
|
|
<div
|
|
v-else
|
|
class="is-flex is-justify-content-center is-align-items-center"
|
|
:style="{
|
|
height: '100%',
|
|
background: 'rgba(0, 0, 0, 0.3)',
|
|
opacity: 0.15,
|
|
}"
|
|
>
|
|
<SvgIcon v-bind="{ name: 'image.svg', type: 'black', size: 180 }" />
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr v-if="content.message">
|
|
<td class="content-padding" :style="{ paddingBottom: '20px', paddingTop: '30px' ,paddingRight: '25px', paddingLeft: '25px'}">
|
|
<div
|
|
:style="{
|
|
border: '1px solid #e5e7eb',
|
|
borderRadius: '12px',
|
|
backgroundColor: '#ffffff',
|
|
overflow: 'hidden',
|
|
}"
|
|
>
|
|
<div :style="{ padding: '15px' }">
|
|
<div
|
|
class="message-content"
|
|
:style="{
|
|
fontSize: '16px',
|
|
margin: '0',
|
|
color: '#374151',
|
|
lineHeight: '1.6',
|
|
wordBreak: 'break-word',
|
|
}"
|
|
>
|
|
<div class="content" v-html="processedMessage" />
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
v-if="hasValidLinks"
|
|
:style="{
|
|
padding: '15px',
|
|
paddingLeft: '35px',
|
|
borderTop: '1px solid #e5e7eb',
|
|
backgroundColor: '#f9fafb',
|
|
}"
|
|
>
|
|
<div>
|
|
<div
|
|
v-for="(link, index) in validLinks"
|
|
:key="index"
|
|
:style="{ width: '100%', marginBottom: '8px' }"
|
|
>
|
|
<ul :style="{ paddingLeft: '20px', margin: 0 }">
|
|
<li :style="{ listStyleType: 'disc' }">
|
|
<a
|
|
:style="{
|
|
color: '#2563eb!important',
|
|
fontWeight: '600',
|
|
textDecoration: 'underline',
|
|
display: 'inline-block',
|
|
wordBreak: 'break-word',
|
|
fontSize: '14px',
|
|
}"
|
|
target="_blank"
|
|
:href="link"
|
|
rel="noopener noreferrer"
|
|
>
|
|
{{ getLinkText(index) }}
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<td class="company-padding" :style="{ paddingBottom: '20px' }">
|
|
<div
|
|
class="company-info"
|
|
:style="{
|
|
background: 'linear-gradient(to right, #000000, #0f9b0f)',
|
|
color: '#ffffff',
|
|
borderRadius: '12px',
|
|
}"
|
|
>
|
|
<div
|
|
class="logo-container"
|
|
:style="{
|
|
width: '100%',
|
|
height: '100%',
|
|
marginBottom: '15px',
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: '8px',
|
|
overflow: 'hidden',
|
|
}"
|
|
>
|
|
<img
|
|
:src="imageUrl"
|
|
alt="Utopia Footer"
|
|
:style="{
|
|
width: '100%',
|
|
height: '100%',
|
|
objectFit: 'cover',
|
|
display: 'block',
|
|
}"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- <tr>
|
|
<td
|
|
:style="{
|
|
backgroundColor: '#f9fafb',
|
|
padding: '20px',
|
|
borderTop: '1px solid #e5e7eb',
|
|
textAlign: 'center',
|
|
}"
|
|
>
|
|
<p
|
|
:style="{
|
|
color: '#9ca3af',
|
|
fontSize: '11px',
|
|
margin: '0',
|
|
lineHeight: '1.5',
|
|
}"
|
|
>
|
|
©2025 Utopia. Tất cả các quyền được bảo lưu.
|
|
</p>
|
|
</td>
|
|
</tr> -->
|
|
</tbody>
|
|
</table>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { imageUrl } from '@/components/marketing/email/Email.utils';
|
|
import { computed } from "vue";
|
|
|
|
interface KeywordItem {
|
|
keyword: string;
|
|
value: string;
|
|
}
|
|
|
|
interface Template1Content {
|
|
subject?: string;
|
|
message?: string;
|
|
imageUrl?: string | null;
|
|
linkUrl?: string[];
|
|
textLinkUrl?: string[];
|
|
keyword?: KeywordItem[];
|
|
}
|
|
|
|
interface Props {
|
|
content: Template1Content;
|
|
previewMode?: boolean;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
previewMode: false,
|
|
});
|
|
|
|
const hasValidLinks = computed(() => {
|
|
return props.content.linkUrl && props.content.linkUrl.some((link) => link && link.trim() !== "");
|
|
});
|
|
|
|
const hasValidImage = computed(() => {
|
|
return props.content.imageUrl && props.content.imageUrl.trim() !== "";
|
|
});
|
|
|
|
const replaceKeywords = (content: string): string => {
|
|
if (!content) return "";
|
|
|
|
let replacedContent = content;
|
|
|
|
if (props.content.keyword && Array.isArray(props.content.keyword)) {
|
|
props.content.keyword.forEach((kw) => {
|
|
if (typeof kw !== "string" && kw.keyword && kw.value) {
|
|
const regex = new RegExp(`\\{\\{${kw.keyword}\\}\\}`, "g");
|
|
replacedContent = replacedContent.replace(regex, kw.value);
|
|
}
|
|
});
|
|
}
|
|
|
|
return replacedContent;
|
|
};
|
|
|
|
const processedMessage = computed(() => replaceKeywords(props.content.message || ""));
|
|
|
|
const validLinks = computed(() => {
|
|
if (!props.content.linkUrl || props.content.linkUrl.length === 0) return [];
|
|
return props.content.linkUrl.filter((link) => link && link.trim() !== "");
|
|
});
|
|
|
|
const getLinkText = (index: number): string => {
|
|
return props.content.textLinkUrl && props.content.textLinkUrl[index] && props.content.textLinkUrl[index].trim() !== ""
|
|
? props.content.textLinkUrl[index]
|
|
: `Link ${index + 1}`;
|
|
};
|
|
|
|
const styles = `
|
|
ol{
|
|
list-style: decimal;
|
|
}
|
|
li{
|
|
list-style: disc;
|
|
}
|
|
.greeting-padding{
|
|
padding: 30px 25px 20px;
|
|
}
|
|
|
|
.content-padding, .company-padding {
|
|
padding: 0px 25px 20px;
|
|
}
|
|
|
|
.message-content p {
|
|
margin: 0 0 12px 0;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.message-content p:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.message-content strong {
|
|
font-weight: 700;
|
|
}
|
|
|
|
.message-content em {
|
|
font-style: italic;
|
|
}
|
|
|
|
.message-content u {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.message-content s {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.message-content ol,
|
|
.message-content ul {
|
|
margin: 12px 0;
|
|
padding-left: 25px;
|
|
}
|
|
|
|
.message-content ol li,
|
|
.message-content ul li {
|
|
margin-bottom: 8px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.message-content a {
|
|
color: #2563eb;
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.message-content h1 {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
margin: 20px 0 12px 0;
|
|
line-height: 1.3;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.message-content h2 {
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
margin: 18px 0 12px 0;
|
|
line-height: 1.3;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.message-content h3 {
|
|
font-size: 20px;
|
|
font-weight: 700;
|
|
margin: 16px 0 12px 0;
|
|
line-height: 1.3;
|
|
color: #1f2937;
|
|
}
|
|
|
|
.message-content .ql-align-center {
|
|
text-align: center;
|
|
}
|
|
|
|
.message-content .ql-align-right {
|
|
text-align: right;
|
|
}
|
|
|
|
.message-content .ql-align-justify {
|
|
text-align: justify;
|
|
}
|
|
|
|
.message-content .ql-indent-1 {
|
|
padding-left: 3em;
|
|
}
|
|
|
|
.message-content .ql-indent-2 {
|
|
padding-left: 6em;
|
|
}
|
|
|
|
|
|
@media only screen and (max-width: 768px) {
|
|
|
|
.email-container {
|
|
width: 100% !important;
|
|
max-width: 100% !important;
|
|
}
|
|
|
|
.greeting-padding{
|
|
padding: 20px 0 0 0 !important;
|
|
}
|
|
|
|
.content-padding {
|
|
padding: 20px 0px !important;
|
|
}
|
|
.company-padding {
|
|
padding: 0px 0px 20px 0px !important;
|
|
}
|
|
.company-info {
|
|
padding: 20px 10px !important;
|
|
}
|
|
.greeting-title{
|
|
padding: 10px !important;
|
|
margin: 0 !important;
|
|
}
|
|
|
|
.header-image {
|
|
width: 100% !important;
|
|
height: 250px !important;
|
|
}
|
|
.greeting-text {
|
|
font-size: 12px !important;
|
|
}
|
|
.message-text {
|
|
font-size: 12px !important;
|
|
}
|
|
.logo-container {
|
|
width: 150px !important;
|
|
height: 45px !important;
|
|
}
|
|
.company-name {
|
|
font-size: 12px !important;
|
|
color: #ffffff !important;
|
|
}
|
|
.contact-info {
|
|
font-size: 11px !important;
|
|
color: #ffffff !important;
|
|
}
|
|
}
|
|
`;
|
|
</script>
|