增加印章
All checks were successful
continuous-integration/drone/pr Build is passing

This commit is contained in:
2025-06-29 03:01:56 +08:00
parent 803139a1c9
commit a262c52c73
11 changed files with 1942 additions and 230 deletions

290
test-seal.html Normal file
View File

@ -0,0 +1,290 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>印章生成器测试</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
background: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
margin-bottom: 20px;
}
.form-group {
display: flex;
flex-direction: column;
}
label {
margin-bottom: 5px;
font-weight: bold;
}
input, select, button {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background: #6366f1;
color: white;
cursor: pointer;
border: none;
}
button:hover {
background: #5855eb;
}
.preview {
text-align: center;
padding: 20px;
background: #f9f9f9;
border-radius: 8px;
}
canvas {
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
</style>
</head>
<body>
<div class="container">
<h1>🖃 印章生成器测试</h1>
<div class="controls">
<div class="form-group">
<label for="sealType">印章类型</label>
<select id="sealType">
<option value="company_round">公司圆章</option>
<option value="company_oval">公司椭圆章</option>
<option value="personal_square">个人方章</option>
<option value="personal_round">个人圆章</option>
</select>
</div>
<div class="form-group">
<label for="mainText">主文字</label>
<input type="text" id="mainText" placeholder="输入公司名称或姓名" value="子归云科技">
</div>
<div class="form-group">
<label for="centerText">中心文字</label>
<input type="text" id="centerText" placeholder="印" value="印" maxlength="2">
</div>
<div class="form-group">
<label for="sealSize">印章大小</label>
<input type="range" id="sealSize" min="200" max="600" value="300">
<span id="sizeValue">300px</span>
</div>
<div class="form-group">
<label for="sealColor">印章颜色</label>
<input type="color" id="sealColor" value="#FF0000">
</div>
<div class="form-group">
<button onclick="generateSeal()">🎨 生成印章</button>
</div>
</div>
<div class="preview">
<h3>印章预览</h3>
<canvas id="sealCanvas" width="300" height="300"></canvas>
<br><br>
<button onclick="downloadSeal()" style="display:none;" id="downloadBtn">📥 下载印章</button>
</div>
</div>
<script>
const canvas = document.getElementById('sealCanvas');
const ctx = canvas.getContext('2d');
const sizeSlider = document.getElementById('sealSize');
const sizeValue = document.getElementById('sizeValue');
// 更新大小显示
sizeSlider.addEventListener('input', function() {
sizeValue.textContent = this.value + 'px';
canvas.width = this.value;
canvas.height = this.value;
});
function generateSeal() {
const sealType = document.getElementById('sealType').value;
const mainText = document.getElementById('mainText').value;
const centerText = document.getElementById('centerText').value;
const sealSize = parseInt(document.getElementById('sealSize').value);
const sealColor = document.getElementById('sealColor').value;
if (!mainText.trim()) {
alert('请输入主文字!');
return;
}
// 清空画布
ctx.clearRect(0, 0, sealSize, sealSize);
// 设置背景
ctx.fillStyle = '#FFFFFF';
ctx.fillRect(0, 0, sealSize, sealSize);
// 设置印章颜色
ctx.strokeStyle = sealColor;
ctx.fillStyle = sealColor;
const centerX = sealSize / 2;
const centerY = sealSize / 2;
if (sealType.startsWith('company')) {
drawCompanySeal(centerX, centerY, sealSize, mainText, centerText, sealColor);
} else {
drawPersonalSeal(centerX, centerY, sealSize, mainText, sealColor);
}
document.getElementById('downloadBtn').style.display = 'inline-block';
}
function drawCompanySeal(centerX, centerY, sealSize, mainText, centerText, sealColor) {
const radius = sealSize * 0.4;
// 绘制外边框
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
ctx.stroke();
// 绘制内边框
ctx.lineWidth = 1;
ctx.beginPath();
ctx.arc(centerX, centerY, radius - 15, 0, 2 * Math.PI);
ctx.stroke();
// 绘制弧形主文字
drawCurvedText(mainText, centerX, centerY, radius - 25, 24);
// 绘制五角星
drawStar(centerX, centerY - radius * 0.1, 15);
// 绘制中心文字
if (centerText.trim()) {
ctx.font = 'bold 40px SimSun, serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(centerText, centerX, centerY + radius * 0.2);
}
}
function drawPersonalSeal(centerX, centerY, sealSize, mainText, sealColor) {
const size = sealSize * 0.8;
const sealType = document.getElementById('sealType').value;
// 绘制边框
ctx.lineWidth = 3;
ctx.beginPath();
if (sealType === 'personal_round') {
ctx.arc(centerX, centerY, size / 2, 0, 2 * Math.PI);
} else {
const halfSize = size / 2;
ctx.rect(centerX - halfSize, centerY - halfSize, size, size);
}
ctx.stroke();
// 绘制文字
const text = mainText.trim();
const textLength = text.length;
const fontSize = 32;
ctx.font = `bold ${fontSize}px SimSun, serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
if (textLength === 2) {
// 两字:上下排列
ctx.fillText(text[0], centerX, centerY - fontSize * 0.6);
ctx.fillText(text[1], centerX, centerY + fontSize * 0.6);
} else if (textLength === 3) {
// 三字:品字形
ctx.fillText(text[0], centerX, centerY - fontSize * 0.8);
ctx.fillText(text[1], centerX - fontSize * 0.7, centerY + fontSize * 0.4);
ctx.fillText(text[2], centerX + fontSize * 0.7, centerY + fontSize * 0.4);
} else if (textLength === 4) {
// 四字:田字格
ctx.fillText(text[0], centerX - fontSize * 0.6, centerY - fontSize * 0.6);
ctx.fillText(text[1], centerX + fontSize * 0.6, centerY - fontSize * 0.6);
ctx.fillText(text[2], centerX - fontSize * 0.6, centerY + fontSize * 0.6);
ctx.fillText(text[3], centerX + fontSize * 0.6, centerY + fontSize * 0.6);
} else {
// 其他情况:单行
ctx.fillText(text, centerX, centerY);
}
}
function drawCurvedText(text, centerX, centerY, radius, fontSize) {
ctx.font = `${fontSize}px SimSun, serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const angleStep = (Math.PI * 1.4) / text.length;
const startOffset = -Math.PI * 0.7;
for (let i = 0; i < text.length; i++) {
const angle = startOffset + i * angleStep;
const x = centerX + Math.cos(angle) * radius;
const y = centerY + Math.sin(angle) * radius;
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle + Math.PI / 2);
ctx.fillText(text[i], 0, 0);
ctx.restore();
}
}
function drawStar(centerX, centerY, radius) {
const spikes = 5;
const outerRadius = radius;
const innerRadius = radius * 0.4;
ctx.beginPath();
for (let i = 0; i < spikes * 2; i++) {
const angle = (i * Math.PI) / spikes - Math.PI / 2;
const r = i % 2 === 0 ? outerRadius : innerRadius;
const x = centerX + Math.cos(angle) * r;
const y = centerY + Math.sin(angle) * r;
if (i === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
}
ctx.closePath();
ctx.fill();
}
function downloadSeal() {
const link = document.createElement('a');
link.download = `seal-${Date.now()}.png`;
link.href = canvas.toDataURL('image/png');
link.click();
}
// 初始生成一个示例印章
setTimeout(() => {
generateSeal();
}, 100);
</script>
</body>
</html>