前端-ICP备案证书生成

前言

好久都没更新了,主要是最近着手一个项目。弄完了,我干我自己的事,想给自己的域名备案,目前都已经到管局审核这一步了,估计最快也要等到下周三去

好了言归正传,都知道一个域名有它的‘域名证书’,所以闲着也是闲着,搞个ICP备案证书玩玩又如何呢

效果图见下:

七要素、一绘图、两控制

七要素

七个Input组件,七个Label组件

需要-网站域名、主办单位名、主办单位性质、审核通过日期、ICP备案号、网站名、网站内容

一绘图

一个Canvas组件

两控制

两个Button组件,一个在七要素下,一个在Canvas下

Example-Code 

 太简单了就不过多赘述了

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ICP备案证书生成器</title>
<style>
   body {
            font-family: 'Arial', sans-serif;
            background-color: #f4f4f9;
            color: #333;
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            min-height: 100vh;
        }
  .form-container {
    width: 100%;
            flex-grow: 1;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
  }
  .certificate-container {
    width: 40%;
    margin-right: 80px;
  }
  #certificate {
    display: none;
    border: 1px solid #333;
  }
  .input-area, .button-area {
            display: flex;
            justify-content: space-around;
            width: 100%;
            margin-bottom: 10px;
        }
        .input-area {
            flex-wrap: wrap;
        }
        .button-area {
            justify-content: space-between;
        }
        textarea, input, button {
            margin: 10px;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin-bottom: -18px;
        }
        textarea {
            width: 100%;
            height: 80px;
            border-radius: 10px;
        }
        button {
            background-color: #4CAF50;
            color: white;
            border: none;
            cursor: pointer;
            transition: background-color 0.3s;
            flex-basis: 45%;
            margin: 5px;
        }
        button:hover {
            background-color: #45a049;
        }
</style>
</head>
<body>
  <div id="form-forms" class="form-container">
    <h1>ICP备案证书生成器</h1>
    <form id="certForm">
      <label for="domain">网站域名:</label>
      <input type="text" id="domain" name="domain" required><br><br>
      <label for="owner">主办单位名称:</label>
      <input type="text" id="owner" name="owner" required><br><br>
      <label for="owner">主办单位性质:</label>
      <input type="text" id="ownerxz" name="ownerxz" required><br><br>
      <label for="date">审核通过日期:</label>
      <input type="date" id="date" name="date" required><br><br>
      <label for="certNumber">ICP备案号:</label>
      <input type="text" id="certNumber" name="certNumber" required><br><br>
      <label for="websiteName">网站名称:</label>
      <input type="text" id="websiteName" name="websiteName" required><br><br>
      <label for="serviceContent">网站内容:</label>
      <textarea id="serviceContent" name="serviceContent" rows="4" required></textarea><br><br>
      <button type="button" onclick="thebookicpsc()">生成证书</button>
    </form>
  </div>
  <div id="canvascsr"  class="certificate-container">
    <canvas id="certificate" width="650" height="400"></canvas>
    <button id="buttontoshow" style="display: none;">重新修改</button>
  </div>
</div>

<script src="certificate.js"></script>
<script>

</script>
</body>
</html>

Js实现

1. 定义全局变量

 首先,我们需要定义两个全局变量

let chatlast;
let ysjlist = [];
  • chatlast 用于存储表单的原始HTML内容
  • ysjlist 用于存储用户输入的信息 

2. 生成序列号

 我们需要为证书设计一个序列号元素,我们可以通过取时间戳和拼接随机生成的字符串完成

十六位

function xlhsc() {
    let timestamp = (Date.now().toString()).substring(8, 14);
    let randompart = (Math.random().toString(36).substring(7)).toUpperCase();
    let serial = timestamp + randompart;
    if (serial.length > 16) {
        return serial.substring(0, 16);
    } else {
        while (serial.length < 16) {
            randompart = (Math.random().toString(36).substring(7)).toUpperCase();
            serial += randompart.charAt(0);
        }
        return serial.substring(0, 16); 
    }
}
  • 生成一个16位的序列号,前8位是时间戳,后8位是随机生成的字符串

3. 文本换行

我们需要考虑,如果网站内容过多的情况。如果网站内容过多,那我们就让它换行

function wrapText(context, text, maxWidth, lineHeight, font) {
    let wrappedText = [];
    let line = '';

    for (let char of text) {
        let testLine = line + char;
        let metrics = context.measureText(testLine);
        let testWidth = metrics.width;
        if (testWidth > maxWidth && line.length > 0) {
            wrappedText.push(line);
            line = char;
        } else {
            line = testLine;
        }
    }

    if (line.length > 0) {
        wrappedText.push(line);
    }

    return wrappedText;
}
  • 根据最大宽度将文本自动换行。

4. 创建印章函数 

我们同样可以为证书设计一个印章元素,使其更专业或有信赖度

function createSeal(id, company, name) {
    var canvas = document.getElementById(id);  
    var context = canvas.getContext('2d'); 
    var width = canvas.width / 2;
    var height = canvas.height / 2;
    context.lineWidth = 7;
    context.strokeStyle = "#f00";
    context.beginPath();
    context.arc(width, height, 110, 0, Math.PI * 2);
    context.stroke();
    create5star(context, width, height, 30, "#f00", 0);  
    context.font = '22px Helvetica';
    context.textBaseline = 'middle';
    context.textAlign = 'center'; 
    context.lineWidth = 1;
    context.fillStyle = '#f00';
    context.fillText(name, width, height + 65);
    context.translate(width, height);
    context.font = '30px Helvetica'
    var count = company.length;
    var angle = 4 * Math.PI / (3 * (count - 1));
    var chars = company.split("");   
    var c;
    for (var i = 0; i < count; i++){
        c = chars[i];
        if (i == 0)
            context.rotate(5 * Math.PI / 6);
        else
            context.rotate(angle);
        context.save(); 
        context.translate(90, 0);
        context.rotate(Math.PI / 2);
        context.fillText(c, 0, 5); 
        context.restore();             
    }
}

5. New Canvas

但是,如果用户需要重新编辑内容,就需要重新生成证书一次,

我们直接删除原canvas,创建一个新的canvas用于印章的二次绘制

function creatnewcanvasdemo() {
    var existingCanvas = document.getElementById('demo');
    if (existingCanvas) {
      existingCanvas.parentNode.removeChild(existingCanvas);
    }
    var canvas = document.createElement('canvas');
    canvas.id = 'demo';
    canvas.style.display = 'none';
    canvas.width = 650;
    canvas.height = 400;
    document.body.appendChild(canvas);
    return canvas;
}

6. 添加水印

水印是必不可少的,随机分布,且根据水印文本长度来调整位置,并不重复

function addwatermarks(canvas, watermarksCount, onepart, twopart, threepart) {
    var ctx = canvas.getContext('2d');
    var watermarkTexts = [onepart, twopart, threepart];
    var usedPositions = new Set(); 
    function isPositionAvailable(x, y, width, height) {
        var position = x + ',' + y;
        return !usedPositions.has(position) && 
               x + width < canvas.width && 
               y + height < canvas.height;
    }

    for (var i = 0; i < watermarksCount; i++) {
        var textIndex = Math.floor(Math.random() * watermarkTexts.length);
        var watermarkText = watermarkTexts[textIndex];
        var x, y, positionAvailable;

        do {
            x = Math.random() * (canvas.width - 100) + 50;
            y = Math.random() * (canvas.height - 30) + 30;
            var textWidth = ctx.measureText(watermarkText).width;
            var textHeight = 20; 
            positionAvailable = isPositionAvailable(x, y, textWidth, textHeight);
        } while (!positionAvailable);

        usedPositions.add(x + ',' + y);
        ctx.font = '20px Arial';
        ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
        ctx.fillText(watermarkText, x, y);
    }
}

 7. 生成证书

拿到表单的所有内容,存入全局变量中,设置外背景以及内背景,填充元素

function thebookicpsc() {
    chatlast = document.getElementById('form-forms').innerHTML;
    const domain = document.getElementById('domain').value;
    const owner = document.getElementById('owner').value;
    const ownerxz = document.getElementById('ownerxz').value;
    const date = document.getElementById('date').value;
    const certNumber = document.getElementById('certNumber').value;
    const websiteName = document.getElementById('websiteName').value;
    const serviceContent = document.getElementById('serviceContent').value;
    const canvas = document.getElementById('certificate');
    if(domain === '' || owner === '' || ownerxz === '' || date === '' || certNumber === '' || websiteName === '' || serviceContent === '') {
        alert('请键入完整信息');
        return false;
    }
    document.getElementById('buttontoshow').style.display = 'block';
    ysjlist['domain'] = domain;
    ysjlist['owner'] = owner;
    ysjlist['ownerxz'] = ownerxz;
    ysjlist['date'] = date;
    ysjlist['websiteName'] = websiteName;
    ysjlist['serviceContent'] = serviceContent;
    ysjlist['certNumber'] = certNumber;
    const ctx = canvas.getContext('2d');
    canvas.height = 600; 
    canvas.width = 650;
    const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
    gradient.addColorStop(0, '#efe8d1');
    gradient.addColorStop(0.5, '#fbfbf3');
    gradient.addColorStop(1, '#efe8d1');
    ctx.fillStyle = '#5969a6';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = gradient; 
    ctx.fillRect(10, 10, canvas.width - 20, canvas.height - 20);
    ctx.font = 'bold 34px Arial';
    ctx.fillStyle = '#000';
    ctx.textAlign = 'center';
    ctx.fillText('ICP备案证书', canvas.width / 2, 60);
    ctx.strokeStyle = "#000000";
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(10, 75); 
    ctx.lineTo(640, 75); 
    ctx.stroke();
    ctx.font = '28px Arial';
    ctx.textAlign = 'left';
    const contentX = 50;
    const contentY = 120;
    const lineHeight = 50;
    ctx.fillText('网站域名:', contentX, contentY);
    ctx.fillText(domain, contentX + 150, contentY);
    ctx.fillText('主办单位名称:', contentX, contentY + lineHeight);
    ctx.fillText(owner, contentX + 190, contentY + lineHeight);
    ctx.fillText('主办单位性质:', contentX, contentY+2 * lineHeight);
    ctx.fillText(ownerxz, contentX + 190, contentY +2* lineHeight);
    ctx.fillText('审核通过日期:', contentX, contentY + 3 * lineHeight);
    ctx.fillText(date, contentX + 190, contentY + 3 * lineHeight);
    ctx.fillText('ICP备案号:', contentX, contentY + 4 * lineHeight);
    ctx.fillText(certNumber, contentX + 150, contentY + 4 * lineHeight);
    ctx.fillText('网站名称:', contentX, contentY + 5 * lineHeight);
    ctx.fillText(websiteName, contentX + 150, contentY + 5 * lineHeight);
    ctx.fillText('网站内容:', contentX, contentY + 6 * lineHeight);
    const contentLines = wrapText(ctx, serviceContent, canvas.width - 230, lineHeight, '28px Arial');
    let currentY = contentY + 6 * lineHeight;
    contentLines.forEach(line => {
        ctx.fillText(line, contentX + 150, currentY);
        currentY += lineHeight;
    });
    const sealCanvas = creatnewcanvasdemo();
    createSeal('demo', certNumber, '备案证书');
    const sealX = canvas.width / 2;
    const sealY = canvas.height - 100;
    ctx.drawImage(sealCanvas, sealX - 80, sealY -180, 540, 340);
    ctx.lineWidth = 2;
    ctx.strokeStyle = '#000';
    ctx.strokeRect(10, 10, canvas.width - 20, canvas.height - 20);
    ctx.font = '15px Arial';
    ctx.fillStyle = '#000';
    ctx.fillText('发行日期:' + date, canvas.width - 180, canvas.height - 20);
    ctx.fillText('证书序列号:' + xlhsc(), 50, canvas.height - 20);
    addwatermarks(canvas,25,owner,certNumber,domain);
    document.getElementById('form-forms').innerHTML = canvas.innerHTML;
    document.getElementById('canvascsr').style.marginLeft = '360px';
    canvas.style.display = 'block';
}

8.恢复表单

document.getElementById('buttontoshow').onclick = function () {
    document.getElementById('form-forms').innerHTML = chatlast;
    document.getElementById('buttontoshow').style.display = 'none';
    document.getElementById('certificate').style.display = 'none';
    document.getElementById('domain').value = ysjlist['domain'];
    document.getElementById('owner').value = ysjlist['owner'];
    document.getElementById('ownerxz').value = ysjlist['ownerxz'];
    document.getElementById('date').value = ysjlist['date'];
    document.getElementById('certNumber').value = ysjlist['certNumber'];
    document.getElementById('websiteName').value = ysjlist['websiteName'];
    document.getElementById('serviceContent').value = ysjlist['serviceContent'];
};

 码云:ICP备案证书生成: 无聊而做 (gitee.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值