Browse Source

健康档案

gorden 3 months ago
parent
commit
7a7d4a0780

+ 7 - 4
app/admin/controller/member/WellnessRecordController.php

@@ -4,7 +4,7 @@ namespace app\admin\controller\member;
 
 use app\admin\validate\life\CinemaIlkValidate;
 use app\admin\validate\member\WellnessRecordValidate;
-use app\common\Pdf;
+use app\common\File;
 use app\controller\Curd;
 use app\model\CinemaIlk as CinemaIlkModel;
 use app\model\SysField;
@@ -568,11 +568,14 @@ class WellnessRecordController extends Curd
 
     public function exportArchivePdf(Request $request)
     {
+        $memberId = $request->get('member_id');
         $data = [
-            'title'=>'导出PDF'
+            'title' => '导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF'
         ];
+        $content = view('member/word', $data)->rawBody();
+
+        return File::exportPdf($content, date('YmdHis') . '.pdf');
 
-        $pdf = Pdf::export('member/archive-pdf',$data);
-        return $pdf->download('example.pdf');
+//        $pdf->stream('my.pdf', ['Attachment' => 1]);
     }
 }

+ 18 - 0
app/admin/view/member/archive-pdf.html

@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <style>
+        body {
+            margin: 0;
+            width: 820px;
+            height: 1160px;
+            font-family:"msyh";
+            word-wrap: break-word;
+        }
+    </style>
+</head>
+<body>
+    <div style="width: 500px;border:1px solid red">导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF导出PDF111</div>
+</body>
+</html>

+ 316 - 0
app/admin/view/member/word.html

@@ -0,0 +1,316 @@
+<!DOCTYPE html>
+<html>
+<head>
+  	<meta charset="utf-8">
+  	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
+<!--  	<title>健康报告word</title>-->
+	<link rel="stylesheet" href="https://img.wanyuewellness.com.cn/static/css/archive-style.css">
+	<style>
+		*{
+			margin: 0;
+			padding: 0;
+		}
+		body {
+			margin: 0;
+			/*width: 820px;*/
+			/*height: 1160px;*/
+			font-family:"msyh";
+			word-wrap: break-word;
+		}
+		table{
+			border-collapse: collapse;
+		}
+		td, th{
+			border:1px solid #969696;
+			color: #000;
+			padding: 6px;
+
+		}
+	</style>
+</head>
+<body>
+<table style="margin: 0 auto;margin-top: 40px;width: 90%" >
+<!--	<thead>-->
+<!--	</thead>-->
+	<tbody>
+	<!--客户基本信息(健康顾问)-->
+	<tr >
+		<th colspan="6" style="text-align: center;"><h2>客户健康档案登记卡</h2></th>
+	</tr>
+	<tr>
+		<th colspan="6"><h3>客户基本信息(健康顾问)</h3></th>
+	</tr>
+	<tr>
+		<td>姓名</td>
+		<td><strong>小红</strong> </td>
+		<td>性别</td>
+		<td><strong>女</strong></td>
+		<td>年龄</td>
+		<td><strong>40岁</strong></td>
+	</tr>
+	<tr>
+		<td rowspan='2'>生日</td>
+		<td>阳历:八月初八</td>
+		<td rowspan='2'>工作单位</td>
+		<td rowspan='2'><strong>山东天下畅通</strong></td>
+		<td rowspan='2'>联系电话</td>
+		<td rowspan='2'><strong>17853102222</strong></td>
+	</tr>
+	<tr>
+		<td>阴历:10月2日</td>
+	</tr>
+	<tr>
+		<td>家庭住址</td>
+		<td colspan="2"><strong>山东省济南市历城区</strong></td>
+		<td>身份证号</td>
+		<td colspan="2"><strong>371425198901524545</strong></td>
+	</tr>
+	<tr>
+		<td>家庭成员</td>
+		<td colspan="5"><strong>女儿、儿子、老公</strong></td>
+	</tr>
+	<tr>
+		<td>紧急联系人</td>
+		<td colspan="2"><strong>女儿</strong></td>
+		<td>联系人电话</td>
+		<td colspan="2"><strong>17853102222</strong></td>
+	</tr>
+	<tr>
+		<th colspan="6"><h3>客户身体指标(检测护士)</h3></th>
+	</tr>
+	<tr>
+		<td>身高</td>
+		<td><strong>165cm</strong> </td>
+		<td>体重</td>
+		<td><strong>40kg</strong></td>
+		<td>BMI值</td>
+		<td><strong>19</strong></td>
+	</tr>
+	<tr>
+		<td>血压</td>
+		<td><strong>120/80</strong> </td>
+		<td>血糖</td>
+		<td><strong>5.5</strong></td>
+		<td>血脂</td>
+		<td><strong>6.87mmol/L</strong></td>
+	</tr>
+	<tr>
+		<td>心率</td>
+		<td><strong>70</strong> </td>
+		<td>视力</td>
+		<td><strong>5.1</strong></td>
+		<td>骨密度</td>
+		<td><strong>40</strong></td>
+	</tr>
+	<!--客户基本信息(健康顾问)end-->
+
+	<!--客户健康状况(健康医生)-->
+	<tr>
+		<th colspan="6"><h3>客户健康状况(健康医生)</h3></th>
+	</tr>
+	<tr>
+		<td>药物过敏史</td>
+		<td colspan="5"><strong>青霉素</strong> </td>
+	</tr>
+	<tr>
+		<td rowspan="6">既往史</td>
+		<td rowspan="4">疾病</td>
+		<td>心脑血管</td>
+		<td colspan="3"><strong>心肌梗塞/冠心病/脑梗,心肌梗塞/冠心病/脑梗,心肌梗塞/冠心病/脑梗,心肌梗塞/冠心病/脑梗,</strong><strong>确诊时间:2022-11-11</strong> </td>
+	</tr>
+	<tr>
+		<td>呼吸系统</td>
+		<td colspan="3"><strong>冠心病/脑梗,</strong><strong>确诊时间:2022-11-11</strong> </td>
+	</tr>
+	<tr>
+		<td>消化系统</td>
+		<td colspan="3"><strong>心肌梗塞/冠心病,</strong><strong>确诊时间:2022-11-11</strong> </td>
+	</tr>
+	<tr>
+		<td>内分泌系统</td>
+		<td colspan="3"><strong>心肌梗塞/脑梗,</strong><strong>确诊时间:2022-11-11</strong> </td>
+	</tr>
+	<tr>
+		<td>手术</td>
+		<td colspan="4"><strong>无</strong> </td>
+	</tr>
+	<tr>
+		<td>外伤</td>
+		<td colspan="4"><strong>有,名称:</strong> </td>
+	</tr>
+
+	<tr>
+		<td>家族史</td>
+		<td colspan="5"><strong>青霉素</strong> </td>
+	</tr>
+	<tr>
+		<td>遗传病史</td>
+		<td colspan="5"><strong>青霉素</strong> </td>
+	</tr>
+	<tr>
+		<td>残疾情况</td>
+		<td colspan="5"><strong>青霉素</strong> </td>
+	</tr>
+	<tr>
+		<td>职业病</td>
+		<td colspan="5"><strong>无</strong> </td>
+	</tr>
+	<!--客户健康状况(健康医生)end-->
+
+	<!--客户生活方式(健康顾问)-->
+	<tr>
+		<th colspan="6"><h3>客户生活方式(健康顾问)</h3></th>
+	</tr>
+	<tr>
+		<td>兴趣爱好</td>
+		<td colspan="5"><strong>一日游、长途游、唱歌、广场舞</strong> </td>
+	</tr>
+	<tr>
+		<td>饮食情况</td>
+		<td colspan="5"><strong>荤素均衡、嗜糖</strong> </td>
+	</tr>
+
+	<tr>
+		<td rowspan="3">运动情况</td>
+		<td>运动频率</td>
+		<td colspan="4"><strong>每天</strong> </td>
+	</tr>
+	<tr>
+		<td>每次锻炼时间</td>
+		<td><strong>2</strong></td>
+		<td>坚持锻炼时间</td>
+		<td colspan="2"><strong>2</strong></td>
+	</tr>
+	<tr>
+		<td>运动类型</td>
+		<td colspan="4"><strong>每天</strong> </td>
+	</tr>
+
+	<tr>
+		<td rowspan="4">睡眠情况</td>
+		<td rowspan="2">睡眠时间</td>
+		<td colspan="4"><strong>4小时以下</strong> </td>
+	</tr>
+	<tr>
+		<td>睡觉时间</td>
+		<td><strong>21:00</strong></td>
+		<td>起床时间</td>
+		<td><strong>7:00</strong></td>
+	</tr>
+	<tr>
+		<td rowspan="2">睡眠质量</td>
+		<td colspan="4"><strong>40分钟内可以入睡</strong> </td>
+	</tr>
+	<tr>
+		<td colspan="4"><strong>夜间从不醒来</strong> </td>
+	</tr>
+
+	<tr>
+		<td rowspan="3">吸烟情况</td>
+		<td>吸烟状况</td>
+		<td colspan="4"><strong>从不吸烟</strong> </td>
+	</tr>
+	<tr>
+		<td>日吸烟量</td>
+		<td colspan="4"><strong>平均5支/天</strong> </td>
+	</tr>
+	<tr>
+		<td>开始吸烟年龄</td>
+		<td><strong>20岁</strong></td>
+		<td>戒烟年龄</td>
+		<td colspan="2"><strong>4年</strong></td>
+	</tr>
+
+	<tr>
+		<td rowspan="4">饮酒情况</td>
+		<td>饮酒频率</td>
+		<td colspan="4"><strong>从不</strong> </td>
+	</tr>
+	<tr>
+		<td>日饮酒量</td>
+		<td colspan="4"><strong>平均2两/天</strong> </td>
+	</tr>
+	<tr>
+		<td>饮酒种类</td>
+		<td colspan="4"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>开始饮酒年龄</td>
+		<td><strong>18岁</strong></td>
+		<td>近一年是否醉酒</td>
+		<td colspan="2"><strong>否</strong> </td>
+	</tr>
+	<!--客户生活方式(健康顾问)end-->
+
+	<!--健康管理计划(健康医生)-->
+	<tr>
+		<th colspan="6"><h3>健康管理计划(健康医生)</h3></th>
+	</tr>
+	<tr>
+		<td>短期目标</td>
+		<td colspan="5"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>长期目标</td>
+		<td colspan="5"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td rowspan="4">管理措施</td>
+		<td>饮食建议</td>
+		<td colspan="4"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>运动方案</td>
+		<td colspan="4"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>心里疏导</td>
+		<td colspan="4"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>复查安排</td>
+		<td colspan="4"><strong>白酒</strong> </td>
+	</tr>
+	<tr>
+		<td>健康医生</td>
+		<td colspan="5"><strong>姓名:肖晓</strong> <strong>时间:2024-11-12</strong></td>
+	</tr>
+	<!--健康管理计划(健康医生)end-->
+
+	<!--随访记录(客服)-->
+	<tr>
+		<th colspan="6"><h3>随访记录(客服)</h3></th>
+	</tr>
+	<tr>
+		<td>随访时间1</td>
+		<td><strong>2024-11-11</strong></td>
+		<td>内容及健康变化</td>
+		<td><strong>1</strong></td>
+		<td>随访人员姓名</td>
+		<td><strong>小红</strong></td>
+	</tr>
+	<tr>
+		<td>随访时间2</td>
+		<td><strong>2024-11-11</strong></td>
+		<td>内容及健康变化</td>
+		<td><strong>1</strong></td>
+		<td>随访人员姓名</td>
+		<td><strong>小红</strong></td>
+	</tr>
+
+	<tr>
+		<td>随访时间3</td>
+		<td><strong>2024-11-11</strong></td>
+		<td>内容及健康变化</td>
+		<td><strong>1</strong></td>
+		<td>随访人员姓名</td>
+		<td><strong>小红</strong></td>
+	</tr>
+	<!--随访记录(客服)end-->
+
+
+	</tbody>
+</table>
+
+</body>
+</html>

+ 27 - 0
app/common/File.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace app\common;
+
+//use Barryvdh\DomPDF\Facade\Pdf;
+use Dompdf\Dompdf;
+
+class File
+{
+    public static function exportPdf($content, $fileName)
+    {
+        $dompdf = new Dompdf();
+        $dompdf->loadHtml($content);
+        $dompdf->setPaper('A4', 'portrait');
+        $dompdf->render();
+        $pdfData = $dompdf->output();
+
+        $savePath = public_path('storage/files/') . date('Ymd') . '/pdf';
+        if (!is_dir($savePath)) {
+            mkdir($savePath,0777,true);
+        }
+        $filePath = $savePath .'/'. $fileName;
+        file_put_contents($filePath, $pdfData);
+
+        return response()->file($filePath);
+    }
+}

+ 0 - 19
app/common/Pdf.php

@@ -1,19 +0,0 @@
-<?php
-
-namespace app\common;
-
-use Barryvdh\DomPDF\PDF as PdfPackage;
-
-class Pdf
-{
-    public static function export($template, $data)
-    {
-        $pdf = new PdfPackage();
-        $pdf->loadHtml(view($template, $data)); // 假设有一个pdf/template视图文件
-
-        return $pdf;
-//        return $pdf->stream(); // 直接显示PDF
-        // 或者
-//         return $pdf->download('example.pdf'); // 下载PDF
-    }
-}

+ 159 - 0
app/functions.php

@@ -3,6 +3,8 @@
  * Here is your custom functions.
  */
 
+use support\Response;
+
 if (!function_exists('http_post')) {
     function http_post($url, $params)
     {
@@ -117,4 +119,161 @@ if (!function_exists('json_throw')) {
 
         return new \support\Response(200, ['Content-Type' => 'application/json'], json_encode($return, $options));
     }
+}
+
+if (!function_exists('json_success')) {
+    function json_success($message, $data = '', $options = JSON_UNESCAPED_UNICODE)
+    {
+        $return = [
+            'code' => 200,
+            'message' => $message,
+            'data' => $data,
+        ];
+        return new Response(200, ['Content-Type' => 'application/json'], json_encode($return, $options));
+    }
+}
+
+if (!function_exists('json_fail')) {
+    function json_fail($message, $options = JSON_UNESCAPED_UNICODE)
+    {
+        $return = [
+            'code' => 0,
+            'message' => $message,
+            'data' => ''
+        ];
+
+        return new Response(200, ['Content-Type' => 'application/json'], json_encode($return, $options));
+    }
+}
+
+if (!function_exists('format_string')) {
+    function format_string($string)
+    {
+        return htmlspecialchars(strip_tags($string));
+    }
+}
+
+if (!function_exists('random_string')) {
+    function random_string($length, $type = 'all')
+    {
+        $string = 'abcdefghijklmnopqrstuvwxyz';
+        $stringUp = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+        $number = '0123456789';
+
+        switch ($type) {
+            case 'all':
+                $result = $string . $number;
+                break;
+            case 'string':
+                $result = $string;
+                break;
+            case 'up':
+                $result = $stringUp . $number;
+                break;
+            case 'number':
+                $result = $number;
+                break;
+            default:
+                $result = '';
+                break;
+        }
+
+        $return = '';
+        $totalLength = strlen($result);
+        for ($i = 0; $i < $length; $i++) {
+            $return .= $result[mt_rand(0, $totalLength - 1)];
+        }
+
+        return $return;
+    }
+}
+
+if (!function_exists('is_json')) {
+    /**
+     * @Desc 验证是否是json数据
+     * @Author Gorden
+     * @Date 2024/2/22 15:37
+     *
+     * @param $string
+     * @return bool
+     */
+    function is_json($string)
+    {
+        if (!is_string($string)) {
+            return false;
+        }
+        json_decode($string);
+        if (json_last_error() === JSON_ERROR_NONE) {
+            return true;
+        }
+        return false;
+    }
+}
+
+if (!function_exists('chinese_week')) {
+    /**
+     * @Desc 周几-汉字
+     * @Author Gorden
+     * @Date 2024/3/5 17:29
+     *
+     * @param $week
+     * @return string
+     */
+    function chinese_week($week)
+    {
+        $weekArray = ['日', '一', '二', '三', '四', '五', '六'];
+
+        return '周' . $weekArray[$week];
+    }
+}
+
+if (!function_exists('hexToRgb')) {
+    /**
+     * @Desc 颜色值转RGB
+     * @Author Gorden
+     * @Date 2024/5/15 17:22
+     *
+     * @param $hexColor
+     * @return mixed
+     */
+    function hexToRgb($hexColor, $type = "string")
+    {
+        // 使用substr函数去掉前缀的'#'
+        $hexColor = ltrim($hexColor, '#');
+
+        // 使用hexdec函数将十六进制转换为十进制
+        $red = hexdec(substr($hexColor, 0, 2));
+        $green = hexdec(substr($hexColor, 2, 2));
+        $blue = hexdec(substr($hexColor, 4, 2));
+        if ($type == "string") {
+            // rgb(46, 209, 153)
+            return "rgb(" . $red . ", " . $green . ", " . $blue . ")";
+        }
+
+        return array('red' => $red, 'green' => $green, 'blue' => $blue);
+    }
+}
+
+
+if (!function_exists('rgbToHex')) {
+    function rgbToHex($rgb)
+    {
+        if (substr($rgb, 0, 3) == 'rgb') {
+            $rgb = str_replace("rgb(", '', $rgb);
+            $rgb = str_replace(")", "", $rgb);
+            [$red, $green, $blue] = explode(',', $rgb);
+            $hexRed = dechex($red);
+            $hexGreen = dechex($green);
+            $hexBlue = dechex($blue);
+
+            // 如果颜色分量不足两位,前面补零
+            $hexRed = strlen($hexRed) == 1 ? '0' . $hexRed : $hexRed;
+            $hexGreen = strlen($hexGreen) == 1 ? '0' . $hexGreen : $hexGreen;
+            $hexBlue = strlen($hexBlue) == 1 ? '0' . $hexBlue : $hexBlue;
+
+            return "#" . $hexRed . $hexGreen . $hexBlue;
+        }
+
+        return "";
+    }
 }

+ 0 - 10
app/view/member/archive-pdf.html

@@ -1,10 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="UTF-8">
-    <title><?= $title?></title>
-</head>
-<body>
-
-</body>
-</html>

+ 1 - 1
composer.json

@@ -47,7 +47,7 @@
     "webman/event": "^1.0",
     "endroid/qr-code": "^4.6",
     "phpoffice/phpspreadsheet": "^1.12",
-    "barryvdh/laravel-dompdf": "^2.2"
+    "dompdf/dompdf": "^2.0"
   },
   "suggest": {
     "ext-event": "For better performance. "

+ 202 - 0
load_font.php

@@ -0,0 +1,202 @@
+<?php
+// 1. [Required] Point to the composer or dompdf autoloader
+require_once "vendor/autoload.php";
+
+// 2. [Optional] Set the path to your font directory
+//    By default dompdf loads fonts to dompdf/lib/fonts
+//    If you have modified your font directory set this
+//    variable appropriately.
+//$fontDir = "lib/fonts";
+
+
+// *** DO NOT MODIFY BELOW THIS POINT ***
+
+use Dompdf\Dompdf;
+use Dompdf\CanvasFactory;
+use Dompdf\Exception;
+use Dompdf\FontMetrics;
+use Dompdf\Options;
+
+use FontLib\Font;
+
+/**
+ * Display command line usage
+ */
+function usage() {
+  echo <<<EOD
+
+Usage: {$_SERVER["argv"][0]} font_family [n_file [b_file] [i_file] [bi_file]]
+
+font_family:      the name of the font, e.g. Verdana, 'Times New Roman',
+                  monospace, sans-serif. If it equals to "system_fonts", 
+                  all the system fonts will be installed.
+
+n_file:           the .ttf or .otf file for the normal, non-bold, non-italic
+                  face of the font.
+
+{b|i|bi}_file:    the files for each of the respective (bold, italic,
+                  bold-italic) faces.
+
+If the optional b|i|bi files are not specified, load_font.php will search
+the directory containing normal font file (n_file) for additional files that
+it thinks might be the correct ones (e.g. that end in _Bold or b or B).  If
+it finds the files they will also be processed.  All files will be
+automatically copied to the DOMPDF font directory, and afm files will be
+generated using php-font-lib (https://github.com/PhenX/php-font-lib).
+
+Examples:
+
+./load_font.php silkscreen /usr/share/fonts/truetype/slkscr.ttf
+./load_font.php 'Times New Roman' /mnt/c_drive/WINDOWS/Fonts/times.ttf
+
+EOD;
+exit;
+}
+
+if ( $_SERVER["argc"] < 3 && @$_SERVER["argv"][1] != "system_fonts" ) {
+  usage();
+}
+
+$dompdf = new Dompdf();
+if (isset($fontDir) && realpath($fontDir) !== false) {
+  $dompdf->getOptions()->set('fontDir', $fontDir);
+}
+
+/**
+ * Installs a new font family
+ * This function maps a font-family name to a font.  It tries to locate the
+ * bold, italic, and bold italic versions of the font as well.  Once the
+ * files are located, ttf versions of the font are copied to the fonts
+ * directory.  Changes to the font lookup table are saved to the cache.
+ *
+ * @param Dompdf $dompdf      dompdf main object 
+ * @param string $fontname    the font-family name
+ * @param string $normal      the filename of the normal face font subtype
+ * @param string $bold        the filename of the bold face font subtype
+ * @param string $italic      the filename of the italic face font subtype
+ * @param string $bold_italic the filename of the bold italic face font subtype
+ *
+ * @throws Exception
+ */
+function install_font_family($dompdf, $fontname, $normal, $bold = null, $italic = null, $bold_italic = null) {
+  $fontMetrics = $dompdf->getFontMetrics();
+  
+  // Check if the base filename is readable
+  if ( !is_readable($normal) )
+    throw new Exception("Unable to read '$normal'.");
+
+  $dir = dirname($normal);
+  $basename = basename($normal);
+  $last_dot = strrpos($basename, '.');
+  if ($last_dot !== false) {
+    $file = substr($basename, 0, $last_dot);
+    $ext = strtolower(substr($basename, $last_dot));
+  } else {
+    $file = $basename;
+    $ext = '';
+  }
+
+  if ( !in_array($ext, array(".ttf", ".otf")) ) {
+    throw new Exception("Unable to process fonts of type '$ext'.");
+  }
+
+  // Try $file_Bold.$ext etc.
+  $path = "$dir/$file";
+  
+  $patterns = array(
+    "bold"        => array("_Bold", "b", "B", "bd", "BD"),
+    "italic"      => array("_Italic", "i", "I"),
+    "bold_italic" => array("_Bold_Italic", "bi", "BI", "ib", "IB"),
+  );
+  
+  foreach ($patterns as $type => $_patterns) {
+    if ( !isset($$type) || !is_readable($$type) ) {
+      foreach($_patterns as $_pattern) {
+        if ( is_readable("$path$_pattern$ext") ) {
+          $$type = "$path$_pattern$ext";
+          break;
+        }
+      }
+      
+      if ( is_null($$type) )
+        echo ("Unable to find $type face file.\n");
+    }
+  }
+
+  $fonts = compact("normal", "bold", "italic", "bold_italic");
+  $entry = array();
+
+  // Copy the files to the font directory.
+  foreach ($fonts as $var => $src) {
+    if ( is_null($src) ) {
+      $entry[$var] = $dompdf->getOptions()->get('fontDir') . '/' . mb_substr(basename($normal), 0, -4);
+      continue;
+    }
+
+    // Verify that the fonts exist and are readable
+    if ( !is_readable($src) )
+      throw new Exception("Requested font '$src' is not readable");
+
+    $dest = $dompdf->getOptions()->get('fontDir') . '/' . basename($src);
+
+    if ( !is_writeable(dirname($dest)) )
+      throw new Exception("Unable to write to destination '$dest'.");
+
+    echo "Copying $src to $dest...\n";
+
+    if ( !copy($src, $dest) )
+      throw new Exception("Unable to copy '$src' to '$dest'");
+    
+    $entry_name = mb_substr($dest, 0, -4);
+    
+    echo "Generating Adobe Font Metrics for $entry_name...\n";
+    
+    $font_obj = Font::load($dest);
+    $font_obj->saveAdobeFontMetrics("$entry_name.ufm");
+    $font_obj->close();
+
+    $entry[$var] = $entry_name;
+  }
+
+  // Store the fonts in the lookup table
+  $fontMetrics->setFontFamily($fontname, $entry);
+
+  // Save the changes
+  $fontMetrics->saveFontFamilies();
+}
+
+// If installing system fonts (may take a long time)
+if ( $_SERVER["argv"][1] === "system_fonts" ) {
+  $fontMetrics = $dompdf->getFontMetrics();
+  $files = glob("/usr/share/fonts/truetype/*.ttf") +
+    glob("/usr/share/fonts/truetype/*/*.ttf") +
+    glob("/usr/share/fonts/truetype/*/*/*.ttf") +
+    glob("C:\\Windows\\fonts\\*.ttf") +
+    glob("C:\\WinNT\\fonts\\*.ttf") +
+    glob("/mnt/c_drive/WINDOWS/Fonts/");
+  $fonts = array();
+  foreach ($files as $file) {
+      $font = Font::load($file);
+      $records = $font->getData("name", "records");
+      $type = $fontMetrics->getType($records[2]);
+      $fonts[mb_strtolower($records[1])][$type] = $file;
+      $font->close();
+  }
+  
+  foreach ( $fonts as $family => $files ) {
+    echo " >> Installing '$family'... \n";
+    
+    if ( !isset($files["normal"]) ) {
+      echo "No 'normal' style font file\n";
+    }
+    else {
+      install_font_family($dompdf, $family, @$files["normal"], @$files["bold"], @$files["italic"], @$files["bold_italic"]);
+      echo "Done !\n";
+    }
+    
+    echo "\n";
+  }
+}
+else {
+  call_user_func_array("install_font_family", array_merge( array($dompdf), array_slice($_SERVER["argv"], 1) ));
+}

BIN
msyh.ttf


+ 0 - 9
start.php

@@ -1,13 +1,4 @@
 #!/usr/bin/env php
 <?php
-// 允许所有域名进行访问
-header('Access-Control-Allow-Origin: *');
-// 允许的HTTP方法
-header('Access-Control-Allow-Methods: GET, POST');
-// 允许的头信息
-header('Access-Control-Allow-Headers: *');
-
-header('Access-Control-Allow-Credentials: true');
-
 require_once __DIR__ . '/vendor/autoload.php';
 support\App::run();

+ 19 - 151
support/helpers.php

@@ -73,13 +73,23 @@ function app_path(string $path = ''): string
 /**
  * Public path
  * @param string $path
+ * @param string|null $plugin
  * @return string
  */
-function public_path(string $path = ''): string
+function public_path(string $path = '', string $plugin = null): string
 {
-    static $publicPath = '';
-    if (!$publicPath) {
-        $publicPath = \config('app.public_path') ?: run_path('public');
+    static $publicPaths = [];
+    $plugin = $plugin ?? '';
+    if (isset($publicPaths[$plugin])) {
+        $publicPath = $publicPaths[$plugin];
+    } else {
+        $prefix = $plugin ? "plugin.$plugin." : '';
+        $pathPrefix = $plugin ? 'plugin' . DIRECTORY_SEPARATOR . $plugin . DIRECTORY_SEPARATOR : '';
+        $publicPath = \config("{$prefix}app.public_path", run_path("{$pathPrefix}public"));
+        if (count($publicPaths) > 32) {
+            $publicPaths = [];
+        }
+        $publicPaths[$plugin] = $publicPath;
     }
     return path_combine($publicPath, $path);
 }
@@ -142,33 +152,6 @@ function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
     return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
 }
 
-function json_success($message, $data = '', $options = JSON_UNESCAPED_UNICODE)
-{
-    $return = [
-        'code' => 200,
-        'message' => $message,
-        'data' => $data,
-    ];
-    return new Response(200, ['Content-Type' => 'application/json'], json_encode($return, $options));
-}
-
-function json_fail($message, $options = JSON_UNESCAPED_UNICODE)
-{
-    $return = [
-        'code' => 0,
-        'message' => $message,
-        'data' => ''
-    ];
-
-    return new Response(200, ['Content-Type' => 'application/json'], json_encode($return, $options));
-}
-
-function format_string($string)
-{
-    return htmlspecialchars(strip_tags($string));
-}
-
-
 /**
  * Xml response
  * @param $xml
@@ -271,9 +254,6 @@ function think_view(string $template, array $vars = [], string $app = null): Res
  * @param array $vars
  * @param string|null $app
  * @return Response
- * @throws LoaderError
- * @throws RuntimeError
- * @throws SyntaxError
  */
 function twig_view(string $template, array $vars = [], string $app = null): Response
 {
@@ -537,7 +517,11 @@ function cpu_count(): int
         if (strtolower(PHP_OS) === 'darwin') {
             $count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
         } else {
-            $count = (int)shell_exec('nproc');
+            try {
+                $count = (int)shell_exec('nproc');
+            } catch (\Throwable $ex) {
+                // Do nothing
+            }
         }
     }
     return $count > 0 ? $count : 4;
@@ -553,119 +537,3 @@ function input(string $param = null, $default = null)
 {
     return is_null($param) ? request()->all() : request()->input($param, $default);
 }
-
-function random_string($length, $type = 'all')
-{
-    $string = 'abcdefghijklmnopqrstuvwxyz';
-    $stringUp = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-    $number = '0123456789';
-
-    switch ($type) {
-        case 'all':
-            $result = $string . $number;
-            break;
-        case 'string':
-            $result = $string;
-            break;
-        case 'up':
-            $result = $stringUp . $number;
-            break;
-        case 'number':
-            $result = $number;
-            break;
-        default:
-            $result = '';
-            break;
-    }
-
-    $return = '';
-    $totalLength = strlen($result);
-    for ($i = 0; $i < $length; $i++) {
-        $return .= $result[mt_rand(0, $totalLength - 1)];
-    }
-
-    return $return;
-}
-
-/**
- * @Desc 验证是否是json数据
- * @Author Gorden
- * @Date 2024/2/22 15:37
- *
- * @param $string
- * @return bool
- */
-function is_json($string)
-{
-    if (!is_string($string)) {
-        return false;
-    }
-    json_decode($string);
-    if (json_last_error() === JSON_ERROR_NONE) {
-        return true;
-    }
-    return false;
-}
-
-
-/**
- * @Desc 周几-汉字
- * @Author Gorden
- * @Date 2024/3/5 17:29
- *
- * @param $week
- * @return string
- */
-function chinese_week($week)
-{
-    $weekArray = ['日', '一', '二', '三', '四', '五', '六'];
-
-    return '周' . $weekArray[$week];
-}
-
-
-/**
- * @Desc 颜色值转RGB
- * @Author Gorden
- * @Date 2024/5/15 17:22
- *
- * @param $hexColor
- * @return mixed
- */
-function hexToRgb($hexColor, $type = "string")
-{
-    // 使用substr函数去掉前缀的'#'
-    $hexColor = ltrim($hexColor, '#');
-
-    // 使用hexdec函数将十六进制转换为十进制
-    $red = hexdec(substr($hexColor, 0, 2));
-    $green = hexdec(substr($hexColor, 2, 2));
-    $blue = hexdec(substr($hexColor, 4, 2));
-    if ($type == "string") {
-        // rgb(46, 209, 153)
-        return "rgb(" . $red . ", " . $green . ", " . $blue . ")";
-    }
-
-    return array('red' => $red, 'green' => $green, 'blue' => $blue);
-}
-
-function rgbToHex($rgb)
-{
-    if (substr($rgb, 0, 3) == 'rgb') {
-        $rgb = str_replace("rgb(", '', $rgb);
-        $rgb = str_replace(")", "", $rgb);
-        [$red, $green, $blue] = explode(',', $rgb);
-        $hexRed = dechex($red);
-        $hexGreen = dechex($green);
-        $hexBlue = dechex($blue);
-
-        // 如果颜色分量不足两位,前面补零
-        $hexRed = strlen($hexRed) == 1 ? '0' . $hexRed : $hexRed;
-        $hexGreen = strlen($hexGreen) == 1 ? '0' . $hexGreen : $hexGreen;
-        $hexBlue = strlen($hexBlue) == 1 ? '0' . $hexBlue : $hexBlue;
-
-        return "#" . $hexRed. $hexGreen. $hexBlue;
-    }
-
-    return "";
-}

+ 5 - 3
webman

@@ -27,9 +27,11 @@ if (is_dir($command_path = Util::guessPath(app_path(), '/command', true))) {
 
 foreach (config('plugin', []) as $firm => $projects) {
     if (isset($projects['app'])) {
-        if ($command_str = Util::guessPath(base_path() . "/plugin/$firm", 'command')) {
-            $command_path = base_path() . "/plugin/$firm/$command_str";
-            $cli->installCommands($command_path, "plugin\\$firm\\$command_str");
+        foreach (['', '/app'] as $app) {
+            if ($command_str = Util::guessPath(base_path() . "/plugin/$firm{$app}", 'command')) {
+                $command_path = base_path() . "/plugin/$firm{$app}/$command_str";
+                $cli->installCommands($command_path, "plugin\\$firm" . str_replace('/', '\\', $app) . "\\$command_str");
+            }
         }
     }
     foreach ($projects as $name => $project) {