feat(ops): v4.0.7 HQ 活动图快链与勾选导出
HQ 指定一张活动图为勾选主合伙人合成 PNG/zip;城市合伙人页增加快链与单下/导出。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Sequential Sharp compose bench (1 / 10 / 50) on a 1080×1920 template.
|
||||
* Usage: node scripts/with-api-env.cjs npx ts-node --transpile-only scripts/bench-activity-poster-pack.ts
|
||||
* or from dukang-api: npx ts-node --transpile-only scripts/bench-activity-poster-pack.ts
|
||||
*/
|
||||
import sharp from 'sharp';
|
||||
import {
|
||||
DEFAULT_ACTIVITY_POSTER_QR_SLOT,
|
||||
activityPosterQrSlotPx,
|
||||
activityPosterTemplateTooLarge,
|
||||
} from '@dukang/shared-types';
|
||||
|
||||
async function png(width: number, height: number, r: number, g: number, b: number) {
|
||||
return sharp({
|
||||
create: { width, height, channels: 3, background: { r, g, b } },
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
async function compose(template: Buffer, qrPng: Buffer) {
|
||||
const meta = await sharp(template).metadata();
|
||||
if (!meta.width || !meta.height) throw new Error('no size');
|
||||
if (activityPosterTemplateTooLarge(meta.width, meta.height)) throw new Error('too large');
|
||||
const { left, top, size } = activityPosterQrSlotPx(
|
||||
meta.width,
|
||||
meta.height,
|
||||
DEFAULT_ACTIVITY_POSTER_QR_SLOT.qrXPct,
|
||||
DEFAULT_ACTIVITY_POSTER_QR_SLOT.qrYPct,
|
||||
DEFAULT_ACTIVITY_POSTER_QR_SLOT.qrSizePct,
|
||||
);
|
||||
const qr = await sharp(qrPng).resize(size, size, { fit: 'fill' }).png().toBuffer();
|
||||
return sharp(template).composite([{ input: qr, left, top }]).png().toBuffer();
|
||||
}
|
||||
|
||||
function rssMb() {
|
||||
return Math.round(process.memoryUsage().rss / 1024 / 1024);
|
||||
}
|
||||
|
||||
async function bench(n: number, template: Buffer, qr: Buffer) {
|
||||
const t0 = Date.now();
|
||||
const rss0 = rssMb();
|
||||
let last = 0;
|
||||
for (let i = 0; i < n; i += 1) {
|
||||
const out = await compose(template, qr);
|
||||
last = out.length;
|
||||
}
|
||||
const ms = Date.now() - t0;
|
||||
return { n, ms, avgMs: Math.round(ms / n), rss0, rss1: rssMb(), lastKb: Math.round(last / 1024) };
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const template = await png(1080, 1920, 160, 32, 32);
|
||||
const qr = await png(430, 430, 255, 255, 255);
|
||||
console.log(`template=${Math.round(template.length / 1024)}KB qr=${Math.round(qr.length / 1024)}KB rss=${rssMb()}MB`);
|
||||
for (const n of [1, 10, 50]) {
|
||||
const row = await bench(n, template, qr);
|
||||
console.log(
|
||||
`n=${row.n} total=${row.ms}ms avg=${row.avgMs}ms rss ${row.rss0}->${row.rss1}MB out≈${row.lastKb}KB`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main();
|
||||
Reference in New Issue
Block a user