101 lines
3.0 KiB
JavaScript
101 lines
3.0 KiB
JavaScript
/**
|
||
* 解析分辨率用于排序:返回较短边、较长边(像素级近似);无法识别则返回 null。
|
||
*/
|
||
function parseResolutionDimsForSort(raw) {
|
||
if (raw == null) return null;
|
||
const s = String(raw).trim();
|
||
if (!s) return null;
|
||
const compact = s.replace(/\s+/g, '');
|
||
const lower = compact.toLowerCase();
|
||
|
||
const wxh = lower.match(/^(\d+)\s*[x×]\s*(\d+)$/i);
|
||
if (wxh) {
|
||
const w = parseInt(wxh[1], 10);
|
||
const h = parseInt(wxh[2], 10);
|
||
if (Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0) {
|
||
return { short: Math.min(w, h), long: Math.max(w, h) };
|
||
}
|
||
}
|
||
|
||
if (/^\d+p$/i.test(compact)) {
|
||
const n = parseInt(compact, 10);
|
||
if (Number.isFinite(n)) return { short: n, long: n };
|
||
}
|
||
|
||
if (lower === '8k') return { short: 4320, long: 7680 };
|
||
if (lower === '4k') return { short: 2160, long: 3840 };
|
||
if (lower === '2k') return { short: 1440, long: 2560 };
|
||
|
||
if (/^\d+k$/i.test(compact)) {
|
||
const n = parseInt(compact, 10);
|
||
if (Number.isFinite(n) && n > 0) {
|
||
const short = n * 720;
|
||
return { short, long: short };
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/**
|
||
* 分辨率从低到高比较(用于定价档位表排序)。
|
||
* 可识别 WxH、720p、4K/2K/8K 等;无法解析的排在已解析项之后,彼此按字符串序。
|
||
*/
|
||
export function compareVideoResolutionAsc(rawA, rawB) {
|
||
const da = parseResolutionDimsForSort(rawA);
|
||
const db = parseResolutionDimsForSort(rawB);
|
||
if (da && db) {
|
||
if (da.short !== db.short) return da.short - db.short;
|
||
if (da.long !== db.long) return da.long - db.long;
|
||
return String(rawA).localeCompare(String(rawB));
|
||
}
|
||
if (da && !db) return -1;
|
||
if (!da && db) return 1;
|
||
return String(rawA ?? '').localeCompare(String(rawB ?? ''));
|
||
}
|
||
|
||
/**
|
||
* 将配置里的分辨率(如 854x480、1280x720)转成用户易读的 480p / 720p / 4K 等。
|
||
* 已是 720p、2K 等形式则尽量规范化后原样返回。
|
||
*/
|
||
export function formatVideoResolutionDisplayLabel(raw) {
|
||
if (raw == null) return '';
|
||
const s = String(raw).trim();
|
||
if (!s) return '';
|
||
|
||
const compact = s.replace(/\s+/g, '');
|
||
const lower = compact.toLowerCase();
|
||
|
||
if (/^\d+p$/i.test(compact)) {
|
||
const n = parseInt(compact, 10);
|
||
return Number.isFinite(n) ? `${n}p` : s;
|
||
}
|
||
if (/^\d+k$/i.test(compact)) {
|
||
const n = parseInt(compact, 10);
|
||
return Number.isFinite(n) ? `${n}K` : s;
|
||
}
|
||
|
||
const m = lower.match(/^(\d+)\s*[x×]\s*(\d+)$/i);
|
||
if (!m) return s;
|
||
|
||
const w = parseInt(m[1], 10);
|
||
const h = parseInt(m[2], 10);
|
||
if (!Number.isFinite(w) || !Number.isFinite(h) || w <= 0 || h <= 0) {
|
||
return s;
|
||
}
|
||
|
||
const short = Math.min(w, h);
|
||
const long = Math.max(w, h);
|
||
|
||
if (long >= 7680 || short >= 4320) return '8K';
|
||
if (short >= 2160) return '4K';
|
||
if (short >= 1440) return '2K';
|
||
if (short >= 1080) return '1080p';
|
||
if (short >= 720) return '720p';
|
||
if (short >= 540) return '540p';
|
||
if (short >= 480) return '480p';
|
||
if (short >= 360) return '360p';
|
||
if (short >= 240) return '240p';
|
||
return `${short}p`;
|
||
}
|