You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

200 lines
4.5 KiB

// 图片URL验证工具
/**
* 验证图片URL是否有效
* @param {string} url - 图片URL
* @returns {boolean} - 是否为有效图片URL
*/
function isValidImageUrl(url) {
if (!url || typeof url !== 'string') {
return false;
}
// 允许各种合法的图片URL格式
// 1. 标准HTTP/HTTPS URL
if (url.startsWith('http://') || url.startsWith('https://')) {
return true;
}
// 2. 阿里云OSS临时URL(可能包含特殊字符)
if (url.includes('oss-cn-') && url.includes('aliyuncs.com')) {
return true;
}
// 3. 小程序本地临时文件路径
if (url.startsWith('wxfile://')) {
return true;
}
// 4. Base64编码的图片数据URL
if (url.startsWith('data:image/')) {
return true;
}
// 5. 占位符URL,在实际场景中会被替换
if (url.startsWith('placeholder://')) {
return true;
}
return false;
}
/**
* 过滤有效的图片URL
* @param {Array<string>} urls - 图片URL数组
* @returns {Array<string>} - 有效的图片URL数组
*/
function filterValidImageUrls(urls) {
if (!Array.isArray(urls)) {
return [];
}
return urls.filter(url => isValidImageUrl(url));
}
/**
* 修复商品对象中的图片URL
* @param {Object} product - 商品对象
* @returns {Object} - 修复后的商品对象
*/
function fixProductImageUrls(product) {
if (!product || typeof product !== 'object') {
return product;
}
// 创建商品的副本以避免直接修改原对象
const fixedProduct = { ...product };
// 修复主图片URL数组
if (fixedProduct.imageUrls && Array.isArray(fixedProduct.imageUrls)) {
fixedProduct.imageUrls = filterValidImageUrls(fixedProduct.imageUrls);
}
// 修复备用图片URL数组(如果存在)
if (fixedProduct.allImageUrls && Array.isArray(fixedProduct.allImageUrls)) {
fixedProduct.allImageUrls = filterValidImageUrls(fixedProduct.allImageUrls);
}
// 修复单个图片URL(如果存在)
if (fixedProduct.imageUrl && !isValidImageUrl(fixedProduct.imageUrl)) {
fixedProduct.imageUrl = '';
}
return fixedProduct;
}
/**
* 修复商品列表中的图片URL
* @param {Array<Object>} products - 商品列表
* @returns {Array<Object>} - 修复后的商品列表
*/
function fixProductListImageUrls(products) {
if (!Array.isArray(products)) {
return products;
}
return products.map(product => fixProductImageUrls(product));
}
/**
* 标准化图片URL格式
* @param {string} url - 图片URL
* @returns {string} - 标准化后的图片URL
*/
function normalizeImageUrl(url) {
if (!url || typeof url !== 'string') {
return '';
}
// 去除URL前后的空格
const trimmedUrl = url.trim();
// 对于占位符URL,不进行任何额外处理,直接返回
if (trimmedUrl.startsWith('placeholder://')) {
return trimmedUrl;
}
// 确保URL格式正确
if (trimmedUrl.startsWith('//')) {
return 'https:' + trimmedUrl;
}
return trimmedUrl;
}
/**
* 标准化图片URL数组
* @param {Array<string>} urls - 图片URL数组
* @returns {Array<string>} - 标准化后的图片URL数组
*/
function normalizeImageUrls(urls) {
if (!Array.isArray(urls)) {
return [];
}
return urls.map(url => normalizeImageUrl(url)).filter(url => url !== '');
}
/**
* 获取图片URL验证统计信息
* @param {Array<string>} urls - 图片URL数组
* @returns {Object} - 验证统计信息
*/
function getImageUrlStats(urls) {
const stats = {
total: 0,
valid: 0,
invalid: 0,
types: {
http: 0,
https: 0,
oss: 0,
wxfile: 0,
data: 0,
placeholder: 0,
other: 0
}
};
if (!Array.isArray(urls)) {
return stats;
}
stats.total = urls.length;
urls.forEach(url => {
if (isValidImageUrl(url)) {
stats.valid++;
if (url.startsWith('http://')) {
stats.types.http++;
} else if (url.startsWith('https://')) {
stats.types.https++;
} else if (url.includes('oss-cn-') && url.includes('aliyuncs.com')) {
stats.types.oss++;
} else if (url.startsWith('wxfile://')) {
stats.types.wxfile++;
} else if (url.startsWith('data:image/')) {
stats.types.data++;
} else if (url.startsWith('uploaded_')) {
stats.types.placeholder++;
} else {
stats.types.other++;
}
} else {
stats.invalid++;
}
});
return stats;
}
module.exports = {
isValidImageUrl,
filterValidImageUrls,
fixProductImageUrls,
fixProductListImageUrls,
normalizeImageUrl,
normalizeImageUrls,
getImageUrlStats
};