where('student_id', $studentId) ->field('id,student_id,height,weight,physical_test_report,created_at,updated_at') ->order('created_at desc') ->page($page, $limit) ->select() ->toArray(); // 处理数据 foreach ($list as &$item) { $item['test_date'] = date('Y-m-d', strtotime($item['created_at'])); $item['height_text'] = $item['height'] . 'cm'; $item['weight_text'] = $item['weight'] . 'kg'; // 处理体测报告PDF文件 $item['has_report'] = !empty($item['physical_test_report']); $item['report_files'] = []; if ($item['physical_test_report']) { $files = explode(',', $item['physical_test_report']); foreach ($files as $file) { if ($file) { $item['report_files'][] = [ 'name' => '体测报告', 'url' => get_image_url($file), 'path' => $file ]; } } } } $total = (new PhysicalTest())->where('student_id', $studentId)->count(); return [ 'list' => $list, 'total' => $total, 'page' => $page, 'limit' => $limit, 'pages' => ceil($total / $limit) ]; } /** * 获取体测详情 * @param int $testId * @return array */ public function getPhysicalTestDetail($testId) { $physicalTest = (new PhysicalTest())->where('id', $testId)->find(); if (!$physicalTest) { throw new CommonException('体测记录不存在'); } $data = $physicalTest->toArray(); // 格式化数据 $data['test_date'] = date('Y-m-d', strtotime($data['created_at'])); $data['height_text'] = $data['height'] . 'cm'; $data['weight_text'] = $data['weight'] . 'kg'; // 处理各项体测指标 $indicators = [ 'seated_forward_bend' => ['name' => '坐位体前屈', 'unit' => 'cm'], 'sit_ups' => ['name' => '仰卧卷腹', 'unit' => '次'], 'push_ups' => ['name' => '九十度仰卧撑', 'unit' => '次'], 'flamingo_balance' => ['name' => '火烈鸟平衡测试', 'unit' => 's'], 'thirty_sec_jump' => ['name' => '三十秒双脚连续跳', 'unit' => '次'], 'standing_long_jump' => ['name' => '立定跳远', 'unit' => 'cm'], 'agility_run' => ['name' => '4乘10m灵敏折返跑', 'unit' => 's'], 'balance_beam' => ['name' => '走平衡木', 'unit' => 's'], 'tennis_throw' => ['name' => '网球掷远', 'unit' => 'm'], 'ten_meter_shuttle_run' => ['name' => '十米往返跑', 'unit' => 's'] ]; $data['indicators'] = []; foreach ($indicators as $key => $info) { if ($data[$key] !== null && $data[$key] !== '') { $data['indicators'][] = [ 'name' => $info['name'], 'value' => $data[$key], 'unit' => $info['unit'], 'value_text' => $data[$key] . $info['unit'] ]; } } // 处理体测报告文件 $data['report_files'] = []; if ($data['physical_test_report']) { $files = explode(',', $data['physical_test_report']); foreach ($files as $file) { if ($file) { $data['report_files'][] = [ 'name' => '体测报告', 'url' => get_image_url($file), 'path' => $file, 'type' => 'pdf' ]; } } } return $data; } /** * 获取体测趋势数据(身高体重变化) * @param array $data * @return array */ public function getPhysicalTestTrend($data) { $studentId = $data['student_id']; $months = $data['months'] ?? 12; // 获取指定月份内的体测数据 $startDate = date('Y-m-d', strtotime("-{$months} months")); $trendData = (new PhysicalTest()) ->where('student_id', $studentId) ->where('created_at', '>=', $startDate) ->field('height,weight,created_at') ->order('created_at asc') ->select() ->toArray(); $heightData = []; $weightData = []; $dates = []; foreach ($trendData as $item) { $date = date('Y-m', strtotime($item['created_at'])); $dates[] = $date; $heightData[] = [ 'date' => $date, 'value' => (float)$item['height'] ]; $weightData[] = [ 'date' => $date, 'value' => (float)$item['weight'] ]; } // 计算增长情况 $heightGrowth = 0; $weightGrowth = 0; if (count($heightData) >= 2) { $heightGrowth = end($heightData)['value'] - $heightData[0]['value']; $weightGrowth = end($weightData)['value'] - $weightData[0]['value']; } return [ 'height_data' => $heightData, 'weight_data' => $weightData, 'dates' => array_unique($dates), 'growth' => [ 'height' => round($heightGrowth, 1), 'weight' => round($weightGrowth, 1), 'height_text' => ($heightGrowth >= 0 ? '+' : '') . round($heightGrowth, 1) . 'cm', 'weight_text' => ($weightGrowth >= 0 ? '+' : '') . round($weightGrowth, 1) . 'kg' ], 'data_count' => count($trendData), 'months' => $months ]; } /** * PDF转图片分享 * @param int $testId * @return array */ public function convertPdfToImage($testId) { $physicalTest = (new PhysicalTest())->where('id', $testId)->find(); if (!$physicalTest) { throw new CommonException('体测记录不存在'); } // 获取第一个PDF文件 $files = explode(',', $physicalTest['physical_test_report']); $pdfFile = trim($files[0]); if (!$pdfFile) { throw new CommonException('PDF文件路径无效'); } // 构建完整文件路径 $pdfPath = public_path() . $pdfFile; if (!file_exists($pdfPath)) { throw new CommonException('PDF文件不存在'); } try { // 使用Imagick将PDF转换为图片 if (!extension_loaded('imagick')) { throw new CommonException('系统不支持PDF转图片功能'); } $imagick = new \Imagick(); $imagick->setResolution(150, 150); $imagick->readImage($pdfPath . '[0]'); // 只转换第一页 $imagick->setImageFormat('jpeg'); $imagick->setImageCompressionQuality(85); // 生成图片文件名 $imageName = 'physical_test_' . $testId . '_' . time() . '.jpg'; $imagePath = 'uploads/share/' . date('Y/m/d') . '/' . $imageName; $fullImagePath = public_path() . $imagePath; // 确保目录存在 $dir = dirname($fullImagePath); if (!is_dir($dir)) { mkdir($dir, 0755, true); } // 保存图片 $imagick->writeImage($fullImagePath); $imagick->clear(); $imagick->destroy(); return [ 'image_url' => get_image_url($imagePath), 'image_path' => $imagePath, 'pdf_url' => get_image_url($pdfFile), 'message' => 'PDF转换为图片成功,可以分享给朋友了' ]; } catch (\Exception $e) { throw new CommonException('PDF转图片失败:' . $e->getMessage()); } } }