Initial commit: RHINE LAB · ANALYSIS OS:三维界面与动效实验(本仓库不含个人归档索引数据)
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
// Local-only phone review server. Reports contain timing and browser metrics.
|
||||
import { createServer } from "vite";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import { randomUUID } from "node:crypto";
|
||||
|
||||
const output = resolve(".tools/mobile-calibration");
|
||||
await mkdir(output, { recursive: true });
|
||||
const server = await createServer({
|
||||
server: { host: "0.0.0.0", port: 5189, strictPort: true },
|
||||
plugins: [{
|
||||
name: "local-mobile-calibration",
|
||||
configureServer(server) {
|
||||
server.middlewares.use("/__mobile-review", (req, res) => {
|
||||
if (req.method !== "POST" || req.headers.origin !== `http://${req.headers.host}`) {
|
||||
res.writeHead(403).end(); return;
|
||||
}
|
||||
let body = "";
|
||||
req.on("data", chunk => {
|
||||
body += chunk;
|
||||
if (body.length > 131072) { res.writeHead(413).end(); req.destroy(); }
|
||||
});
|
||||
req.on("end", async () => {
|
||||
try {
|
||||
const report = JSON.parse(body);
|
||||
if (report.version !== 1 || !Array.isArray(report.samples) || report.samples.length > 30)
|
||||
throw new Error("Invalid report");
|
||||
const id = `${Date.now()}-${randomUUID()}`;
|
||||
await writeFile(resolve(output, `${id}.json`), JSON.stringify({ receivedAt: new Date().toISOString(), ...report }, null, 2));
|
||||
res.writeHead(200, { "Content-Type": "application/json" }).end(JSON.stringify({ id }));
|
||||
console.log(`Mobile calibration received: ${id} (${String(report.userAgent).slice(0, 180)})`);
|
||||
} catch { res.writeHead(400).end(); }
|
||||
});
|
||||
});
|
||||
},
|
||||
}],
|
||||
});
|
||||
await server.listen();
|
||||
server.printUrls();
|
||||
console.log("Open /reference/mobile-review.html on the phone; keep the tab visible during measurement.");
|
||||
Reference in New Issue
Block a user