最新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.mzph.cn/news/608949.shtml

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

相关文章

CTF-PWN-栈溢出-中级ROP-【栈迁移】

文章目录 栈迁移具体流程 VNCTF 2023 traveler libc-2.27检查源码main函数![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/386c35c30f854434ae43667b9473c58a.png)全局变量地址局部变量地址 PIE保护开启PIE关闭PIE 思路exp 栈迁移参考 栈迁移参考 栈迁移 顾名思义…

HCIA-Datacom题库(自己整理分类的)_15_VRP平台多选【9道题】

1.VRP操作平台存在哪些命令行视图? 用户视图 接口视图 协议视图 系统视图 2.以下哪些存储介质是华为路由器常用的存储介质 SDRAM NVRAM Flash Hard Disk SD Card 解析&#xff1a;Hard Disk是硬盘&#xff0c;一般网络设备没有。 3.VRP支持通过哪几种方式对路由器…

C#操作注册表

说明 今天用C#开发了一个简单的服务&#xff0c;需要设置成为自启动&#xff0c;网上有很多方法&#xff0c;放到启动运行等&#xff0c;但是今天想介绍一个&#xff0c;通过修改注册表实现&#xff0c;同时介绍一下操作注册表。 private void TestReg(){//仅对当前用户有效 H…

分析一个项目(微信小程序篇)二

目录 首页&#xff1a; 发现&#xff1a; 购物车&#xff1a; 我的&#xff1a; 分析一个项目讲究的是如何进行对项目的解析分解&#xff0c;进一步了解项目的整体结构&#xff0c;熟悉项目的结构&#xff0c;能够知道每个组件所处在哪个位置&#xff0c;发挥什么作用。 接…

基于Springboot的计算机学院校友网(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的计算机学院校友网(有报告)。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring…

密码学(二)

文章目录 前言一、Certificate Authorities二、Key Agreement Protocols 前言 本文来自 Intel SGX Explained 请参考&#xff1a;密码学&#xff08;一&#xff09; 一、Certificate Authorities 非对称密钥密码学中的公钥和私钥假设每个参与方都拥有其他参与方的正确公钥。…

【JAVA】Java8开始ConcurrentHashMap,为什么舍弃分段锁

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a; JAVA ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 分段锁的好处&#xff1a; 结语 我的其他博客 前言 在Java 8中&#xff0c;ConcurrentHashMap的实现经历了重大的改进&am…

在Ubuntu中检查内存的五个命令,总有一种适合你

序言 作为Ubuntu用户,尤其是管理员,我们需要检查系统使用了多少内存资源,以及有多少是可用的。我们还知道,大多数管理任务最好从Linux命令行完成,而不是从图形用户界面完成。例如,服务器通常在shell上工作,没有图形用户界面。由于控制服务器上的内存资源是最重要的,因…

Linux 如何 kill 指定的 python 进程

文章目录 写在前面一、显示python相关的进程二、找到自己想要 kill 的进程&#xff0c;执行下述指令 写在前面 自己的系统是 Ubuntu 20.04 一、显示python相关的进程 ps -ef | grep python显示结果如下 其中&#xff0c;第二列分别是各个进程的 PID 号。 二、找到自己想要…

facebook广告对于推广的重要性

广告覆盖广泛&#xff1a; Facebook是全球最大的社交媒体平台之一&#xff0c;拥有数十亿的用户。通过在Facebook上投放广告&#xff0c;广告主可以覆盖到大量潜在客户&#xff0c;提高品牌曝光度。 精准定位和定向广告&#xff1a; Facebook提供了强大的广告定位和定向功能&a…

python 基础笔记

基本数据类型 函数 lamda 匿名函数 成员方法 类 类与对象 构造方法 魔术方法 私有成员 私有方法 继承 注解 变量注解 函数注解 Union类型 多态 参考链接&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了_哔哩哔哩_bilib…

【Azure 架构师学习笔记】- Azure Databricks (5) - Unity Catalog 简介

本文属于【Azure 架构师学习笔记】系列。 本文属于【Azure Databricks】系列。 接上文 【Azure 架构师学习笔记】- Azure Databricks (4) - 使用Azure Key Vault 管理ADB Secret 前言 DataBricks Unity Catalog&#xff08;UC&#xff09;是一个统一的对数据资产治理的解决方案…

C# 一看就懂的装箱拆箱案例

文章目录 装箱&#xff08;Boxing&#xff09;拆箱&#xff08;Unboxing&#xff09;编程语言中的装箱与拆箱优缺点 在C#中&#xff0c;装箱&#xff08;Boxing&#xff09;和拆箱&#xff08;Unboxing&#xff09;是值类型与引用类型之间相互转换的过程。 装箱&#xff08;Box…

Java实现基于GDAL将单波段影像转为三波段影像-唯一值渲染

在处理遥感影像的渲染时&#xff0c;经常需要处理单波段影像。单波段影像没有任何颜色&#xff0c;只有一个波段的值。渲染时只能采用色带拉伸、离散颜色、唯一值渲染这几种方式。直接将单波段影像转成三波段的影像&#xff0c;并将三个波段转为颜色对应的rgb值&#xff0c;这样…

2023高级人工智能期末总结

1、人工智能概念的一般描述 人工智能是那些与人的思维相关的活动&#xff0c;诸如决策、问题求解和学习等的自动化&#xff1b; 人工智能是一种计算机能够思维&#xff0c;使机器具有智力的激动人心的新尝试&#xff1b; 人工智能是研究如何让计算机做现阶段只有人才能做得好的…

接口自动化测试要做什么?

作者&#xff1a;不辣的皮皮 链接&#xff1a;https://www.zhihu.com/question/384727359/answer/1124441469 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 可以分为四个步骤/阶段。 原理 》 业务逻辑》 工具》 …

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》

【现代密码学】笔记3.1-3.3 --规约证明、伪随机性《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第一部分密码学的计算方法论计算安全加密的定义&#xff1a;对称加密算法 伪随机性伪随机生成器&#xff08;PRG&#xff09; 规约法规约证明 构造安全…

Python算法例34 寻找丢失的数

1. 问题描述 给一个由1~n的整数随机组成的一个字符串序列&#xff0c;其中丢失了一个整数&#xff0c;本例将找到它。 2. 问题示例 给出n20&#xff0c;str19201234567891011121314151618&#xff0c;丢失的数是17。 3. 代码实现 def find_missing_number(n, string):nums…

【代码随想录】刷题笔记Day47

前言 又过了个愉快的周末~大组会终于不用开了&#xff0c;理论上已经可以回家了&#xff01;但是我多留学校几天吧&#xff0c;回家实在太无聊了&#xff0c;也没太多学习的氛围 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; dp[i]含义 考虑下标i&#xff08;包括…

【leetcode】力扣算法之两数相加【中等难度】

题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数都…