Files
Wechat/components/popup-notice/popup-notice.js

323 lines
9.3 KiB
JavaScript

// 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 });
},
// 自定义图片预览
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 = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAwIiBoZWlnaHQ9IjEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI1MCIgZmlsbD0iI2NjY2NjYyIvPjxwYXRoIGQ9Ik01MCAyNWMtMTMuOCAwLTI1IDExLjItMjUgMjUgMCAzLjIgMS4yIDYuMSAzLjIgOC4zQzM0LjQgNzAuNyA0Mi4xIDc1IDUwIDc1czE1LjYtNC4zIDIxLjgtMTEuN0M3My44IDU2LjEgNzUgNTMuMiA3NSA1MGMwLTEzLjgtMTEuMi0yNS0yNS0yNXoiIGZpbGw9IiNmZmZmZmYiLz48L3N2Zz4=';
}
if (avatarUrl && !avatarUrl.startsWith('http') && !avatarUrl.startsWith('data:')) {
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() {}
}
});