141 lines
3.2 KiB
Vue
141 lines
3.2 KiB
Vue
<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>
|