1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140 |
- <?php
- /**
- * Created by PhpStorm.
- * User: Bear
- * Date: 2018/11/29
- * Time: 下午4:39
- */
- namespace app\main\service;
- use app\common\constants\Common;
- use app\common\library\Ip;
- use app\common\library\Redis;
- use app\common\model\Book;
- use app\common\model\BookLimit;
- use app\common\model\ChapterEdited;
- use app\common\model\Chapterendrecommend;
- use app\common\model\FollowRecommand;
- use app\common\model\Guide;
- use app\common\model\GuideWx;
- use app\common\model\ReturnRecommand;
- use app\common\model\UserRecentlyRead;
- use app\common\service\VipCpService;
- use app\common\service\WaterBookService;
- use app\main\constants\BookConstants;
- use app\main\constants\CacheConstants;
- use app\main\constants\ClientApiConstants;
- use app\main\constants\ErrorCodeConstants;
- use app\main\helper\ArrayHelper;
- use app\main\model\object\ReturnObject;
- use think\Config;
- use think\Cookie;
- use think\Env;
- class BookService extends BaseService
- {
- /**
- * @var BookService
- */
- protected static $self = NULL;
- /**
- * @return BookService
- */
- public static function instance()
- {
- if (self::$self == NULL) {
- self::$self = new self();
- }
- return self::$self;
- }
- /**
- * @return Book
- */
- public function getBookModel()
- {
- return model('Book');
- }
- /**
- * @return UserRecentlyRead
- */
- public function getUserRecentlyRead()
- {
- return model('UserRecentlyRead');
- }
- /**
- * @return FollowRecommand
- */
- public function getFollowRecommandModel()
- {
- return model('FollowRecommand');
- }
- /**
- * @return ReturnRecommand
- */
- public function getReturnRecommandModel()
- {
- return model('ReturnRecommand');
- }
- /**
- * @return BookLimit
- */
- public function getBookLimit()
- {
- return model('BookLimit');
- }
- /**
- * @return Guide
- */
- public function getGuideModel()
- {
- return model('Guide');
- }
- /**
- * @return GuideWx
- */
- public function getGuideWxModel()
- {
- return model('GuideWx');
- }
- /**
- * @return ChapterEdited
- */
- public function getChapterEditedModel()
- {
- return model('ChapterEdited');
- }
- /**
- * @return \app\common\model\BookShelf
- */
- public function getBookShelfModel()
- {
- return model('BookShelf');
- }
- /**
- * @return Chapterendrecommend
- */
- public function getChapterEndRecommendModel()
- {
- return model('Chapterendrecommend');
- }
- /**
- * @param $admin_id
- * @return string
- */
- public function getEventTextNoResult($admin_id)
- {
- $site_url = getCurrentDomain($admin_id);
- trim($site_url, '/');
- $msg = implode("\n\n", [
- "对不起,找不到相关的小说",
- "您可以试试:",
- "1、<a href=\"{$site_url}/index/user/recent\">查看阅读记录>></a>",
- "2、<a href=\"{$site_url}/index/index/search\">精准找书>></a>",
- "3、<a href=\"{$site_url}\">去首页看看>></a>",
- ]);
- return $msg;
- }
- /**
- * @param $message
- * @return bool|mixed
- * @throws \Exception
- * @throws \think\db\exception\DataNotFoundException
- * @throws \think\db\exception\ModelNotFoundException
- * @throws \think\exception\DbException
- */
- public function getWeinxinSearchBooks($message,$is_water, $admin_id)
- {
- $search = $message->Content;
- $openid = $message->FromUserName;
- $return = false;
- $type = 0; //0 精准匹配 1 推荐
- if (trim($search)) {
- $search = addslashes($search);
- $searchKey = 'SEB:' . $search;
- $issetBookSearch = true;
- if (Redis::instance()->exists($searchKey)) {
- $issetBookSearch = false;
- $redData = Redis::instance()->get($searchKey);
- $booksData = json_decode($redData, true);
- $books = $booksData['books'];
- $total = $booksData['total'];
- LogService::info('redis'.json_encode($books));
- } else {
- $where = [];
- $where['state'] = 1;
- $where['name|keywords'] = ['like', '%'.addslashes($search).'%'];
- if ($is_water) {
- $where['classify_white_list'] = 1;
- }
- //模糊查询的排序-- 优先推送全匹配的书籍,所以只取一本即可 wdd 191028
- $order = "(case
- when name = '".$search."' then 0
- when name like '".$search."%' then 1
- when name like '%".$search."' then 2
- when name like '%".$search."%' then 3
- else 4
- end) asc";
- // $total = BookService::instance()->getBookModel()->where($where)->count();
- $books = BookService::instance()->getBookModel()->where($where)->page(0, 1)->order($order)->select();
- }
- if ( !empty($books) ) {
- //判断来源是redis里的还是数据库
- if ($issetBookSearch) {
- $books = array_pop($books);
- LogService::info('数据库'.json_encode($books));
- $saveReData = [];
- $saveReData['books'] = $books;
- $saveReData['total'] = 1;
- Redis::instance()->setex($searchKey, 86400, json_encode($saveReData));
- }
- $return[0] = $books;
- } else {
- //没有搜到书 从关键字回复书库取
- $type = 1;
- $where = [];
- $where['book.state'] = ['eq','1'];
- $where['gzhreply_recommand.status'] = ['eq','normal'];
- if ($is_water) {
- $where['classify_white_list'] = 1;
- }
- if ($uid = OfficialAccountsService::instance()->getOpenidModel()->getUserId($admin_id, $openid)) {
- $soruceReadLog = model('UserRecentlyRead')->setConnect($uid)->getRecentlyRead(0,10,$uid);
- if ($soruceReadLog['totalNum'] > 0) {
- foreach ($soruceReadLog['data'] as $val) {
- $bookIds[] = $val['book_id'];
- }
- $bookIdsToStr = implode(',', $bookIds);
- $where['gzhreply_recommand.book_id'] = ['not in', $bookIdsToStr];
- }
- $userInfo = model('User')->getUserInfo($uid);
- if(empty($userInfo['sex'])){
- $where['gzhreply_recommand.sex'] = ['eq','1'];
- }else{
- $where['gzhreply_recommand.sex'] = ['eq',$userInfo['sex']];
- }
- $totalNum = model('GzhreplyRecommand')->join('book', 'book.id = gzhreply_recommand.book_id')->where($where)->count();
- $randNum = $totalNum > 3 ? $totalNum-3 : 0;
- if($randNum>0){
- $randNum = mt_rand(0,$randNum);
- }
- $result = model('GzhreplyRecommand')->join('book', 'book.id = gzhreply_recommand.book_id')->field('book.*')->where($where)->limit($randNum,3)->select();
- if (!empty($result)) {
- $return = $result;
- }
- }
- }
- }
- return [$type, $return];
- }
- /**
- * 合并游客阅读记录 @todo 已废弃
- * @throws \Exception
- */
- public function mergeGuestReadingRecord()
- {
- if (UserService::instance()->isLogin() && Cookie::has('read')) {
- $readTmp = Cookie::get('read');
- $userId = UserService::instance()->getUserInfo()->id;
- foreach ($readTmp as $key => $val) {
- $book = BookService::instance()->getBookModel()->bookinfo($key);
- $bookInfo = [];
- $bookInfo['image'] = $book['image'];
- $bookInfo['book_name'] = $book['name'];
- $bookInfo['last_chapter_name'] = $book['last_chapter_name'];
- $bookInfo['last_chapter_utime'] = $book['last_chapter_utime'];
- $bookInfo['state'] = $book['state'];
- $insertData = [];
- $insertData['user_id'] = $userId;
- $insertData['book_id'] = $val['book_id'];
- $insertData['chapter_id'] = $val['chapter_id'];
- $insertData['chapter_name'] = $val['chapter_name'];
- $insertData['createtime'] = time();
- $insertData['updatetime'] = $val['updatetime'];
- UserService::instance()->getUserRecentlyReadModel()->setConnect($userId)->insert($insertData);
- $id = UserService::instance()->getUserRecentlyReadModel()->setConnect($userId)->getLastInsID();
- $insertData['id'] = $id;
- $insertArr = array_merge($insertData, $bookInfo);
- $key = 'U-R:' . $userId;
- $hkey = 'U-B:' . $userId . ':' . $val['book_id'];
- Redis::instance()->hmset($hkey, $insertArr);
- Redis::instance()->zrem($key, $hkey);
- Redis::instance()->zadd($key, $insertArr['updatetime'], $hkey);
- Redis::instance()->expire($key, 43200);
- Redis::instance()->expire($hkey, 43200);
- }
- Cookie::delete('read');
- }
- }
- /**
- * 获取书籍与当前章节信息
- * @param $book_id
- * @param $chapter_id
- * @param $sid
- * @return \app\main\model\object\ReturnObject
- */
- public function getBookChapterInfo($book_id, $chapter_id, $sid = '', $isWater=false)
- {
- try{
- //参数错误
- if (!$book_id) {
- return $this->setCode(ErrorCodeConstants::REDIRECT)->setData('/')->getReturn();
- }
- $bookInfoRedirect = $this->getBookIndexPage($book_id)->data;
- //书籍不存在
- $bookinfo = BookService::instance()->getBookModel()->BookInfo($book_id);
- if ($isWater && (!isset($bookinfo['classify_white_list']) || $bookinfo['classify_white_list'] !=1)){//清水逻辑 按照下架处理
- return $this->setCode(ErrorCodeConstants::REDIRECT_VIEW)->setData([
- 'tpl' => 'public/forbiddenread',
- 'bind' => [
- 'book' => $bookinfo,
- ],
- ])->getReturn();
- }
- if (!$bookinfo) {
- return $this->setCode(ErrorCodeConstants::REDIRECT_VIEW)->setData(['tpl'=>'public/nobook'])->getReturn();
- }
- if($bookinfo['recommand_book_id']){
- $recmooand = BookService::instance()->getBookModel()->BookInfo($bookinfo['recommand_book_id']);
- if ($recmooand) {
- $bookinfo['recommand_book_image'] =$recmooand['image'];
- $bookinfo['recommand_book_name'] =$recmooand['name'];
- }else{
- $bookinfo['recommand_book_image'] = '';
- $bookinfo['recommand_book_name'] = '';
- }
- }
- //书籍已下架
- if ($bookinfo['state'] == BookConstants::BOOK_STATE_OFF_SALE) {
- return $this->setCode(ErrorCodeConstants::REDIRECT_VIEW)->setData([
- 'tpl' => 'public/forbiddenread',
- 'bind' => [
- 'book' => $bookinfo,
- ],
- ])->getReturn();
- }
- if (!$chapter_id) {
- if (!$chapter_id && UserService::instance()->isLogin()) {
- $user_id = UserService::instance()->getUserInfo()->id;
- $readlog = $this->getUserRecentlyRead()->getone($user_id, $book_id);
- if ($readlog) {
- $chapter_id = $readlog['chapter_id'];
- }
- }
- if (!$chapter_id) {
- if ($sid) {
- $chapter_id = $sid;
- } else {
- $chapter_id = $bookinfo['first_chapter_id'];
- }
- }
- }
- //章节参数缺失
- if (!$chapter_id) {
- $this->setCode(ErrorCodeConstants::REDIRECT)->setData($bookInfoRedirect)->getReturn();
- }
- $chapter_data = $this->getChapterInfo($book_id, $chapter_id);
- //章节异常
- if ($chapter_data->code == ErrorCodeConstants::EXCEPTION) {
- return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($bookInfoRedirect)->getReturn();
- }
- //章节缺失
- if ($chapter_data->code == ErrorCodeConstants::RESULT_EMPTY) {
- return $this->setCode(ErrorCodeConstants::REDIRECT)->setData($bookInfoRedirect)->getReturn();
- }
- $chapter = $chapter_data->data;
- if(is_array($chapter['content'])){
- $content = array_map(function($item){
- return '<p>'.$item.'</p>';
- },$chapter['content']);
- $chapter['content'] = implode('', $content);
- }
- //空内容,无下一章
- if (!strip_tags($chapter['content']) && !isset($chapter['next_id'])) {
- return $this->setCode(ErrorCodeConstants::REDIRECT_VIEW)->setData([
- 'tpl' => 'public/nobook',
- 'bind' => [
- 'book' => $bookinfo,
- ],
- ])->getReturn();
- }
- //空内容,有下一章
- if (!strip_tags($chapter['content']) && isset($chapter['next_id'])) {
- return $this->setCode(ErrorCodeConstants::REDIRECT_VIEW)->setData([
- 'tpl' => 'public/nocontent',
- 'bind' => [
- 'book' => $bookinfo,
- 'chapter' => $chapter,
- 'next_link' => '/index/book/chapter?book_id=' . $book_id . '&chapter_id=' . $chapter['next_id'],
- ],
- ])->getReturn();
- }
- $preid = 0;
- if (empty($chapter['pre_id'])) {
- $pre_link = "javascript:consoleMain('已经是第一章了');";
- } else {
- $pre_link = '/index/book/chapter?book_id=' . $book_id . '&chapter_id=' . $chapter['pre_id'];
- $preid = $chapter['pre_id'];
- }
- if ($chapter['next_id']) {
- $next_link = '/index/book/chapter?book_id=' . $book_id . '&chapter_id=' . $chapter['next_id'];
- } else {
- if ($bookinfo['is_finish'] == BookConstants::BOOK_IS_FINISH_YES) {
- $next_link = '/index/book/statuspage/code/2/book_id/' . $book_id;
- } else {
- $next_link = '/index/book/statuspage/code/1/book_id/' . $book_id;
- }
- }
- $data = [
- 'chapter' => $chapter,
- 'book' => $bookinfo,
- 'pre_link' => $pre_link,
- 'next_link' => $next_link,
- 'pre_id' => $preid
- ];
- return $this->setData($data)->getReturn();
- }catch (\Exception $e){
- return $this->getExceptionReturn($e);
- }
- }
- /**
- * 获取章节信息
- *
- * @param int $book_id 书籍ID
- * @param int $page_no 第几页
- * @param int $limit 单页条数
- * @return \app\main\model\object\ReturnObject|array
- */
- public function getChapterList($book_id, $page_no = 1, $limit = 20)
- {
- if ((bool)Config::get('redis.change') == CacheConstants::BOOK_CHAPTER_CACHE_CHANGED_YES) {
- $cacheKey = CacheConstants::getBookChapterCacheKeyNew($book_id);
- $code = $this->getConnectCode($cacheKey);
- $redis = Redis::instanceBookChange($code);
- $list = $redis->zRange($cacheKey, 0, -1);
- } else {
- $redis = Redis::instanceBook();
- $cacheKey = CacheConstants::getBookChapterCacheKey($book_id);
- $list = $redis->lRange($cacheKey, 0, -1);
- }
- $all = []; //全部章节
- $data = [
- 'data' => [],
- 'pageNo' => $page_no,
- 'limit' => $limit,
- 'totalNum' => 0,
- 'totalPage' => 0,
- ];
- foreach ($list as $key => $value) {
- if ((bool)Config::get('redis.change') == CacheConstants::BOOK_CHAPTER_CACHE_CHANGED_YES) {
- $json = json_decode($value, true);
- } else {
- $json = json_decode(gzdecode($value), true);
- }
- $all[] = [
- 'id' => $json[4] ?? $json['chapterId'],
- 'idx' => count($all) + 1,
- 'name' => $json[5] ?? $json['chapterName'],
- ];
- }
- if ($limit > 0) {
- $data['data'] = array_slice($all, ($page_no - 1) * $limit, $limit);
- } else { //获取全部
- $data['data'] = $all;
- $data['limit'] = count($all);
- }
- if (!$data['data']) {
- LogService::notice('获取章节列表失败!书籍ID:' . $book_id . ' 分页:' . $page_no . ' 条数:' . $limit);
- return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
- }
- $data['totalNum'] = count($all);
- $data['totalPage'] = ceil(count($all) / $limit);
- return $this->setData($data)->getReturn();
- }
- /**
- * 获取章节详情
- *
- * @param int $book_id 书籍ID
- * @param int $chapter_id 章节ID
- * @return array | ReturnObject
- */
- public function getChapterInfo($book_id, $chapter_id, $user_id = false)
- {
- try{
- $chapterList = self::getChapterList($book_id, 1, -1);
- if ($chapterList->code != ErrorCodeConstants::SUCCESS) {
- LogService::notice('获取章节列表失败!书籍ID:' . $book_id);
- return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
- }
- $data = [];
- $allChapterIds = array_column($chapterList->data['data'], 'id');
- //如果章节不存在
- if (!in_array($chapter_id, $allChapterIds)) {
- $id = 0;
- foreach ($allChapterIds as $id) {
- if ($id >= $chapter_id) {
- break;
- }
- }
- $chapter_id = $id;
- }
- foreach ($chapterList->data['data'] as $key => $chapter) {
- if ($chapter['id'] >= $chapter_id) {
- $data['name'] = $chapter['name'];
- $data['idx'] = $chapter['idx'];
- $data['id'] = $chapter['id'];
- if ($key == 0) {
- $data['pre_id'] = '';
- } else {
- $data['pre_id'] = $chapterList->data['data'][$key - 1]['id'];
- }
- if (isset($chapterList->data['data'][$key + 1])) {
- $data['next_id'] = $chapterList->data['data'][$key + 1]['id'];
- } else {
- $data['next_id'] = '';
- }
- $chapter_id = $chapter['id'];
- break;
- }
- }
- $redis = Redis::instance();
- $cacheKey = CacheConstants::getBookSingleChapterCacheKey($chapter_id);
- $aChapter = [];
- if ($redis->exists($cacheKey)) {
- if(json_decode($redis->get($cacheKey), true)){
- $aChapter = json_decode($redis->get($cacheKey), true);
- }else{
- $aChapter = $redis->get($cacheKey);
- }
- } else {
- $chapter_result = $this->getChapter($book_id, $chapter_id)->data;
- $data['from'] = $chapter_result['from'];
- if (array_key_exists('name', $chapter_result)) {
- $data['name'] = $chapter_result['name'];
- }
- if ($content = $chapter_result['content']) {
- $content = str_replace("\r", '', $content);
- $arr = explode("\n", $content);
- foreach ($arr as $value) {
- $value = ltrim($value);
- $value = mb_ereg_replace('^( | )+','', $value);
- $value = mb_convert_encoding($value, "UTF-8", "UTF-8"); //强制转换一次UTF-8编码
- if ($value) {
- $aChapter[] = $value;
- }
- }
- } else {
- LogService::error('获取章节内容失败!ID:' . $book_id . ' 章节ID:' . $chapter_id);
- }
- if ($aChapter) {
- $keyNum = 'BCN:' . $chapter_id . ':' . date('i');
- if ($redis->incr($keyNum) > 10) {
- $redis->setex($cacheKey, 3600, json_encode($aChapter, true));
- }
- $redis->expire($keyNum, 60);
- }
- }
- $data['content'] = $aChapter;
- return $this->setData($data)->getReturn();
- }catch (\Exception $e){
- LogService::exception($e);
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->getReturn();
- }
- }
- public function getChapter($book_id, $chapter_id)
- {
- $data = ['content'=>'','from'=>'cache'];
- $content = $this->getChapterEditedModel()->getChapterFromDb($chapter_id);
- if ($content) {
- $data = [
- 'content' => $content['content'],
- 'name' => $content['name'],
- 'from' => 'db',
- ];
- } else {
- $path = Config::get('site.chapter_path');
- if (empty($path)) {
- $path = 'cppartner';
- }
- $file = $this->getChapterContentPath($path, $book_id, $chapter_id);
- LogService::info('章节文件路径:' . $file);
- if (is_file($file)) {
- $content = file_get_contents($file);
- $data['content'] = $content;
- }
- }
- return $this->setData($data)->getReturn();
- }
- /**
- * 获取书籍章节路径
- * @param $path
- * @param $book_id
- * @param $chapter_id
- * @return string
- */
- public function getChapterContentPath($path, $book_id, $chapter_id)
- {
- return ROOT_PATH . "public/assets/" . $path . self::getPath($book_id) . "{$chapter_id}.txt";
- }
- /**
- * 获取书籍缓存连接参数
- * @param $val
- * @return int
- */
- public function getConnectCode($val)
- {
- $bKey = md5($val, true);
- $rv = (ord($bKey[3]) & 0xFF) << 24
- | (ord($bKey[2]) & 0xFF) << 16
- | (ord($bKey[1]) & 0xFF) << 8
- | ord($bKey[0]) & 0xFF;
- return $rv & 0xffffffff;
- }
- /**
- * 根据书籍id获取存储路径
- *
- * @param $book_id
- * @return string
- */
- protected function getPath($book_id)
- {
- $path = '/' . substr($book_id, 0, 1) . 'x' . substr($book_id, 1, 1)
- . '/' . substr($book_id, 0, 2) . 'x' . substr($book_id, 2, 1)
- . '/' . substr($book_id, 0, 3) . 'x' . substr($book_id, 3, 1)
- . '/' . $book_id . '/';
- return $path;
- }
- /**
- * @param int $book_id
- * @param int $referral_id
- * @return ReturnObject
- */
- public function getGuidChapterIdx($book_id = 0, $referral_id = 0)
- {
- try {
- //链接导粉
- if ($referral_id) {
- //检查内推外派,内推不导粉
- $ref_info = UrlService::instance()->getReferralModel()->getone($referral_id,false);
- if(isset($ref_info['push']) && $ref_info['push']){
- return $this->setData(0)->getReturn();
- }
- //推广链接导粉
- $idx = UrlService::instance()->getReferralModel()->getone($referral_id);
- if ($idx) {
- return $this->setData($idx)->getReturn();
- }
- }
- $runTime = UserService::instance()->getRunTimeObject();
- $admin_id = $runTime->adminId;
- if (empty($admin_id)) {
- //网站全局导粉章节数
- $web_guide = config('site.book_guide_chapter_idx');
- if ($web_guide) {
- return $this->setData($web_guide)->getReturn();
- } else {
- return $this->setData(0)->getReturn();
- }
- }
- $df_config = $runTime->adminConfig;
- $adminIds = [];
- if ($runTime->agentId) {
- $adminIds[] = $runTime->agentId;
- }
- $adminIds[] = $runTime->channelId;
- foreach ($adminIds as $adminId) {
- $guide = 0;
- //guide表导粉章节数 代理商导粉
- $key = 'GUIDE:' . $adminId;
- if (Redis::instance()->exists($key)) {
- $guide =(int)Redis::instance()->hget($key, $book_id);
- } else {
- $db_data = collection($this->getGuideModel()->field('book_id,chapter_idx')->where('admin_id=' . $adminId)->select())->toArray();
- if (empty($db_data)) {
- Redis::instance()->hset($key, 1, 1);
- } else {
- Redis::instance()->hdel($key, 1);
- $db_data_temp = [];
- foreach ($db_data as $value) {
- $db_data_temp[$value['book_id']] = $value['chapter_idx'];
- if ($value['book_id'] == $book_id) {
- $guide = $value['chapter_idx'];
- }
- }
- Redis::instance()->hMSet($key,$db_data_temp);
- unset($db_data_temp);
- unset($db_data);
- }
- Redis::instance()->expire($key, 86400);
- }
- if ($guide) {
- return $this->setData($guide)->getReturn();
- }
- }
- //渠道商全局导粉章节数
- if ($df_config['book_guide_chapter_idx']) {
- return $this->setData($df_config['book_guide_chapter_idx'])->getReturn();
- }
- //网站全局导粉章节数
- $web_guide = config('site.book_guide_chapter_idx');
- if ($web_guide) {
- return $this->setData($web_guide)->getReturn();
- }
- return $this->setData(0)->getReturn();
- } catch (\Exception $e) {
- LogService::exception($e);
- return $this->setData(0)->getReturn();
- }
- }
- /**
- * 随机获取导粉二维码
- * @param $admin_id
- * @return ReturnObject
- */
- public function getRandomGuideQrCode($admin_id)
- {
- $data = '';
- try {
- $redis = Redis::instance();
- $key = 'GW:' . $admin_id;
- if ($redis->exists($key)) {
- $gwRes = $redis->srandmember($key);
- if ($gwRes === '') {
- $data = '';
- } else {
- $data = json_decode($gwRes, true);
- }
- } else {
- $result = $this->getGuideWxModel()->where(['admin_id' => $admin_id, 'state' => '1'])->select();
- if ($result) {
- foreach ($result as $val) {
- $redis->sadd($key, json_encode($val, JSON_UNESCAPED_UNICODE));
- }
- $redis->expire($key, 86400 * 2);
- $gwRes = $redis->srandmember($key);
- $data = json_decode($gwRes, true);
- } else {
- $data = '';
- $redis->sadd($key, '');
- $redis->expire($key, 86400 * 2);
- }
- }
- } catch (\Exception $e) {
- LogService::exception($e);
- }
- return $this->setData($data)->getReturn();
- }
- /**
- * 设置最近阅读
- * @param $chapter_name 章节名称
- * @param $chapter_id 章节id
- * @param $bookId 书籍id
- * @param $chapter_idx 章节索引
- * @param null $userId 用户id
- * @return ReturnObject
- */
- public function setRecentlyRead($chapter_name, $chapter_id, $bookId, $chapter_idx, $userId = null)
- {
- try {
- if (empty($userId)) {
- $userId = UserService::instance()->getUserInfo()->id;
- }
- if (empty($bookId)) {
- return $this->getReturn();
- }
- $recentlyReadModel = $this->getUserRecentlyRead();
- $urKey = $recentlyReadModel->getURKey($userId);//最近阅读记录zset结构
- $ubKey = $recentlyReadModel->getUBKey($userId, $bookId);//最近阅读阅读记录每条的数据:hash结构
- $redis = Redis::instance();
- //用户阅读章节数,KL使用
- $cacheChapter = CacheConstants::getUserChapterCacheKey($userId);
- $redis->pfAdd($cacheChapter, $chapter_id);
- $RecentlyReadDB = $this->getUserRecentlyRead()->setConnect($userId);
- if (empty($userId)) { //游客
- $chapterInfo = [
- 'id' => $chapter_id,
- 'name' => $chapter_name,
- ];
- $RecentlyReadDB->recentCookie($bookId, $chapterInfo); //阅读记录记入cookie 只记录5条数据
- return $this->getReturn();
- }
- if (!$redis->exists($urKey)) { //如果redis里最近阅读记录为空拉取一下最近阅读记录(防灾)
- $RecentlyReadDB->getRecentlyRead(0, 10, $userId);
- }
- if (!($userRead = $redis->hGetAll($ubKey))) {
- $userRead = $RecentlyReadDB->getone($userId, $bookId);
- $userRead = $userRead ? $userRead->toArray() : null;
- }
- $userRecentInfo = [
- 'chapter_id' => $chapter_id,
- 'chapter_name' => $chapter_name,
- 'updatetime' => time(),
- 'flag' => 1
- ];
- if (config('site.book_auto_shelf_chapter_num') <= $chapter_idx) {
- $userRecentInfo['book_shelf_add'] = 1;
- $userRecentInfo['book_shelf_flag'] = 1;
- $usKey = $recentlyReadModel->getUSKey($userId);
- if (!$redis->exists($usKey)) {
- $this->_getBookShelf(0, 10, $userId);
- }
- $redis->zAdd($usKey, $userRecentInfo['updatetime'], $ubKey);
- $redis->expire($usKey, 43200);
- $this->delRecommendShelfBookByBookId($bookId, $userId);
- }
- if (!empty($userRead)) { //更新
- $getId = $userRead['id'];
- $RecentlyReadDB->where(['id' => $getId])->update($userRecentInfo);
- $userRecentInfo = array_merge($userRead, $userRecentInfo);//构造redis用的数据
- } else {//创建阅读记录
- $userRecentInfo['user_id'] = $userId;
- $userRecentInfo['book_id'] = $bookId;
- $userRecentInfo['createtime'] = time();
- $RecentlyReadDB->insert($userRecentInfo);
- $id = $RecentlyReadDB->getLastInsID();
- $userRecentInfo['id'] = $id;
- if (!$redis->exists($urKey)) { //(如果redis里最近阅读记录为空拉取一下最近阅读记录防灾)
- $RecentlyReadDB->getRecentlyRead(time() + 1, 10, $userId);
- }
- }
- $redis->hmset($ubKey, $userRecentInfo);
- $redis->expire($ubKey, 43200); //设置失效时间
- $redis->zadd($urKey, $userRecentInfo['updatetime'], $ubKey);
- $redis->expire($urKey, 43200); //设置失效时间
- return $this->getReturn();
- } catch (\Exception $e) {
- return $this->getExceptionReturn($e);
- }
- }
- /**
- * 获取章节阅读配置
- */
- public function getReadingSetting()
- {
- $return = [
- 'read_body_fontsize' => 'read_body_fontsize_2',
- 'read_theme' => 'read_theme_1',
- 'day_night' => '',
- ];
- if (!Config::get('template.view_theme')) {
- $return['read_theme'] = 'read_theme_2'; //西瓜
- } else {
- $return['read_theme'] = 'read_theme_1'; //袋鼠 沙发 美书
- }
- if (Cookie::has('cs')) {
- $cs['l'] = 1;
- $cs = json_decode(Cookie::get('cs'), true); //章节排序 l=1正序 l=2倒序
- if ($cs['f'] !== null) {
- //字号
- $return['read_body_fontsize'] = 'read_body_fontsize_' . intval($cs['f']);
- }
- if ($cs['b'] !== null) {
- //背景色
- $return['read_theme'] = 'read_theme_' . intval($cs['b']);
- }
- if ($cs['d'] == 2) {
- //白天/夜间 主题
- $return['day_night'] = 'read_theme_5';
- }
- }
- return $this->setData($return)->getReturn();
- }
- /**
- * 获取书籍默认链接
- * @param $book_id
- * @return ReturnObject
- */
- public function getBookIndexPage($book_id)
- {
- return $this->setData('/index/book/info?book_id=' . $book_id)->getReturn();
- }
- /**
- * 随机获取一本返回推荐书籍
- * @return ReturnObject
- */
- public function getReturnRecommandBook()
- {
- $book_data = false;
- $recentNum = Env::get('app.return_filter_recent_num', 100);
- $recentRead = UserService::instance()->getUserRecentlyReadModel()->getRecentlyRead(0, $recentNum);
- $book_ids = [];
- if ($recentRead['totalNum'] > 0) {
- $book_ids = array_column($recentRead['data'], 'book_id');
- }
- $count = $this->getReturnRecommandModel()
- ->where('status', 'normal')
- ->whereNotIn('book_id', $book_ids)
- ->count();
- if ($count) {
- $index = rand(0, $count - 1);
- $book_list = model('ReturnRecommand')
- ->where('status', 'normal')
- ->whereNotIn('book_id', $book_ids)
- ->limit($index, 1)
- ->select();
- $book = $book_list[0];
- $book_data = BookService::instance()->getBookModel()->BookInfo($book['book_id']);
- if ($book_data) {
- $book_data['url'] = '/index/book/chapter?book_id=' . $book['book_id'] . '&sid=' . $book_data['first_chapter_id'];
- }
- }
- return $this->setData($book_data)->getReturn();
- }
- /**
- * @param $bookInfo 书籍信息
- * @param $chapterId 章节id
- * @param $type 类型,0当前章节;1上一章;2、下一章;
- * @return ReturnObject
- */
- public function getBookChapterInfoForClient($bookInfo, $chapterId, $type)
- {
- try {
- $bookId = $bookInfo['id'];
- //如果章节id为空,则获取当前书籍第一章的内容
- if (empty($chapterId)) {
- $chapterId = $bookInfo['first_chapter_id'];
- }
- if (empty($chapterId)) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg('首章id不存在')->getReturn();
- }
- $chapterResult = $this->getChapterInfoForClient($bookId, $chapterId, $type);
- if ($chapterResult->code != ErrorCodeConstants::SUCCESS) {
- return $this->setCode($chapterResult->code)->setMsg($chapterResult->msg)->getReturn();
- }
- return $this->setData($chapterResult->data)->getReturn();
- } catch (\Exception $e) {
- LogService::exception($e);
- $this->setCode(ErrorCodeConstants::EXCEPTION)->getReturn();
- }
- }
- /**
- * 获取章节信息
- * @param $bookId 书籍id
- * @param $chapterId 章节id
- * @param $type 类型,0当前章节;1上一章;2、下一章;
- * @return ReturnObject
- */
- private function getChapterInfoForClient($bookId, $chapterId, $type)
- {
- try {
- $chapterList = self::getChapterList($bookId, 1, -1);
- if ($chapterList->code != ErrorCodeConstants::SUCCESS) {
- LogService::notice('获取章节列表失败!书籍ID:' . $bookId);
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg('章节不存在')->getReturn();
- }
- $data = [];
- foreach ($chapterList->data['data'] as $key => $chapter) {
- if ($chapter['id'] == $chapterId) {
- $idx = $key;
- switch ($type) {
- case ClientApiConstants::GET_CHAPTER_TYPE_PRE:
- $idx = $key - 1;
- break;
- case ClientApiConstants::GET_CHAPTER_TYPE_NEXT:
- $idx = $key + 1;
- break;
- default:
- break;
- }
- $chapterInfo = isset($chapterList->data['data'][$idx]) ? $chapterList->data['data'][$idx] : null;
- if (isset($chapterInfo)) {
- $chapterInfoId = $chapterInfo['id'];
- $data['name'] = $chapterInfo['name'];
- $data['idx'] = $chapterInfo['idx'];
- $data['id'] = $chapterInfoId;
- if ($idx == 0) {
- $data['pre_id'] = '';
- } else {
- $data['pre_id'] = $chapterList->data['data'][$idx - 1]['id'];
- }
- if (isset($chapterList->data['data'][$idx + 1])) {
- $data['next_id'] = $chapterList->data['data'][$idx + 1]['id'];
- } else {
- $data['next_id'] = '';
- }
- }
- break;
- }
- }
- if (empty($data)) {
- return $this->setCode(ClientApiConstants::CHAPTER_NOT_EXIST)->getReturn();
- }
- $redis = Redis::instance();
- $cacheKey = CacheConstants::getBookSingleChapterCacheKey($chapterInfoId);
- $aChapter = [];
- if ($redis->exists($cacheKey)) {
- if (json_decode($redis->get($cacheKey), true)) {
- $aChapter = json_decode($redis->get($cacheKey), true);
- } else {
- $aChapter = $redis->get($cacheKey);
- $aChapter = str_replace('<p>', '', $aChapter);
- $aChapter = explode('</p>', $aChapter);
- }
- } else {
- $path = Config::get('site.chapter_path');
- if (empty($path)) {
- $path = 'cppartner';
- }
- $file = $this->getChapterContentPath($path, $bookId, $chapterInfoId);
- LogService::info('章节文件路径:' . $file);
- if (is_file($file)) {
- $content = file_get_contents($file);
- $content = str_replace("\r", '', $content);
- $arr = explode("\n", $content);
- foreach ($arr as $value) {
- $value = ltrim($value, "\0\t\n\\x0B\r ");
- $value = mb_convert_encoding($value, "UTF-8", "UTF-8"); //强制转换一次UTF-8编码
- if ($value) {
- $aChapter[] = $value;
- }
- }
- } else {
- LogService::error('获取章节内容失败!书籍路径:' . $file . ',ID:' . $bookId . ' 章节ID:' . $chapterInfoId);
- $data['status'] = ClientApiConstants::ORDER_CHAPTER_STATE_NO_CONTENT;
- }
- if ($aChapter) {
- $keyNum = sprintf('BCN:%s:%s', $chapterInfoId, date('i'));
- if ($redis->incr($keyNum) > 10) {
- $redis->setex($cacheKey, 3600, json_encode($aChapter, true));
- }
- $redis->expire($keyNum, 60);
- }
- }
- $data['content'] = is_array($aChapter) ? implode("\n", $aChapter) : $aChapter;
- return $this->setData($data)->getReturn();
- } catch (\Exception $e) {
- LogService::exception($e);
- return $this->getExceptionReturn($e);
- }
- }
- /**
- * 获取书籍全部章节信息
- * @param $bookId 书籍id
- * @return ReturnObject
- */
- public function getChapterListForClient($bookId)
- {
- $chapters = model("Book")::getChapterLimit($bookId, 0, -1);
- if (empty($chapters)) {
- return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->setMsg('没有获取到目录信息')->getReturn();
- } else {
- return $this->setData($chapters)->getReturn();
- }
- }
- /**
- * 获取app使用的推荐书籍id列表
- * @param $sex 性别
- * @param int $limit
- * @return array|mixed
- */
- public function getRecommendBookIdsForClient($sex, $limit)
- {
- $redis = Redis::instance();
- $key = sprintf('%s:%s:%s', ClientApiConstants::RECOMMAND_BOOK_KEY, $sex, $limit);
- if ($redis->exists($key)) {
- $data = $redis->get($key);
- $ids = json_decode($data, true);
- } else {
- if ($sex != 0) {
- $map['sex'] = $sex;
- }
- $map['state'] = 1;
- $ids = model('Book')->where($map)->order("idx", "desc")->limit($limit)->column("id");
- $json = json_encode($ids);
- $redis->setex($key, 900, $json);
- }
- return $ids;
- }
- /**
- * 删除最近阅读记录
- * @param $recentId
- * @param $bookId
- * @param null $userId
- * @return ReturnObject
- */
- public function removeRecentlyRead_old($recentId, $bookId, $userId = null)
- {
- $result = $this->getUserRecentlyRead()->removeBook($recentId, $bookId, $userId);
- if ($result) {
- return $this->getReturn();
- } else {
- return $this->setCode(ErrorCodeConstants::API_ERROR)->setMsg('删除最近阅读失败')->getReturn();
- }
- }
- /**
- * @param $aRecentIds
- * @param $aBookIds
- * @param null $userId
- * @return ReturnObject
- */
- public function removeRecentlyRead($aRecentIds, $aBookIds, $userId = null)
- {
- if (!$userId) {
- $userId = UserService::instance()->getUserInfo()->id;
- }
- if (empty($aRecentIds)) {
- LogService::error('删除最近阅读失败,$aRecentIds为空,userId:' . $userId);
- return $this->setCode(ErrorCodeConstants::API_ERROR)->setMsg('删除最近阅读失败')->getReturn();
- }
- if (empty($aBookIds)) {
- LogService::error('删除最近阅读失败,$aBookIds为空,userId:' . $userId);
- return $this->setCode(ErrorCodeConstants::API_ERROR)->setMsg('删除最近阅读失败')->getReturn();
- }
- $userRecentModel = $this->getUserRecentlyRead()->setConnect($userId);
- $dbRes = $userRecentModel->whereIn('id', $aRecentIds)->update(['flag' => 0]);
- if ($dbRes) {
- $redis = Redis::instance();
- $urKey = $userRecentModel->getURKey($userId);
- $ubKeys = [];
- foreach ($aBookIds as $bookId) {
- $ubKeys[] = $userRecentModel->getUBKey($userId, $bookId);
- }
- $redis->zrem($urKey, ...$ubKeys);
- $getUBKeyRedisIndex = Redis::splitKeysByRule($ubKeys);
- array_walk($getUBKeyRedisIndex, function ($v, $k) {
- $redis = Redis::getRedisConnect($k);
- $redis->del(...$v);
- });
- }
- return $this->getReturn();
- }
- /**
- * 获取书籍客户端需要的状态
- * @param array $bookInfo 书籍信息
- * @param $chapterKey 最后一章id
- * @return int
- */
- public static function makeBookStatusForClient($bookInfo, $chapterKey = null)
- {
- if ($bookInfo['state'] == 0) {
- return ClientApiConstants::BOOK_STATE_OFF;
- }
- if (isset($chapterKey) && $bookInfo['last_chapter_id'] != $chapterKey) {
- return ClientApiConstants::BOOK_STATE_UPDATE;
- }
- $now = time();
- if ($now > $bookInfo['free_stime'] && $now < $bookInfo['free_etime']) {
- return ClientApiConstants::BOOK_STATE_LIMIT_FREE;
- }
- return ClientApiConstants::BOOK_STATE_NORMAL;
- }
- #region 书架相关
- /**
- * 从最近阅读记录表获取书架信息
- * @param int $updatetime
- * @param int $pageSize
- * @param bool $userId
- * @return array
- */
- private function _getBookShelf($updatetime = 0, $pageSize = 10, $userId = false)
- {
- if (!$userId) {
- $userId = UserService::instance()->getUserInfo()->id;
- }
- $redis = Redis::instance();
- $usKey = $this->getUserRecentlyRead()->getUSKey($userId);
- if ($updatetime) {
- $pageBegin = $updatetime - 1;
- $resUS = $redis->zRevRangeByScore($usKey, $pageBegin, '-inf', ['limit' => [0, $pageSize]]);
- } else {
- $pageBegin = 0;
- $resUS = $redis->zRevRange($usKey, 0, $pageSize - 1);
- }
- if (empty($resUS)) {
- $result = $this->getUserRecentlyRead()->getShelfRecentlyByDB($userId, $pageBegin, $pageSize);
- } else {
- $result = $this->getUserRecentlyRead()->getShelfRecentlyByRedis($userId, $resUS);
- #region 如果U-B中没有book_shelf_add或者book_shelf_flag属性,那么从数据库中获取
- // 此处代码上线一段时间后可删除
- foreach ($result as $item) {
- if (!isset($item['book_shelf_add']) || !isset($item['book_shelf_flag'])) {
- // 将shelf库里的数据刷到阅读记录
- $result = $this->getUserRecentlyRead()->getShelfRecentlyByDB($userId, $pageBegin, $pageSize);
- break;
- }
- }
- #endregion
- }
- $bookIds = array_column($result, 'book_id');
- $booksInfo = model('Book')->getBooksInfo($bookIds);
- foreach ($result as &$item) {
- $bookId = $item['book_id'];
- if (isset($booksInfo[$bookId])) {
- $book = $booksInfo[$bookId];
- $item['image'] = $book['image'];
- $item['name'] = $book['name'];
- $item['state'] = $book['state'];
- $item['free_stime'] = $book['free_stime'];
- $item['free_etime'] = $book['free_etime'];
- $item['chapter_id'] = empty($item['chapter_id']) ? $book['first_chapter_id'] : $item['chapter_id'];
- $item['last_chapter_id'] = $book['last_chapter_id'];
- $item['recommend'] = false;
- }
- }
- return $result;
- }
- /**
- * 获取用户的书架
- * @return ReturnObject
- */
- public function getBookShelf()
- {
- try {
- // 获取用户加入书架的书籍id
- $shelfBooks = $this->getRecommendShelfBooks();
- $recommendShelfBooks = ArrayHelper::array_column_search($shelfBooks, 'insert_type',
- BookConstants::SHELF_INSERT_TYPE_RECOMMEND, false);
- $recommendShelfBookIds = array_column($recommendShelfBooks, 'book_id');
- $userInfo = UserService::instance()->getUserInfo();
- $userId = $userInfo->id;
- $redis = Redis::instance();
- #region 如果shelf数据库有用户主动加入的书籍,迁移到最近阅读表,并删除shelf表的数据
- if (count($shelfBooks) > count($recommendShelfBooks)) {
- $userRecentlyModel = $this->getUserRecentlyRead()->setConnect($userId);
- $shelfBookIds = array_column($shelfBooks, 'book_id');
- $needToRecentBookIds = array_diff($shelfBookIds, $recommendShelfBookIds);
- //用户已经阅读过的书籍
- $existBookIds = $userRecentlyModel->whereIn('book_id',
- $needToRecentBookIds)->where('user_id', $userId)->column('book_id');
- //修改数据库
- if (!empty($existBookIds)) {
- $userRecentlyModel->whereIn('book_id',
- $existBookIds)->where('user_id', $userId)->update([
- 'book_shelf_add' => 1,
- 'book_shelf_flag' => 1
- ]);
- }
- //插入数据库
- $unReadBookIds = array_diff($needToRecentBookIds, $existBookIds);
- $insData = [];
- foreach ($unReadBookIds as $unReadBookId) {
- $insData[] = [
- 'user_id' => $userId,
- 'book_id' => $unReadBookId,
- 'chapter_id' => 0,
- 'chapter_name' => '',
- 'flag' => 1,
- 'book_shelf_add' => 1,
- 'book_shelf_flag' => 1,
- 'createtime' => time(),
- 'updatetime' => time(),
- ];
- }
- $userRecentlyModel->insertAll($insData);
- #region 删除redis U-R U-B
- $redis->del($userRecentlyModel->getURKey($userId));
- $ubKeys = [];
- foreach ($needToRecentBookIds as $needToRecentBookId) {
- $ubKeys[] = $userRecentlyModel->getUBKey($userId, $needToRecentBookId);
- }
- $getUBRedisIndex = Redis::splitKeysByRule($ubKeys);
- array_walk($getUBRedisIndex, function ($v, $k) {
- $redis = Redis::getRedisConnect($k);
- $redis->del(...$v);
- });
- $redis->del($this->_shelfBooksKey($userId));
- #endregion
- //删除书架数据库里的非推荐书籍
- $this->getBookShelfModel()->setConnect($userId)->where('user_id', $userId)->whereIn('book_id',
- $needToRecentBookIds)->update(['flag' => Common::NO]);
- }
- #endregion
- $userRecentlyList = model('UserRecentlyRead')->setConnect($userId)->getRecentlyRead(0, 50, $userId);
- $userRecentlyList = $userRecentlyList['data'];
- $channelId = UserService::instance()->getUserChannelId()->data;
- $isWater = WaterBookService::instance()->showBook($channelId, $userId, Ip::ip());
- #region 为推荐书籍增加书籍属性
- $recommendShelfBookInfos = $this->getBookModel()->getBooksInfo($recommendShelfBookIds);
- $recommendSimpleBooksInfo = [];
- foreach ($recommendShelfBookInfos as $recommendShelfBookInfo) {
- $userRecentlyItem = ArrayHelper::array_column_search($userRecentlyList, 'book_id',
- $recommendShelfBookInfo['id']);
- $recentlyChapterId = empty($userRecentlyItem) ? $recommendShelfBookInfo['first_chapter_id'] : $userRecentlyItem['chapter_id'];
- $_recommendBookInfo = ArrayHelper::array_column_search($recommendShelfBooks, 'book_id',
- $recommendShelfBookInfo['id']);
- $recommendBookUpdatetime = empty($_recommendBookInfo['updatetime']) ? 0 : $_recommendBookInfo['updatetime'];
- $item = [
- 'book_id' => $recommendShelfBookInfo['id'],
- 'image' => $recommendShelfBookInfo['image'],
- 'name' => $recommendShelfBookInfo['name'],
- 'state' => $recommendShelfBookInfo['state'],
- 'free_stime' => $recommendShelfBookInfo['free_stime'],
- 'free_etime' => $recommendShelfBookInfo['free_etime'],
- 'chapter_id' => $recentlyChapterId,
- 'last_chapter_id' => $recommendShelfBookInfo['last_chapter_id'],
- 'updatetime' => $recommendBookUpdatetime,
- 'recommend' => true,
- ];
- if ($isWater && (!isset($recommendShelfBookInfo['classify_white_list']) || $recommendShelfBookInfo['classify_white_list'] != 1)) {
- $item['state'] = 0;
- }
- $recommendSimpleBooksInfo[] = $item;
- }
- #endregion
- // $recentSimpleList = $this->_getBookShelf(0, 100);
- #region 从最近阅读记录表获取书架信息
- $usKey = $this->getUserRecentlyRead()->getUSKey($userId);
- $pageBegin = 0;
- $resUS = $redis->zRevRange($usKey, 0, 99);
- if (empty($resUS)) {
- $result = $this->getUserRecentlyRead()->getShelfRecentlyByDB($userId, $pageBegin, 100);
- } else {
- $result = $this->getUserRecentlyRead()->getShelfRecentlyByRedis($userId, $resUS);
- }
- $bookIds = array_column($result, 'book_id');
- $booksInfo = model('Book')->getBooksInfo($bookIds);
- foreach ($result as &$item) {
- $bookId = $item['book_id'];
- if (isset($booksInfo[$bookId])) {
- $book = $booksInfo[$bookId];
- $item['image'] = $book['image'];
- $item['name'] = $book['name'];
- $item['state'] = $book['state'];
- if ($isWater && (!isset($book['classify_white_list']) || $book['classify_white_list'] != 1)) {
- $item['state'] = 0;
- }
- $item['free_stime'] = $book['free_stime'];
- $item['free_etime'] = $book['free_etime'];
- $item['chapter_id'] = empty($item['chapter_id']) ? $book['first_chapter_id'] : $item['chapter_id'];
- $item['last_chapter_id'] = $book['last_chapter_id'];
- $item['recommend'] = false;
- }
- }
- $recentSimpleList = $result;
- #endregion
- $booksInfo = array_merge($recommendSimpleBooksInfo, $recentSimpleList);
- $sortArr = array_column($booksInfo, 'updatetime');
- array_multisort($sortArr, SORT_DESC, $booksInfo);
- #region 书架书籍展示逻辑
- $freeLimit = array_keys(BuyMoreService::instance()->getFreeLimitCacheBook($userId)->data);
- $permanent = FinancialService::instance()->getConsumeModel()->setConnect($userId)
- ->where('type', BookConstants::BOOK_BILLING_MODEL_BOOK)
- ->where('kandian', 0)
- ->where('free_kandian', 0)
- ->column('book_id');
- foreach ($booksInfo as &$item) {
- if ($item['state'] == 0) {//书籍下架
- $item['show_status'] = 0;
- } elseif (in_array($item['book_id'], $permanent)) {//充值加购,赠送
- $item['show_status'] = 1;
- } elseif ($item['free_stime'] <= time() && $item['free_etime'] >= time()) {//限免
- $item['show_status'] = 2;
- } elseif (in_array($item['book_id'], $freeLimit)) {//充值加购,限免
- $item['show_status'] = 5;
- } elseif ($userInfo->vip_endtime > time() && !VipCpService::instance()->isFreeCpBookForVip($item['book_id'], $userId, $userInfo->vip_endtime)) {
- // vip 用户进行 CP书籍,对VIP收费
- $item['show_status'] = 11;
- } elseif ($item['recommend'] == true) {//推荐
- $item['show_status'] = 3;
- } elseif ($item['chapter_id'] < $item['last_chapter_id']) {//更新
- $item['show_status'] = 4;
- } elseif (in_array($item['book_id'], $freeLimit)) {//充值加购,限免
- $item['show_status'] = 5;
- } else {
- $item['show_status'] = 10;
- }
- }
- #endregion
- return $this->setCode(ErrorCodeConstants::SUCCESS)->setData($booksInfo)->getReturn();
- } catch (\Exception $e) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg($e->getMessage())->getReturn();
- }
- }
- /**
- * 是否展示 '非VIP书籍' 角标
- * @param $book_id
- * @return bool
- */
- public function showCpVipSubScript($book_id)
- {
- return false;
- /*$userInfo = UserService::instance()->getUserInfo();
- $vip_endtime = $userInfo->vip_endtime;
- if ($vip_endtime > time()) {
- if (VipCpService::instance()->isFreeCpBookForVip($book_id, $userInfo->id, $vip_endtime)) {
- return false;
- } else {
- return true;
- }
- } else {
- return false;
- }*/
- }
- /**
- * 获取书籍角标, 角标优先级:下架 -> 限免 -> 付费书籍 -> 推荐
- * @param array $bookinfo
- * @return int
- */
- /*public function getBookSubscript(array $bookinfo)
- {
- $show_status = -1;
- $userInfo = UserService::instance()->getUserInfo();
- $userId = $userInfo->id;
- $vip_endtime = $userInfo->vip_endtime;
- $bookinfo['recommend'] = true;
- $freeLimit = array_keys(BuyMoreService::instance()->getFreeLimitCacheBook($userId)->data);
- $permanent = FinancialService::instance()->getConsumeModel()->setConnect($userId)
- ->where('type', BookConstants::BOOK_BILLING_MODEL_BOOK)
- ->where('kandian', 0)
- ->where('free_kandian', 0)
- ->column('book_id');
- if ($bookinfo['state'] == 0) {//书籍下架
- $show_status = 0;
- } elseif (in_array($bookinfo['id'], $permanent)) {//充值加购,赠送
- $show_status = 1;
- } elseif ($bookinfo['free_stime'] <= time() && $bookinfo['free_etime'] >= time()) {//限免
- $show_status = 2;
- } elseif (in_array($bookinfo['id'], $freeLimit)) {//充值加购,限免
- $show_status = 5;
- } elseif ($vip_endtime > time()) { // vip 用户进行
- if (!VipCpService::instance()->isFreeCpBookForVip($bookinfo['id'], $userId, $vip_endtime)) {
- // CP书籍,对VIP收费
- $show_status = 11;
- }
- } elseif ($bookinfo['recommend'] == true) {//推荐
- $show_status = 3;
- } elseif ($bookinfo['chapter_id'] < $bookinfo['last_chapter_id']) {//更新
- $show_status = 4;
- } elseif (in_array($bookinfo['id'], $freeLimit)) {//充值加购,限免
- $show_status = 5;
- } else {
- $show_status = 10;
- }
- return $show_status;
- }*/
- /**
- * 获取用户加入书架书籍信息列表
- * @param $userId
- * @return array|mixed
- */
- private function getRecommendShelfBooks($userId = null)
- {
- if (empty($userId)) {
- $userInfo = UserService::instance()->getUserInfo();
- $userId = $userInfo->id;
- }
- $key = $this->_shelfBooksKey($userId);
- $redis = Redis::instance();
- if ($strData = $redis->get($key)) {
- $shelfBooks = json_decode($strData, true);
- } else {
- $shelfBooks = $this->getBookShelfModel()->setConnect($userId)
- ->where('user_id', $userId)
- ->where('flag', Common::YES)
- ->order('id')
- ->field(['id', 'book_id', 'updatetime', 'insert_type'])
- ->select();
- $strData = json_encode($shelfBooks);
- $redis->setex($key, 86400, $strData);
- }
- return $shelfBooks;
- }
- /**
- * 删除用户推荐库中的推荐书籍
- * @param $bookId
- * @param $userId
- */
- private function delRecommendShelfBookByBookId($bookId, $userId)
- {
- $recommendBooks = $this->getRecommendShelfBooks($userId);
- $recmdShelfBookInfo = ArrayHelper::array_column_search($recommendBooks, 'book_id', $bookId);
- if (!empty($recmdShelfBookInfo)) {
- $key = $this->_shelfBooksKey($userId);
- $redis = Redis::instance();
- $this->getBookShelfModel()->setConnect($userId)
- ->where('id', $recmdShelfBookInfo['id'])
- ->update(['flag' => Common::NO]);
- $recommendBooksDeleted = [];
- foreach ($recommendBooks as $item) {
- if ($item['id'] == $recmdShelfBookInfo['id']) {
- continue;
- }
- $recommendBooksDeleted[] = $item;
- }
- $strData = json_encode($recommendBooksDeleted);
- $redis->setex($key, 86400, $strData);
- }
- }
- /**
- * 获取书架展示书库的书籍id列表
- * @return array|mixed
- */
- public function getShelfRecommendBookIds($sex,$isWater=false)
- {
- $sex = $sex == 0 ? 1 : $sex;
- $key = $this->_shelfRecommendBookIdsKey($sex,$isWater);
- $redis = Redis::instance();
- if ($strData = $redis->get($key)) {
- $ids = json_decode($strData, true);
- } else {
- $waterWhere = $isWater ? ' and classify_white_list=1' : '';
- $obj = model('BookshelfRecommand')->alias('bsf');
- $obj->join('book','book.id=book_id and book.state=1'.$waterWhere,'inner');
- $ids = $obj ->where('bsf.sex', $sex)->where('bsf.status', Common::STATUS_NORMAL)->limit(6)->column('bsf.book_id');
- $strData = json_encode($ids);
- $redis->set($key, $strData);
- $redis->expire($key,900);
- }
- return $ids;
- }
- /**
- * 书籍推广书籍插入用户书架
- * @param $userId
- * @param $sex
- * @return bool
- */
- public function insertShelfRecommendBooks($userId, $sex,$channelId)
- {
- try {
- $channelId = AdminService::instance()->getAdminExtendModel()->getChannelId($channelId);
- $isWater = WaterBookService::instance()->showBook($channelId,$userId);
- $bookIds = $this->getShelfRecommendBookIds($sex, $isWater);
- if (empty($bookIds)) {
- return false;
- }
- $data = [];
- foreach ($bookIds as $bookId) {
- $data[] = [
- 'user_id' => $userId,
- 'book_id' => $bookId,
- 'insert_type' => BookConstants::SHELF_INSERT_TYPE_RECOMMEND,
- 'createtime' => time(),
- 'updatetime' => time(),
- ];
- }
- $this->getBookShelfModel()->setConnect($userId)->insertAll($data);
- return true;
- } catch (\Exception $e) {
- LogService::error($e->getMessage());
- }
- }
- /**
- * 清除书架展示书库缓存
- */
- public function clearShelfRecommendBookIds()
- {
- try {
- $redis = Redis::instance();
- $key = $this->_shelfRecommendBookIdsKey(1);
- $redis->del($key);
- $key = $this->_shelfRecommendBookIdsKey(2);
- $redis->del($key);
- $key = $this->_shelfRecommendBookIdsKey(1,true);
- $redis->del($key);
- $key = $this->_shelfRecommendBookIdsKey(1,true);
- $redis->del($key);
- return $this->getReturn();
- } catch (\Exception $e) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setData($e->getMessage())->getReturn();
- }
- }
- /**
- * 清除文末书籍推荐缓存
- */
- public function clearNovelEndRecommendBookIds()
- {
- try {
- $redis = Redis::instance();
- $key = $this->_novelEndRecommendBookIdsKey(1);
- $redis->del($key);
- $key = $this->_novelEndRecommendBookIdsKey(2);
- $redis->del($key);
- $redis->del('NERC:W:' . 1);
- $redis->del('NERC:W:' . 2);
- return $this->getReturn();
- } catch (\Exception $e) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setData($e->getMessage())->getReturn();
- }
- }
- /**
- * 构造用户加入书架书籍id缓存的key
- * @param $userId
- * @return string
- */
- private function _shelfBooksKey($userId)
- {
- return 'SBIK:' . $userId;
- }
- /**
- * 构造书架推荐书籍id缓存的key
- * @param $sex
- * @return string
- */
- private function _shelfRecommendBookIdsKey($sex,$isWater=false)
- {
- return $isWater ? 'BEHD:W:' . $sex : 'BEHD:' . $sex;
- }
- /**
- * 构造文末书架推荐书籍id缓存的key
- * @param $sex
- * @return string
- */
- private function _novelEndRecommendBookIdsKey($sex)
- {
- return 'NERC:' . $sex;
- }
- /**
- * 加入书架
- * @param $bookId string 书籍id
- * @param $userId
- * @return ReturnObject
- */
- public function setBookShelf($bookId, $userId = null)
- {
- try {
- if (empty($userId)) {
- $userId = UserService::instance()->getUserInfo()->id;
- }
- $recentlyReadModel = $this->getUserRecentlyRead();
- $usKey = $recentlyReadModel->getUSKey($userId);
- $ubKey = $recentlyReadModel->getUBKey($userId, $bookId);
- $redis = Redis::instance();
- $RecentlyReadDB = $this->getUserRecentlyRead()->setConnect($userId);
- if (!($userRead = $redis->hGetAll($ubKey))) {
- $userRead = $RecentlyReadDB->getone($userId, $bookId);
- $userRead = $userRead ? $userRead->toArray() : null;
- }
- $userRecentInfo = [
- 'updatetime' => time(),
- 'book_shelf_add' => 1,
- 'book_shelf_flag' => 1,
- 'flag' => 0,//用户主动加入书架,阅读记录不生效
- ];
- if (!empty($userRead)) { //更新
- $getId = $userRead['id'];
- $RecentlyReadDB->where(['id' => $getId])->update($userRecentInfo);
- $userRecentInfo = array_merge($userRead, $userRecentInfo);//构造redis用的数据
- } else {//创建阅读记录
- $userRecentInfo['user_id'] = $userId;
- $userRecentInfo['book_id'] = $bookId;
- $userRecentInfo['createtime'] = time();
- $userRecentInfo['chapter_id'] = 0;
- $userRecentInfo['chapter_name'] = "";
- $RecentlyReadDB->insert($userRecentInfo);
- $id = $RecentlyReadDB->getLastInsID();
- $userRecentInfo['id'] = $id;
- if (!$redis->exists($usKey)) { //(如果redis里最近阅读记录为空拉取一下最近阅读记录防灾)
- $RecentlyReadDB->getRecentlyRead(time() + 1, 10, $userId);
- }
- }
- $redis->hMSet($ubKey, $userRecentInfo);
- $redis->expire($ubKey, 43200);
- $redis->zAdd($usKey, $userRecentInfo['updatetime'], $ubKey);
- $redis->expire($usKey, 43200);
- $this->delRecommendShelfBookByBookId($bookId, $userId);
- return $this->getReturn();
- } catch (\Exception $e) {
- return $this->getExceptionReturn($e);
- }
- }
- /**
- * 用户删除书架上的书籍
- * @param array $bookIds 书籍id列表
- * @return ReturnObject
- */
- public function delBookShelf($bookIds)
- {
- if (empty($bookIds)) {
- return $this->setCode(ErrorCodeConstants::API_ERROR)->setMsg('删除书籍id为空')->getReturn();
- }
- $userInfo = UserService::instance()->getUserInfo();
- $userId = $userInfo->id;
- $userRecentModel = $this->getUserRecentlyRead();
- try {
- #region 书架分库里删除数据
- $this->getBookShelfModel()->setConnect($userId)->where('user_id', $userId)
- ->whereIn('book_id', $bookIds)
- ->where('flag', Common::YES)
- ->update(['flag' => Common::NO, 'updatetime' => time()]);
- //删除书架书籍id列表缓存 & 删除书架排除书籍id列表缓存
- $redis = Redis::instance();
- $shelfBookIdsKey = $this->_shelfBooksKey($userId);
- $redis->del($shelfBookIdsKey);
- #endregion
- #region 阅读记录表里删除数据
- $recentlyRead = $userRecentModel->setConnect($userId);
- $recentlyRead->where('user_id', $userId)->whereIn('book_id', $bookIds)->update([
- 'book_shelf_add' => 1,
- 'book_shelf_flag' => 0
- ]);
- #endregion
- #region 删除U-B的数据
- $ubKeys = [];
- foreach ($bookIds as $bookId) {
- $ubKeys[] = $userRecentModel->getUBKey($userId, $bookId);
- }
- $getUBRedisIndex = Redis::splitKeysByRule($ubKeys);
- array_walk($getUBRedisIndex, function ($v, $k) {
- $redis = Redis::getRedisConnect($k);
- $redis->del(...$v);
- });
- #endregion
- #region 在U-S中删除U-B的元素
- $usKey = $userRecentModel->getUSKey($userId);
- $redis->zRem($usKey, ...$ubKeys);
- #endregion
- return $this->getReturn();
- } catch (\Exception $e) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->getReturn();
- }
- }
- /**
- * 检查用户是否将书籍加入书架
- * @param $bookId
- * @return ReturnObject
- */
- public function checkBookInShelf($bookId)
- {
- try {
- $shelfBooks = $this->getRecommendShelfBooks();
- $result = ArrayHelper::array_column_search($shelfBooks, 'book_id', $bookId);
- if (!empty($result)) {
- return $this->setCode(ErrorCodeConstants::SUCCESS)->setData(true)->getReturn();
- }
- $userInfo = UserService::instance()->getUserInfo();
- $userId = $userInfo->id;
- $usKey = $this->getUserRecentlyRead()->getUSKey($userId);
- $ubKey = $this->getUserRecentlyRead()->getUBKey($userId, $bookId);
- $redis = Redis::instance();
- $score = $redis->zScore($usKey, $ubKey);
- if (empty($score)) {
- $bookShelfList = $this->_getBookShelf(0, 100);
- $match = ArrayHelper::array_column_search($bookShelfList, 'book_id', $bookId);
- if (empty($match)) {
- return $this->setCode(ErrorCodeConstants::SUCCESS)->setData(false)->getReturn();
- } else {
- return $this->setCode(ErrorCodeConstants::SUCCESS)->setData(true)->getReturn();
- }
- } else {
- return $this->setCode(ErrorCodeConstants::SUCCESS)->setData(true)->getReturn();
- }
- } catch (\Exception $e) {
- return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg($e->getMessage())->getReturn();
- }
- }
- /**
- * 获取当前渠道商是否展示书架功能
- * @return bool
- */
- public function showBookShelfFun()
- {
- /*$showBookShelf = false;
- $bookShelfChannelWhitelist = config('site.book_shelf_channel_whitelist');
- if ($bookShelfChannelWhitelist == '-1') {
- $showBookShelf = true;
- } elseif ($bookShelfChannelWhitelist == '0') {
- $showBookShelf = false;
- } else {
- $aBookShelfChannelWhite = explode(',', $bookShelfChannelWhitelist);
- $channel_id = UserService::instance()->getUserInfo()->channel_id;
- if (in_array($channel_id, $aBookShelfChannelWhite)) {
- $showBookShelf = true;
- }
- }
- return $showBookShelf;*/
- $channel_id = UserService::instance()->getUserInfo()->channel_id;
- return model("ChannelSpecialManage")->isWhite("show_shelf", $channel_id);
- }
- #endregion
- /**
- * 获取章末推荐书籍
- * @param $book_id
- * @param $chapter_id
- * @return ReturnObject
- */
- public function getChapterEndRecommendBook($book_id, $chapter_id)
- {
- $return = false;
- $cacheKey = CacheConstants::getChapterEndRecommendIds($book_id);
- $book_info = [];
- if ($list = Redis::instance()->zRangeByScore($cacheKey, 0, $chapter_id)) {
- foreach ($list as $index=>$item) {
- $book_info[$index] = json_decode($item, true);
- }
- } else {
- $list = $this->getChapterEndRecommendModel()
- ->alias('ce')
- ->join('book', 'book.id=ce.relation_book_id')
- ->where('book.state', BookConstants::BOOK_STATE_ON_SALE)
- ->where('ce.book_id', $book_id)
- ->where('ce.status', 'normal')
- ->field('ce.relation_book_id, ce.chapter_show, ce.recommend, ce.tip')
- ->select();
- if ($list) {
- foreach ($list as $item) {
- Redis::instance()->zAdd($cacheKey, $item['chapter_show'], json_encode($item->getData(), JSON_UNESCAPED_UNICODE));
- }
- foreach ($list as $index=>$item) {
- $book_info[$index] = $item->getData();
- }
- } else {
- Redis::instance()->zAdd($cacheKey, 0, '{"chapter_show":0}');
- }
- Redis::instance()->expire($cacheKey, 600);
- }
- $end_close = Cookie::get('chapter_end-'.$book_id);
- if ($end_close) {
- $close_ids = explode('.', $end_close);
- } else {
- $close_ids = [];
- }
- $book_info = array_filter($book_info, function ($v) use ($chapter_id, $close_ids) {
- return $v['chapter_show'] && $v['chapter_show'] <= $chapter_id && !in_array($v['relation_book_id'], $close_ids);
- });
- if ($book_info) {
- $random = ArrayHelper::array_random($book_info);
- $mBook = \app\common\service\BookService::instance()->getBookModel();
- $book = $mBook->BookInfo($random['relation_book_id']);
- if ($book) {
- $return = array_merge($book, $random);
- if (!$return['recommend']) {
- $return['recommend'] = $book['description'];
- }
- if (mb_strlen($return['recommend']) > 30) {
- $return['recommend'] = mb_substr($return['recommend'], 0, 30) . '...';
- }
- }
- }
- return $this->setData($return)->getReturn();
- }
- /*
- * 榜单列表 rank1男频 rank2女频 rank0不区分男女 按照idx排序
- */
- public function ranklist($type, $is_water)
- {
- if($is_water){
- $join = ' and book.classify_white_list=1';
- $key0 = 'RANK:0:W';
- $key1 = 'RANK:1:W';
- $key2 = 'RANK:2:W';
- }else{
- $join = '';
- $key0 = 'RANK:0';
- $key1 = 'RANK:1';
- $key2 = 'RANK:2';
- }
- $boydata = [];
- $girldata = [];
- if (Redis::instance()->exists($key1) && Redis::instance()->exists($key2) && Redis::instance()->exists($key0)) {
- $boydata = json_decode(Redis::instance()->get($key1), true);
- $girldata = json_decode(Redis::instance()->get($key2), true);
- $idxdata = json_decode(Redis::instance()->get($key0), true);
- } else {
- $boydata['click'] = collection(
- model('Book')->join('book_category bc','bc.id = book.book_category_id'.$join,'LEFT')
- ->where(['book.state' => 1, 'book.sex' => 1])
- ->field('book.*,bc.name as bc_name')
- ->order('book.read_num desc')
- ->limit(10)
- ->select()
- )->toArray();
- foreach ($boydata['click'] as &$value) {
- $value['vip_pay'] = BookService::instance()->showCpVipSubScript($value['id']);
- $value['read_nums'] = friend_date($value['read_num']);
- $value['author'] = $value['bc_name'];
- }
- $boydata['idx'] = collection(
- model('Book')->join('book_category bc','bc.id = book.book_category_id'.$join,'LEFT')
- ->where(['book.state' => 1, 'book.sex' => 1])
- ->field('book.*,bc.name as bc_name')
- ->order('book.idx desc')
- ->limit(10)
- ->select()
- )->toArray();
- foreach ($boydata['idx'] as &$value) {
- $value['vip_pay'] = BookService::instance()->showCpVipSubScript($value['id']);
- $value['read_nums'] = friend_date($value['read_num']);
- $value['author'] = $value['bc_name'];
- }
- $girldata['click'] = collection(
- model('Book')->join('book_category bc','bc.id = book.book_category_id'.$join,'LEFT')
- ->where(['book.state' => 1, 'book.sex' => 2])
- ->field('book.*,bc.name as bc_name')
- ->order('book.read_num desc')
- ->limit(10)
- ->select()
- )->toArray();
- foreach ($girldata['click'] as &$value) {
- $value['vip_pay'] = BookService::instance()->showCpVipSubScript($value['id']);
- $value['read_nums'] = friend_date($value['read_num']);
- $value['author'] = $value['bc_name'];
- }
- $girldata['idx'] = collection(
- model('Book')->join('book_category bc','bc.id = book.book_category_id'.$join,'LEFT')
- ->where(['book.state' => 1, 'book.sex' => 2])
- ->field('book.*,bc.name as bc_name')
- ->order('book.idx desc')
- ->limit(10)
- ->select()
- )->toArray();
- foreach ($girldata['idx'] as &$value) {
- $value['vip_pay'] = BookService::instance()->showCpVipSubScript($value['id']);
- $value['read_nums'] = friend_date($value['read_num']);
- $value['author'] = $value['bc_name'];
- }
- $idxdata['idx'] = collection(
- model('Book')->join('book_category bc','bc.id = book.book_category_id'.$join,'LEFT')
- ->where(['book.state' => 1])
- ->field('book.*,bc.name as bc_name')
- ->order('book.idx desc')
- ->limit(10)
- ->select()
- )->toArray();
- foreach ($idxdata['idx'] as &$value) {
- $value['vip_pay'] = BookService::instance()->showCpVipSubScript($value['id']);
- $value['read_nums'] = friend_date($value['read_num']);
- $value['author'] = $value['bc_name'];
- }
- if (!empty($boydata)) {
- Redis::instance()->setex($key1, 600, json_encode($boydata, JSON_UNESCAPED_UNICODE));
- }
- if (!empty($girldata)) {
- Redis::instance()->setex($key2, 600, json_encode($girldata, JSON_UNESCAPED_UNICODE));
- }
- if (!empty($idxdata)) {
- Redis::instance()->setex($key0, 600, json_encode($idxdata, JSON_UNESCAPED_UNICODE));
- }
- }
- if ($type == 1) {
- return $boydata;
- } elseif ($type == 2) {
- return $girldata;
- } elseif ($type == 'boy') {
- return $boydata;
- } elseif ($type == 'girl') {
- return $girldata;
- } else {
- return $idxdata;
- }
- }
- /*
- * 主编推荐列表
- */
- public function recommendList($book_id)
- {
- if($book_id){
- $bookInfo = model("book")->BookInfo($book_id);
- }else{
- return false;
- }
- $where = [];
- $where['state'] = '1';
- $where['book_category_id'] = $bookInfo['book_category_id'];
- //最近阅读
- $recentList = model('UserRecentlyRead')->getRecentlyRead(0);
- $recentIds[] = $bookInfo['id'];
- if ($recentList['totalNum'] > 0) {
- foreach ($recentList['data'] as $v) {
- $recentIds[] = $v['book_id'];
- }
- }
- if ($recentIds) {
- $where['id'] = ['not in', $recentIds];
- }
- $pagedata[0]['name'] = "主编推荐";
- $pagedata[0]['page_id'] = 1;
- $pagedata[0]['second_name'] = "主编推荐";
- $pagedata[0]['block_resource'] = collection(model("Book")
- ->where($where)
- ->order('rand()')
- ->limit(4)
- ->select())->toArray();
- if($pagedata[0]['block_resource']){
- foreach ($pagedata[0]['block_resource'] as &$v){
- $v['book_id'] = $v['id'];
- }
- }
- return $pagedata;
- }
- }
|