优化证书生成与正式部署配置

This commit is contained in:
2026-06-15 18:23:46 +08:00
parent f1d7491288
commit 668e0403af
31 changed files with 1603 additions and 145 deletions

View File

@@ -4,8 +4,10 @@
const state = document.getElementById("renderState");
const qrScratch = document.getElementById("qrScratch");
const W = canvas.width;
const H = canvas.height;
const W = 1024;
const H = 759;
let scaleX = 1;
let scaleY = 1;
const text = {
loading: "\u52a0\u8f7d\u4e2d",
@@ -53,8 +55,11 @@
controls.showDebug = document.getElementById("showDebug");
const original = new Image();
original.src = "./assets/original.jpg";
original.onload = render;
original.src = "./assets/original.png";
original.onload = () => {
syncCanvasSize(true);
render();
};
original.onerror = () => {
state.textContent = text.imageFailed;
render();
@@ -104,9 +109,12 @@
function render() {
try {
state.textContent = text.rendering;
ctx.clearRect(0, 0, W, H);
const usingOriginal = controls.showOriginal.checked && original.complete && original.naturalWidth;
syncCanvasSize(usingOriginal);
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setTransform(scaleX, 0, 0, scaleY, 0, 0);
if (usingOriginal) {
ctx.drawImage(original, 0, 0, W, H);
@@ -115,7 +123,7 @@
drawFallbackBase();
}
drawStudentName();
drawStudentName();
drawMainText();
drawIssueDate();
drawCertificateNo();
@@ -139,9 +147,17 @@
}
}
function syncCanvasSize(usingOriginal) {
const nextWidth = usingOriginal ? original.naturalWidth : W;
const nextHeight = usingOriginal ? original.naturalHeight : H;
if (canvas.width !== nextWidth) canvas.width = nextWidth;
if (canvas.height !== nextHeight) canvas.height = nextHeight;
scaleX = nextWidth / W;
scaleY = nextHeight / H;
}
const areas = [
{ x: 150, y: 442, w: 760, h: 132, pad: 16 },
{ x: 404, y: 675, w: 220, h: 38, pad: 10 }
{ x: 150, y: 455, w: 760, h: 119, pad: 16 }
];
function eraseEditableAreas() {
@@ -152,11 +168,12 @@
if (!original.complete || !original.naturalWidth) return;
const pad = area.pad || 8;
const sourceX = 72;
const sourceW = 88;
const sourceX = Math.round((area.sourceX || 72) * scaleX);
const sourceY = Math.round((area.sourceY || Math.max(0, area.y - pad)) * scaleY);
const sourceW = Math.round(88 * scaleX);
const patch = document.createElement("canvas");
patch.width = area.w + pad * 2;
patch.height = area.h + pad * 2;
patch.width = Math.round((area.w + pad * 2) * scaleX);
patch.height = Math.round((area.h + pad * 2) * scaleY);
const p = patch.getContext("2d");
for (let x = 0; x < patch.width; x += sourceW) {
@@ -164,7 +181,7 @@
p.drawImage(
original,
sourceX,
Math.max(0, area.y - pad),
sourceY,
tileW,
patch.height,
x,
@@ -176,7 +193,7 @@
p.globalCompositeOperation = "destination-in";
p.globalCompositeOperation = "source-over";
p.globalAlpha = 0.38;
p.globalAlpha = area.blendAlpha || 0.38;
p.fillStyle = "#fbf7ef";
p.fillRect(0, 0, patch.width, patch.height);
p.globalAlpha = 1;
@@ -199,7 +216,10 @@
p.fillStyle = gx;
p.fillRect(0, 0, patch.width, patch.height);
ctx.drawImage(patch, area.x - pad, area.y - pad);
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.drawImage(patch, Math.round((area.x - pad) * scaleX), Math.round((area.y - pad) * scaleY));
ctx.restore();
}
function drawFallbackBase() {
@@ -244,17 +264,17 @@
let x = 185;
const y = 494;
x = drawInlineText(text.inWord, x, y, 24, 400, 18);
x = drawInlineText(value("startYear"), x, y, 24, 900, 8, "dateNumber");
x = drawInlineText(value("startYear"), x, y, 24, 400, 8);
x = drawInlineText(text.year, x, y, 24, 400, 12);
x = drawInlineText(value("startMonth"), x, y, 24, 900, 6, "dateNumber");
x = drawInlineText(value("startMonth"), x, y, 24, 400, 6);
x = drawInlineText(text.month, x, y, 24, 400, 12);
x = drawInlineText(value("startDay"), x, y, 24, 900, 4, "dateNumber");
x = drawInlineText(value("startDay"), x, y, 24, 400, 4);
x = drawInlineText(`${text.day}${text.toWord}`, x, y, 24, 400, 12);
x = drawInlineText(value("endYear"), x, y, 24, 900, 8, "dateNumber");
x = drawInlineText(value("endYear"), x, y, 24, 400, 8);
x = drawInlineText(text.year, x, y, 24, 400, 12);
x = drawInlineText(value("endMonth"), x, y, 24, 900, 6, "dateNumber");
x = drawInlineText(value("endMonth"), x, y, 24, 400, 6);
x = drawInlineText(text.month, x, y, 24, 400, 12);
x = drawInlineText(value("endDay"), x, y, 24, 900, 4, "dateNumber");
x = drawInlineText(value("endDay"), x, y, 24, 400, 4);
x = drawInlineText(`${text.day}\u5b8c\u6210\u4e86`, x, y, 24, 400, 8);
drawInlineFlow([
{ text: `\u201c${value("courseName")}\u201d`, style: "course" },
@@ -346,9 +366,12 @@
function drawIssueDate() {
ctx.textAlign = "center";
ctx.fillStyle = "#43382f";
ctx.fillStyle = "#111";
ctx.font = '700 13px "SimSun", serif';
ctx.fillText(`${text.issueDate}${value("issueDate")}`, W / 2, 704);
const parts = (value("issueDate").match(/\d+/g) || []);
ctx.fillText(parts[0] || "", 500, 688);
ctx.fillText(parts[1] || "", 535, 688);
ctx.fillText(parts[2] || "", 566, 688);
}
function drawCertificateNo() {