chore: initial commit

This commit is contained in:
hailin
2026-05-18 13:52:47 +08:00
commit 0753129afe
148 changed files with 14202 additions and 0 deletions

2272
server/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

21
server/package.json Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "report-server",
"version": "1.0.0",
"scripts": {
"start": "node src/index.js",
"build": "tsc"
},
"dependencies": {
"body-parser": "^1.20.4",
"cors": "^2.8.6",
"express": "^4.22.1",
"puppeteer": "^22.15.0"
},
"devDependencies": {
"@types/cors": "^2.8.17",
"@types/express": "^4.17.21",
"@types/node": "^20.11.0",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}

100
server/src/index.js Normal file
View File

@@ -0,0 +1,100 @@
const express = require('express');
const puppeteer = require('puppeteer');
const cors = require('cors');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 3002;
app.use(cors({
origin: ['http://localhost:5173', 'http://0.0.0.0:5173'],
credentials: true
}));
app.use(bodyParser.json({ limit: '50mb' }));
let browser = null;
async function getBrowser() {
if (!browser) {
browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
}
return browser;
}
app.post('/api/generate-pdf', async (req, res) => {
const reportData = req.body;
const targetUrl = process.env.TARGET_URL || 'http://localhost:5173';
console.log('Received PDF generation request for:', reportData.companyName);
let page = null;
try {
const browserInstance = await getBrowser();
page = await browserInstance.newPage();
await page.setViewport({
width: 794,
height: 1123,
deviceScaleFactor: 2,
});
const url = new URL(targetUrl);
url.searchParams.set('print', 'true');
console.log('Navigating to:', url.toString());
await page.goto(url.toString(), { waitUntil: 'networkidle0' });
console.log('Injecting data...');
await page.evaluate((data) => {
if (window.loadServerData) {
window.loadServerData(data);
} else {
console.error('window.loadServerData not found');
}
}, reportData);
console.log('Waiting for report ready signal...');
await page.waitForFunction(() => window.isReportReady === true, {
timeout: 30000,
polling: 100
});
await new Promise(resolve => setTimeout(resolve, 1000));
console.log('Printing PDF...');
const pdfBuffer = await page.pdf({
format: 'A4',
printBackground: true,
margin: {
top: '0px',
right: '0px',
bottom: '0px',
left: '0px'
},
preferCSSPageSize: true,
displayHeaderFooter: false
});
console.log('PDF generated successfully');
res.contentType('application/pdf');
res.send(pdfBuffer);
} catch (error) {
console.error('PDF generation failed:', error);
res.status(500).json({
error: 'Failed to generate PDF',
details: error instanceof Error ? error.message : String(error)
});
} finally {
if (page) {
await page.close();
}
}
});
app.listen(port, '0.0.0.0', () => {
console.log(`PDF Generation Server running at http://0.0.0.0:${port}`);
});