// pages/user/map/index.js const { museumApi } = require('../../../utils/api.js'); const { processHtmlContent } = require('../../../utils/htmlProcessor.js'); const WxParse = require('../../../utils/wxParse/wxParse.js'); Page({ /** * 页面的初始数据 */ data: { loading: false, detailData: null, processedContent: '', shouldShowBackButton: true }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { // 检查是否来自微信,如果是则隐藏返回按钮 if (options.isfrom === 'weixin') { this.setData({ shouldShowBackButton: false }); } // 加载详情数据 this.loadDetailData(); }, /** * 导航前往 */ openNavitor() { wx.openLocation({ latitude: 45.605550, longitude: 84.902629, name: '克拉玛依博物馆', address: '克拉玛依博物馆', scale: 18, success: function(res) { console.log('打开地图成功', res); }, fail: function(err) { console.error('打开地图失败', err); wx.showToast({ title: '打开地图失败', icon: 'none' }); } }); }, /** * 返回上一页 */ goBack() { wx.navigateBack({ delta: 1 }); }, /** * 加载详情数据 */ loadDetailData() { let that = this; this.setData({ loading: true }); museumApi.getMuseumDetail(2) .then(response => { if (response) { // const parsedContent = this.parseContent(response.content || response.context); let article = response.context; // console.log('解析后的内容:', parsedContent); WxParse.wxParse('article', 'html', article, that, 5); this.setData({ detailData: response, // contentItems: parsedContent }); } }) .catch(error => { console.error('获取地图详情数据失败:', error); this.setData({ detailData: null }); wx.showToast({ title: '加载失败', icon: 'none' }); }) .finally(() => { this.setData({ loading: false }); }); }, /** * 处理HTML实体编码 */ processHtmlEntities(text) { if (!text) return ''; return text .replace(/ /g, ' ') .replace(/ /g, '  ') .replace(/ /g, '    ') .replace(/ /g, ' ') .replace(/ /g, ' '); }, /** * 解析style属性 */ parseStyleAttribute(styleStr) { const styles = {}; if (styleStr) { styleStr.split(';').forEach(rule => { const [property, value] = rule.split(':').map(s => s.trim()); if (property && value) { styles[property] = value; } }); } return styles; }, /** * 检查是否有删除线样式 */ hasStrikethrough(attributes) { // 检查style属性中的text-decoration const styleMatch = attributes.match(/style="([^"]*)"/i); if (styleMatch) { const styles = this.parseStyleAttribute(styleMatch[1]); return styles['text-decoration']?.includes('line-through') || styles['text-decoration-line']?.includes('line-through'); } // 检查class属性中是否包含删除线相关类名 const classMatch = attributes.match(/class="([^"]*)"/i); if (classMatch) { const classes = classMatch[1].toLowerCase(); return classes.includes('strikethrough') || classes.includes('line-through') || classes.includes('deleted'); } return false; }, /** * 解析HTML内容为不同类型的内容项 */ parseContent(content) { if (!content) return []; const contentItems = []; const matches = []; // 定义所有匹配规则 const patterns = [ { regex: /]*?)>(.*?)<\/h[1-6]>/gi, type: 'heading', handler: (match) => { let text = match[2].replace(/<[^>]*>/g, ''); let attributes = match[1]; let isCenter = /text-align\s*:\s*center/i.test(attributes) || /style="[^"]*text-align\s*:\s*center[^"]*"/i.test(attributes); return { type: 'heading', content: this.processHtmlEntities(text), center: isCenter }; } }, { regex: /]*>(.*?)<\/span>/gi, type: 'span', handler: (match) => { let text = match[1].replace(/<[^>]*>/g, ''); return { type: 'span', content: this.processHtmlEntities(text) }; } }, // 检测删除线标签(del, s, strike) { regex: /<(del|s|strike)[^>]*>(.*?)<\/(del|s|strike)>/gi, type: 'strikethrough', handler: (match) => { let text = match[2].replace(/<[^>]*>/g, ''); return { type: 'strikethrough', content: this.processHtmlEntities(text) }; } }, // 检测带有删除线样式的任意标签 { regex: /<(\w+)([^>]*style="[^"]*text-decoration[^"]*line-through[^"]*"[^>]*)>(.*?)<\/\1>/gi, type: 'strikethrough', handler: (match) => { let text = match[3].replace(/<[^>]*>/g, ''); return { type: 'strikethrough', content: this.processHtmlEntities(text) }; } }, // 检测带有删除线类名的任意标签 { regex: /<(\w+)([^>]*class="[^"]*(?:strikethrough|line-through|deleted)[^"]*"[^>]*)>(.*?)<\/\1>/gi, type: 'strikethrough', handler: (match) => { let text = match[3].replace(/<[^>]*>/g, ''); return { type: 'strikethrough', content: this.processHtmlEntities(text) }; } }, { regex: /]*>(.*?)<\/p>/gi, type: 'text', handler: (match) => { let text = match[1].replace(/<[^>]*>/g, ''); return { type: 'text', content: this.processHtmlEntities(text) }; } }, { regex: /]*class="[^"]*media-wrap[^"]*image-wrap[^"]*"[^>]*>.*?]*src="([^"]+)"[^>]*(?:alt="([^"]*)")?\/?>.* ?<\/div>/gi, type: 'image', handler: (match) => ({ type: 'image', src: match[1], alt: match[2] || '图片' }) }, { regex: /]*class="[^"]*media-wrap[^"]*video-wrap[^"]*"[^>]*>.*?]*src="([^"]+)"[^>]*(?:poster="([^"]*)")?\/?>.* ?<\/div>/gi, type: 'video', handler: (match) => ({ type: 'video', src: match[1], poster: match[2] || '' }) }, { regex: /]*class="[^"]*media-wrap[^"]*audio-wrap[^"]*"[^>]*>.*?]*src="([^"]+)"[^>]*(?:title="([^"]*)")?\/?>.* ?<\/div>/gi, type: 'audio', handler: (match) => ({ type: 'audio', src: match[1], title: match[2] || '音频' }) } ]; // 收集所有匹配项及其位置 patterns.forEach(pattern => { let match; pattern.regex.lastIndex = 0; // 重置正则表达式的lastIndex while ((match = pattern.regex.exec(content)) !== null) { const item = pattern.handler(match); if ((item.type === 'text' && item.content.trim()) || item.type !== 'text') { matches.push({ index: match.index, length: match[0].length, item: item }); } } }); // 按照在原HTML中的位置排序 matches.sort((a, b) => a.index - b.index); // 移除重叠的匹配项(保持原始顺序,只过滤真正重复的内容) const filteredMatches = []; const typesPriority = ['heading', 'strikethrough', 'span', 'text']; // 优先级从高到低 for (let i = 0; i < matches.length; i++) { const current = matches[i]; let shouldSkip = false; // 检查是否与已添加的项有重叠 for (let j = 0; j < filteredMatches.length; j++) { const existing = filteredMatches[j]; // 检查是否有重叠 if (current.index < existing.index + existing.length && current.index + current.length > existing.index) { // 如果有重叠,比较优先级 const currentPriority = typesPriority.indexOf(current.item.type); const existingPriority = typesPriority.indexOf(existing.item.type); // 只有当前项优先级明显低于已存在项时才跳过 if (currentPriority > existingPriority && existingPriority !== -1) { shouldSkip = true; break; } } } if (!shouldSkip) { filteredMatches.push(current); } } // 提取排序后的内容项 return filteredMatches.map(match => match.item); }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { } });