1 Star 0 Fork 1

cxj-mayun / html2image-service

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
main.ts 5.72 KB
一键复制 编辑 原始数据 按行查看 历史
cxj-mayun 提交于 2022-08-29 17:39 . feat: 显示不包括港澳台及海外
import express = require("express");
import { Page, Browser } from "puppeteer";
import puppeteer = require("puppeteer");
import { Request, Response } from "express";
import { createSSRApp, h } from "vue";
import { renderToString } from "@vue/server-renderer";
const areaList = require("./areas.json");
interface BrowserTabHandle extends Page {
__running?: boolean;
}
const PORT = process.env.MJ_BANNER_SERVICE_PORT || 3333;
const IP = "0.0.0.0";
const DEBUG = process.env.NODE_ENV === "development";
console.log("当前环境:", process.env.NODE_ENV);
const TB_DEFAULT_FONT = 'tahoma, arial, "Hiragino Sans GB", 宋体, sans-serif';
let browser: Browser;
const pagePool: Array<BrowserTabHandle> = [];
const PAGE_POOL_SIZE = 8;
const app = express();
app.use(express.json());
app.use(
express.urlencoded({
extended: false,
})
);
// 根据地区码计算包邮地区
export function getFreeShipAreaDesc(areas: Array<any>) {
if (areas.length === 0) {
return "未设置";
}
if (areas.length === areaList.length) {
return "不包括 港澳台及海外";
}
if (areas.length <= Math.ceil(areaList.length / 2)) {
return (
"包邮地区:" + areas.map((area) => area.name).join(",") + ",港澳台及海外"
);
}
const otherAreas = areaList.filter(
(item: any) => !areas.find((area) => item.code === area.code)
);
return "不包括 " + otherAreas.map((area: any) => area.name).join(",");
}
function activityToData(activity: any) {
return {
startTime: activity.start_time,
endTime: activity.end_time,
name: activity.label,
isAll: activity.type === "mjs_all",
comment: activity.data.comments || "",
discounts: activity.data.settings.map((config: any) => {
const areaCodes = String(config.area).split("|");
const areas = areaList.filter((item: any) =>
areaCodes.find((code) => Number(code) === item.code)
);
return {
totalPrice: config.totalPrice / 100, // 满多少元
count: config.count, // 满多少件
decreaseMoney: config.decreaseMoney / 100, // 减多少钱
discountRate: config.discountRate / 100, // 打多少折
areas: getFreeShipAreaDesc(areas), // 包邮地区
giftName: config.giftName, // 礼物名
giftUrl: config.giftId, // 礼物id
multi: config.amountMulti || config.countMulti, // 上不封顶
useTotalPrice: config.hasOwnProperty("totalPrice"), // 是否使用满元
useCount: config.hasOwnProperty("count"), // 是否使用满件
useDecreaseMoney: config.hasOwnProperty("decreaseMoney"), // 是否使用减钱
useDiscountRate: config.hasOwnProperty("discountRate"), // 是否使用打折
freeDelivery: config.hasOwnProperty("area"), // 是否包邮
useGift: config.hasOwnProperty("giftName"), // 是否送礼
};
}),
};
}
function MjBanner(props: any) {
return h(
{
props: Object.keys(props.data),
template: props.template,
},
{ ...props.data }
);
}
async function templateToHtml(template: string, data: any) {
const app = createSSRApp({
render() {
return h(MjBanner, {
template,
data,
});
},
});
const appContent = await renderToString(app);
return `
<html>
<body style="font-family: ${TB_DEFAULT_FONT}">
${appContent}
</body>
</html>
`;
}
async function htmlToImage(page: Page, html: string) {
await page.bringToFront();
await page.setContent(html);
const elHandle = (await page.$("#mj-banner")) || (await page.$("body"));
if (!elHandle) return "";
return await elHandle.screenshot({
encoding: "base64",
type: "png",
omitBackground: true,
});
}
app.post("/api/screenshot/html", async (req: Request, res: Response) => {
const { preview } = req.query;
const { html } = req.body;
const page = pagePool.find((page) => !page.__running) || pagePool[0];
page.__running = true;
try {
const base64 = await htmlToImage(page, html);
if (preview === "1") {
res.send(`<img src="data:image/png;base64,${base64}">`);
// res.set('Content-Type', 'image/png')
// res.send(base64)
} else {
res.send({
code: 0,
data: base64,
});
}
} catch (err: any) {
res.status(500).send(err.message);
} finally {
page.__running = false;
}
});
app.post("/api/screenshot/mj-banner", async (req, res) => {
const { preview } = req.query;
const { template, activity } = req.body;
const page = pagePool.find((page) => !page.__running) || pagePool[0];
page.__running = true;
try {
const data = activityToData(activity);
const html = await templateToHtml(template, data);
const base64 = await htmlToImage(page, html);
if (preview === "1") {
res.send(`<img src="data:image/png;base64,${base64}">`);
// res.set('Content-Type', 'image/png')
// res.send(base64)
} else {
res.send({
code: 0,
data: base64,
});
}
} catch (err: any) {
res.status(500).send(err.message);
} finally {
page.__running = false;
}
});
function startServer() {
return new Promise((resolve) => {
app.listen(PORT as number, IP, () => {
resolve(app);
});
});
}
(async () => {
browser = await puppeteer.launch({
headless: !DEBUG,
args: ["--no-sandbox", "--disable-setuid-sandbox"],
});
const initPageTask = Array.from({ length: PAGE_POOL_SIZE }, () => {
return browser
.newPage()
.then((page) => {
pagePool.push(page);
return page;
})
.then((page) => {
return page.setViewport({
width: 1080,
height: 2560,
});
});
});
await Promise.all(initPageTask);
await startServer();
})().then(() => {
console.log("初始化完成");
});
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/cxj-mayun/html2image-service.git
git@gitee.com:cxj-mayun/html2image-service.git
cxj-mayun
html2image-service
html2image-service
master

搜索帮助

344bd9b3 5694891 D2dac590 5694891