123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- // 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]([^>]*?)>(.*?)<\/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[^>]*>(.*?)<\/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[^>]*>(.*?)<\/p>/gi,
- type: 'text',
- handler: (match) => {
- let text = match[1].replace(/<[^>]*>/g, '');
- return {
- type: 'text',
- content: this.processHtmlEntities(text)
- };
- }
- },
- {
- regex: /<div[^>]*class="[^"]*media-wrap[^"]*image-wrap[^"]*"[^>]*>.*?<img[^>]*src="([^"]+)"[^>]*(?:alt="([^"]*)")?\/?>.* ?<\/div>/gi,
- type: 'image',
- handler: (match) => ({
- type: 'image',
- src: match[1],
- alt: match[2] || '图片'
- })
- },
- {
- regex: /<div[^>]*class="[^"]*media-wrap[^"]*video-wrap[^"]*"[^>]*>.*?<video[^>]*src="([^"]+)"[^>]*(?:poster="([^"]*)")?\/?>.* ?<\/div>/gi,
- type: 'video',
- handler: (match) => ({
- type: 'video',
- src: match[1],
- poster: match[2] || ''
- })
- },
- {
- regex: /<div[^>]*class="[^"]*media-wrap[^"]*audio-wrap[^"]*"[^>]*>.*?<audio[^>]*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() {
- }
- });
|