Files
Mycontent/miniprogram/pages/super-article-detail/super-article-detail.js
乘风 73d56a225a feat: enhance link handling in reading page
- 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
2026-04-24 16:17:07 +08:00

130 lines
4.0 KiB
JavaScript
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.

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, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
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))}` : '',
}
},
})