// components/popup-notice/popup-notice.js import PopupService from '../../services/popupService.js'; Component({ data: { // 原有全屏弹窗数据 visible: false, title: '', images: [], processedImages: [], hasImages: false, hasTextOnly: false, textContent: '', duration: 0, remainingSeconds: 0, muteChecked: false, showMuteCheckbox: false, isFullscreen: false, timer: null, // 悬浮窗相关数据 isMinimized: false, floatX: 20, floatY: 200, savedRemainingSeconds: 0, floatAvatarUrl: '', // 🆕 自定义预览数据 showCustomPreview: false, // 是否显示自定义预览遮罩 previewUrls: [], // 当前预览的图片URL列表 currentPreviewIndex: 0, // 当前预览图片索引 }, lifetimes: { detached() { this.clearTimer(); } }, methods: { // ========== 原有所有方法(完全不变,一字不漏) ========== async show(config, onCloseCallback) { const { title, images, duration, showMuteCheckbox, serverTime } = config; this.onCloseCallback = onCloseCallback; let safeImages = JSON.parse(JSON.stringify(images || [])); const hasImages = safeImages.length > 0; let hasTextOnly = false, textContent = ''; if (!hasImages) { hasTextOnly = true; textContent = config.text || '暂无内容'; } this.setData({ visible: true, isMinimized: false, title: title || '', images: safeImages, hasImages, hasTextOnly, textContent, duration: duration || 0, remainingSeconds: duration || 0, muteChecked: false, showMuteCheckbox: showMuteCheckbox || false, isFullscreen: false, processedImages: [], }); if (duration > 0) { this.startCountdown(); } if (hasImages) { const processed = []; const screenWidth = wx.getSystemInfoSync().windowWidth; const containerWidth = screenWidth * 0.9; const imageWidth = containerWidth - 60; for (let i = 0; i < safeImages.length; i++) { const img = safeImages[i]; const fullUrl = this.getFullImageUrl(img.url); let imageHeight = 200; try { const res = await this.getImageInfoPromise(fullUrl); const realHeight = (imageWidth * res.height) / res.width; imageHeight = realHeight; } catch (e) { console.error('获取图片信息失败', fullUrl, e); } processed.push({ url: fullUrl, text: img.text, height: imageHeight, }); } this.setData({ processedImages: processed }); } }, getImageInfoPromise(url) { return new Promise((resolve, reject) => { wx.getImageInfo({ src: url, success: resolve, fail: reject, }); }); }, hide(muteToday = false) { this.clearTimer(); this.setData({ visible: false, isMinimized: false }); if (this.onCloseCallback) { this.onCloseCallback({ muteToday }); } }, startCountdown() { this.clearTimer(); this.timer = setInterval(() => { let sec = this.data.remainingSeconds; if (sec <= 1) { this.clearTimer(); this.setData({ remainingSeconds: 0 }); } else { this.setData({ remainingSeconds: sec - 1 }); } }, 1000); }, clearTimer() { if (this.timer) { clearInterval(this.timer); this.timer = null; } }, onCloseTap() { if (this.data.remainingSeconds > 0) { wx.showToast({ title: `请阅读${this.data.remainingSeconds}秒后再关闭`, icon: 'none' }); return; } if (this.data.showMuteCheckbox && this.data.muteChecked) { wx.showModal({ title: '提示', content: '今天将不再收到本页面的任何公告,确认吗?', success: (res) => { if (res.confirm) this.hide(true); }, }); } else { this.hide(false); } }, onMuteChange(e) { this.setData({ muteChecked: e.detail.value.length > 0 }); }, // 🆕 替换原有的 onPreviewImage,改用自定义预览(不触发 onShow) onCustomPreview(e) { const index = e.currentTarget.dataset.index; const urls = this.data.processedImages.map(img => img.url); this.setData({ showCustomPreview: true, previewUrls: urls, currentPreviewIndex: index !== undefined ? index : 0 }); }, // 🆕 关闭自定义预览 onCloseCustomPreview() { this.setData({ showCustomPreview: false, previewUrls: [], currentPreviewIndex: 0 }); }, // 🆕 swiper 切换事件 onPreviewSwiperChange(e) { this.setData({ currentPreviewIndex: e.detail.current }); }, // 保留原 onPreviewImage 方法以防外部调用,但不再使用 onPreviewImage(e) { // 重定向到自定义预览 this.onCustomPreview(e); }, onImageError(e) { console.error('图片加载失败:', e.currentTarget.dataset.url); }, toggleFullscreen() { this.setData({ isFullscreen: !this.data.isFullscreen }); }, getFullImageUrl(relativeUrl) { if (!relativeUrl) return ''; if (relativeUrl.startsWith('http')) return relativeUrl; const app = getApp(); let base = app.globalData.ossImageUrl || ''; base = base.replace(/\/+$/, ''); const clean = relativeUrl.replace(/^\/+/, ''); return base ? base + '/' + clean : clean; }, preventMove() {}, onMinimize() { const remaining = this.data.remainingSeconds; this.clearTimer(); const app = getApp(); let avatarUrl = ''; if (app.globalData.morentouxiang) { avatarUrl = app.globalData.morentouxiang; } else { avatarUrl = '/images/default-avatar.png'; } if (avatarUrl && !avatarUrl.startsWith('http')) { const ossBase = app.globalData.ossImageUrl || ''; avatarUrl = ossBase.replace(/\/+$/, '') + '/' + avatarUrl.replace(/^\/+/, ''); } this.setData({ visible: false, isMinimized: true, savedRemainingSeconds: remaining, floatX: 20, floatY: 200, floatAvatarUrl: avatarUrl }); }, onFloatChange(e) { this.setData({ floatX: e.detail.x, floatY: e.detail.y }); }, onFloatTap() { this.setData({ visible: true, isMinimized: false, remainingSeconds: this.data.savedRemainingSeconds }); if (this.data.duration > 0 && this.data.savedRemainingSeconds > 0) { this.startCountdown(); } }, onFloatAvatarError() { this.setData({ floatAvatarUrl: '/images/avatar-placeholder.png' }); }, cleanup() { this.clearTimer(); this.setData({ visible: false, isMinimized: false }); PopupService.reset(); }, onFloatTouchStart(e) { const touch = e.touches[0]; this.touchStartX = touch.clientX; this.touchStartY = touch.clientY; this.startFloatX = this.data.floatX; this.startFloatY = this.data.floatY; this.hasMoved = false; return false; }, onFloatTouchMove(e) { const touch = e.touches[0]; const deltaX = touch.clientX - this.touchStartX; const deltaY = touch.clientY - this.touchStartY; if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) { this.hasMoved = true; } let newX = this.startFloatX + deltaX; let newY = this.startFloatY + deltaY; const systemInfo = wx.getSystemInfoSync(); const screenWidth = systemInfo.windowWidth; const screenHeight = systemInfo.windowHeight; const estimatedSize = 60; newX = Math.max(0, Math.min(newX, screenWidth - estimatedSize)); newY = Math.max(0, Math.min(newY, screenHeight - estimatedSize)); this.setData({ floatX: newX, floatY: newY }); return false; }, onFloatTouchEnd(e) { if (!this.hasMoved) { this.onFloatTap(); } return false; }, // 🆕 阻止事件冒泡(用于预览遮罩内部点击不关闭) stopPropagation() {} } });