侧栏「最近更新」:短文显示正文摘录(贴链接的回退到卡片标题、纯图显示占位)+ 配图短文带 34px 缩略图

This commit is contained in:
Sakurasan
2026-09-28 22:39:06 +08:00
parent da0333e09c
commit a74299d716
+56 -7
View File
@@ -3,7 +3,7 @@ import { computed, onMounted, ref } from 'vue'
import { publicApi } from '../api' import { publicApi } from '../api'
import { site } from '../site' import { site } from '../site'
import { socialIcon } from '../socialIcons' import { socialIcon } from '../socialIcons'
import { relativeDate } from '../utils' import { relativeDate, stripTags, thumbURL } from '../utils'
// vivid 是单栏布局,右栏整体不渲染(省掉 latest/tags 两次请求)。 // vivid 是单栏布局,右栏整体不渲染(省掉 latest/tags 两次请求)。
const isVivid = computed(() => site.ui_id === 'vivid') const isVivid = computed(() => site.ui_id === 'vivid')
@@ -27,6 +27,26 @@ const links = [
const latest = ref([]) const latest = ref([])
const tags = ref([]) const tags = ref([])
// 短文没有标题,侧栏拿正文开头当标识(flomo/Twitter 的做法),
// 纯图片短文显示占位;有配图时右侧带一张小缩略图。
const EXCERPT_LEN = 22
function excerpt(p) {
if (p.kind !== 'short') return p.title || '无题'
// 先剥 <a>:贴链接的短文开头是 URL 本身,摘出来没有信息量;
// 剥完没字了(纯链接贴)就退到链接卡片的标题
const noLinks = (p.content_html || '').replace(/<a\b[^>]*>[\s\S]*?<\/a>/gi, ' ')
const text = stripTags(noLinks).replace(/\s+/g, ' ').trim()
if (text) return text.length > EXCERPT_LEN ? text.slice(0, EXCERPT_LEN) + '…' : text
if (p.link_card && p.link_card.title) {
const t = p.link_card.title
return t.length > EXCERPT_LEN ? t.slice(0, EXCERPT_LEN) + '…' : t
}
return p.images && p.images.length ? '📷 图片' : '短文'
}
function thumbOf(p) {
return p.kind === 'short' && p.images && p.images.length ? thumbURL(p.images[0], 160) : ''
}
onMounted(async () => { onMounted(async () => {
if (isVivid.value) return if (isVivid.value) return
try { try {
@@ -52,12 +72,22 @@ onMounted(async () => {
<p class="eyebrow">最近更新</p> <p class="eyebrow">最近更新</p>
<ul class="list"> <ul class="list">
<li v-for="p in latest" :key="p.id"> <li v-for="p in latest" :key="p.id">
<RouterLink :to="`/post/${p.slug}`" class="row"> <RouterLink :to="`/post/${p.slug}`" class="row" :class="{ withThumb: thumbOf(p) }">
<span class="title"> <span class="row-main">
{{ p.kind === 'short' ? '短文' : p.title || '无题' }} <span class="title">
<span v-if="p.kind === 'short'" class="badge">短</span> {{ excerpt(p) }}
<span v-if="p.kind === 'short'" class="badge">短</span>
</span>
<span class="date">{{ relativeDate(p.published_at) }}</span>
</span> </span>
<span class="date">{{ relativeDate(p.published_at) }}</span> <img
v-if="thumbOf(p)"
class="thumb"
:src="thumbOf(p)"
alt=""
loading="lazy"
decoding="async"
/>
</RouterLink> </RouterLink>
</li> </li>
</ul> </ul>
@@ -152,7 +182,9 @@ onMounted(async () => {
} }
.row { .row {
display: block; display: flex;
align-items: center;
gap: 10px;
padding: 7px 0; padding: 7px 0;
border-bottom: 1px dashed var(--line-soft); border-bottom: 1px dashed var(--line-soft);
} }
@@ -161,10 +193,27 @@ onMounted(async () => {
border-bottom: 0; border-bottom: 0;
} }
/* 文字列吃满剩余宽度,缩略图固定在右 */
.row-main {
flex: 1;
min-width: 0;
}
.title { .title {
display: block; display: block;
font-size: 14px; font-size: 14px;
line-height: 1.7; line-height: 1.7;
overflow-wrap: anywhere;
}
.thumb {
flex: 0 0 auto;
width: 34px;
height: 34px;
object-fit: cover;
border-radius: 6px;
background: var(--card);
border: 1px solid var(--line-soft);
} }
.badge { .badge {