Files
a_long/components/popup-notice/popup-notice.js
2026-06-14 02:38:05 +08:00

324 lines
9.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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() {}
}
});