最新ThinkPHP版本实现证书查询系统,实现批量数据导入,自动生成电子证书
前提:朋友弄了一个培训机构,培训考试合格后,给发证书,需要一个证书查询系统。委托我给弄一个,花了几个晚上给写的证书查询系统。
实现功能:
- 前端按照姓名+手机号码进行证书查询
- 证书信息展示+证书展示,支持点击下载
- 后端证书信息录入+带一寸照片数据批量导入
技术栈:
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]);}
}
- 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
];
弄了写数据模拟下,最终实现的功能成果如下:
相关文章:

最新ThinkPHP版本实现证书查询系统,实现批量数据导入,自动生成电子证书
前提:朋友弄了一个培训机构,培训考试合格后,给发证书,需要一个证书查询系统。委托我给弄一个,花了几个晚上给写的证书查询系统。 实现功能: 前端按照姓名手机号码进行证书查询证书信息展示证书展示&#x…...
windows安装运行Apache James(基于spring的版本)
下载地址 下载列表 https://james.apache.org/download.cgi 直接下载基于spring版本 https://www.apache.org/dyn/closer.lua/james/server/3.8.0/james-server-app-3.8.0-app.zip 设置签名 解压,并切换到james-server-spring-app-3.8.0目录下,在powe…...
Elasticsearch 基本概念:快速入门指南【记录】
简单记录,后续整理补充 介绍: Elasticsearch是一个分布式、可扩展、实时的搜索和分析引擎,建立在开源搜索库Lucene之上。它提供了强大的全文搜索功能和复杂的分析能力,适用于各种场景,包括应用日志分析、电子商务搜索…...

【JVM 基础】类字节码详解
JVM 基础 - 类字节码详解 多语言编译为字节码在JVM运行Java字节码文件Class文件的结构属性从一个例子开始反编译字节码文件字节码文件信息常量池方法表集合类名 再看两个示例分析try-catch-finallykotlin 函数扩展的实现 源代码通过编译器编译为字节码,再通过类加载…...

【算法】基础算法001之双指针
👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 🌝每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.数组分块…...

[力扣 Hot100]Day2 字母异位词分组
题目描述 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 出处 思路 这题有点考阅读理解,意思就是把输入数组中的所含字母相同但顺序不同的单词放到同…...
记一次 easyswoole 热重载失效复盘 grpc扩展惹的祸
首先看一下运行环境 swoole version 4.8.11 php version 7.4.33 easyswoole version 3.4.6 在easyswoole 的入口文件 如下: <?php namespace EasySwoole\EasySwoole; use App\WebSocket\WebSocketEvents; use Ap…...
存储过程从表中获取数据库名称
---------------业务数据库信息 CREATE TABLE [dbo].[app_erp_datbabase_conf] ( [id] [int] IDENTITY(1,1) NOT NULL, [database_type] [varchar](200) NOT NULL, [database_name] [varchar](200) NOT NULL, [create_time] [datetime] NULL, [modify_t…...

.NET 反射的介绍和简单应用
什么是反射? 反射就是动态发现类型信息的能力。它帮助程序设计人员在程序运行时利用一些信息去动态地使用类型,这些信息在设计时是未知的,这种能力类似于后期绑定。反射还支持的更高级的行为,能在运行时动态创建新类型࿰…...

在drawio中使用BPMN2.0绘制详细的业务流程图和编排模型
在drawio中使用BPMN2.0绘制详细的业务流程图和编排模型 drawio是一款强大的图表绘制软件,支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用,则直接输入网址draw.io或者使用drawon(桌案), drawon.cn内部完整的集成了drawio的所有功…...
GO——defer函数
定义 当前函数返回之前执行传入函数的一个关键字 执行时间 当前函数返回前执行 常用于 关闭文件描述符关闭数据库链接解锁资源 原理 参考:https://draveness.me/golang/docs/part2-foundation/ch05-keyword/golang-defer/ 后调用的 defer 函数会先执行&…...

【UE Niagara学习笔记】06 - 制作火焰喷射过程中飞舞的火星
在上一篇博客(【UE Niagara学习笔记】05 - 喷射火焰顶部的蓝色火焰)的基础上继续实现喷射火焰的火星的效果。 目录 效果 步骤 一、创建材质实例 二、添加新的发射器 2.1 设置粒子材质 2.2 设置发射器持续生成粒子 2.3 设置粒子生成数量 2.4 设…...

机器学习笔记一之入门概念
目录 一 基本分类二 按模型分类概率模型(Probabilistic Models)非概率模型(Non-Probabilistic Models)对比结论线性模型 (Linear Models)非线性模型 (Non-linear Models)对比 三 按算法分类1.批量学习(Batch Learning&…...
用于脚本支持的 CSS 媒体查询
Chrome 120 于近日发布,在这个版本中,我们获得了用于脚本支持的 CSS 媒体查询。简单地说,此媒体查询允许我们测试脚本语言是否可用,并根据支持定制页面内容和样式。我是白特,让我们一起来学习下吧。 媒体查询语法 媒…...
【HBase】——整合Phoenix
1 概述 Phoenix 是 HBase 的开源 SQL 皮肤。可以使用标准 JDBC API 代替 HBase 客户端 API 来创建表,插入数据和查询 HBase 数据。 Phoenix 在 5.0 版本默认提供有两种客户端使用(瘦客户端和胖客户端),在 5.1.2 版本 安装包中…...

【操作系统xv6】学习记录5--实验1 Lab: Xv6 and Unix utilities
ref:https://pdos.csail.mit.edu/6.828/2020/xv6.html 实验:Lab: Xv6 and Unix utilities 环境搭建 实验环境搭建:https://blog.csdn.net/qq_45512097/article/details/126741793 搭建了1天,大家自求多福吧,哎。~搞环境真是折磨…...

Python从入门到网络爬虫(控制语句详解)
前言 做任何事情都要遵循一定的原则。例如,到图书馆去借书,就需要有借书证,并且借书证不能过期,这两个条件缺一不可。程序设计亦是如此,需要使用流程控制实现与用户的交流,并根据用户需求决定程序“做什么…...

transbigdata笔记:数据预处理
0 数据 使用 transbigdata/docs/source/gallery/data/TaxiData-Sample.csv at main ni1o1/transbigdata (github.com) 和transbigdata/docs/source/gallery/data/sz.json at main ni1o1/transbigdata (github.com) 0.1 导入库 import transbigdata as tbd import pandas …...

java中解码和编码出现乱码原因
一、UTF-8和GBK编码方式 如果采用的是UTF-8的编码方式,那么1个英文字母 占 1个字节,1个中文占3个字节如果采用GBK的编码方式,那么1个英文字母 占 1个字节,1个中文占2个字节 二、idea和eclipse的默认编码方式 其实idea和eclipse的…...

60V降压3.3V稳压芯片 60V降压5V稳压芯片60V降压12V稳压芯片
60V降压3.3V稳压芯片、60V降压5V稳压芯片和60V降压12V稳压芯片是针对不同输出电压需求的降压稳压芯片。这些芯片通常被用于工业控制、通信设备、汽车电子和其他需要高电压输入并提供稳定输出电压的场合。 这些芯片通常具有高效率、低功耗和高稳定性的特点,能够在输…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...