upload project
This commit is contained in:
commit
06961cae04
422 changed files with 110626 additions and 0 deletions
164
utils/map-feed-helpers.js
Normal file
164
utils/map-feed-helpers.js
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
const DEFAULT_THUMBNAILS = {
|
||||
image: '/images/placeholder.svg',
|
||||
video: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/component/picker/image-default.png',
|
||||
mixed: '/images/placeholder.svg'
|
||||
};
|
||||
|
||||
const MAP_FEED_MARKER_STYLE = {
|
||||
single: {
|
||||
background: '#f02d05',
|
||||
color: '#FFFFFF',
|
||||
icon: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/icon_nav/icon_nav_location_blue.png'
|
||||
},
|
||||
cluster: {
|
||||
background: '#BB10BB',
|
||||
color: '#FFFFFF',
|
||||
icon: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/icon_nav/icon_nav_discover.png'
|
||||
},
|
||||
administrative: {
|
||||
background: '#f0500a',
|
||||
color: '#FFFFFF',
|
||||
icon: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/icon_nav/icon_nav_map.png'
|
||||
},
|
||||
stranger: {
|
||||
background: '#f0500a',
|
||||
color: '#FFFFFF',
|
||||
icon: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/icon_nav/icon_nav_map.png'
|
||||
},
|
||||
friend: {
|
||||
background: '#44a186',
|
||||
color: '#FFFFFF',
|
||||
icon: 'https://res.wx.qq.com/a/wx_fed/weui-design/assets/icon_nav/icon_nav_map.png'
|
||||
}
|
||||
};
|
||||
|
||||
const MAP_FEED_SCALE_BUCKETS = [
|
||||
{ mode: 'nearby', level: 'street', minScale: 11 },
|
||||
{ mode: 'administrative', level: 'district', minScale: 9 },
|
||||
{ mode: 'administrative', level: 'city', minScale: 7 },
|
||||
{ mode: 'administrative', level: 'province', minScale: 5 },
|
||||
{ mode: 'administrative', level: 'country', minScale: 0 }
|
||||
];
|
||||
|
||||
const MAP_FEED_DEBOUNCE = 400;
|
||||
const MAP_FEED_CACHE_TTL = 3 * 60 * 1000;
|
||||
const MAP_FEED_BUBBLE_LIMIT = 5;
|
||||
|
||||
function getFeedScalePreset(scale) {
|
||||
if (typeof scale !== 'number') {
|
||||
return MAP_FEED_SCALE_BUCKETS[0];
|
||||
}
|
||||
|
||||
return MAP_FEED_SCALE_BUCKETS.find((bucket) => scale >= bucket.minScale) || MAP_FEED_SCALE_BUCKETS[MAP_FEED_SCALE_BUCKETS.length - 1];
|
||||
}
|
||||
|
||||
function pickCorner(bounds = {}, key) {
|
||||
return bounds[key] || bounds[key?.toLowerCase?.()] || bounds[key?.replace?.(/([A-Z])/g, '_$1').toLowerCase?.()] || null;
|
||||
}
|
||||
|
||||
function normalizeCorner(corner) {
|
||||
if (!corner) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (corner.latitude !== undefined && corner.longitude !== undefined) {
|
||||
return {
|
||||
latitude: Number(corner.latitude),
|
||||
longitude: Number(corner.longitude)
|
||||
};
|
||||
}
|
||||
|
||||
if (corner.lat !== undefined && corner.lng !== undefined) {
|
||||
return {
|
||||
latitude: Number(corner.lat),
|
||||
longitude: Number(corner.lng)
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildBoundsPayload(bounds) {
|
||||
if (!bounds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const northEastRaw = pickCorner(bounds, 'northEast') || pickCorner(bounds, 'northeast');
|
||||
const southWestRaw = pickCorner(bounds, 'southWest') || pickCorner(bounds, 'southwest');
|
||||
const northEast = normalizeCorner(northEastRaw);
|
||||
const southWest = normalizeCorner(southWestRaw);
|
||||
|
||||
if (!northEast || !southWest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Number.isNaN(northEast.latitude) || Number.isNaN(northEast.longitude) || Number.isNaN(southWest.latitude) || Number.isNaN(southWest.longitude)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
bounds: {
|
||||
northEast,
|
||||
southWest
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function resolveFeedThumbnail(point = {}) {
|
||||
let candidate = point.thumbnail || point.cover || point.preview || (Array.isArray(point.media) && point.media.length > 0 ? point.media[0]?.url : null);
|
||||
|
||||
if (candidate && typeof candidate === 'string') {
|
||||
if (candidate.startsWith('/')) {
|
||||
return candidate;
|
||||
}
|
||||
const lower = candidate.toLowerCase();
|
||||
if (lower.includes('example.com') || lower.startsWith('http://example.com') || lower.includes('placeholder')) {
|
||||
return DEFAULT_THUMBNAILS.mixed;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
|
||||
const typeKey = point.contentType || point.type || 'mixed';
|
||||
return DEFAULT_THUMBNAILS[typeKey] || DEFAULT_THUMBNAILS.mixed;
|
||||
}
|
||||
|
||||
function buildCacheKey({ mode, level }, payload = {}) {
|
||||
const boundsKey = payload?.bounds
|
||||
? [
|
||||
payload.bounds.northEast?.latitude?.toFixed(4),
|
||||
payload.bounds.northEast?.longitude?.toFixed(4),
|
||||
payload.bounds.southWest?.latitude?.toFixed(4),
|
||||
payload.bounds.southWest?.longitude?.toFixed(4)
|
||||
].join(',')
|
||||
: 'unknown';
|
||||
|
||||
const filterParts = [
|
||||
payload?.timeFilter?.enabled ? payload.timeFilter.range : 'all',
|
||||
Array.isArray(payload?.contentTypes) ? payload.contentTypes.sort().join('|') : 'all',
|
||||
payload?.level || 'none'
|
||||
];
|
||||
|
||||
return `${mode}:${level}:${boundsKey}:${filterParts.join(':')}`;
|
||||
}
|
||||
|
||||
function isCacheFresh(entry, ttl = MAP_FEED_CACHE_TTL) {
|
||||
if (!entry || !entry.timestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Date.now() - entry.timestamp < ttl;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
DEFAULT_THUMBNAILS,
|
||||
MAP_FEED_SCALE_BUCKETS,
|
||||
MAP_FEED_DEBOUNCE,
|
||||
MAP_FEED_CACHE_TTL,
|
||||
MAP_FEED_BUBBLE_LIMIT,
|
||||
MAP_FEED_MARKER_STYLE,
|
||||
getFeedScalePreset,
|
||||
buildBoundsPayload,
|
||||
resolveFeedThumbnail,
|
||||
buildCacheKey,
|
||||
isCacheFresh
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue