$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']; /** * 获取 * @param $uid * @return array */ public static function getReadRecord_($uid) { $read_bids = Redis::hgetall('book_read:' . $uid); $res = []; $i = 0; foreach ($read_bids as $key => $v) { $record = explode('_', $v); $latest_read_cid = $record[0]; $book_name = $record[1]; $chapter_name = $record[2]; $latest_read_time = $record[count($record) - 1]; $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 $res; } /** * 获取 升级版 * @param $uid * @return array */ public static function getReadRecord($uid, $is_need_check_db = false) { if ($is_need_check_db) { self::resetRecordFromDB($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]; $book_name = self::bid2BookName($key); $chapter_name = self::cid2ChapterName($latest_read_cid); $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 $uid * @param $bid * @param $cid * @param $book_name * @param $chapter_name */ public static function addReadRecord_($param) { $uid = $param['uid']; $bid = $param['bid']; $cid = $param['cid']; $book_name = $param['book_name']; $chapter_name = $param['chapter_name']; Redis::hset('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_{$book_name}_{$chapter_name}_" . time()); //Redis::hset('book_read:'.$uid, $bid, $cid."_".time()); Redis::hset('book_read:' . $uid, $bid, "{$cid}_{$book_name}_{$chapter_name}_" . time()); } /** * 添加阅读记录升级版 * @param array $param */ public static function addReadRecord($param) { $uid = $param['uid']; $bid = $param['bid']; $cid = $param['cid']; $book_name = isset($param['book_name']) ? $param['book_name'] : ''; $chapter_name = isset($param['chapter_name']) ? $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); } } /** * 获取最近一条阅读记录 * @param $uid */ public static function getFirstReadRecord_($uid) { $all = self::getReadRecord($uid); if (empty($all)) return []; $first = $all[0]; if (!$first) return []; if (!isset($first['bid'])) return []; try { //$bid = Hashids::encode($first['bid']); $bid = $first['bid']; $book_info = BookConfigService::getBookById($bid); $cid = $first['cid']; $book_name = $first['book_name']; $res = [ 'url' => '/reader?bid=' . $bid . '&cid=' . $cid, 'book_name' => $book_name, 'cover' => $book_info->cover, 'channel_name' => $book_info->channel_name, ]; } catch (\Exception $e) { $res = []; } return $res; } /** * 获取最近一条阅读记录(升级版) * @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; } /** * 获取客服消息点击数 * @param $uid */ public static function getCustomerMsgClickNum($channel_id, $from, $date) { $key = "fromcustomermsgenter:distribution_channel_id:" . $channel_id . 'from:' . $from; return Redis::hget($key, $date); } /** * 获取某本书的阅读记录 */ 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) { $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; } } } /** * 根据cid获取章节名 * @param $cid * @return bool|null|string */ public static function cid2ChapterName($cid) { $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; } } return $chapter_name; } /** * 删除阅读记录中的书名和章节名 * @param $uid * @param $record */ public static function delBookNameAndChapter($uid) { $base_record = Redis::hget('book_base:' . $uid, 'last_read'); if ($base_record) { $record_arr = explode('_', $base_record); $c = count($record_arr); if ($c > 3) { $bid = $record_arr[0]; $cid = $record_arr[1]; $time = $record_arr[$c - 1]; Redis::hset('book_base:' . $uid, 'last_read', "{$bid}_{$cid}_" . $time); } } $records = Redis::hgetall('book_read:' . $uid); foreach ($records as $key => $v) { $record = explode('_', $v); $count = count($record); if ($count > 3) { $latest_read_cid = $record[0]; $book_name = $record[1]; $chapter_name = $record[2]; $latest_read_time = $record[$count - 1]; Redis::hset('book_read:' . $uid, $key, "{$latest_read_cid}_" . $latest_read_time); $book_key = 'wap:string:book:' . $key; $chapter_key = 'wap:string:chapter:' . $latest_read_cid; Redis::set($book_key, $book_name); Redis::set($chapter_key, $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; } public static function ReadRecordStatistical(int $uid, int $distribution_channel_id, string $from) { try { DB::table('temp_read_active')->insert([ 'uid' => $uid, 'distribution_channel_id' => $distribution_channel_id, 'from' => $from, 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ]); } catch (\Exception $e) { } } /** * 获取当前的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 $uid * @param $inner_order_id */ public static function setInnerSendOrderId($uid, $inner_order_id) { try { Redis::hset('book_read:' . $uid, 'inner_send_order_id', $inner_order_id); } catch (\Exception $e) { } } /** * 获取内部派单 * @param $uid * @return string */ public static function getInnerSendOrderId($uid) { try { $inner_send_order_id = Redis::hget('book_read:' . $uid, 'inner_send_order_id'); if ($inner_send_order_id) { return $inner_send_order_id; } return ''; } catch (\Exception $e) { } return ''; } /** * 签到日期 * @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 setSmartPush($uid, $bid) { $old = self::getSmartPush($uid); if ($old && !in_array($bid, $old)) { array_push($old, $bid); $bid_str = implode(',', $old); return Redis::hset('book_read:' . $uid, 'smart_push', $bid_str); } else { return Redis::hset('book_read:' . $uid, 'smart_push', $bid); } } public static function getSmartPush(int $uid): array { $res = Redis::hget('book_read:' . $uid, 'smart_push'); if ($res) { return explode(',', $res); } return []; } 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 ''; } private static function resetRecordFromDB($uid) { if (self::getByField($uid, 'last_read')) { return; } $record = ReadRecordFromRedis::where('uid', $uid)->select('field', 'value')->get(); if ($record->isNotEmpty()) { foreach ($record as $item) { if (!in_array($item->field, self::$not_uid_key) || $item->field == 'last_read') { Redis::hset('book_read:' . $uid, $item->field, $item->value); } } } } //删除多余的阅读纪律 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); } }