pdf插件:tcpdf
TP5.0框架
报告单截图
PDF字体:yahei
参考代码如下:
public function testpdflib()
{
require_once(ROOT_PATH.'/../extend/tcpdf/tcpdf.php');
$tcpdf = new Pdf();
$title = '';//标题
$fileName = 'demo';//文件名称
/*$imgs["wbc"] = "https://applet.linic.com.cn/static/histpaiter/46210_WBC.png";
$imgs["plt"] = "https://applet.linic.com.cn/static/histpaiter/46210_PLT.png";
$imgs["rbc"] = "https://applet.linic.com.cn/static/histpaiter/46210_RBC.png";
$data_json = '[{"Flag":"","Name":"wbc","RangeHigh":"9.5","RangeLow":"3.5","Unit":"10^9\/L","Value":"9.44","CName":"白细胞"},{"Flag":"","Name":"lym%","RangeHigh":"50","RangeLow":"20","Unit":"%","Value":"20.6","CName":"淋巴细胞百分比"},{"Flag":"","Name":"gran%","RangeHigh":"75","RangeLow":"40","Unit":"%","Value":"68.8","CName":"粒细胞百分比"},{"Flag":"Up","Name":"mid%","RangeHigh":"10","RangeLow":"3","Unit":"%","Value":"10.6","CName":"中间群细胞百分比"},{"Flag":"","Name":"lym#","RangeHigh":"3.2","RangeLow":"1.1","Unit":"10^9\/L","Value":"1.94","CName":"淋巴细胞数目"},{"Flag":"Up","Name":"gran#","RangeHigh":"6.3","RangeLow":"1.8","Unit":"10^9\/L","Value":"6.50","CName":"粒细胞数目"},{"Flag":"Up","Name":"mid#","RangeHigh":"0.6","RangeLow":"0.1","Unit":"10^9\/L","Value":"1.00","CName":"中间群细胞数目"},{"Flag":"","Name":"rbc","RangeHigh":"5.8","RangeLow":"3.8","Unit":"10^12\/L","Value":"4.09","CName":"红细胞"},{"Flag":"","Name":"hgb","RangeHigh":"175","RangeLow":"115","Unit":"g\/L","Value":"134","CName":"血红蛋白"},{"Flag":"","Name":"hct","RangeHigh":"50","RangeLow":"35","Unit":"%","Value":"36.1","CName":"红细胞压积"},{"Flag":"","Name":"mcv","RangeHigh":"120","RangeLow":"82","Unit":"fL","Value":"88.2","CName":"红细胞平均体积"},{"Flag":"","Name":"mch","RangeHigh":"34","RangeLow":"27","Unit":"pg","Value":"32.7","CName":"平均血红蛋白含量"},{"Flag":"Up","Name":"mchc","RangeHigh":"354","RangeLow":"316","Unit":"g\/L","Value":"371","CName":"平均血红蛋白浓度"},{"Flag":"","Name":"rdw-cv","RangeHigh":"16","RangeLow":"11","Unit":"%","Value":"11.4","CName":"红细胞变异系数"},{"Flag":"","Name":"rdw-sd","RangeHigh":"56","RangeLow":"35","Unit":"fL","Value":"36.2","CName":"分布宽度标准差"},{"Flag":"","Name":"plt","RangeHigh":"350","RangeLow":"125","Unit":"10^9\/L","Value":"333","CName":"血小板"},{"Flag":"","Name":"mpv","RangeHigh":"12","RangeLow":"6.5","Unit":"fL","Value":"9.0","CName":"血小板平均体积"},{"Flag":"Down","Name":"pdw","RangeHigh":"17","RangeLow":"9","Unit":"fL","Value":"6.3","CName":"血小板分布宽度"},{"Flag":"Up","Name":"pct","RangeHigh":"0.282","RangeLow":"0.108","Unit":"%","Value":"0.298","CName":"血小板压积"},{"Flag":"","Name":"p-lcr","RangeHigh":"45","RangeLow":"11","Unit":"%","Value":"12.1","CName":"大血小板比例"},{"Flag":"","Name":"p-lcc","RangeHigh":"90","RangeLow":"30","Unit":"10^9\/L","Value":"40","CName":"大血小板数目"}]';
$data_json = json_decode($data_json,true);
list($tabledata1,$tabledata2) = array_chunk($data_json,14);
$subtable2 = $subtable1 = '<table border="0" cellspacing="0" cellpadding="0" ><tr><th style="width:145px;font-weight: bold;" >检测项目</th><th style="width:80px;font-weight: bold;" >结果</th><th style="width:60px;font-weight: bold;">单位</th><th style="width:80px;font-weight: bold;">参考范围</th></tr>';
foreach ($tabledata1 as $k => $v){
$subtable1 .= "<tr><td style='font-weight: bold;'>".($k + 1)." ".$v["CName"]."(".$v["Name"].")"."</td>";
$subtable1 .= "<td >".$v["Value"]." <span style='color: red;font-weight: normal;'>↑</span></td>";
$subtable1 .= "<td >".$v["Unit"]."</td><td >".$v["RangeLow"] . "~" .$v["RangeHigh"]."</td></tr>";
}
$subtable1 .= '</table>';
foreach ($tabledata2 as $k => $v){
$subtable2 .= "<tr><td style='font-weight: bold;'>".($k + 1)." ".$v["CName"]."(".$v["Name"].")"."</td>";
$subtable2 .= "<td >".$v["Value"]." <span style='color: blue;font-weight: normal;'>↓</span></td>";
$subtable2 .= "<td >".$v["Unit"]."</td><td >".$v["RangeLow"] . "~" .$v["RangeHigh"]."</td></tr>";
}
$subtable2 .= '</table>';
$tdsubtable = '<td align="left" colspan="2" style="width:49%;height: 350px;">'.$subtable1.'</td><td align="left" colspan="2" style="width:47%;height: 350px;">'.$subtable2.'</td>';
*/
$imgs = [];
$tabledata = [
[
"Flag" => "",
"Name" => "CRP",
"RangeHigh" => "9.5",
"RangeLow" => "3.5",
"Unit" => "10^9\/L",
"Value" => "9.44",
"CName" => "C反应蛋白"
],
[
"Flag" => "",
"Name" => "Hp-Ab",
"RangeHigh" => "9.5",
"RangeLow" => "3.5",
"Unit" => "10^9\/L",
"Value" => "9.44",
"CName" => "胃幽门螺杆菌抗体"
],
[
"Flag" => "",
"Name" => "MP-IgM",
"RangeHigh" => "9.5",
"RangeLow" => "3.5",
"Unit" => "10^9\/L",
"Value" => "9.44",
"CName" => "肺炎支原体IgM抗体"
]
];
$tdsubtable = '<td align="left" colspan="4" style="width:100%;height: 350px;"><table border="0" cellspacing="0" cellpadding="0" ><tr><th style="width:300px;font-weight: bold;" >检测项目</th><th style="font-weight: bold;" >结果</th><th style="font-weight: bold;">单位</th><th style="font-weight: bold;">参考范围</th></tr>';
foreach ($tabledata as $k => $v){
$tdsubtable .= "<tr><td style='font-weight: bold;'>".($k + 1)." ".$v["CName"]."(".$v["Name"].")"."</td>";
$tdsubtable .= "<td >".$v["Value"]." <span style='color: blue;font-weight: normal;'>↓</span></td>";
$tdsubtable .= "<td >".$v["Unit"]."</td><td >".$v["RangeLow"] . "~" .$v["RangeHigh"]."</td></tr>";
}
$tdsubtable .= '</table></td>';
$html = <<<EOF
<style>
.tabheader{
border-bottom: 1px solid #000;
width: 100%;
}
.tabfooter{
border-top: 1px solid #000;
width: 100%;
margin-top: 4px;
}
</style>
<table border="0" cellspacing="2" cellpadding="3" class="tabheader">
<tr>
<th align="center" colspan="4" style="font-weight: bold;font-size: 16px">长沙中质恒泰医学验报告单</th>
</tr>
<tr>
<td style="font-weight: bold;padding-left: 20px"><label >患者姓名:</label>刘子琴</td>
<td colspan="2" style="font-weight: bold"><label >样本类型:</label>全血,血清,血浆</td>
<td style="font-weight: bold"><label >样本编号:</label>202489</td>
</tr>
<tr>
<td style="font-weight: bold;padding-left: 20px"><label >性 别:</label>男</td>
<td colspan="2" style="font-weight: bold"><label >年 龄:</label>13 周岁</td>
<td style="font-weight: bold" ><label >检验时间:</label>2023-09-14 08:19:41</td>
</tr>
</table>
<table border="0" cellspacing="2" cellpadding="3" >
<tr>
$tdsubtable
</tr>
</table>
<table border="0" cellspacing="0" cellpadding="1" class="tabfooter">
<tr >
<td align="left" style="width: 180px;font-weight: bold;padding-left: 20px"><label >报告时间:</label>2023-09-11 13:34:26</td>
<td align="left" style="width: 180px;font-weight: bold;"><label>打印时间:</label>2023-09-11 13:34:26</td>
<td align="right" style="font-weight: bold"><label >检测人:</label> </td>
<td align="center" style="font-weight: bold"><label >审核人:</label> </td>
</tr>
<tr><td colspan="4" style="font-weight: bold;">注:此检验结果仅对此次检验标本负责,结果仅供临床参考!</td></tr>
</table>
EOF;
$synthesis = [];//图片水印 可多个
$info = [];//二维码相关参数
echo $tcpdf->pdfRender_D($html, $title, $fileName, $synthesis, $info,$imgs);//生成PDF
}
封装的PDF类:
class Pdf {
/*
* 生成pdf
* @param string $html 内容
* @param string $title 标题
* @param string $fileName 生成的文件名称
* @param string $synthesis 要合成的图片路径
* @param number $x x轴
* @param number $y Y轴
* @param number $m 图片宽度
* @param number $h 图片高度
* @param number $setPage 图片放置在第几页
* @param array $info
* @param number $pdf_type 新的PDF存储路径标识 2019/10/23
* @return 合成正确返回PDF路径 合成失败返回为false
*/
public function pdfRender_D($html, $title = '', $fileName, $synthesis = [], $info=[],$imgs=[])
{
//新增路径标识
$path = '/static/preview/' . date('Ym') . '/';//文件存放路径
$directory = ROOT_PATH;//根目录
$is_path = $directory . $path;//全路径
//检测并创建文件夹
if ($this->exists_dir($is_path) === false) {
return false;
}
// GetX获取x轴坐标 GetY获取y轴坐标
$pdf = new \TCPDF("L", PDF_UNIT, "A5", true, 'UTF-8', false);//A4 PDF_PAGE_FORMAT
//设置件信息
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor(str_replace("http://", "", $_SERVER['HTTP_HOST']));
$pdf->SetTitle($title);
$pdf->SetSubject($title);
$pdf->SetKeywords('TCPDF, PDF, example, test, guide,PHP');
// 设置间距
//设置默认等宽字体
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
//设置间距 左侧、上侧、右侧的间距
$pdf->SetMargins(5, 5, 5);//PDF_MARGIN_TOP
//$pdf->SetFooterMargin(0);
$pdf->setCellPaddings(0, 0, 0, 0);
$pdf->SetLineStyle(array('width' => 0, 'cap' => 'butt', 'join' => 'miter', 'dash' => '0', 'color' => array(0, 0, 0)));
//设置自动分页符
//$pdf->MultiCell(0, 0, 'DISK CACHING TEST: check the parameters of the class constructor.', 1, 'L', 0, 0, '', '', true);
$pdf->SetAutoPageBreak(TRUE, 10);
//设置图像比例因子
$pdf->setCellHeightRatio(1.2);//设置单元格行高 1.3 1.2
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
$pdf->SetFont('yahei', '', 9); //设置中文显示 stsongstdlight
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->AddPage();
$pdf->Cell(0, 1, '', 0, 1, 'C');//1.5
if(!empty($imgs)){
$pdf->Image($imgs["wbc"],8 ,90,50,36);
$pdf->Image($imgs["plt"],80 ,90,50,36);
$pdf->Image($imgs["rbc"],150 ,90,50,36);
}
$pdf->writeHTML($html);//时间要的多
//PDF添加图片
/*$num_num = $pdf->getNumPages();//获取当前页码
if ($synthesis) {
$count = count($synthesis);
foreach ($synthesis as $k => $v) {
if ($count > 10 && isset($v['qm'])) {//签名标记
$v['setPage'] = $num_num - 1;
}
if (!isset($v['h'])) {
$v['h'] = '';
}
if (isset($v['setPage'])) {
$pdf->setPage($v['setPage']);//setPage 在那样插入图片 默认为最后一页 $k>=6 || 图片太多要加新页面
}
$pdf->Image($v['org'], $v['x'], $v['y'], $v['w'], $v['h'], '', '', '', false, 300);//时间要的多
if (isset($v['html']) && $v['html']) {
$pdf->writeHTMLCell('', '', $v['x'] - 5, $v['y'] + 8, $v['html'], '', 0, 0, true, 'L', true);
}
}
}*/
//添加二维码 on_off=1 开启 set_page 二维码放置在第几页
/*$this->qr_code_pdf(
[
'pdf' => $pdf, 'uniq_key' => $info['uniq_key'] ?? '',
'on_off' => $info['on_off'] ?? 0,
'set_page' => $info['set_page'] ?? $num_num,
'num_num' => $num_num,
'is_wine' => $info['wine_footer'] ?? 0,//0股权 其他为酒业
]
);*/
/*$pdf->SetFontSize(5);
//分页
$this->footer($pdf);//自定义分页*/
$pdf->Output($is_path . $fileName . ".pdf","D");
/*$url = $path . $fileName . ".pdf";
if (file_exists($is_path . $fileName . ".pdf") !== false) {
return $url;
}
return false;*/
}
/*Page footer 自定义分页
*param object PDF插件对象
*param array $info['uniq_key'] 唯一标识
* */
public function footer($pdf): void
{
$page = 1;//页码
//$pdf->setPage(1);//设置页面
//用此函数可以设置可选边框,背景颜色和HTML文本字符串来输出单元格(矩形区域) W:设置单元格宽度。0,伸展到右边幅的距离 H:设置单元格最小的高度 X:以左上角为原点的横坐标 Y:以左上角为原点的纵坐标 Html:html文本 Border:边框 Ln:0,单元格后的内容插到表格右边或左边,1,单元格的下一行,2,在单元格下面 Fill:填充 Reseth:true,重新设置最后一行的高度 Align:文本的位置 Autopadding:true,自动调整文本到边框的距离。
$pdf->writeHTMLCell('', '', 14, 2, '<span style="color:#000;">' . $page . ' page</span>', '2', 0, 0, true, 'L', true);
$pdf->writeHTMLCell('', '', 80, 2, '<span style="color:#000;">页眉内容</span>', '2', 0, 0, true, 'L', true);
//设置单行单元格:W:设置单元格的宽 H:设置单元格的高 Text:单元格文本 Border:设置单元格的边框。0,无边框,1,一个框,L,左边框,R,右边框,B, 底边框,T,顶边框,LTRB指四个边都显示 Ln:0,单元格后的内容插到表格右边或左边,1,单元格的下一行,2,在单元格下面 Align:文本位置。L,左对齐,R,右对齐,C,居中,J,自动对齐 Fill:填充。false,单元格的背景为透明,true,单元格必需被填充 Link:设置单元格文本的链接。
$pdf->SetY(8);
$pdf->Cell(180, 0, '', 1, 0, 'C', 0, '', 0, true);//180
}
/**
* Notes:pdf 加二维码 http:/hw.com/sign/pdf/demo
* User: ZHOU WEI YUN
* Date: 2021/9/23 0023
* Time: 下午 5:37
* @param array $arr on_off=1 开启添加二维码 uniq_key:唯一标识 pdf控件对象 set_page放置页面
* @return void
*/
public function qr_code_pdf(array $arr): void
{
//生成二维码 文档 https://tcpdf.org/examples/example_027/
if (!empty($arr['on_off']) && $arr['on_off'] === 1) {
if ($arr['num_num'] < $arr['set_page']) {
$arr['set_page'] = $arr['num_num'];
}
//二维码链接
$url = $this->site() . '/h5_contract_url/' . $arr['uniq_key'];
$arr['pdf']->setPage($arr['set_page']);//二维码放置指定的页面
$style = array(
'border' => false,
'padding' => 0,
'fgcolor' => array(0, 0, 0),
'bgcolor' => false, //array(255,255,255)
//'module_width' => 1, // width of a single module in points
//'module_height' => 1 // height of a single module in points
);
//生成二维码
$arr['pdf']->write2DBarcode($url, 'QRCODE,L', 16, 12, 17, 17, $style, 'N');
}
}
/**
* Notes: 获取当前域名
* User: ZHOU WEI YUN
* Date: 2022/2/12 0012
* Time: 上午 11:38
* @param array
* @return string
*/
public function site(): string
{
return $_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['SERVER_NAME'];
}
/**
* Notes: 检测文件夹是否存在 不存在自动创建文件夹
* User: ZHOU WEI YUN
* Date: 2021/3/23 0023
* Time: 上午 10:51
* @param string $path 文件的绝对路径
* @return bool false 文件创建失败 其他返回为true
*/
public function exists_dir(string $path): bool
{
if (file_exists($path) === false) {
$path = str_replace("\\", '/', $path);
$path_arr = explode('/', $path);
$ping = '';
//循环逐级检测 不存在则创建
foreach ($path_arr as $k => $v) {
$ping .= $v . '/';
if (file_exists($ping) === false && !mkdir($ping, 755) && is_dir($ping)) {
return false;
}
}
}
return true;
}
}