Files
yunzerwebsiteallinone/platform/src/views/website/content/article/components/preview.vue
T
2026-09-17 23:00:06 +08:00

141 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-drawer v-model="visible" title="文章预览" size="60%">
<div class="preview" v-loading="!model">
<h1 class="preview__title">{{ model?.title || '-' }}</h1>
<div class="preview__meta">
<span v-if="model?.cate">分类:{{ model.cate }}</span>
<span v-if="model?.author">作者:{{ model.author }}</span>
<span>发布时间:{{ formatDateTime(model?.publish_time || model?.publish_date) }}</span>
<span v-if="model?.views">浏览:{{ model.views }}</span>
</div>
<el-divider />
<p v-if="model?.desc" class="preview__desc">{{ model.desc }}</p>
<img v-if="model?.image" :src="previewUrl(model.image)" class="preview__cover" alt="封面" />
<div v-if="model?.is_trans === 1 && model?.transurl" class="preview__trans">
本文为转载内容,原文地址:
<el-link type="primary" :href="model.transurl" target="_blank">{{ model.transurl }}</el-link>
</div>
<div class="preview__content" v-html="contentHtml"></div>
</div>
</el-drawer>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { formatDateTime } from '@/utils/datetime'
const props = defineProps({
modelValue: { type: Boolean, default: false },
model: { type: Object, default: null }
})
const emit = defineEmits(['update:modelValue'])
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || ''
const visible = ref(props.modelValue)
// 无正文时给出占位提示,避免抽屉内容区空白
const contentHtml = computed(
() => props.model?.content || '<p style="color:#999">暂无正文</p>'
)
watch(
() => props.modelValue,
(val) => {
visible.value = val
}
)
watch(visible, (val) => {
emit('update:modelValue', val)
})
const previewUrl = (url) => {
if (!url) return ''
if (/^https?:\/\//i.test(url)) return url
return API_BASE_URL + url
}
</script>
<style lang="less" scoped>
.preview {
padding: 0 8px 40px;
&__title {
margin: 0 0 12px;
font-size: 24px;
font-weight: 600;
line-height: 1.4;
}
&__meta {
display: flex;
flex-wrap: wrap;
gap: 16px;
font-size: 13px;
color: var(--el-text-color-secondary);
}
&__desc {
margin: 0 0 16px;
padding: 12px 14px;
background: var(--el-fill-color-light);
border-radius: 6px;
font-size: 13px;
line-height: 1.8;
color: var(--el-text-color-regular);
}
&__cover {
width: 100%;
max-height: 260px;
object-fit: cover;
border-radius: 6px;
margin-bottom: 16px;
}
&__trans {
margin-bottom: 16px;
font-size: 13px;
color: var(--el-text-color-secondary);
word-break: break-all;
}
&__content {
font-size: 15px;
line-height: 1.9;
color: var(--el-text-color-primary);
word-break: break-word;
:deep(img) {
max-width: 100%;
border-radius: 4px;
}
:deep(pre) {
padding: 12px 16px;
background: var(--el-fill-color-light);
border-radius: 4px;
overflow-x: auto;
}
:deep(table) {
width: 100%;
border-collapse: collapse;
th,
td {
border: 1px solid var(--el-border-color);
padding: 8px 12px;
}
}
}
}
</style>