最新ThinkPHP版本实现证书查询系统,实现批量数据导入,自动生成电子证书

前提:朋友弄了一个培训机构,培训考试合格后,给发证书,需要一个证书查询系统。委托我给弄一个,花了几个晚上给写的证书查询系统。

实现功能:

  1. 前端按照姓名+手机号码进行证书查询
  2. 证书信息展示+证书展示,支持点击下载
  3. 后端证书信息录入+带一寸照片数据批量导入

技术栈:
4. ThinkPHP8.0
5. MySQL8.0.12
6. layui

有几个技术点,得记录下:
1、给一个证书模板、一寸照片、两个电子印章图片,这个技术点是:GD库添加水印技术,水印添加也包括文字水印

添加扩展:

"ext-gd": "*",

相关代码:

// 向不同格式的图片中间画一个字符串(也是文字水印)
public function image(){// $id = Request::param('id');$one = Db::table('certificate')->where(Request::param())->find();// $this->pic($one['id']);/*$one = ["certificate_no" => "440420230078","create_time" => "2022-10-10","end_time" => "2032-10-10","id" => 8,"id_no" => "4404202206223919","id_type" => "身份证","institution" => "智能研究院","job" => "电工","name" => "曹操","occupation" => "低压电工证","phone" => "13588889999","sex" => "男","skill_level" => "中级","start_time" => "2022-10-10"];*/// 图片路径$imagePath = './static/images/zsmb.png';// 图片信息$imageInfo = getimagesize($imagePath);//  [0] => 2000 [1] => 1414 [2] => 3 [3] => width="2000" height="1414" [bits] => 8 [mime] => image/png// 图片扩展名$imageExtension = image_type_to_extension($imageInfo[2], false);// png// 获取图片$func = 'imagecreatefrom' . $imageExtension;// imagecreatefrompng$image = $func($imagePath);/***************************** 文字水印开始 ********************************/// 水印字体$font = './static/fonts/SourceHanSansSC-Medium-2.otf';// 水印文字// $content = '曹操';// 水印颜色$color = imagecolorallocatealpha($image, 0, 0, 0, 30);// 添加水印imagettftext($image, 22, 0, 1450, 650, $color, $font, $one['name']);imagettftext($image, 22, 0, 1450, 740, $color, $font, $one['id_type']);imagettftext($image, 22, 0, 1450, 830, $color, $font, $one['id_no']);imagettftext($image, 22, 0, 1450, 910, $color, $font, $one['occupation']);imagettftext($image, 22, 0, 1480, 985, $color, $font, $one['job']);imagettftext($image, 22, 0, 1480, 1075, $color, $font, $one['skill_level']);imagettftext($image, 22, 0, 1450, 1155, $color, $font, $one['certificate_no']);imagettftext($image, 22, 0, 750, 1080, $color, $font, date("Y年n月j日", strtotime($one['create_time'])));imagettftext($image, 22, 0, 300, 1080, $color, $font, date("Y年n月j日", strtotime($one['create_time'])));imagettftext($image, 22, 0, 500, 498, $color, $font, $one['institution']);/***************************** 文字水印开始 ********************************//***************************** 图片水印开始 ********************************/// 获取水印图片$watermarkPath = './static/images/water.png';$watermarkInfo = getimagesize($watermarkPath);$watermarkExtension = image_type_to_extension(getimagesize($watermarkPath)[2], false);$func = 'imagecreatefrom' . $watermarkExtension;$watermark = $func($watermarkPath);// 添加图片水印imagecopymerge($image, $watermark, 1280, 180, 0, 0, $watermarkInfo[0], $watermarkInfo[1], 100);// 销毁水印图片imagedestroy($watermark);// 生成二维码$qr = "./static/images/qr.png";$str = 'http://thinkcms.cc/index/index/image?id=' . $one['id'];$img_data = \tekintian\TekinQR::getQRImg($str, 5, null, 3);file_put_contents($qr, $img_data);$watermarkInfo = getimagesize($qr);$watermarkExtension = image_type_to_extension(getimagesize($qr)[2], false);$func = 'imagecreatefrom' . $watermarkExtension;$watermark = $func($qr);// 添加图片水印imagecopymerge($image, $watermark, 1580, 370, 0, 0, $watermarkInfo[0], $watermarkInfo[1], 100);// 销毁水印图片imagedestroy($watermark);$watermarkPath = './static/images/nyyz.png';$watermarkInfo = getimagesize($watermarkPath);$watermarkExtension = image_type_to_extension(getimagesize($watermarkPath)[2], false);$func = 'imagecreatefrom' . $watermarkExtension;$watermark = $func($watermarkPath);// 添加图片水印imagecopymerge($image, $watermark, 220, 850, 0, 0, $watermarkInfo[0], $watermarkInfo[1], 100);// 销毁水印图片imagedestroy($watermark);$watermarkPath = './static/images/gjyz.png';$watermarkInfo = getimagesize($watermarkPath);$watermarkExtension = image_type_to_extension(getimagesize($watermarkPath)[2], false);$func = 'imagecreatefrom' . $watermarkExtension;$watermark = $func($watermarkPath);// 添加图片水印imagecopymerge($image, $watermark, 720, 850, 0, 0, $watermarkInfo[0], $watermarkInfo[1], 100);// 销毁水印图片imagedestroy($watermark);/***************************** 图片水印开始 ********************************/// 输出图片header('Content-Type:' . $imageInfo['mime']);$func = 'image' . $imageExtension;$func($image, null, 6);// 销毁图片imagedestroy($image);exit;}

在这里插入图片描述

2、证书里的二维码,扫码就能扫码出来,是PHP生成二维码,其二维码中间也是支持加logo的

添加扩展:

"tekintian/phpqrcode": "^1.1",

相关代码:

// 生成二维码
$qr = "./static/images/qr.png";
// 这个本地测试域名,不是外网,扫码不了,上线改成外网扫了才有效
$str = 'http://thinkcms.cc/index/index/image?id=' . $one['id'];
$img_data = \tekintian\TekinQR::getQRImg($str, 5, null, 3);
file_put_contents($qr, $img_data);

3、后台实现带图片excel数据导入,这个摸索了点时间,因为PHPExcel停止维护了,改了半天源码还有问题,最后放弃了,换了一个扩展。

添加扩展:

"phpoffice/phpspreadsheet": "^1.20.0"

相关代码:

/*** 字母序列化为数字*/
public function ABC2decimal($abc)
{$ten = 0;$len = strlen($abc);for ($i = 1; $i <= $len; $i++) {$char = substr($abc, 0 - $i, 1);//反向获取单个字符$int = ord($char);$ten += ($int - 65) * pow(26, $i - 1);}return $ten;
}public function excel()
{if ($file = request()->file('excel')) {try {$saveName = Filesystem::disk('public')->putFile('/static/upload/excels', $file);if (!is_file($saveName)) {return json(['code' => 1, 'msg' => '文件不存在', 'data' => null]);}$ext = pathinfo($saveName, PATHINFO_EXTENSION);// xls不支持图片导入// if (!in_array($ext, ['xlsx', 'xls'])) {if (!in_array($ext, ['xlsx'])) {return json(['code' => 1, 'msg' => '文件类型不正确', 'data' => null]);}// 有两种格式,xlsx和xlsif ($ext == 'xlsx') {$objReader = IOFactory::createReader('Xlsx');} else {$objReader = IOFactory::createReader('Xls');}// 图片保存路径$imageFilePath1 = root_path() . '/public/'; // 图片保存目录$imageFilePath2 = 'static/upload/images/' . date("Ymd") . '/';$imageFilePath = $imageFilePath1 . $imageFilePath2;if (!file_exists($imageFilePath)) {mkdir("$imageFilePath", 0777, true);}// 载入excel文件$excel = $objReader->load($saveName);// 读取第一张表$sheet = $excel->getActiveSheet();// 读取总行数$highestRow = $sheet->getHighestRow();// 读取第一张表转换成数组$data = $sheet->toArray();// 处理图片foreach ($sheet->getDrawingCollection() as $drawing) {list($startColumn, $startRow) = Coordinate::coordinateFromString($drawing->getCoordinates());$imageFileName = $drawing->getIndexedFilename();  // 获取文件名switch ($drawing->getExtension()) {case 'jpg':case 'jpeg':$source = imagecreatefromjpeg($drawing->getPath());imagejpeg($source, $imageFilePath . $imageFileName);break;case 'gif':$source = imagecreatefromgif($drawing->getPath());imagegif($source, $imageFilePath . $imageFileName);break;case 'png':$source = imagecreatefrompng($drawing->getPath());imagepng($source, $imageFilePath . $imageFileName);break;}$startColumn = $this->ABC2decimal($startColumn);$data[$startRow - 1][$startColumn] = $imageFilePath2 . $imageFileName;}// 数据写入数据库$add_data = [];for ($i = 1; $i <= $highestRow - 1; $i++) {$add_data[$i]['institution'] = $data[$i][0];$add_data[$i]['name'] = $data[$i][1];$add_data[$i]['sex'] = $data[$i][2];$add_data[$i]['phone'] = $data[$i][3];$add_data[$i]['id_type'] = $data[$i][4];$add_data[$i]['id_no'] = $data[$i][5];$add_data[$i]['occupation'] = $data[$i][6];$add_data[$i]['job'] = $data[$i][7];$add_data[$i]['skill_level'] = $data[$i][8];$add_data[$i]['certificate_no'] = $data[$i][9];$add_data[$i]['create_time'] = $data[$i][10];$add_data[$i]['start_time'] = $data[$i][11];$add_data[$i]['end_time'] = $data[$i][12];$add_data[$i]['path'] = $data[$i][13];}// 数据插入数据库$success_count = Db::table('certificate')->insertAll($add_data);if ($success_count > 0) {return json(['code' => 0, 'msg' => '数据插入成功', 'data' => null]);} else {return json(['code' => 1, 'msg' => '数据插入失败', 'data' => null]);}} catch (\Exception $e) {return json(['code' => 1, 'msg' => $e->getMessage(), 'data' => null]);}} else {return json(['code' => 1, 'msg' => '上传文件不能为空', 'data' => null]);}
}
  1. ThinkPHP8.0开启session,没有采取前后端分离,就是前后端分离后,SEO不友好,再去前端优化搜索,那还不如直接MVC来的快,所以用到了session。根据官方手册没有配置成功,session没有生效,后面尝试了下面的方法,两者都进行配置才生效。这里记录下。

全局config配置middleware.php中

<?php
// 中间件配置
return [// 别名或分组'alias'    => [],// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行'priority' => ['think\middleware\SessionInit'],
];

后端应用middleware.php中

<?php
// 这是系统自动生成的middleware定义文件
return [// 无关代码省略...\think\middleware\SessionInit::class
];

弄了写数据模拟下,最终实现的功能成果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kotlin运行

1.使用android studio 由于我本身是做android的&#xff0c;android studio本身有内置kotlin的插件。但若只是想跑kotlin的程序&#xff0c;并不像和android程序绑在一起&#xff0c;可以创建一个kt文件&#xff0c;在里面写一个main函数&#xff0c;就可以直接运行kotlin程序…

2024.1.13每日一题

LeetCode 2182.构造限制重复的字符串 2182. 构造限制重复的字符串 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个字符串 s 和一个整数 repeatLimit &#xff0c;用 s 中的字符构造一个新字符串 repeatLimitedString &#xff0c;使任何字母 连续 出现的次数都…

[足式机器人]Part2 Dr. CAN学习笔记 - Ch02动态系统建模与分析

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记 - Ch02动态系统建模与分析 1. 课程介绍2. 电路系统建模、基尔霍夫定律3. 流体系统建模4. 拉普拉斯变换&#xff08;Laplace&#xff09;传递函数、微分方程4.1 Laplace Transform 拉式变换4.2 收…

【python】07.字符串和常用数据结构

字符串和常用数据结构 使用字符串 第二次世界大战促使了现代电子计算机的诞生&#xff0c;最初计算机被应用于导弹弹道的计算&#xff0c;而在计算机诞生后的很多年时间里&#xff0c;计算机处理的信息基本上都是数值型的信息。世界上的第一台电子计算机叫ENIAC&#xff08;电…

Vue+ElementUI+Axios实现携带参数的文件上传(数据校验+进度条)

VueElementUIAxios实现携带参数的文件上传&#xff08;数据校验进度条&#xff09; 可以实现对上传文件的类型&#xff0c;大小进行数据校验&#xff0c;以及对上传文件所要携带的数据也进行的校验&#xff0c;也有文件上传进度的进度条。 一、Vue 结构部分 弹窗显示&#xff0…

Java 面试题 - 多线程并发篇

线程基础 创建线程有几种方式 继承Thread类 可以创建一个继承自Thread类的子类&#xff0c;并重写其run()方法来定义线程的行为。然后可以通过创建该子类的实例来启动线程。 示例代码&#xff1a; class MyThread extends Thread {public void run() {// 定义线程的行为} …

ubuntu20.04网络问题以及解决方案

1.网络图标消失&#xff0c;wired消失&#xff0c;ens33消失 参考&#xff1a;https://blog.51cto.com/u_204222/2465609 https://blog.csdn.net/qq_42265170/article/details/123640669 原始是在虚拟机中切换网络连接方式&#xff08;桥接和NAT&#xff09;&#xff0c; 解决…

K8S--安装MySQL8(单机)

原文网址&#xff1a;K8S--安装MySQL8&#xff08;单机&#xff09;-CSDN博客 简介 本文介绍K8S部署MySQL8&#xff08;单机&#xff09;的方法。 ----------------------------------------------------------------------------------------------- 分享Java真实高频面试题…

解决虚拟机的网络图标不见之问题

在WIN11中&#xff0c;启动虚拟机后&#xff0c;发现网络图标不见了&#xff0c;见下图&#xff1a; 1、打开虚拟机终端 输入“sudo server network-manager stop”&#xff0c;停止网络管理器 输入“cd /回车” &#xff0c; 切换到根目录 输入“cd var回车” &#xff0c;…

探索Shadowsocks-Android:保护你的网络隐私

探索Shadowsocks-Android&#xff1a;保护你的网络隐私 I. 引言 在数字时代&#xff0c;网络隐私和安全变得愈发重要。我们越来越依赖互联网&#xff0c;但同时也面临着各种网络限制和监控。在这个背景下&#xff0c;Shadowsocks-Android应用程序应运而生&#xff0c;为用户提…

java Servlet体育馆运营管理系统myeclipse开发mysql数据库网页mvc模式java编程计算机网页设计

一、源码特点 JSP 体育馆运营管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统采用serlvetdaobean&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。 java Servlet体育馆运营管理系…

自定义数据实现SA3D

SA3D&#xff1a;Segment Anything in 3D with NeRFs 实现了3D目标分割 原理是利用SAM(segment anything) 模型和Nerf分割渲染3D目标&#xff0c; SAM只能分块&#xff0c;是没有语义标签的&#xff0c;如何做到语义连续&#xff1f; SA3D中用了self-prompt, 根据前一帧的mask…

【Java】正则表达式( Pattern 和 Matcher 类)

快速入门 Java 提供了 java.util.regex 包&#xff0c;它包含了 Pattern 和 Matcher 类&#xff0c;用于处理正则表达式的匹配操作。 java.util.regex 包主要包括以下三个类&#xff1a; Pattern 类&#xff1a; pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共…

书生·浦语大模型--第二节课笔记

书生浦语大模型--第二节课 大模型及InternLM基本介绍实战部分demo部署准备工作模型下载代码准备终端运行web demo 运行 Lagent 智能体工具调用 Demo准备工作Demo 运行 浦语灵笔图文理解创作 Demo环境准备下载模型下载代码运行 大模型及InternLM基本介绍 大模型 定义&#xff…

C语言快速排序——qsort函数

上面的是我们标准C语言库里面对qsort函数的介绍&#xff0c;我们先来从排序说起&#xff1a; 这就不得不提出编程中最最基础的排序算法---冒泡排序 对于一个任意的无序数列&#xff0c;我们如果想要把他排成顺序数列的话&#xff0c;我们就可以让每一项跟后面的一项去比较&…

Windows11 安装MySQL8.0操作

一、从MySQL官网下载MySQL安装包 官网地址&#xff1a; www.mysql.com &#xff08;1&#xff09;首先 选择 DOWNLOADS 下载界面 &#xff08;2&#xff09;其次选择 MySQL 客户端 下载 &#xff08;3&#xff09;选择windows安装MySQL &#xff08;4&#xff09;选择MySQL类型…

Ubuntu开机自动挂载硬盘

前言&#xff1a; 因为我的电脑是WIN10 Ubuntu18.04双系统&#xff0c;且两个系统都装在C盘上&#xff0c;而D盘作为数据和代码存储盘&#xff0c;经常会开机就被访问&#xff0c;例如上一次关机前用VS Code访问D盘代码&#xff0c;然后下一次开机的时候打开VSCode发现打不开…

锁定查询功能,完成查询后防止他人查询

查询者想要实现自己查询完成后&#xff0c;任何人都无法再次查询&#xff0c;发布者应该如何设置&#xff1f;易查分的【锁定查询功能】就可实现&#xff0c;本次就来介绍如何使用此功能。 &#x1f4cc;使用教程 &#x1f512;锁定查询功能介绍 ✅用户自主锁定&#xff1a;开启…

使用Scrapy框架和代理IP进行大规模数据爬取

目录 一、前言 二、Scrapy框架简介 三、代理IP介绍 四、使用Scrapy框架进行数据爬取 1. 创建Scrapy项目 2. 创建爬虫 3. 编写爬虫代码 4. 运行爬虫 五、使用代理IP进行数据爬取 1. 安装依赖库 2. 配置代理IP和User-Agent 3. 修改爬虫代码 4. 运行爬虫 六、总结 一…

数据结构 模拟实现二叉树(孩子表示法)

目录 一、二叉树的简单概念 &#xff08;1&#xff09;关于树的一些概念 &#xff08;2&#xff09;二叉树的一些概念及性质 定义二叉树的代码&#xff1a; 二、二叉树的方法实现 &#xff08;1&#xff09;createTree &#xff08;2&#xff09;preOrder &#xff08;…