|
|
@@ -569,7 +569,7 @@
|
|
|
</div>
|
|
|
</header>
|
|
|
|
|
|
- <!-- 配图轮播:仅用 URL 与 options.item 的 checkInImages;无图则用 images/map.png(不用 coverUrl / imagePath) -->
|
|
|
+ <!-- 配图轮播:checkInImages;含视频时仅展示封面静图,不播放视频 -->
|
|
|
<div class="checkin-hero" id="dynHero">
|
|
|
<div class="checkin-hero__track" id="dynHeroTrack"></div>
|
|
|
<div class="checkin-hero__dots" id="dynHeroDots" aria-hidden="true"></div>
|
|
|
@@ -2017,10 +2017,93 @@
|
|
|
: '';
|
|
|
}
|
|
|
|
|
|
- /** 轮播仅使用 checkInImages:① URL 参数 ② options.item.checkInImages;无则用默认图 */
|
|
|
+ /** 与 App checkIn/details isVideoClockUrl 一致 */
|
|
|
+ function isCheckInVideoUrl(url) {
|
|
|
+ var s = normalizeMediaUrl(String(url || ''));
|
|
|
+ if (!s) return false;
|
|
|
+ var lower = s.toLowerCase();
|
|
|
+ if (lower.indexOf('m3u8') >= 0) return true;
|
|
|
+ var path = lower.split('?')[0].split('#')[0];
|
|
|
+ if (path.indexOf('/video/') >= 0) return true;
|
|
|
+ return /\.(mp4|m4v|mov|webm|3gp|avi|mkv)$/i.test(path);
|
|
|
+ }
|
|
|
+
|
|
|
+ function getMp4PlaybackUrl(url) {
|
|
|
+ var u = normalizeMediaUrl(String(url || ''));
|
|
|
+ if (!u) return '';
|
|
|
+ var q = u.indexOf('?');
|
|
|
+ var h = u.indexOf('#');
|
|
|
+ var cut = u.length;
|
|
|
+ if (q >= 0) cut = Math.min(cut, q);
|
|
|
+ if (h >= 0) cut = Math.min(cut, h);
|
|
|
+ var base = u.slice(0, cut);
|
|
|
+ if (/\.mp4$/i.test(base)) return base;
|
|
|
+ return u;
|
|
|
+ }
|
|
|
+
|
|
|
+ function mp4UrlToJpgUrl(u) {
|
|
|
+ var q = u.indexOf('?');
|
|
|
+ var h = u.indexOf('#');
|
|
|
+ var cut = u.length;
|
|
|
+ if (q >= 0) cut = Math.min(cut, q);
|
|
|
+ if (h >= 0) cut = Math.min(cut, h);
|
|
|
+ var pathPart = u.slice(0, cut);
|
|
|
+ var rest = u.slice(cut);
|
|
|
+ if (!/\.mp4$/i.test(pathPart)) return '';
|
|
|
+ return pathPart.slice(0, -4) + '.jpg' + rest;
|
|
|
+ }
|
|
|
+
|
|
|
+ function mp4UrlToOssSnapshotUrl(mp4Base) {
|
|
|
+ if (!mp4Base) return '';
|
|
|
+ return (
|
|
|
+ mp4Base +
|
|
|
+ (mp4Base.indexOf('?') >= 0 ? '&' : '?') +
|
|
|
+ 'x-oss-process=video/snapshot,t_0,f_jpg,m_fast'
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ function getCheckInPosterFallbacks() {
|
|
|
+ var list = [];
|
|
|
+ function pushStill(u) {
|
|
|
+ u = normalizeMediaUrl(String(u || '').trim());
|
|
|
+ if (!u || isCheckInVideoUrl(u)) return;
|
|
|
+ if (list.indexOf(u) < 0) list.push(u);
|
|
|
+ }
|
|
|
+ pushStill(getMergedParam('coverUrl') || q('coverUrl'));
|
|
|
+ var item = parseOptionsItem();
|
|
|
+ if (item) {
|
|
|
+ ['videoFirstFrame', 'coverImage', 'cover', 'coverUrl', 'poster', 'entranceImage'].forEach(
|
|
|
+ function (k) {
|
|
|
+ if (item[k] != null) pushStill(item[k]);
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ return list;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 视频地址 → 封面静图 URL(不渲染 video 标签) */
|
|
|
+ function resolveCheckInHeroDisplayUrl(rawUrl, posterFallbacks) {
|
|
|
+ var url = normalizeMediaUrl(rawUrl);
|
|
|
+ if (!url) return '';
|
|
|
+ if (!isCheckInVideoUrl(url)) return url;
|
|
|
+ var fallbacks = posterFallbacks || getCheckInPosterFallbacks();
|
|
|
+ for (var i = 0; i < fallbacks.length; i++) {
|
|
|
+ if (fallbacks[i]) return fallbacks[i];
|
|
|
+ }
|
|
|
+ var playUrl = getMp4PlaybackUrl(url);
|
|
|
+ if (playUrl) {
|
|
|
+ var jpg = mp4UrlToJpgUrl(playUrl);
|
|
|
+ if (jpg) return jpg;
|
|
|
+ return mp4UrlToOssSnapshotUrl(playUrl);
|
|
|
+ }
|
|
|
+ return CHECKIN_HERO_DEFAULT_MAP_SRC;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 轮播:checkInImages;视频项替换为封面图 */
|
|
|
function collectImageUrlsFromUrl() {
|
|
|
var merged = getMergedQueryString();
|
|
|
var urls = [];
|
|
|
+ var posterFallbacks = getCheckInPosterFallbacks();
|
|
|
|
|
|
getAllParamValuesCI(merged, 'checkinimages').forEach(function (val) {
|
|
|
pushUrlsFromRawParam(urls, val);
|
|
|
@@ -2037,10 +2120,20 @@
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (!urls.length) {
|
|
|
- pushUniqueUrl(urls, CHECKIN_HERO_DEFAULT_MAP_SRC);
|
|
|
+ var displayUrls = [];
|
|
|
+ urls.forEach(function (u) {
|
|
|
+ var display = resolveCheckInHeroDisplayUrl(u, posterFallbacks);
|
|
|
+ if (display) pushUniqueUrl(displayUrls, display);
|
|
|
+ });
|
|
|
+
|
|
|
+ if (!displayUrls.length) {
|
|
|
+ if (posterFallbacks.length) {
|
|
|
+ pushUniqueUrl(displayUrls, posterFallbacks[0]);
|
|
|
+ } else {
|
|
|
+ pushUniqueUrl(displayUrls, CHECKIN_HERO_DEFAULT_MAP_SRC);
|
|
|
+ }
|
|
|
}
|
|
|
- return urls;
|
|
|
+ return displayUrls;
|
|
|
}
|
|
|
|
|
|
var heroI = 0;
|
|
|
@@ -2114,8 +2207,19 @@
|
|
|
var s = document.createElement('div');
|
|
|
s.className = 'checkin-hero__slide';
|
|
|
var im = document.createElement('img');
|
|
|
- im.src = url;
|
|
|
im.alt = '';
|
|
|
+ im.decoding = 'async';
|
|
|
+ im.src = url;
|
|
|
+ im.onerror = function () {
|
|
|
+ if (this.dataset.fallbackApplied === '1') {
|
|
|
+ this.src = CHECKIN_HERO_DEFAULT_MAP_SRC;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.dataset.fallbackApplied = '1';
|
|
|
+ var fb = getCheckInPosterFallbacks();
|
|
|
+ if (fb.length) this.src = fb[0];
|
|
|
+ else this.src = CHECKIN_HERO_DEFAULT_MAP_SRC;
|
|
|
+ };
|
|
|
s.appendChild(im);
|
|
|
track.appendChild(s);
|
|
|
var dot = document.createElement('span');
|