fix: 抢单池弹窗等 OSS 就绪再拼图,避免相对 URL 空白
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
7eca128bb5
commit
0067a63093
5 files changed
+152
-42
No files matched your search
@@ -216,6 +216,12 @@ App({
|
||||
refreshDashouMembership(this).catch(() => {});
|
||||
}
|
||||
|
||||
// ③ 先应用本地缓存配置(必须在 reLaunch 抢单池之前,否则弹窗图片拼不出 OSS)
|
||||
const cachedConfig = this.readConfigFromStorage();
|
||||
if (cachedConfig) {
|
||||
this.applyDynamicConfig(cachedConfig);
|
||||
}
|
||||
|
||||
// 纯打手端:未登录必进登录页;已认证进抢单池
|
||||
const targetPage = isFighterOnly()
|
||||
? resolveFighterOnlyLaunchUrl()
|
||||
@@ -226,12 +232,6 @@ App({
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// ③ 应用本地缓存配置
|
||||
const cachedConfig = this.readConfigFromStorage();
|
||||
if (cachedConfig) {
|
||||
this.applyDynamicConfig(cachedConfig);
|
||||
}
|
||||
|
||||
// ④ 初始化
|
||||
this.initGoEasyWithConfig(); // 只有appkey有效时才真正初始化
|
||||
ChatCore.initGlobalMessageSystem(this);
|
||||
|
||||
@@ -41,15 +41,24 @@ Component({
|
||||
async show(config, onCloseCallback) {
|
||||
const { title, images, duration, showMuteCheckbox, serverTime } = config;
|
||||
this.onCloseCallback = onCloseCallback;
|
||||
|
||||
this._showToken = (this._showToken || 0) + 1;
|
||||
const token = this._showToken;
|
||||
|
||||
let safeImages = JSON.parse(JSON.stringify(images || []));
|
||||
// 兼容 url / image_url
|
||||
safeImages = safeImages.map((img) => ({
|
||||
...img,
|
||||
url: img.url || img.image_url || '',
|
||||
text: img.text || '',
|
||||
})).filter((img) => !!img.url);
|
||||
|
||||
const hasImages = safeImages.length > 0;
|
||||
let hasTextOnly = false, textContent = '';
|
||||
if (!hasImages) {
|
||||
hasTextOnly = true;
|
||||
textContent = config.text || '暂无内容';
|
||||
}
|
||||
|
||||
|
||||
this.setData({
|
||||
visible: true,
|
||||
isMinimized: false,
|
||||
@@ -65,34 +74,91 @@ Component({
|
||||
isFullscreen: false,
|
||||
processedImages: [],
|
||||
});
|
||||
|
||||
|
||||
if (duration > 0) {
|
||||
this.startCountdown();
|
||||
}
|
||||
|
||||
if (hasImages) {
|
||||
const screenWidth = wx.getSystemInfoSync().windowWidth;
|
||||
const containerWidth = Math.min(screenWidth * 0.86, 310);
|
||||
const imageWidth = Math.max(containerWidth - 30, 200);
|
||||
// 先立刻用默认高度展示,避免 getImageInfo 慢/失败时空白
|
||||
const processed = safeImages.map((img) => ({
|
||||
url: this.getFullImageUrl(img.url),
|
||||
text: img.text,
|
||||
height: 280,
|
||||
}));
|
||||
this.setData({ processedImages: processed });
|
||||
for (let i = 0; i < processed.length; i++) {
|
||||
const fullUrl = processed[i].url;
|
||||
try {
|
||||
const res = await this.getImageInfoPromise(fullUrl);
|
||||
const realHeight = (imageWidth * res.height) / res.width;
|
||||
this.setData({ [`processedImages[${i}].height`]: realHeight });
|
||||
} catch (e) {
|
||||
console.error('获取图片信息失败', fullUrl, e);
|
||||
}
|
||||
|
||||
if (!hasImages) return;
|
||||
|
||||
// 等 OSS 域名就绪再拼接,避免相对路径导致整图空白
|
||||
await this.ensureOssBase(4000);
|
||||
if (token !== this._showToken) return;
|
||||
|
||||
const processed = safeImages.map((img) => ({
|
||||
url: this.getFullImageUrl(img.url),
|
||||
text: img.text,
|
||||
height: 0,
|
||||
}));
|
||||
console.log('[popup-notice] 图片URL:', processed.map((p) => p.url));
|
||||
this.setData({ processedImages: processed });
|
||||
|
||||
// 可选:量真实高度(失败也不影响 widthFix 展示)
|
||||
const screenWidth = wx.getSystemInfoSync().windowWidth;
|
||||
const containerWidth = Math.min(screenWidth * 0.86, 310);
|
||||
const imageWidth = Math.max(containerWidth - 30, 200);
|
||||
for (let i = 0; i < processed.length; i++) {
|
||||
if (token !== this._showToken) return;
|
||||
const fullUrl = processed[i].url;
|
||||
if (!fullUrl || !/^https?:\/\//.test(fullUrl)) {
|
||||
console.error('[popup-notice] OSS未就绪或URL非法', fullUrl);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
const res = await this.getImageInfoPromise(fullUrl);
|
||||
const realHeight = (imageWidth * res.height) / res.width;
|
||||
this.setData({ [`processedImages[${i}].height`]: realHeight });
|
||||
} catch (e) {
|
||||
console.error('获取图片信息失败', fullUrl, e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/** 等待 / 回读本地缓存,确保能拼出完整 COS 地址 */
|
||||
ensureOssBase(timeoutMs = 3000) {
|
||||
const app = getApp();
|
||||
const readOss = () => this.resolveOssBase();
|
||||
if (readOss()) return Promise.resolve(readOss());
|
||||
|
||||
return new Promise((resolve) => {
|
||||
let done = false;
|
||||
const finish = () => {
|
||||
if (done) return;
|
||||
done = true;
|
||||
if (app.off) app.off('configApplied', onCfg);
|
||||
clearInterval(timer);
|
||||
clearTimeout(timerOut);
|
||||
resolve(readOss());
|
||||
};
|
||||
const onCfg = () => finish();
|
||||
if (app.on) app.on('configApplied', onCfg);
|
||||
const timer = setInterval(() => {
|
||||
if (readOss()) finish();
|
||||
}, 100);
|
||||
const timerOut = setTimeout(finish, timeoutMs);
|
||||
// 主动再读一次缓存配置
|
||||
try {
|
||||
if (typeof app.readConfigFromStorage === 'function') {
|
||||
const cached = app.readConfigFromStorage();
|
||||
if (cached && app.applyDynamicConfig) app.applyDynamicConfig(cached);
|
||||
}
|
||||
} catch (e) {}
|
||||
if (readOss()) finish();
|
||||
});
|
||||
},
|
||||
|
||||
resolveOssBase() {
|
||||
const app = getApp();
|
||||
let base = (app.globalData && app.globalData.ossImageUrl) || '';
|
||||
if (!base && app && typeof app.readConfigFromStorage === 'function') {
|
||||
try {
|
||||
const cached = app.readConfigFromStorage();
|
||||
base = (cached && cached.cos && cached.cos.ossImageUrl) || '';
|
||||
if (base && app.globalData) app.globalData.ossImageUrl = base;
|
||||
} catch (e) {}
|
||||
}
|
||||
return base || '';
|
||||
},
|
||||
|
||||
getImageInfoPromise(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -202,12 +268,18 @@ Component({
|
||||
|
||||
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;
|
||||
if (relativeUrl.startsWith('http://') || relativeUrl.startsWith('https://')) {
|
||||
return relativeUrl;
|
||||
}
|
||||
// 后端 cos.ossImageUrl 带尾斜杠;相对路径不带前导 /
|
||||
let base = this.resolveOssBase();
|
||||
if (!base) {
|
||||
console.warn('[popup-notice] ossImageUrl 为空,无法拼接', relativeUrl);
|
||||
return '';
|
||||
}
|
||||
if (!base.endsWith('/')) base += '/';
|
||||
const clean = String(relativeUrl).replace(/^\/+/, '');
|
||||
return base + clean;
|
||||
},
|
||||
|
||||
preventMove() {},
|
||||
|
||||
@@ -25,15 +25,17 @@
|
||||
<view wx:for="{{processedImages}}" wx:key="index" class="image-block">
|
||||
<view wx:if="{{item.text}}" class="block-text">{{item.text}}</view>
|
||||
<view class="image-padding">
|
||||
<image
|
||||
class="block-image"
|
||||
src="{{item.url}}"
|
||||
style="width:100%; height:{{item.height}}px; display:block;"
|
||||
<image
|
||||
class="block-image"
|
||||
src="{{item.url}}"
|
||||
mode="widthFix"
|
||||
style="width:100%; {{item.height > 0 ? 'height:' + item.height + 'px;' : ''}} display:block;"
|
||||
data-index="{{index}}"
|
||||
data-url="{{item.url}}"
|
||||
bindtap="onCustomPreview"
|
||||
binderror="onImageError"
|
||||
lazy-load="{{false}}"
|
||||
show-menu-by-longpress="{{true}}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -136,12 +136,42 @@ Page({
|
||||
this._skipShowRefresh = true;
|
||||
},
|
||||
|
||||
tryShowAcceptOrderPopup() {
|
||||
async tryShowAcceptOrderPopup() {
|
||||
if (app.globalData._acceptOrderPopupDone) return;
|
||||
// 先确保 OSS 配置已加载,再拉弹窗(否则相对 URL 拼不出图)
|
||||
await this.ensureOssReadyForPopup(4000);
|
||||
if (app.globalData._acceptOrderPopupDone) return;
|
||||
app.globalData._acceptOrderPopupDone = true;
|
||||
PopupService.checkAndShow(this, 'jiedan');
|
||||
},
|
||||
|
||||
ensureOssReadyForPopup(timeoutMs = 3000) {
|
||||
const hasOss = () => !!(app.globalData && app.globalData.ossImageUrl);
|
||||
if (hasOss()) return Promise.resolve(true);
|
||||
try {
|
||||
const cached = app.readConfigFromStorage && app.readConfigFromStorage();
|
||||
if (cached && app.applyDynamicConfig) {
|
||||
app.applyDynamicConfig(cached);
|
||||
}
|
||||
} catch (e) {}
|
||||
if (hasOss()) return Promise.resolve(true);
|
||||
return new Promise((resolve) => {
|
||||
let finished = false;
|
||||
const done = () => {
|
||||
if (finished) return;
|
||||
finished = true;
|
||||
if (app.off) app.off('configApplied', onCfg);
|
||||
clearInterval(poll);
|
||||
clearTimeout(to);
|
||||
resolve(hasOss());
|
||||
};
|
||||
const onCfg = () => done();
|
||||
if (app.on) app.on('configApplied', onCfg);
|
||||
const poll = setInterval(() => { if (hasOss()) done(); }, 100);
|
||||
const to = setTimeout(done, timeoutMs);
|
||||
});
|
||||
},
|
||||
|
||||
persistPageCache(extra = {}) {
|
||||
const d = this.data;
|
||||
app.globalData._acceptOrderPageCache = {
|
||||
@@ -160,6 +190,11 @@ Page({
|
||||
},
|
||||
|
||||
onHide: function () {
|
||||
// 只释放 PopupService 锁,不强制关掉正在展示的弹窗内容(避免刚拼好 URL 就被清掉)
|
||||
PopupService.reset();
|
||||
},
|
||||
|
||||
onUnload: function () {
|
||||
const popupComp = this.selectComponent('#popupNotice');
|
||||
if (popupComp && popupComp.cleanup) {
|
||||
popupComp.cleanup();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"usingComponents": {
|
||||
"chenghao-tag": "/components/chenghao-tag/chenghao-tag",
|
||||
"global-notification": "/components/global-notification/global-notification",
|
||||
"kefu-float": "/components/kefu-float/kefu-float"
|
||||
"kefu-float": "/components/kefu-float/kefu-float",
|
||||
"popup-notice": "/components/popup-notice/popup-notice"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user