mirror of
https://github.com/LifeArchiveProject/WeChatDataAnalysis.git
synced 2026-06-18 15:54:08 +08:00
353 lines
13 KiB
Vue
353 lines
13 KiB
Vue
<script>
|
|
import { defineComponent, h, ref, watch } from 'vue'
|
|
import miniProgramIconUrl from '~/assets/images/wechat/mini-program.svg'
|
|
|
|
const finderLogoUrl = '/assets/images/wechat/channels-logo.svg'
|
|
|
|
export default defineComponent({
|
|
name: 'LinkCard',
|
|
props: {
|
|
href: { type: String, default: '' },
|
|
heading: { type: String, default: '' },
|
|
abstract: { type: String, default: '' },
|
|
preview: { type: String, default: '' },
|
|
fromAvatar: { type: String, default: '' },
|
|
from: { type: String, default: '' },
|
|
linkType: { type: String, default: '' },
|
|
isSent: { type: Boolean, default: false },
|
|
badge: { type: String, default: '' },
|
|
variant: { type: String, default: 'default' }
|
|
},
|
|
setup(props) {
|
|
const fromAvatarImgOk = ref(false)
|
|
const fromAvatarImgError = ref(false)
|
|
|
|
watch(
|
|
() => String(props.fromAvatar || '').trim(),
|
|
() => {
|
|
fromAvatarImgOk.value = false
|
|
fromAvatarImgError.value = false
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
const getFromText = () => {
|
|
const raw = String(props.from || '').trim()
|
|
if (raw) return raw
|
|
try {
|
|
const href = String(props.href || '').trim()
|
|
if (!/^https?:\/\//i.test(href)) return ''
|
|
return String(new URL(href).hostname || '').trim()
|
|
} catch {
|
|
return ''
|
|
}
|
|
}
|
|
|
|
return () => {
|
|
const fromText = getFromText()
|
|
const href = String(props.href || '').trim()
|
|
const canNavigate = /^https?:\/\//i.test(href)
|
|
const badgeText = String(props.badge || '').trim()
|
|
const fromAvatarText = (() => {
|
|
const text = String(fromText || '').trim()
|
|
return text ? (Array.from(text)[0] || '') : ''
|
|
})()
|
|
const fromAvatarUrl = String(props.fromAvatar || '').trim()
|
|
const headingText = String(props.heading || href || '').trim()
|
|
let abstractText = String(props.abstract || '').trim()
|
|
if (abstractText && headingText && abstractText === headingText) abstractText = ''
|
|
const isMiniProgram = String(props.linkType || '').trim() === 'mini_program'
|
|
const isFinder = String(props.linkType || '').trim() === 'finder'
|
|
const isCoverVariant = !isMiniProgram && String(props.variant || '').trim() === 'cover'
|
|
const Tag = canNavigate ? 'a' : 'div'
|
|
|
|
const showFromAvatarImg = Boolean(fromAvatarUrl) && !fromAvatarImgError.value
|
|
const showFromAvatarText = (!fromAvatarUrl) || (!fromAvatarImgOk.value)
|
|
const fromAvatarStyle = fromAvatarImgOk.value
|
|
? {
|
|
background: isCoverVariant ? 'rgba(255, 255, 255, 0.92)' : '#fff',
|
|
color: 'transparent'
|
|
}
|
|
: null
|
|
const miniProgramAvatarStyle = fromAvatarImgOk.value
|
|
? {
|
|
background: '#fff',
|
|
color: 'transparent'
|
|
}
|
|
: null
|
|
const onFromAvatarLoad = () => {
|
|
fromAvatarImgOk.value = true
|
|
fromAvatarImgError.value = false
|
|
}
|
|
const onFromAvatarError = () => {
|
|
fromAvatarImgOk.value = false
|
|
fromAvatarImgError.value = true
|
|
}
|
|
|
|
if (isCoverVariant) {
|
|
const fromRow = h('div', { class: 'wechat-link-cover-from' }, [
|
|
h('div', { class: 'wechat-link-cover-from-avatar', style: fromAvatarStyle, 'aria-hidden': 'true' }, [
|
|
showFromAvatarText ? (fromAvatarText || '\u200B') : null,
|
|
showFromAvatarImg
|
|
? h('img', {
|
|
src: fromAvatarUrl,
|
|
alt: '',
|
|
class: 'wechat-link-cover-from-avatar-img',
|
|
referrerpolicy: 'no-referrer',
|
|
onLoad: onFromAvatarLoad,
|
|
onError: onFromAvatarError
|
|
})
|
|
: null
|
|
].filter(Boolean)),
|
|
h('div', { class: 'wechat-link-cover-from-name', style: { flex: '1 1 auto', minWidth: '0' } }, fromText || '\u200B'),
|
|
badgeText ? h('div', { class: 'wechat-link-cover-badge' }, badgeText) : null
|
|
].filter(Boolean))
|
|
|
|
return h(
|
|
Tag,
|
|
{
|
|
...(canNavigate ? { href, target: '_blank', rel: 'noreferrer' } : { role: 'group', 'aria-disabled': 'true' }),
|
|
class: [
|
|
'wechat-link-card-cover',
|
|
!canNavigate ? 'wechat-link-card--disabled' : '',
|
|
'wechat-special-card',
|
|
'msg-radius',
|
|
props.isSent ? 'wechat-special-sent-side' : ''
|
|
].filter(Boolean).join(' '),
|
|
style: {
|
|
width: '137px',
|
|
minWidth: '137px',
|
|
maxWidth: '137px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
boxSizing: 'border-box',
|
|
flex: '0 0 auto',
|
|
background: 'var(--merged-history-bg)',
|
|
border: 'none',
|
|
boxShadow: 'none',
|
|
textDecoration: 'none',
|
|
outline: 'none'
|
|
}
|
|
},
|
|
[
|
|
props.preview
|
|
? h('div', { class: 'wechat-link-cover-image-wrap' }, [
|
|
h('img', {
|
|
src: props.preview,
|
|
alt: props.heading || '链接封面',
|
|
class: 'wechat-link-cover-image',
|
|
referrerpolicy: 'no-referrer'
|
|
}),
|
|
fromRow
|
|
])
|
|
: fromRow,
|
|
h('div', { class: 'wechat-link-cover-title' }, props.heading || href)
|
|
].filter(Boolean)
|
|
)
|
|
}
|
|
|
|
if (isFinder) {
|
|
return h(
|
|
Tag,
|
|
{
|
|
...(canNavigate ? { href, target: '_blank', rel: 'noreferrer' } : { role: 'group', 'aria-disabled': 'true' }),
|
|
class: [
|
|
'wechat-link-card-finder',
|
|
!canNavigate ? 'wechat-link-card--disabled' : '',
|
|
'wechat-special-card',
|
|
'msg-radius',
|
|
props.isSent ? 'wechat-special-sent-side' : ''
|
|
].filter(Boolean).join(' '),
|
|
style: {
|
|
width: '135px',
|
|
minWidth: '135px',
|
|
maxWidth: '135px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
boxSizing: 'border-box',
|
|
flex: '0 0 auto',
|
|
border: 'none',
|
|
boxShadow: 'none',
|
|
textDecoration: 'none',
|
|
outline: 'none'
|
|
}
|
|
},
|
|
[
|
|
h('div', { class: ['wechat-link-finder-cover', !props.preview ? 'wechat-link-finder-cover--empty' : ''].filter(Boolean).join(' ') }, [
|
|
props.preview
|
|
? h('img', {
|
|
src: props.preview,
|
|
alt: props.heading || '视频号封面',
|
|
class: 'wechat-link-finder-cover-img',
|
|
referrerpolicy: 'no-referrer'
|
|
})
|
|
: h('div', { class: 'wechat-link-finder-cover-placeholder', 'aria-hidden': 'true' }, [
|
|
h('svg', { viewBox: '0 0 24 24', fill: 'currentColor' }, [
|
|
h('path', { d: 'M8 5v14l11-7z' })
|
|
])
|
|
]),
|
|
h('div', { class: 'wechat-link-finder-cover-shade', 'aria-hidden': 'true' }),
|
|
h('div', { class: 'wechat-link-finder-play', 'aria-hidden': 'true' }, [
|
|
h('svg', { viewBox: '0 0 24 24', fill: 'currentColor' }, [
|
|
h('path', { d: 'M8 5v14l11-7z' })
|
|
])
|
|
]),
|
|
h('div', { class: 'wechat-link-finder-meta' }, [
|
|
h('div', { class: 'wechat-link-finder-author' }, [
|
|
h('div', { class: 'wechat-link-finder-author-avatar', 'aria-hidden': 'true' }, [
|
|
h('img', {
|
|
src: finderLogoUrl,
|
|
alt: '',
|
|
class: 'wechat-link-finder-author-avatar-img'
|
|
})
|
|
]),
|
|
h('div', { class: 'wechat-link-finder-author-name' }, fromText || '视频号')
|
|
])
|
|
])
|
|
])
|
|
]
|
|
)
|
|
}
|
|
|
|
if (isMiniProgram) {
|
|
return h(
|
|
Tag,
|
|
{
|
|
...(canNavigate ? { href, target: '_blank', rel: 'noreferrer' } : { role: 'group', 'aria-disabled': 'true' }),
|
|
class: [
|
|
'wechat-link-card',
|
|
'wechat-link-card--mini-program',
|
|
!canNavigate ? 'wechat-link-card--disabled' : '',
|
|
'wechat-special-card',
|
|
'msg-radius',
|
|
props.isSent ? 'wechat-special-sent-side' : ''
|
|
].filter(Boolean).join(' '),
|
|
style: {
|
|
width: '210px',
|
|
minWidth: '210px',
|
|
maxWidth: '210px',
|
|
maxHeight: '270px',
|
|
height: '270px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
boxSizing: 'border-box',
|
|
flex: '0 0 auto',
|
|
background: 'var(--merged-history-bg)',
|
|
border: 'none',
|
|
boxShadow: 'none',
|
|
textDecoration: 'none',
|
|
outline: 'none'
|
|
}
|
|
},
|
|
[
|
|
h('div', { class: 'wechat-link-mini-body' }, [
|
|
h('div', { class: 'wechat-link-mini-header' }, [
|
|
h('div', { class: 'wechat-link-mini-header-avatar', style: miniProgramAvatarStyle, 'aria-hidden': 'true' }, [
|
|
showFromAvatarText ? (fromAvatarText || '\u200B') : null,
|
|
showFromAvatarImg
|
|
? h('img', {
|
|
src: fromAvatarUrl,
|
|
alt: '',
|
|
class: 'wechat-link-mini-header-avatar-img',
|
|
referrerpolicy: 'no-referrer',
|
|
onLoad: onFromAvatarLoad,
|
|
onError: onFromAvatarError
|
|
})
|
|
: null
|
|
].filter(Boolean)),
|
|
h('div', { class: 'wechat-link-mini-header-name' }, fromText || '\u200B')
|
|
]),
|
|
h('div', { class: 'wechat-link-mini-title' }, headingText || abstractText || href),
|
|
h('div', { class: ['wechat-link-mini-preview', !props.preview ? 'wechat-link-mini-preview--empty' : ''].filter(Boolean).join(' ') }, [
|
|
props.preview
|
|
? h('img', {
|
|
src: props.preview,
|
|
alt: props.heading || '小程序预览',
|
|
class: 'wechat-link-mini-preview-img',
|
|
referrerpolicy: 'no-referrer'
|
|
})
|
|
: null
|
|
].filter(Boolean))
|
|
]),
|
|
h('div', { class: 'wechat-link-mini-footer' }, [
|
|
h('img', {
|
|
src: miniProgramIconUrl,
|
|
alt: '',
|
|
class: 'wechat-link-mini-footer-icon',
|
|
'aria-hidden': 'true'
|
|
}),
|
|
h('span', { class: 'wechat-link-mini-footer-text' }, '小程序')
|
|
])
|
|
]
|
|
)
|
|
}
|
|
|
|
return h(
|
|
Tag,
|
|
{
|
|
...(canNavigate ? { href, target: '_blank', rel: 'noreferrer' } : { role: 'group', 'aria-disabled': 'true' }),
|
|
class: [
|
|
'wechat-link-card',
|
|
!canNavigate ? 'wechat-link-card--disabled' : '',
|
|
'wechat-special-card',
|
|
'msg-radius',
|
|
props.isSent ? 'wechat-special-sent-side' : ''
|
|
].filter(Boolean).join(' '),
|
|
style: {
|
|
width: '210px',
|
|
minWidth: '210px',
|
|
maxWidth: '210px',
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
boxSizing: 'border-box',
|
|
flex: '0 0 auto',
|
|
background: 'var(--merged-history-bg)',
|
|
border: 'none',
|
|
boxShadow: 'none',
|
|
textDecoration: 'none',
|
|
outline: 'none'
|
|
}
|
|
},
|
|
[
|
|
h('div', { class: 'wechat-link-content' }, [
|
|
h('div', { class: 'wechat-link-title' }, headingText || href),
|
|
(abstractText || props.preview)
|
|
? h('div', { class: 'wechat-link-summary' }, [
|
|
abstractText ? h('div', { class: 'wechat-link-desc' }, abstractText) : null,
|
|
props.preview
|
|
? h('div', { class: 'wechat-link-thumb' }, [
|
|
h('img', {
|
|
src: props.preview,
|
|
alt: props.heading || '链接预览',
|
|
class: 'wechat-link-thumb-img',
|
|
referrerpolicy: 'no-referrer'
|
|
})
|
|
])
|
|
: null
|
|
].filter(Boolean))
|
|
: null
|
|
].filter(Boolean)),
|
|
h('div', { class: 'wechat-link-from' }, [
|
|
h('div', { class: 'wechat-link-from-avatar', style: fromAvatarStyle, 'aria-hidden': 'true' }, [
|
|
showFromAvatarText ? (fromAvatarText || '\u200B') : null,
|
|
showFromAvatarImg
|
|
? h('img', {
|
|
src: fromAvatarUrl,
|
|
alt: '',
|
|
class: 'wechat-link-from-avatar-img',
|
|
referrerpolicy: 'no-referrer',
|
|
onLoad: onFromAvatarLoad,
|
|
onError: onFromAvatarError
|
|
})
|
|
: null
|
|
].filter(Boolean)),
|
|
h('div', { class: 'wechat-link-from-name', style: { flex: '1 1 auto', minWidth: '0' } }, fromText || '\u200B'),
|
|
badgeText ? h('div', { class: 'wechat-link-badge' }, badgeText) : null
|
|
].filter(Boolean))
|
|
].filter(Boolean)
|
|
)
|
|
}
|
|
}
|
|
})
|
|
</script>
|