vite+vue3+typescript+elementPlus前端实现电子证书查询系统

news2024/11/15 1:32:41

实现背景:之前电子证书的实现是后端实现的,主要采用GD库技术,在底图上添加文字水印和图片水印实现的。这里采用前端技术实现电子证书的呈现以及点击证书下载,优点是:后端给前端传递的是一组数据,不需要传证书的图片,交互所需数据流大大减少了。后端不需要生成证书,就不需要额外开辟存储证书的空间,当用户量很大时,节省开支。

前端技术栈:vite+vue3+typescript+elementPlus

证书查询首页实现,代码如下:

<template>
  <el-row class="header">
    <el-col :span="24">
      <el-text>电子证书查询系统</el-text>
    </el-col>
  </el-row>

  <el-row class="main">
    <el-col :span="24">
      <el-card style="max-width: 680px" shadow="always">
        <template #header>
          <div class="card-header">
            <span>证书查询系统</span>
          </div>
        </template>
        <el-form
          ref="ruleFormRef"
          :model="ruleForm"
          :rules="rules"
          label-width="auto"
          class="demo-ruleForm"
          :size="formSize"
          :label-position="labelPosition"
          status-icon
        >
          <el-form-item label="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" prop="name">
            <el-input v-model="ruleForm.name" placeholder="请输入姓名" />
          </el-form-item>

          <el-form-item label="身份证号" prop="idNo">
            <el-input v-model="ruleForm.idNo" placeholder="请输入身份证号" />
          </el-form-item>

          <el-form-item label="证书编号" prop="certificateNo">
            <el-input v-model="ruleForm.certificateNo" placeholder="请输入证书编号" />
          </el-form-item>

          <el-form-item>
            <el-button type="primary" @click="submitForm(ruleFormRef)"> 查询 </el-button>
          </el-form-item>
        </el-form>
      </el-card>
    </el-col>
  </el-row>
</template>

<script lang="ts" setup name="CertificateIndex">
import { reactive, ref } from 'vue'
import type { ComponentSize, FormInstance, FormRules, FormProps } from 'element-plus'
import { ElMessage } from 'element-plus'
import { createItem } from '../services/crudService'
import { useRouter } from 'vue-router'

const router = useRouter()

interface RuleForm {
  name: string
  idNo: string
  certificateNo: string
}

const formSize = ref<ComponentSize>('large')
const labelPosition = ref<FormProps['labelPosition']>('left')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive<RuleForm>({
  name: '',
  idNo: '',
  certificateNo: ''
})

const rules = reactive<FormRules<RuleForm>>({
  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
  idNo: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
  certificateNo: [{ required: true, message: '请输入证书编号', trigger: 'blur' }]
})

const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return

  // Validate the form
  await formEl.validate()

  // If validation passes, call createItem with the form data
  const { data } = await createItem(ruleForm)

  if (!data.id) {
    ElMessage({
      message: '暂无此人相关证书!',
      type: 'warning'
    })
    return
  }
  router.push({ name: 'CertificateDetail', query: { data: JSON.stringify(data) } })
}
</script>

<style scoped style="scss">
.header {
  background-color: #1174c2;
  width: 100%;
  height: 50px;
  .el-col {
    text-align: center;
    vertical-align: center;
    padding: 0.5rem 0;
    .el-text {
      font-size: 1.5rem;
      color: #fff;
    }
  }
}

.main {
  margin-top: 100px;
  .el-col {
    .el-card {
      margin: 0 auto;
      .card-header {
        text-align: center;
        vertical-align: center;
        font-size: 1.5rem;
        background-color: #1174c2;
        color: #fff;
        width: 100%;
        padding: 0.8rem 0;
      }
      .el-form {
        .el-form-item {
          margin: 2rem auto;
        }
        .el-button {
          font-size: 1.5rem;
          padding: 1.5rem 0;
          width: 100%;
          background-color: #1174c2;
        }
      }
    }
  }
}
</style>

证书查询首页实现,效果呈现如下:

在这里插入图片描述

电子证书查询结果实现,代码如下:

<template>
  <div class="main">
    <div
      class="card-header p-2 w-full bg-[#1174c2] text-[#fff] text-center text-xl fixed top-0 left-0 w-full z-50"
    >
      <span>电子证书查询结果</span>
    </div>
    <el-card shadow="always" class="mt-20">
      <div class="content" ref="contentToCapture">
        <div class="logo w-28 h-10 mt-4"></div>
        <div class="text-center mt-20 mb-6 text-lg dirBlod font-bold">内部审核员证书</div>
        <div class="mb-4 main">
          <img
            :src="crossOriginImageSrc"
            alt="Cross-origin image"
            style="width: 88px; height: 118px"
            fit="cover"
          />
          <div class="text-base mt-6">{{ form.name }}</div>
        </div>
        <div class="id text-base mb-4 dirBlod text-center">ID: {{ form.idNo }}</div>
        <div class="text text-base">
          <div class="mb-4 dirBlod text-center">兹证明其参加了 {{ form.course }}</div>
          <div class="ml-4 dirBlod">内部审核员培训课程并经考核合格,特发此证。</div>
        </div>
        <div class="footer mt-20">
          <div class="text-xs">
            <div class="dirBlod leading-6">发证日期 {{ form.authorizationDate }}</div>
            <div class="dirBlod leading-6">编号 {{ form.certificateNo }}</div>
            <div class="dirBlod leading-6">查询 {{ form.url }}</div>
          </div>
          <div class="text-base dirBlod gz-bg">
            <div class="gz-bg-img"></div>
            xx教育培训有限公司
          </div>
        </div>
      </div>

      <div @click="captureAndDownload" class="text-center mt-5 text-blue-600 cursor-pointer">
        证书下载
      </div>
    </el-card>
  </div>
</template>

<script lang="ts" setup name="CertificateDetail">
import { ref, reactive, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import html2canvas from 'html2canvas'
import { saveAs } from 'file-saver'
// 后端基本路径
const url = '/dev-api'
const route = useRoute()
const form = reactive(JSON.parse(route.query.data as string))
const crossOriginImageSrc = ref(url + form.path) // 示例跨域图片
const contentToCapture = ref<HTMLDivElement>()

async function captureAndDownload() {
  if (!contentToCapture.value) return

  try {
    const canvas = await html2canvas(contentToCapture.value, {
      useCORS: true // 允许跨域请求
    })
    const imgDataUrl = canvas.toDataURL('image/png')
    const uniqueBlobUrl = URL.createObjectURL(
      new Blob([await fetch(imgDataUrl).then((res) => res.blob())], { type: 'image/png' })
    )
    saveAs(uniqueBlobUrl, 'screenshot.png')
  } catch (error) {
    console.error('Error capturing screenshot:', error)
  }
}
</script>
<style scoped lang="scss">
.main {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}
.card-header {
  height: 50px;
}
.el-card {
  margin-top: 60px;
  margin-bottom: 60px;
  width: 620px;
}

.content {
  position: relative;
  background: url(@/assets/images/bg.png) no-repeat;
  background-size: 100% 100%;
  height: 880px;
  padding: 106px;
  font-family: 'dirBlod', sans-serif;
  .logo {
    background: url(@/assets/images/logo.png) no-repeat;
    background-size: 100% 100%;
  }
}

.footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.dirBlod {
  font-family: 'dirBlod', sans-serif;
}
.gz-bg {
  position: relative;
  .gz-bg-img {
    position: absolute;
    top: -280%;
    left: 20%;
    width: 120px;
    height: 120px;
    background: url(@/assets/images/seal.png) no-repeat;
    background-size: 100% 100%;
  }
}
</style>

电子证书查询结果实现,效果呈现如下:

在这里插入图片描述
小结:
1、节省了存储电子证书图片的空间;
2、后端负责数据,前端负责呈现,实现更加灵活

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2115636.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

假期学习-- iOS runloop了解和使用

iOS runloop的总结和理解 https://juejin.cn/post/7167497134294433829?searchId202408060922235E28560E3792F91107ED runloop的概念和数据结构 一般情况下&#xff0c;程序&#xff08;或者说线程&#xff09;在执行完毕后会立即退出或销毁&#xff1b;&#xff0c;但如果对…

体育馆智能可视化:提升场馆管理与观赛体验

利用图扑可视化技术&#xff0c;实时呈现体育馆内各项动态&#xff0c;优化场馆管理&#xff0c;提升观众的观赛体验。

基于人工智能的手写数字识别系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 手写数字识别是一种经典的计算机视觉任务&#xff0c;目标是让机器能够识别手写数字。通过人工智能技术&#xff0c;特别是卷积神经网…

JS_变量

二、JS的变量 JS中的变量具有如下特征 1 弱类型变量,可以统一声明成var 2 var声明的变量可以再次声明 3 变量可以使用不同的数据类型多次赋值 4 JS的语句可以以; 结尾,也可以不用;结尾 5 变量标识符严格区分大小写 6 标识符的命名规则参照JAVA 7 如果使用了 一个没有声明的变量…

JAVA基础:值传递和址传递

1 值传递和址传递 值传递 方法调用时&#xff0c;传递的实参是一个基本类型的数据 形参改变&#xff0c;实参不变 public static void doSum(int num1,int num2){} main(){doSum(10,20);int i 10 ;int j 20 ;doSum(i,j) ; } public static void t1(int num){num 20 ;Sys…

STM32CubeMX和HAL库-新建项目

目录 新建项目 选择开发板 MCU图形化配置界面总览 MCU配置 新建项目 新建项目包含选择MCU创建项目、选择开发板新建项目和交叉选择MCU新建项目三部分。 1. 选择MCU创建项目 单击主菜单项File→New Project&#xff0c;或Home视图上的ACCESS TO MCU SELECTOR 按钮&#xff0c…

Mac+Pycharm配置PyQt6教程

安装包 pip install PyQt6 PyQt6-tools #查看Qt版本 pip show PyQt6 pip show pyqt6-tools 配置扩展工具 QTD(界面设计) Program&#xff1a;/Users/wan/PycharmProjects/NewDemo/venv/lib/python3.11/site-packages/qt6_applications/Qt/bin/Designer.app Working directo…

dubbo 服务消费原理分析之服务目录

文章目录 前言一、RegistryDirectory1、DynamicDirectory2、RegistryProtocol.doCreateInvoker2、RegistryProtocol.subscribe3、ListenerRegistryWrapper.subscribe4、FailbackRegistry.subscribe5、ZookeeperRegistry.doSubscribe6、RegistryDirectory.notify7、RegistryDire…

无人叉车里程计模块专题

1.无人叉车里程计模块传感器要求 2.里程计功能需求 3.无人叉车里程计模块测试用例 4.无人叉车里程计算法方案 5.源码

合理应用词云图,快速提升你的幻灯展示效果!|科研插图·24-09-08

小罗碎碎念 本期主题&#xff1a;词云图 这一期推文介绍一个非常具有实用价值的图——词云图&#xff0c;正好最近在准备开题答辩的PPT&#xff0c;顺手写一期推文&#xff0c;和大家分享一下。 R语言和Python的代码都准备了一份&#xff0c;其中Python的版本就是我用自己开始…

复制PPT模板

文章目录 环境需求步骤参考 环境 Windows 11 家庭中文版WPS Office&#xff1a;2024夏季更新 (17827) 注&#xff1a;查看WPS Office版本的方法&#xff1a; 点击左上角的“WPS Office”图标&#xff0c;然后点击右上角的三条横线&#xff0c;在弹出菜单中&#xff0c;选择“…

仕考网:公务员面试流程介绍

通知进面信息——资格审查——面试签到——抽签候考 面试形式&#xff1a; 面试分为结构化和无领导小组两种形式 1.在结构化面试中&#xff0c;当轮到某位考生时&#xff0c;引导员将在候考室宣布其编号&#xff0c;随后考生跟随引导人员前往考场入口。考生在开始考试时需回…

Origin画图——怎么才能使折线图更好看

1.这是化的原始图&#xff0c;看着也不错&#xff0c;但是总觉得缺少什么东西 2.下面就来对其进行改造&#xff0c;首先改的是坐标轴和标签。刻度的显示&#xff0c;网格线取消&#xff0c;坐标轴上轴右轴的刻度取消&#xff0c;字体的大小与style改成Arial。 3.对图层底色…

oc打包:权限弹窗无法正常弹出

在遇到编写了权限无法弹出弹窗时,需要查看是不是调用时机不对,这里直接教万能改法。 将权限获取方法编写在applicationDidBecomeActive 进入前台的生命周期接口中,如下: if (@available(iOS 14, *)) {NSLog<

基于yolov5的水稻叶病害检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv5的水稻叶病害检测系统是一种利用深度学习技术实现的高效、准确的病害识别工具。该系统采用YOLOv5算法&#xff0c;该算法以其高效的检测速度和良好的识别准确性在目标检测领域广受好评。 该系统能够实时处理水稻叶片的图像数据&#xff0c;快速准确地…

SpringBoot登录退出|苍穹外卖登录退出分析

文章目录 概要整体流程注意事项一、拦截路径二、token三、注册防止用户重复提交 苍穹外卖登录退出分析注意解决JWT退出后依然有效的问题 概要 结合Spring Boot和Vue3实现安全的用户登录和退出功能&#xff0c;并使用拦截器、JWT和Redis缓存来提高系统的安全性和性能。 整体流…

NC 合并二叉树

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 已知两颗二叉…

【魔法 / NOI】

题目 思路 动态规划&#xff1a; 状态定义&#xff1a; f [ k ] [ i ] [ j ] 对应使用了不超过 k 次魔法&#xff0c;从 i 到 j 的路径集合 f[k][i][j] 对应使用了不超过k次魔法&#xff0c;从i到j的路径集合 f[k][i][j]对应使用了不超过k次魔法&#xff0c;从i到j的路径集合 状…

驱动(RK3588S)第八课时:平台设备总线

目录 目标一、平台设备总线的概念1、什么是平台设备总线2、平台设备总线 platform 的匹配3、设备树和平台设备总线的关系&#xff0c;以及匹配 二、平台设备总线的函数接口1、注册设备端的资源信息2、设备端提供的资源的信息3、注销申请的设备端的资源4、驱动端的函数&#xff…

如何做好网络安全

随着互联网技术的飞速发展&#xff0c;网站已成为企业对外展示、交流和服务的重要窗口。然而&#xff0c;随之而来的网站安全问题也日益凸显&#xff0c;给企业的业务发展和用户数据安全带来了巨大威胁。因此&#xff0c;高度重视网站安全已成为网络安全的首要任务。今天我们就…