$cid, 'record_chapter_name' => $name]; } return false; } /** * 删除最近阅读记录 * @param int $uid * @param array $bids */ public static function delReadRecordStatic(int $uid, array $bids) { $key = 'book_read:' . $uid; $last_record = explode('_', Redis::hGet($key, 'last_read')); $last_record_bid = $last_record[0]; $is_del_last = false; foreach ($bids as $bid) { if ($bid == $last_record_bid) { $is_del_last = true; } Redis::hDel($key, $bid); } if ($is_del_last) { self::reSetLastRecord($uid); } } /** * 重置用户最近阅读记录 * @param int $uid */ public static function reSetLastRecord($uid) { $key = 'book_read:' . $uid; $alls = Redis::hGetAll($key); $has_record = false; $last_timestamp = 0; $last_record = ''; foreach ($alls as $k => $v) { if (is_numeric($k)) { $has_record = true; $record = explode('_', $v); $timestamp = $record[1]; if ($last_timestamp < $timestamp) { $last_record = $k . '_' . $v; $last_timestamp = $timestamp; } } } if ($last_record) { Redis::hSet($key, 'last_read', $last_record); } if (!$has_record) { Redis::hDel($key, 'last_read'); } } //阅读记录数 const RECORD_COUNT = 50; private static $not_uid_key = ['last_read', 'send_order_id', 'sign_count', 'sign_counts', 'sign_info', 'sign_day', 'smart_push', 'inner_send_order_id', 'gxhp', 'property', 'bind_phone_status', 'ua', 'sign_version', 'new_outer', 'new_inner', 'new_total', 'next_push_hour', 'person_account_id','soid_time']; /** * 获取 升级版 * @param $uid * @return array */ public static function getReadRecord($uid) { self::delTheLastRecord($uid); $read_bids = Redis::hgetall('book_read:' . $uid); $res = []; $i = 0; foreach ($read_bids as $key => $v) { if (in_array($key, self::$not_uid_key)) { continue; } $record = explode('_', $v); $latest_read_cid = $record[0]; $latest_read_time = $record[count($record) - 1]; $channel_name = ''; $book_name = self::bid2BookName($key,$channel_name); $change_chapter_name = 0; list($is_split,$is_change_chapter_name) = BookService::splitContent($key); if($is_split && ($channel_name == '男频' || $is_change_chapter_name) ){ $change_chapter_name = 1; } $chapter_name = self::cid2ChapterName($latest_read_cid,$change_chapter_name); $res[$i] = ['book_name' => $book_name, 'bid' => $key, 'cid' => (int)$latest_read_cid, 'time' => (int)$latest_read_time, 'chapter_name' => $chapter_name]; $i++; } usort($res, function ($a, $b) { if ($a['time'] >= $b['time']) return -1; return 1; }); return collect($res)->sortByDesc('time')->values()->all(); } /** * 添加阅读记录升级版 * @param $param * @return bool * @throws \Exception */ public static function addReadRecord($param) { // 第一章不计入阅读记录 $sequence = (int)getProp($param, 'sequence'); // if ($sequence <= 1) { // return false; // } $uid = $param['uid']; $bid = $param['bid']; $cid = $param['cid']; $book_name = getProp($param, 'book_name'); $chapter_name = getProp($param, 'chapter_name'); $book_key = 'wap:string:book:' . $bid; $chapter_key = 'wap:string:chapter:' . $cid; if ($book_name) { Redis::setex($book_key, 3600, $book_name); } if ($chapter_name) { Redis::setex($chapter_key, 3600, $chapter_name); } Redis::hmset('book_read:' . $uid, 'last_read', "{$bid}_{$cid}_" . time(), $bid, "{$cid}_" . time(), 'next_push_hour', 8); $num = random_int(1, 100); if ($num <= 3) { self::delTheLastRecord($uid); } return true; } /** * 获取最近一条阅读记录(升级版) * @param $uid * @return array */ public static function getFirstReadRecord($uid) { self::delBookBase($uid); $record = Redis::hget('book_read:' . $uid, 'last_read'); if ($record) { $record_arr = explode('_', $record); $bid = $record_arr[0]; $bid = Hashids::encode($bid); $cid = $record_arr[1]; $time = $record_arr[2]; $book_info = BookConfigService::getBookById($bid); $book_name = isset($book_info->book_name) ? $book_info->book_name : ''; $cover = isset($book_info->cover) ? $book_info->cover : ''; $channel_name = isset($book_info->channel_name) ? $book_info->channel_name : ''; $res = [ 'url' => '/reader?bid=' . $bid . '&cid=' . $cid, 'book_name' => $book_name, 'cover' => $cover, 'channel_name' => $channel_name, 'time' => $time ]; return $res; } return []; } /** * 获取简单阅读记录 * @param $uid * @return int */ public static function getSimpleFirstReadRecord($uid) { try { $record = Redis::hget('book_read:' . $uid, 'last_read'); if ($record) { $record_arr = explode('_', $record); $bid = $record_arr[0]; return (int)$bid; } } catch (\Exception $e) { } return 0; } /** * 获取某本书的阅读记录 */ public static function getRecordByUidBid($uid, $bid) { return Redis::hget('book_read:' . $uid, $bid); } /** * 根据bid获取书名 * @param $bid * @return bool|null|string */ public static function bid2BookName($bid,&$channel_name) { $book_key = 'wap:string:book:' . $bid; $book_name = Redis::get($book_key); Redis::EXPIRE($book_key, 3600); if (!$book_name) { $book_name = ''; $book_info = BookConfigService::getBookById($bid); if ($book_info && isset($book_info->book_name)) { $book_name = $book_info->book_name; $channel_name = $book_info->channel_name; } } return $book_name; } /** * 根据cid获取章节名 * @param $cid * @return bool|null|string */ public static function cid2ChapterName($cid,$change_chapter_name) { $chapter_key = 'wap:string:chapter:' . $cid; $chapter_name = Redis::get($chapter_key); Redis::EXPIRE($chapter_key, 3600); if (!$chapter_name) { $chapter_name = ''; $chapter_info = Chapter::getChapterNameById($cid); if ($chapter_info && isset($chapter_info->name)) { //$chapter_name = $chapter_info->name; if($change_chapter_name){ $chapter_name = '第'.$chapter_info->sequence.'章'; }else{ $chapter_name = $chapter_info->name; } } } return $chapter_name; } public static function delBookBase($uid) { $base_record = Redis::hget('book_base:' . $uid, 'last_read'); if ($base_record) { Redis::del('book_base:' . $uid); Redis::hset('book_read:' . $uid, 'last_read', $base_record); } } /** * 获取简单阅读记录只有bid * @param int $uid * @return array */ public static function getSimpleReadRecord(int $uid): array { $read_bids = Redis::hgetall('book_read:' . $uid); $res = []; if (!$read_bids) { return $res; } foreach ($read_bids as $key => $v) { if (in_array($key, self::$not_uid_key)) { continue; } array_push($res, $key); } return $res; } /** * 获取当前的send_order_id * @param int $uid * @return int */ public static function getSendOrderId(int $uid) { try { $send_order_id = Redis::hget('book_read:' . $uid, 'send_order_id'); if ($send_order_id) return (int)$send_order_id; } catch (\Exception $e) { } return 0; } /** * 签到日期 * @param int $uid * @return mixed */ public static function getSignDay(int $uid) { try { return Redis::hget('book_read:' . $uid, 'sign_day'); } catch (\Exception $e) { } return -1; } public static function setSignDay(int $uid) { return Redis::hset('book_read:' . $uid, 'sign_day', date('Y-m-d')); } /** * 签到次数和日期 * @param int $uid */ public static function sign(int $uid, bool $is_incr) { try { if ($is_incr) { Redis::hincrby('book_read:' . $uid, 'sign_counts', 1); } else { self::setSignCount($uid, 1); } self::setSignDay($uid); } catch (\Exception $e) { \Log::info('sign_ept:' . $e->getMessage()); } return; } /** * @param int $uid * @return int */ public static function getSignCount(int $uid) { try { $count = Redis::hget('book_read:' . $uid, 'sign_counts'); if ($count) { return $count; } } catch (\Exception $e) { } return 0; } /** * 获取简单签到次数 * @param int $uid * @return int */ public static function getSignCountSimple(int $uid) { try { $count = Redis::hget('book_read:' . $uid, 'sign_counts'); if ($count) { return (int)$count; } return 0; } catch (\Exception $e) { } return 0; } public static function setSignCount(int $uid, int $count) { Redis::hset('book_read:' . $uid, 'sign_counts', $count); } public static function setSignInfo(int $uid, string $info) { Redis::hset('book_read:' . $uid, 'sign_info', $info); } public static function getByField(int $uid, $field) { try { return Redis::hget('book_read:' . $uid, $field); } catch (\Exception $e) { } return ''; } public static function getByMultiField(int $uid, ...$field) { try { return Redis::hmget('book_read:' . $uid, $field); } catch (\Exception $e) { } return ''; } public static function setByField(int $uid, $field, $value) { if (!in_array($field, self::$not_uid_key)) { return false; } try { return Redis::hset('book_read:' . $uid, $field, $value); } catch (\Exception $e) { } return ''; } public static function setByMultiField(int $uid, $kv) { $keys = array_keys($kv); foreach ($keys as $field) { if (!in_array($field, self::$not_uid_key)) { return false; } } try { return Redis::hmset('book_read:' . $uid, $kv); } catch (\Exception $e) { } return ''; } //删除多余的阅读纪律 public static function delTheLastRecord($uid) { $length = Redis::hlen('book_read:' . $uid); if ($length <= self::RECORD_COUNT + count(self::$not_uid_key)) { return; } $read_bids = Redis::hgetall('book_read:' . $uid); $i = 0; foreach ($read_bids as $key => $v) { if (in_array($key, self::$not_uid_key)) { continue; } $record = explode('_', $v); $latest_read_cid = $record[0]; $latest_read_time = $record[count($record) - 1]; $res[$i++] = ['bid' => $key, 'cid' => (int)$latest_read_cid, 'time' => (int)$latest_read_time]; } usort($res, function ($a, $b) { if ($a['time'] >= $b['time']) return -1; return 1; }); $j = 0; foreach ($res as $v) { if ($j++ >= self::RECORD_COUNT) { Redis::hdel('book_read:' . $uid, $v['bid']); } } } /** * 添加用户的阅读记录 */ public static function addReadLog(int $uid, array $data) { $log = ReadLog::model($uid); $log->create($data); } }