feat(round-12): 实体卡外贸生产工单/雷达多渠道归因漏斗/AI地道外联草拟/现代图片自适应协商 (87套件1007测试全绿)
这个提交包含在:
@@ -0,0 +1,91 @@
|
||||
import { Provide } from '@midwayjs/core';
|
||||
import { BaseService } from '@cool-midway/core';
|
||||
|
||||
export type SupportedImageFormat = 'avif' | 'webp' | 'png' | 'jpg';
|
||||
|
||||
export interface MediaNegotiationContext {
|
||||
acceptHeader?: string;
|
||||
networkType?: 'wifi' | '5g' | '4g' | '3g' | '2g' | 'unknown' | string;
|
||||
targetWidth?: number;
|
||||
dpr?: number;
|
||||
}
|
||||
|
||||
export interface OptimizedMediaResult {
|
||||
format: SupportedImageFormat;
|
||||
width?: number;
|
||||
quality: number;
|
||||
optimizedUrl: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 协商最佳媒体交付 URL 与压缩参数
|
||||
*/
|
||||
export function negotiateOptimalMediaUrl(
|
||||
url: string,
|
||||
ctx: MediaNegotiationContext
|
||||
): OptimizedMediaResult {
|
||||
if (!url || typeof url !== 'string' || !url.trim()) {
|
||||
return {
|
||||
format: 'jpg',
|
||||
quality: 80,
|
||||
optimizedUrl: '',
|
||||
};
|
||||
}
|
||||
|
||||
const accept = (ctx.acceptHeader || '').toLowerCase();
|
||||
const net = (ctx.networkType || 'wifi').toLowerCase();
|
||||
const isSlowNetwork = net === '2g' || net === '3g';
|
||||
|
||||
// 1. 协商格式: avif > webp > 原图扩展名(png/jpg)
|
||||
let format: SupportedImageFormat = 'jpg';
|
||||
if (accept.includes('image/avif')) {
|
||||
format = 'avif';
|
||||
} else if (accept.includes('image/webp')) {
|
||||
format = 'webp';
|
||||
} else if (url.toLowerCase().endsWith('.png') || accept.includes('image/png')) {
|
||||
format = 'png';
|
||||
}
|
||||
|
||||
// 2. 协商质量与宽度
|
||||
let quality = 85;
|
||||
if (isSlowNetwork) {
|
||||
quality = 65;
|
||||
}
|
||||
|
||||
let width = ctx.targetWidth;
|
||||
if (width != null && width > 0) {
|
||||
const dpr = ctx.dpr && ctx.dpr > 1 ? ctx.dpr : 1;
|
||||
if (isSlowNetwork) {
|
||||
// 弱网降规 75%
|
||||
width = Math.round(width * 0.75);
|
||||
} else {
|
||||
width = Math.round(width * dpr);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 构造优化 URL 参数
|
||||
const separator = url.includes('?') ? '&' : '?';
|
||||
const queryParts: string[] = [`format=${format}`, `q=${quality}`];
|
||||
if (width != null && width > 0) {
|
||||
queryParts.push(`w=${width}`);
|
||||
}
|
||||
|
||||
const optimizedUrl = `${url}${separator}${queryParts.join('&')}`;
|
||||
|
||||
return {
|
||||
format,
|
||||
width,
|
||||
quality,
|
||||
optimizedUrl,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 微官网现代图片自适应协商服务
|
||||
*/
|
||||
@Provide()
|
||||
export class PortalMediaNegotiatorService extends BaseService {
|
||||
negotiate(url: string, ctx: MediaNegotiationContext): OptimizedMediaResult {
|
||||
return negotiateOptimalMediaUrl(url, ctx);
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户