251 lines
7.7 KiB
PHP
251 lines
7.7 KiB
PHP
<?php
|
|
|
|
namespace app\api\logic\tcm;
|
|
|
|
use app\common\model\tcm\DailyFamilyLike;
|
|
use app\common\model\tcm\DailyShareInvite;
|
|
|
|
/**
|
|
* 家人点赞(邀请观看页 → 患者日常页展示)
|
|
*/
|
|
class DailyFamilyLikeLogic
|
|
{
|
|
protected static string $error = '';
|
|
|
|
/** @var string[] */
|
|
protected static array $praisePool = [
|
|
'坚持得很好,为您点赞!',
|
|
'每天记录真棒,继续保持!',
|
|
'您的自律让人佩服!',
|
|
'加油,家人一直支持您!',
|
|
'稳糖路上,您并不孤单!',
|
|
'好习惯正在养成,真为您高兴!',
|
|
];
|
|
|
|
public static function getError(): string
|
|
{
|
|
return self::$error;
|
|
}
|
|
|
|
protected static function setError(string $msg): bool
|
|
{
|
|
self::$error = $msg;
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 校验当日邀请码
|
|
*
|
|
* @return array{diagnosis_id:int,invite_code:string}|false
|
|
*/
|
|
protected static function resolveInvite(string $inviteCode): array|false
|
|
{
|
|
$inviteCode = strtoupper(trim($inviteCode));
|
|
if ($inviteCode === '') {
|
|
return self::setError('邀请码不能为空') ? false : false;
|
|
}
|
|
|
|
$row = DailyShareInvite::where('invite_code', $inviteCode)->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;
|
|
}
|
|
|
|
$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);
|
|
}
|
|
}
|