123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- // pages/exhibition/activeDetails/index.js
- const { museumApi } = require('../../../utils/api.js');
- const WxParse = require('../../../utils/wxParse/wxParse.js');
- Page({
- /**
- * 页面的初始数据
- */
- data: {
- loading: false,
- detailData: null,
- contentItems: [],
- fromtype: '',
- isFrom: '',
- shouldShowBackButton: true,
- isPreviewMode: false,
- formattedPublishTime: '',
- isLoggedIn: false
- },
- /**
- * 生命周期函数--监听页面加载
- */
- onLoad(options) {
- // 检查登录状态
- this.checkLoginStatus();
-
- // 检查是否来自微信,如果是则隐藏返回按钮
- if (options.isfrom === 'weixin') {
- this.setData({
- shouldShowBackButton: false,
- isFrom: 'weixin'
- });
- }
-
- // 检查是否为预览模式
- if (options.preview === '1') {
- this.setData({
- isPreviewMode: true
- });
- }
-
- // 设置页面参数
- this.setData({
- fromtype: options.type || '',
- isFrom: options.isFrom || ''
- });
-
- // 加载详情数据
- this.loadDetailData(options);
- },
- /**
- * 返回上一页
- */
- goBack() {
- wx.navigateBack({
- delta: 1
- });
- },
- /**
- * 跳转到线上观展
- */
- goToOnlineExhibition() {
- const { detailData, isPreviewMode } = this.data;
- let targetUrl;
-
- // 如果是预览模式,优先使用webSiteB
- if (isPreviewMode && detailData.webSiteB) {
- targetUrl = detailData.webSiteB;
- } else {
- targetUrl = detailData.webSite;
- }
-
- if (targetUrl) {
- // 小程序中使用web-view或复制链接
- wx.setClipboardData({
- data: targetUrl,
- success: function() {
- wx.showToast({
- title: '链接已复制',
- icon: 'success'
- });
- }
- });
- }
- },
- /**
- * 跳转到活动预约页面
- */
- goToActivePreview() {
- const { detailData } = this.data;
- const activityId = detailData.activityId || detailData.id;
-
- wx.navigateTo({
- url: `/pages/index/active-page/active-page?activityId=${activityId}&type=2`
- });
- },
- /**
- * 处理链接点击
- */
- onLinkTap(e) {
- const { url } = e.currentTarget.dataset;
- if (url) {
- // 复制链接到剪贴板
- wx.setClipboardData({
- data: url,
- success: function() {
- wx.showToast({
- title: '链接已复制',
- icon: 'success'
- });
- }
- });
- }
- },
- /**
- * 处理rich-text中的链接点击
- */
- onRichTextTap(e) {
- const { links } = e.currentTarget.dataset;
- if (links && links.length > 0) {
- // 如果只有一个链接,直接打开
- if (links.length === 1) {
- const url = links[0].url;
- this.openLink(url);
- } else {
- // 如果有多个链接,显示选择列表
- const itemList = links.map(link => link.text);
- wx.showActionSheet({
- itemList: itemList,
- success: (res) => {
- const selectedLink = links[res.tapIndex];
- this.openLink(selectedLink.url);
- }
- });
- }
- }
- },
- /**
- * 打开链接
- */
- openLink(url) {
- if (url) {
- // 复制链接到剪贴板
- wx.setClipboardData({
- data: url,
- success: function() {
- wx.showToast({
- title: '链接已复制',
- icon: 'success'
- });
- }
- });
- }
- },
- /**
- * 格式化时间(横线分隔)
- */
- formatTimeWithDash(timeStr) {
- console.log('formatTimeWithDash:', timeStr);
- if (!timeStr) return '';
- const date = new Date(timeStr);
- const year = date.getFullYear();
- const month = String(date.getMonth() + 1).padStart(2, '0');
- const day = String(date.getDate()).padStart(2, '0');
- return `${year}-${month}-${day}`;
- },
- /**
- * 获取字段值(支持预览模式)
- */
- getFieldValue(fieldName) {
- const { detailData, isPreviewMode } = this.data;
- if (!detailData) return '';
-
- if (isPreviewMode) {
- // 预览模式下优先读取带B后缀的字段
- const bFieldName = fieldName + 'B';
- return detailData[bFieldName] || detailData[fieldName] || '';
- } else {
- return detailData[fieldName] || '';
- }
- },
- /**
- * 加载详情数据
- */
- loadDetailData(options) {
- const { id, type } = options;
- const that = this;
- if (!id) {
- console.error('缺少ID参数');
- return;
- }
- this.setData({
- loading: true
- });
- let apiPromise;
-
- // 根据类型调用不同的接口
- switch (type) {
- case 'information':
- apiPromise = museumApi.getInformationDetail(id);
- break;
- case 'exhibition':
- apiPromise = museumApi.getExhibitDetail(id);
- break;
- case 'activity':
- apiPromise = museumApi.getActivityDetail(id);
- break;
- case 'news':
- apiPromise = museumApi.getNewsDetail(id);
- break;
- case 'museum':
- apiPromise = museumApi.getMuseumDetail(1);
- break;
- default:
- console.error('未知的详情类型:', type);
- this.setData({ loading: false });
- return;
- }
- apiPromise
- .then(response => {
- if (response) {
- // 获取内容字段
- // const content = this.getContentForParsing(response);
- // const parsedContent = this.parseContent(content);
- let article = response.context;
- WxParse.wxParse('article', 'html', article, that, 5);
- // 格式化发布时间
- const formattedTime = this.formatTimeWithDash(response.publish);
-
- this.setData({
- detailData: response,
- // contentItems: parsedContent,
- formattedPublishTime: formattedTime
- });
- }
- })
- .catch(error => {
- console.error('获取详情数据失败:', error);
- this.setData({
- detailData: null
- });
- wx.showToast({
- title: '加载失败',
- icon: 'none'
- });
- })
- .finally(() => {
- this.setData({
- loading: false
- });
- });
- },
- /**
- * 获取用于解析的内容
- */
- getContentForParsing(detailData) {
- const { isPreviewMode } = this.data;
-
- if (isPreviewMode) {
- // 预览模式下优先使用带B后缀的字段
- return detailData.contextB || detailData.context || '';
- } else {
- return detailData.context || '';
- }
- },
- /**
- * 解析HTML内容为不同类型的内容项(使用map页面的解析规则)
- */
- parseContent(content) {
- if (!content) return [];
-
- const contentItems = [];
- const matches = [];
-
- // 定义所有匹配规则
- const patterns = [
- {
- regex: /<p[^>]*>(.*?)<\/p>/gi,
- type: 'text',
- handler: (match) => {
- let content = match[1];
- // 检查是否包含缩进样式
- const hasIndent = match[0].includes('text-indent:2em') || match[0].includes('text-indent: 2em');
-
- // 检查是否包含a标签链接
- const linkRegex = /<a[^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/gi;
- const hasLinks = linkRegex.test(content);
-
- if (hasLinks) {
- // 如果包含链接,转换为rich-text节点格式
- let processedContent = content;
- const links = [];
- let linkMatch;
- linkRegex.lastIndex = 0; // 重置正则表达式
-
- // 收集所有链接信息
- while ((linkMatch = linkRegex.exec(content)) !== null) {
- links.push({
- url: linkMatch[1],
- text: linkMatch[2].replace(/<[^>]*>/g, '')
- });
- }
-
- // 将a标签转换为带样式的span标签
- processedContent = processedContent.replace(
- /<a[^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/gi,
- '<span style="color: #007bff; text-decoration: underline;" data-url="$1">$2</span>'
- );
-
- return {
- type: 'text_with_links',
- content: processedContent,
- links: links,
- indent: hasIndent
- };
- } else {
- // 普通文本处理
- let text = content.replace(/<[^>]*>/g, '');
-
- // 将HTML实体编码的空格转换为对应数量的
- text = text.replace(/ /g, ' ');
- text = text.replace(/ /g, ' ');
- text = text.replace(/ /g, ' ');
- text = text.replace(/ /g, ' ');
- // 将普通空格也转换为
- text = text.replace(/ /g, ' ');
-
- // 如果有缩进样式,在文本前添加缩进
- if (hasIndent) {
- text = ' ' + text;
- }
-
- return {
- type: 'text',
- content: text,
- indent: hasIndent
- };
- }
- }
- },
- {
- 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,
- item: item
- });
- }
- }
- });
-
- // 按照在原HTML中的位置排序
- matches.sort((a, b) => a.index - b.index);
-
- // 提取排序后的内容项
- return matches.map(match => match.item);
- },
- /**
- * 生命周期函数--监听页面初次渲染完成
- */
- onReady() {
- },
- /**
- * 生命周期函数--监听页面显示
- */
- onShow() {
- // 每次显示页面时检查登录状态
- this.checkLoginStatus();
- },
- /**
- * 检查登录状态
- */
- checkLoginStatus() {
- const app = getApp();
- const token = wx.getStorageSync('token');
- const isLoggedIn = !!(token && !app.globalData.isGuest);
-
- this.setData({
- isLoggedIn: isLoggedIn
- });
- },
- /**
- * 生命周期函数--监听页面隐藏
- */
- onHide() {
- },
- /**
- * 生命周期函数--监听页面卸载
- */
- onUnload() {
- },
- /**
- * 页面相关事件处理函数--监听用户下拉动作
- */
- onPullDownRefresh() {
- },
- /**
- * 页面上拉触底事件的处理函数
- */
- onReachBottom() {
- },
- /**
- * 用户点击右上角分享
- */
- onShareAppMessage() {
- }
- });
|