| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import puppeteer from "puppeteer-core";
- import path from "path";
- import fs from "fs";
- import { fileURLToPath } from "url";
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
- const root = path.resolve(__dirname, "..");
- const outDir = path.join(root, "mockups");
- const html = path.join(root, "index.html");
- const chrome =
- "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
- fs.mkdirSync(outDir, { recursive: true });
- const pages = [
- { name: "01-home", hash: "home", prep: null, full: false },
- {
- name: "02-notice",
- hash: "notice",
- full: true,
- prep: async (page) => {
- await page.evaluate(() => {
- if (typeof startFeedback === "function") startFeedback();
- const btn = document.getElementById("btn-enter-feedback");
- const num = document.getElementById("countdown");
- if (btn) {
- btn.disabled = true;
- btn.textContent = "请阅读须知(5s)";
- }
- if (num) num.textContent = "5";
- });
- },
- },
- { name: "03-feedback", hash: "feedback", prep: null, full: true },
- { name: "04-suggest", hash: "suggest", prep: null, full: true },
- { name: "05-hotline", hash: "hotline", prep: null, full: true },
- {
- name: "06-share",
- hash: "home",
- full: false,
- prep: async (page) => {
- await page.evaluate(() => {
- if (typeof go === "function") go("home");
- if (typeof showShare === "function") showShare();
- const tip = document.getElementById("share-url");
- if (tip) tip.textContent = "https://jjb.ajyy.example.com";
- });
- await page.waitForSelector("#share-overlay.show", { timeout: 5000 });
- },
- },
- ];
- const browser = await puppeteer.launch({
- executablePath: chrome,
- headless: "new",
- args: ["--no-sandbox", "--hide-scrollbars"],
- defaultViewport: { width: 390, height: 844, deviceScaleFactor: 2 },
- });
- const page = await browser.newPage();
- const fileUrl = "file://" + html;
- for (const item of pages) {
- // Force full reload each time (hash-only nav would keep DOM mutations)
- await page.goto(fileUrl + "?t=" + Date.now() + "#" + item.hash, {
- waitUntil: "networkidle0",
- timeout: 30000,
- });
- await page.waitForSelector(".device", { timeout: 10000 });
- await page.evaluate(() => {
- const device = document.querySelector(".device");
- if (device) {
- device.style.height = "844px";
- device.style.minHeight = "844px";
- device.style.borderRadius = "0";
- }
- });
- await page
- .waitForFunction(() => {
- const img = document.querySelector(".logo-wrap img, .mine-avatar img");
- if (!img) return true;
- return img.complete && img.naturalWidth > 0;
- }, { timeout: 8000 })
- .catch(() => {});
- if (item.prep) await item.prep(page);
- await new Promise((r) => setTimeout(r, 400));
- const out = path.join(outDir, `mockup-${item.name}.png`);
- if (item.full) {
- await page.evaluate(() => {
- const device = document.querySelector(".device");
- const view = document.querySelector(".view.active");
- const scroll = view?.querySelector(".scroll");
- if (!device || !view || !scroll) return;
- device.style.height = "auto";
- device.style.minHeight = "0";
- device.style.borderRadius = "0";
- view.style.position = "relative";
- view.style.height = "auto";
- view.style.minHeight = "0";
- scroll.style.overflow = "visible";
- scroll.style.flex = "none";
- scroll.style.paddingBottom = "24px";
- const tab = view.querySelector(".tab-bar");
- if (tab) tab.style.display = "none";
- });
- await new Promise((r) => setTimeout(r, 200));
- }
- const el = await page.$(".device");
- const box = await el.boundingBox();
- if (!box || box.height < 2) {
- await page.screenshot({ path: out, type: "png", fullPage: true });
- } else {
- await el.screenshot({ path: out, type: "png" });
- }
- console.log("saved", out, box ? `${Math.round(box.width)}x${Math.round(box.height)}` : "fullPage");
- }
- await browser.close();
- console.log("done");
|