- Added functionality to open article links in a mini program web-view, allowing users to preview external links. - Implemented mobile hints for external links to improve user experience on mobile devices. - Updated content parser to support new link types, including regular hyperlinks. - Enhanced styling for article links to improve visibility and interaction. Made-with: Cursor
130 lines
4.0 KiB
JavaScript
130 lines
4.0 KiB
JavaScript
const app = getApp()
|
||
|
||
function formatTime(value) {
|
||
if (!value) return ''
|
||
const d = new Date(value)
|
||
if (isNaN(d.getTime())) return ''
|
||
const m = `${d.getMonth() + 1}`.padStart(2, '0')
|
||
const day = `${d.getDate()}`.padStart(2, '0')
|
||
const hh = `${d.getHours()}`.padStart(2, '0')
|
||
const mm = `${d.getMinutes()}`.padStart(2, '0')
|
||
return `${m}-${day} ${hh}:${mm}`
|
||
}
|
||
|
||
function buildH5ReadUrl(articleId) {
|
||
if (!articleId) return ''
|
||
const base = String((app.globalData && app.globalData.baseUrl) || 'https://soulapi.quwanzhi.com').replace(/\/$/, '')
|
||
const ref = (app.globalData.userInfo && app.globalData.userInfo.referralCode) || ''
|
||
const id = String(articleId)
|
||
return ref ? `${base}/s/${encodeURIComponent(id)}?ref=${encodeURIComponent(ref)}` : `${base}/s/${encodeURIComponent(id)}`
|
||
}
|
||
|
||
function renderArticleHtml(text) {
|
||
const src = String(text || '')
|
||
const isHtml = /<[a-z][\s\S]*>/i.test(src)
|
||
|
||
// 富文本:保留原 HTML,仅统一补充 a 标签样式(可点击 + 高亮)
|
||
if (isHtml) {
|
||
return src.replace(/<a\b([^>]*)>/gi, (full, attrs) => {
|
||
if (!/href\s*=/.test(attrs)) return full
|
||
const hasStyle = /\sstyle\s*=/.test(attrs)
|
||
const styleText = 'color:#22d3ee;text-decoration:underline;word-break:break-all;'
|
||
if (hasStyle) {
|
||
return `<a${attrs.replace(/\sstyle\s*=\s*(['"])(.*?)\1/i, (_m, q, s) => ` style=${q}${s};${styleText}${q}`)}>`
|
||
}
|
||
return `<a${attrs} style="${styleText}">`
|
||
})
|
||
}
|
||
|
||
// 纯文本:高亮 @/# 并自动识别 URL
|
||
const escaped = src
|
||
.replace(/&/g, '&')
|
||
.replace(/</g, '<')
|
||
.replace(/>/g, '>')
|
||
.replace(/"/g, '"')
|
||
const withMentions = escaped.replace(/(^|[\s])(@[\u4e00-\u9fa5A-Za-z0-9_]+)/g, '$1<span style="color:#67e8f9;">$2</span>')
|
||
const withTags = withMentions.replace(/(^|[\s])(#[^\s#]+)/g, '$1<span style="color:#5eead4;">$2</span>')
|
||
const withLinks = withTags.replace(
|
||
/(https?:\/\/[^\s<]+)/g,
|
||
'<a href="$1" style="color:#22d3ee;text-decoration:underline;word-break:break-all;">$1</a>'
|
||
)
|
||
return withLinks.replace(/\n/g, '<br/>')
|
||
}
|
||
|
||
Page({
|
||
data: {
|
||
statusBarHeight: 44,
|
||
article: null,
|
||
articleId: '',
|
||
h5ReadUrl: '',
|
||
loading: true,
|
||
},
|
||
onLoad(options) {
|
||
this.setData({ statusBarHeight: app.globalData.statusBarHeight || 44 })
|
||
const id = options?.id
|
||
if (!id) {
|
||
this.setData({ loading: false })
|
||
return
|
||
}
|
||
this.loadArticle(id)
|
||
},
|
||
async loadArticle(id) {
|
||
this.setData({ loading: true })
|
||
try {
|
||
const res = await app.request({
|
||
url: `/api/miniprogram/super/articles/${encodeURIComponent(String(id))}`,
|
||
silent: true,
|
||
})
|
||
const article = res?.data
|
||
if (!article) {
|
||
this.setData({ loading: false })
|
||
return
|
||
}
|
||
this.setData({
|
||
article: {
|
||
...article,
|
||
createdAtText: formatTime(article.createdAt),
|
||
contentHtml: renderArticleHtml(article.content),
|
||
},
|
||
articleId: String(id),
|
||
h5ReadUrl: buildH5ReadUrl(id),
|
||
loading: false,
|
||
})
|
||
} catch (_) {
|
||
this.setData({ loading: false })
|
||
}
|
||
},
|
||
goBack() {
|
||
wx.navigateBack({ fail: () => wx.switchTab({ url: '/pages/my/my' }) })
|
||
},
|
||
copyH5Link() {
|
||
const url = this.data.h5ReadUrl
|
||
if (!url) {
|
||
wx.showToast({ title: '链接未就绪', icon: 'none' })
|
||
return
|
||
}
|
||
wx.setClipboardData({
|
||
data: url,
|
||
success: () => wx.showToast({ title: 'H5 链接已复制', icon: 'success' }),
|
||
})
|
||
},
|
||
onShareAppMessage() {
|
||
const a = this.data.article
|
||
const id = this.data.articleId
|
||
return {
|
||
title: a && a.title ? a.title : '文章',
|
||
path: id
|
||
? `/pages/super-article-detail/super-article-detail?id=${encodeURIComponent(String(id))}`
|
||
: '/pages/super-article-detail/super-article-detail',
|
||
}
|
||
},
|
||
onShareTimeline() {
|
||
const a = this.data.article
|
||
const id = this.data.articleId
|
||
return {
|
||
title: a && a.title ? a.title : '文章',
|
||
query: id ? `id=${encodeURIComponent(String(id))}` : '',
|
||
}
|
||
},
|
||
})
|