checkLogin(); // 接收参数 $courseId = request('course_id', 0); $fontPath = public_path() . '/fonts/msyh14.ttf'; // 指定字体文件路径 //学习课程名称 $courseName = $courseModel->query()->where([['id', '=', $courseId]])->value('name'); $courseName = str_replace(' ', '', $courseName); //去除课程名称中的空格 //获取总积分(客户) $totalScore = $examRecordModel->query()->where([['course_id', '=', $courseId], ['custom_uid', '=', $uid]])->sum('get_score'); try { // 加载图片 $image = Image::make(public_path('uploads/images/default/') . 'learn_report_share_base.png'); $lineHeight = 30; // 行高 $fontSize = 24; $maxWidth = 330; // 课程名称过长的时候需要截断 $lines = $this->truncateText($courseName, $fontPath, $fontSize, $maxWidth); $y = 170; // 初始 y 坐标 // 处理数据 foreach ($lines as $line) { $image->text($line, 30, $y, function ($font) use ($fontPath, $fontSize) { $font->file($fontPath); $font->size($fontSize); $font->color('#2B3D7c'); $font->align('left'); }); $y += $lineHeight; // 下一行的 y 坐标 } // 给图片写入文字(总积分) $image->text($totalScore, 90, 310, function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(30); // 字体大小 $font->color('#E86D8F'); $font->align('center'); }); // 基础路径 $basepath = 'images/video_report_exam/'.date('Ymd').'/'; // 保存路径 $path = public_path('uploads/'.$basepath); // 如果路劲不存在 if (!is_dir($path)) mkdir($path, 0755, true); // 路径组合 $filename = $courseId.'_'.$uid.'.jpg'; // 保存图片 $image->encode('jpg', 90)->save($path.$filename); // 下发路径 $path = path_compat($basepath.$filename); // 返回路径 return json_send(['code' => 'success', 'msg' => '生成成功', 'data' => ['image_url' => $path.'?t='.time(),'title'=>$courseName]]); } catch (\Throwable $th) { // 返回 return json_send(['code' => 'error', 'msg' => $th->getMessage()]); } } //获取课后分析的答题数量 public function get_after_study_report_image_share(ExamRecord $examRecordModel) { // 登录信息 $uid = $this->checkLogin(); // 接收参数 $courseId = request('course_id', 0); $recordId = request('record_id', 0); $url = request('page', 'pages/video/record'); $size = request('size', 150); $scene = request('scene', ''); $position = 'bottom-left'; $fontPath = public_path() . '/fonts/msyh14.ttf'; // 指定字体文件路径 //获取总积分(客户) $reportData = $examRecordModel->query()->where([['id','=',$recordId]])->first(['question_total','isanswer_total']); // 如果没有数据 if( !$reportData ) return json_send(['code' => 'error', 'msg' => '没有答题记录']); // 返回结果 $totalQuestionNum = $reportData['question_total']; $correctNum = $reportData['isanswer_total']; $inCorrectNum = $totalQuestionNum - $correctNum; $accuracy = $totalQuestionNum ? ($correctNum / $totalQuestionNum) * 100 : 100; $accuracy = $accuracy < 100 ? number_format($accuracy, 1) : 100; try { // 加载图片 $image = Image::make(public_path('uploads/images/default/') . 'analysis_report_share_base.png'); // 生成小程序二维码 $qrcode = Mini::getUnlimit($scene, ['page' => $url, 'width' => $size, 'is_hyaline' => true]); // 错误提示 if (isset($qrcode['error'])) return json_send(['code' => 'error', 'msg' => $qrcode['error']]); // 加载图片 压缩 $qrcode = $size < 280 ? Image::make($qrcode)->resize($size, $size) : Image::make($qrcode); $image->insert($qrcode, $position, 20, 20); // 给图片写入文字总题数: $image->text($totalQuestionNum . '题', 260, 300, function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(24); // 字体大小 $font->color('#FF7B01'); $font->align('left'); }); // 给图片写入文字正确题数 $image->text($correctNum . '题', 290, 388, function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(24); // 字体大小 $font->color('#0E670F'); $font->align('left'); }); // 给图片写入文字错误题数 $image->text($inCorrectNum . '题', 290, 476, function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(24); // 字体大小 $font->color('#FF0101'); $font->align('left'); }); // 给图片写入文字(正确率) $image->text($accuracy . '%', 100, 582, function (Font $font) use ($fontPath) { $font->file($fontPath); // 字体文件地址 $font->size(36); // 字体大小 $font->color('#FA9517'); $font->align('left'); }); //插入二维码图片 $image = $image->encode('jpg', 90)->__toString(); // 转base64 $base64 = 'data:image/jpg;base64,' . base64_encode($image); // 返回 return json_send(['code' => 'success', 'msg' => '生成成功', 'data' => ['base64_image' => $base64]]); } catch (\Throwable $th) { dd($th); // 返回 return json_send(['code' => 'error', 'msg' => $th->getMessage()]); } } // 截断文字并添加省略号 function truncateText($text, $fontFile, $fontSize, $maxWidth) { $lines = []; $textLength = mb_strlen($text); $charIndex = 0; // 第一行 $firstLine = ''; while ($charIndex < $textLength) { $firstLine .= mb_substr($text, $charIndex, 1); $testBox = imagettfbbox($fontSize, 0, $fontFile, $firstLine); $testWidth = abs($testBox[2] - $testBox[0]); if ($testWidth > $maxWidth) { // 第一行超出宽度,截断 $firstLine = mb_substr($firstLine, 0, -1); break; } $charIndex++; } // 第一行没有超出宽度,直接添加到结果中 $lines[] = $firstLine; // 第二行 if ($charIndex < $textLength) { $secondLine = mb_substr($text, $charIndex); $testBox = imagettfbbox($fontSize, 0, $fontFile, $secondLine); $testWidth = abs($testBox[2] - $testBox[0]); if ($testWidth > $maxWidth) { // 第二行超出宽度,截断并添加省略号 while ($charIndex < $textLength) { $secondLine = mb_substr($secondLine, 0, -1); $testBox = imagettfbbox($fontSize, 0, $fontFile, $secondLine); $testWidth = abs($testBox[2] - $testBox[0]); if ($testWidth <= $maxWidth) { $secondLine .= '...'; break; } } } $lines[] = $secondLine; } return $lines; } }