Files
Sheep-Service/api/middleware/genCards.js
Rozenrod 4b96ef0806 Додана сторінка "Розклад зібрань"
Перероблен генератор карточок територій APІ
2025-11-22 20:17:50 +02:00

58 lines
5.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const os = require('os');
const fs = require('fs');
const path = require('path');
const { chromium } = require('playwright');
const sharp = require('sharp');
const DIR = process.env.CARDS_PATH || '../cards';
async function genCards({ id, type }) {
if (!process.env.DOMAIN) throw new Error("❌ DOMAIN не заданий у .env");
if (!process.env.ADMIN_TOKEN) throw new Error("❌ ADMIN_TOKEN не заданий у .env");
if (!process.env.CARDS_PATH) throw new Error("❌ CARDS_PATH не заданий у .env");
const name = type == 'homestead' ? `H${id}` : `T${id}`
const URL = `https://${process.env.DOMAIN}/api/${type}/${id}`; // Замени на свой URL
const AUTH_TOKEN = process.env.ADMIN_TOKEN;
const DIR = process.env.CARDS_PATH || '../cards';
const SCREENSHOT_FILE = path.resolve(`${DIR}/cache/${type}/${name}.png`);
const OUTPUT_FILE = path.resolve(`${DIR}/${type}/${name}.webp`);
// --- Отримуємо дані ---
const res = await fetch(URL, {
headers: { 'Authorization': AUTH_TOKEN, 'Accept': 'application/json' }
});
if (!res.ok) throw new Error(`Помилка запиту: ${res.status}`);
const data = await res.json();
// --- Генеруємо HTML ---
const html = `<!DOCTYPE html><html><head><meta charset="UTF-8" /><link rel="stylesheet" href="https://sheep-service.com/lib/components/leaflet/leaflet.css" /><script src="https://sheep-service.com/lib/components/leaflet/leaflet.js"></script><script src="https://sheep-service.com/lib/components/qrcode.min.js"></script><style>@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");html, body {height: calc(100% + 50px);}* {border: 0;padding: 0;font-family: "Roboto", sans-serif;margin: 0;font-weight: 500;outline: none;}#content {width: 100%;height: 100%;position: absolute;z-index: 9999;display: flex;flex-direction: column;}#content > #title {width: calc(100% - 30px);min-height: 90px;background: rgb(255 255 255 / 51%);backdrop-filter: blur(10px);display: flex;flex-direction: row;justify-content: space-between;padding: 15px;align-items: center;color: #333;}#content > #title > div {display: flex;flex-direction: column;width: 100%;align-items: center;}#content > #title > h1 {font-size: 60px;font-weight: 700;margin: 0;min-width: 200px;text-align: center;}#content > #title > div > h2 {font-size: 35px;font-weight: 700;margin: 0;}#content > #title > div > h3 {font-size: 28px;font-weight: 500;margin: 0px 0 10px 0;}#qrcode {position: absolute;bottom: 20px;left: 20px;width: 100px;height: 100px;background: #fff;padding: 10px;border-radius: 2px;}.line-left {position: absolute;left: 0;top: 120px;width: 10px;height: calc(100% - 120px);background: rgb(255 255 255 / 51%);backdrop-filter: blur(10px);}.line-right {position: absolute;right: 0;top: 120px;width: 10px;height: calc(100% - 120px);background: rgb(255 255 255 / 51%);backdrop-filter: blur(10px);}.line-bottom {position: absolute;left: 10px;bottom: 0;width: calc(100% - 20px);height: 10px;background: rgb(255 255 255 / 51%);backdrop-filter: blur(10px);}#map {width: 100%;height: 100%;}</style></head><body><div id="content"><div id="title"><div><h3>Картка плану території</h3><h2 id="address"></h2></div><h1 id="number"></h1></div><div id="qrcode"></div><div class="line-left"></div><div class="line-right"></div><div class="line-bottom"></div></div><div id="map"></div><script>const urlParams = new URLSearchParams(window.location.search);let coordinates = ${JSON.stringify(data.points)};let center = [${data.geo.lat}, ${data.geo.lng}];let zoom = ${data.zoom};let type = "${type}";let address = "${data.title} ${data.number ?? ""}";let osm = L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",{});let mytile = L.tileLayer("https://sheep-service.com/map/{z}/{x}/{y}.webp",{maxZoom: 20,minZoom: 15,tms: true,});let map = L.map("map", {renderer: L.canvas(),center,zoom,zoomControl: false,layers: [osm, mytile],});let baseMaps = {OpenStreetMap: osm,"Sheep Service Map": mytile,};let polygonOptions =type === "homestead"? {color: "#f2bd53",radius: 500,fillOpacity: 0.3,dashArray: "20,15",dashOffset: "20",}: {color: "#585858",fillColor: "#f2bd53",fillOpacity: 0.8,};window.onload = async function () {let polygon = L.polygon(coordinates, polygonOptions).addTo(map);let text = 'https://www.google.com/maps/search/?api=1&query='+center[0]+','+center[1];new QRCode(document.getElementById("qrcode"), {text: text,width: 100,height: 100,correctLevel: QRCode.CorrectLevel.L,version: 5,});document.getElementById("address").innerText = address;document.getElementById("number").innerText = '${name}';};</script></body></html>`;
// --- Зберігаємо тимчасовий HTML ---
const tmpFile = path.join(os.tmpdir(), 'map.html');
fs.writeFileSync(tmpFile, html, 'utf-8');
// --- Зберігаємо ---
// const browser = await chromium.launch();
const browser = await chromium.launch({
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || '/usr/bin/chromium-browser',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage({ viewport: { width: 811, height: 531 } });
await page.goto(`file://${tmpFile}`);
await page.waitForTimeout(2000); // пауза 1 секунда для провантаження карти
await page.screenshot({ path: SCREENSHOT_FILE });
await browser.close();
await sharp(SCREENSHOT_FILE)
.webp()
.toFile(OUTPUT_FILE);
console.log(`Зображеня збережене: ${name}.png`);
// return fs.existsSync(OUTPUT_FILE);
}
module.exports = genCards;