BodyProfileService.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <?php
  2. namespace app\common\Service;
  3. use app\common\model\BodyProfile;
  4. use app\common\model\BodyMeasurements;
  5. use app\common\model\BodyTypeSelection;
  6. use app\common\model\BodyAiReport;
  7. use think\Db;
  8. use app\common\exception\BusinessException;
  9. /**
  10. * 身体档案服务类
  11. */
  12. class BodyProfileService
  13. {
  14. /**
  15. * 创建身体档案
  16. */
  17. public static function createProfile($data)
  18. {
  19. // 处理身体照片
  20. if (isset($data['body_photos']) && is_array($data['body_photos'])) {
  21. $data['body_photos'] = json_encode($data['body_photos']);
  22. }
  23. Db::startTrans();
  24. try {
  25. $profile = new BodyProfile();
  26. $result = $profile->save($data);
  27. if ($result === false) {
  28. throw new BusinessException($profile->getError() ?: '创建档案失败');
  29. }
  30. Db::commit();
  31. return $profile;
  32. } catch (\Throwable $e) {
  33. Db::rollback();
  34. throw new BusinessException($e->getMessage());
  35. }
  36. }
  37. /**
  38. * 更新身体档案
  39. */
  40. public static function updateProfile($profileId, $userId, $data)
  41. {
  42. $profile = BodyProfile::where('id', $profileId)
  43. ->where('user_id', $userId)
  44. ->find();
  45. if (!$profile) {
  46. throw new BusinessException('档案不存在');
  47. }
  48. // 处理身体照片
  49. if (isset($data['body_photos']) && is_array($data['body_photos'])) {
  50. $data['body_photos'] = json_encode($data['body_photos']);
  51. }
  52. Db::startTrans();
  53. try {
  54. $result = $profile->save($data);
  55. if ($result === false) {
  56. throw new BusinessException($profile->getError() ?: '更新档案失败');
  57. }
  58. Db::commit();
  59. return $profile;
  60. } catch (\Throwable $e) {
  61. Db::rollback();
  62. throw new BusinessException($e->getMessage());
  63. }
  64. }
  65. /**
  66. * 删除身体档案
  67. */
  68. public static function deleteProfile($profileId, $userId)
  69. {
  70. $profile = BodyProfile::where('id', $profileId)
  71. ->where('user_id', $userId)
  72. ->find();
  73. if (!$profile) {
  74. throw new BusinessException('档案不存在');
  75. }
  76. Db::startTrans();
  77. try {
  78. // 删除相关数据
  79. BodyMeasurements::where('profile_id', $profileId)->delete();
  80. BodyTypeSelection::where('profile_id', $profileId)->delete();
  81. BodyAiReport::where('profile_id', $profileId)->delete();
  82. // 删除档案
  83. $profile->delete();
  84. Db::commit();
  85. return true;
  86. } catch (\Throwable $e) {
  87. Db::rollback();
  88. throw new BusinessException($e->getMessage());
  89. }
  90. }
  91. /**
  92. * 获取用户档案列表
  93. */
  94. public static function getUserProfiles($userId)
  95. {
  96. $profiles = BodyProfile::where('user_id', $userId)
  97. ->with(['latestMeasurement', 'latestAiReport'])
  98. ->order('is_own DESC, id DESC')
  99. ->select();
  100. $result = [];
  101. foreach ($profiles as $profile) {
  102. $data = $profile->toArray();
  103. $data['bmi'] = $profile->calculateBMI();
  104. $data['bmi_level'] = $profile->getBMILevel();
  105. $result[] = $data;
  106. }
  107. return $result;
  108. }
  109. /**
  110. * 获取档案详情
  111. */
  112. public static function getProfileDetail($profileId, $userId)
  113. {
  114. $profile = BodyProfile::where('id', $profileId)
  115. ->where('user_id', $userId)
  116. ->find();
  117. if (!$profile) {
  118. throw new BusinessException('档案不存在');
  119. }
  120. return $profile->getFullProfileData();
  121. }
  122. /**
  123. * 添加测量数据
  124. */
  125. public static function addMeasurement($profileId, $userId, $measurementData)
  126. {
  127. // 验证档案归属
  128. $profile = BodyProfile::where('id', $profileId)
  129. ->where('user_id', $userId)
  130. ->find();
  131. if (!$profile) {
  132. throw new BusinessException('档案不存在');
  133. }
  134. // 过滤测量数据字段
  135. $measurementFields = array_keys(BodyMeasurements::getMeasurementFields($profile->gender));
  136. $filteredData = ['profile_id' => $profileId];
  137. foreach ($measurementFields as $field) {
  138. if (isset($measurementData[$field]) && $measurementData[$field] !== '') {
  139. $filteredData[$field] = floatval($measurementData[$field]);
  140. }
  141. }
  142. // 设置测量日期
  143. if (isset($measurementData['measurement_date']) && $measurementData['measurement_date']) {
  144. $filteredData['measurement_date'] = strtotime($measurementData['measurement_date']);
  145. } else {
  146. $filteredData['measurement_date'] = time();
  147. }
  148. $measurement = new BodyMeasurements();
  149. $result = $measurement->save($filteredData);
  150. if ($result === false) {
  151. throw new BusinessException($measurement->getError() ?: '添加测量数据失败');
  152. }
  153. return $measurement;
  154. }
  155. /**
  156. * 获取测量历史
  157. */
  158. public static function getMeasurementHistory($profileId, $userId, $page = 1, $limit = 10)
  159. {
  160. // 验证档案归属
  161. $profile = BodyProfile::where('id', $profileId)
  162. ->where('user_id', $userId)
  163. ->find();
  164. if (!$profile) {
  165. throw new BusinessException('档案不存在');
  166. }
  167. $list = BodyMeasurements::where('profile_id', $profileId)
  168. ->order('measurement_date DESC')
  169. ->paginate($limit, false, ['page' => $page]);
  170. return [
  171. 'list' => $list->items(),
  172. 'total' => $list->total(),
  173. 'page' => $page,
  174. 'limit' => $limit
  175. ];
  176. }
  177. /**
  178. * 保存体型选择
  179. */
  180. public static function saveBodyTypeSelection($profileId, $userId, $selections)
  181. {
  182. // 验证档案归属
  183. $profile = BodyProfile::where('id', $profileId)
  184. ->where('user_id', $userId)
  185. ->find();
  186. if (!$profile) {
  187. throw new BusinessException('档案不存在');
  188. }
  189. $result = BodyTypeSelection::saveUserSelections($profileId, $selections);
  190. if (!$result) {
  191. throw new BusinessException('保存体型选择失败');
  192. }
  193. return true;
  194. }
  195. /**
  196. * 获取体型推荐
  197. */
  198. public static function getBodyTypeRecommendation($profileId, $userId)
  199. {
  200. // 验证档案归属
  201. $profile = BodyProfile::where('id', $profileId)
  202. ->where('user_id', $userId)
  203. ->with(['latestMeasurement'])
  204. ->find();
  205. if (!$profile) {
  206. throw new BusinessException('档案不存在');
  207. }
  208. if (!$profile->latestMeasurement) {
  209. throw new BusinessException('请先添加身体测量数据');
  210. }
  211. return BodyTypeService::getSmartRecommendation($profileId, $profile->latestMeasurement);
  212. }
  213. /**
  214. * 生成AI测试报告
  215. */
  216. public static function generateAiReport($profileId, $userId, $reportType = 'comprehensive')
  217. {
  218. // 验证档案归属
  219. $profile = BodyProfile::where('id', $profileId)
  220. ->where('user_id', $userId)
  221. ->find();
  222. if (!$profile) {
  223. throw new BusinessException('档案不存在');
  224. }
  225. $report = BodyAiReport::generateReport($profileId, $reportType);
  226. if (!$report) {
  227. throw new BusinessException('生成报告失败,请确保已填写完整的身体数据');
  228. }
  229. return $report;
  230. }
  231. /**
  232. * 获取AI报告详情
  233. */
  234. public static function getAiReport($reportId, $userId)
  235. {
  236. $report = BodyAiReport::with(['profile'])
  237. ->where('id', $reportId)
  238. ->find();
  239. if (!$report || $report->profile->user_id != $userId) {
  240. throw new BusinessException('报告不存在');
  241. }
  242. return $report;
  243. }
  244. /**
  245. * 获取AI报告列表
  246. */
  247. public static function getAiReportList($profileId, $userId, $page = 1, $limit = 10)
  248. {
  249. // 验证档案归属
  250. $profile = BodyProfile::where('id', $profileId)
  251. ->where('user_id', $userId)
  252. ->find();
  253. if (!$profile) {
  254. throw new BusinessException('档案不存在');
  255. }
  256. $list = BodyAiReport::where('profile_id', $profileId)
  257. ->order('generated_time DESC')
  258. ->paginate($limit, false, ['page' => $page]);
  259. return [
  260. 'list' => $list->items(),
  261. 'total' => $list->total(),
  262. 'page' => $page,
  263. 'limit' => $limit
  264. ];
  265. }
  266. /**
  267. * 获取体型选择建议报告
  268. */
  269. public static function getSelectionReport($profileId, $userId)
  270. {
  271. // 验证档案归属
  272. $profile = BodyProfile::where('id', $profileId)
  273. ->where('user_id', $userId)
  274. ->find();
  275. if (!$profile) {
  276. throw new BusinessException('档案不存在');
  277. }
  278. return BodyTypeService::generateSelectionReport($profileId);
  279. }
  280. }