find(); if (!$row) { return self::setError('邀请码无效或已失效') ? false : false; } $today = date('Y-m-d'); if ((string) $row['invite_date'] !== $today) { return self::setError('邀请码已过期,仅可在分享当天点赞') ? false : false; } return [ 'diagnosis_id' => (int) $row['diagnosis_id'], 'invite_code' => $inviteCode, ]; } protected static function normalizeViewerKey(string $viewerKey): string { $viewerKey = preg_replace('/[^\w\-]/', '', trim($viewerKey)) ?? ''; if (strlen($viewerKey) < 8) { return ''; } return substr($viewerKey, 0, 64); } protected static function normalizeNickname(string $nickname): string { $nickname = trim($nickname); if ($nickname === '') { return '家人'; } $nickname = mb_substr($nickname, 0, 8, 'UTF-8'); return $nickname !== '' ? $nickname : '家人'; } public static function countToday(int $diagnosisId, ?string $likeDate = null): int { $likeDate = $likeDate ?: date('Y-m-d'); return (int) DailyFamilyLike::where('diagnosis_id', $diagnosisId) ->where('like_date', $likeDate) ->count(); } public static function likedByViewer(int $diagnosisId, string $viewerKey, ?string $likeDate = null): bool { $viewerKey = self::normalizeViewerKey($viewerKey); if ($viewerKey === '') { return false; } $likeDate = $likeDate ?: date('Y-m-d'); return DailyFamilyLike::where('diagnosis_id', $diagnosisId) ->where('like_date', $likeDate) ->where('viewer_key', $viewerKey) ->find() !== null; } /** * 邀请预览附加点赞信息 */ public static function metaForInvite(string $inviteCode, string $viewerKey = ''): array { $resolved = self::resolveInvite($inviteCode); if ($resolved === false) { return [ 'like_count' => 0, 'liked_by_me' => false, ]; } $diagnosisId = $resolved['diagnosis_id']; $viewerKey = self::normalizeViewerKey($viewerKey); return [ 'like_count' => self::countToday($diagnosisId), 'liked_by_me' => $viewerKey !== '' && self::likedByViewer($diagnosisId, $viewerKey), ]; } /** * 家人点赞(无需登录) */ public static function addLike(string $inviteCode, string $viewerKey, string $nickname = ''): array|false { self::$error = ''; $resolved = self::resolveInvite($inviteCode); if ($resolved === false) { return false; } $viewerKey = self::normalizeViewerKey($viewerKey); if ($viewerKey === '') { return self::setError('设备标识无效,请重试') ? false : false; } $diagnosisId = $resolved['diagnosis_id']; $likeDate = date('Y-m-d'); $nickname = self::normalizeNickname($nickname); $exists = DailyFamilyLike::where('diagnosis_id', $diagnosisId) ->where('like_date', $likeDate) ->where('viewer_key', $viewerKey) ->find(); if ($exists) { return [ 'already_liked' => true, 'like_count' => self::countToday($diagnosisId, $likeDate), 'praise_message' => '您今天已经点过赞啦,谢谢您的鼓励', 'nickname' => (string) ($exists['nickname'] ?? '家人'), ]; } $todayCount = self::countToday($diagnosisId, $likeDate); if ($todayCount >= 50) { return self::setError('今日点赞已满,明天再来吧') ? false : false; } DailyFamilyLike::create([ 'diagnosis_id' => $diagnosisId, 'like_date' => $likeDate, 'invite_code' => $resolved['invite_code'], 'viewer_key' => $viewerKey, 'nickname' => $nickname, 'create_time' => time(), ]); $likeCount = self::countToday($diagnosisId, $likeDate); $idx = $likeCount > 0 ? ($likeCount - 1) % count(self::$praisePool) : 0; return [ 'already_liked' => false, 'like_count' => $likeCount, 'praise_message' => self::$praisePool[$idx], 'nickname' => $nickname, ]; } /** * 患者查看今日家人点赞(需登录且拥有诊单) */ public static function summaryForPatient(int $userId, int $diagnosisId): array|false { self::$error = ''; if ($userId <= 0) { return self::setError('请先登录') ? false : false; } if ($diagnosisId <= 0) { return self::setError('诊单ID不能为空') ? false : false; } $owned = \think\facade\Db::name('diagnosis_view_records') ->where('user_id', $userId) ->where('diagnosis_id', $diagnosisId) ->where('delete_time', null) ->find(); if (!$owned) { return self::setError('无权查看该诊单') ? false : false; } $diagnosis = Diagnosis::where('id', $diagnosisId)->where('delete_time', null)->field('show_card')->find(); if (!$diagnosis || (int) ($diagnosis['show_card'] ?? 1) !== 1) { return self::setError('该就诊卡已在统计端隐藏') ? false : false; } $likeDate = date('Y-m-d'); $count = self::countToday($diagnosisId, $likeDate); $rows = DailyFamilyLike::where('diagnosis_id', $diagnosisId) ->where('like_date', $likeDate) ->order('id', 'desc') ->limit(8) ->select() ->toArray(); $recent = []; foreach ($rows as $r) { $recent[] = [ 'nickname' => (string) ($r['nickname'] ?? '家人'), 'time_label' => self::timeLabel((int) ($r['create_time'] ?? 0)), ]; } $summaryLine = $count > 0 ? "今日有 {$count} 位家人为您点赞,继续加油!" : '分享战报给家人,邀请他们为您点赞鼓劲'; return [ 'like_count' => $count, 'summary_line' => $summaryLine, 'recent' => $recent, ]; } protected static function timeLabel(int $ts): string { if ($ts <= 0) { return '刚刚'; } $diff = time() - $ts; if ($diff < 60) { return '刚刚'; } if ($diff < 3600) { return (int) floor($diff / 60) . '分钟前'; } return date('H:i', $ts); } }