ClientAppService.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: lts
  5. * Date: 2019-04-01
  6. * Time: 19:01
  7. */
  8. namespace app\main\service;
  9. use app\common\library\Redis;
  10. use app\main\constants\ClientApiConstants;
  11. use app\common\model\ClientConfig;
  12. use app\common\model\User as mUser;
  13. use app\common\model\Recharge;
  14. use app\common\model\Sign;
  15. use app\common\model\ClientManageBlock;
  16. use app\common\model\ClientManageBlockResource;
  17. use app\common\model\Hearbook;
  18. use app\common\model\ClientDefaultRecommand;
  19. use app\main\constants\ErrorCodeConstants;
  20. use app\main\constants\MqConstants;
  21. use app\main\constants\PayConstants;
  22. use app\main\model\object\DotObject;
  23. use think\Config;
  24. use think\Request;
  25. use think\Url;
  26. class ClientAppService extends BaseService
  27. {
  28. protected $ranklivetime = 600; //榜单生存时间秒
  29. protected $hotsearch_extime = 86400; //热门搜索书籍默认保存1天
  30. protected $pex_fix = 'DZ#';
  31. /**
  32. * @var OpenPlatformService
  33. */
  34. protected static $self = null;
  35. const REGISTER_RULE = 'YmdH';
  36. /**
  37. * @return $this\OpenPlatformService
  38. */
  39. public static function instance()
  40. {
  41. if (self::$self == null) {
  42. self::$self = new self();
  43. }
  44. return self::$self;
  45. }
  46. /**
  47. * @return ClientConfig
  48. */
  49. public function getClientConfigModel()
  50. {
  51. return model('ClientConfig');
  52. }
  53. /**
  54. * @return Hearbook
  55. */
  56. public function getHearbookModel()
  57. {
  58. return model('Hearbook');
  59. }
  60. /**
  61. * @return mUser
  62. */
  63. public function getUserModel()
  64. {
  65. return model('User');
  66. }
  67. /**
  68. * @return Recharge
  69. */
  70. public function getRechargeModel()
  71. {
  72. return model('Recharge');
  73. }
  74. /**
  75. * @return Sign
  76. */
  77. public function getSignModel()
  78. {
  79. return model('Sign');
  80. }
  81. /**
  82. * @return ClientManageBlock
  83. */
  84. public function getClientManageBlockModel()
  85. {
  86. return model('ClientManageBlock');
  87. }
  88. /**
  89. * @return ClientManageBlockResource
  90. */
  91. public function getClientManageBlockResourceModel()
  92. {
  93. return model('ClientManageBlockResource');
  94. }
  95. /**
  96. * @return ClientDefaultRecommand
  97. */
  98. public function getClientDefaultRecommandModel()
  99. {
  100. return model('ClientDefaultRecommand');
  101. }
  102. public function getAppVersionModel()
  103. {
  104. return model('AppVersion');
  105. }
  106. /**
  107. * 加密
  108. * @param $str
  109. * @return string
  110. */
  111. private function encrypt($str)
  112. {
  113. $data = openssl_encrypt($str, 'AES-128-ECB', ClientApiConstants::USER_SIGN_KEY, OPENSSL_RAW_DATA);
  114. $data = base64_encode($data);
  115. return $data;
  116. }
  117. /**
  118. * 解密
  119. * @param $str
  120. * @return string
  121. */
  122. private function decrypt($str)
  123. {
  124. $decrypted = openssl_decrypt(base64_decode($str), 'AES-128-ECB', ClientApiConstants::USER_SIGN_KEY,
  125. OPENSSL_RAW_DATA);
  126. return $decrypted;
  127. }
  128. /**
  129. * 获取阳光app用户注册码
  130. * 按小时加用户id生成注册码,注册码在当前小时有效
  131. * @param $channelId CPS用户对应的渠道商id
  132. * @param $openId CPS用户的openid
  133. * @param $hasPreFix 是否加前缀 默认false
  134. * @return string
  135. */
  136. public function makeUserRegisterCode($channelId, $openId, $hasPreFix = false)
  137. {
  138. $str = date(self::REGISTER_RULE) . $channelId . '_' . $openId;
  139. if($hasPreFix){
  140. return $this->pex_fix.$this->encrypt($str);
  141. }else{
  142. return $this->encrypt($str);
  143. }
  144. }
  145. /**
  146. * 用户注册
  147. * @param $code
  148. * @return \app\main\model\object\ReturnObject
  149. */
  150. public function userRegister($code)
  151. {
  152. $str = $this->decrypt($code);
  153. if ($str === false) {
  154. return $this->setCode(ClientApiConstants::REGISTER_FAIL)->setMsg('微信动态码错误!')->getReturn();
  155. }
  156. $nowStr = date(self::REGISTER_RULE);
  157. $codeTimeStr = substr($str, 0, strlen($nowStr));
  158. if ($nowStr != $codeTimeStr) {
  159. return $this->setCode(ClientApiConstants::REGISTER_TIMEOUT)->setMsg('微信动态码超时!')->getReturn();
  160. }
  161. $str = str_replace($nowStr, '', $str);//去掉时间串后的字符串
  162. $separateIdx = strpos($str, '_');
  163. if ($separateIdx === false) {
  164. return $this->setCode(ClientApiConstants::REGISTER_TIMEOUT)->setMsg('微信动态码超时!')->getReturn();
  165. }
  166. $channelId = substr($str, 0, $separateIdx);
  167. $openId = substr($str, $separateIdx + 1, strlen($str) - $separateIdx - 1);
  168. $userId = OfficialAccountsService::instance()->getOpenidModel()->getUserId($channelId, $openId);
  169. if (empty($userId)) {
  170. return $this->setCode(ClientApiConstants::REGISTER_NON_EXISTENT_USER)->setMsg('用户不存在!')->getReturn();
  171. }
  172. //维护绑定时间
  173. $userInfo = $this->getUserModel()->getUserInfo($userId);
  174. if(empty($userInfo->bindtime)){
  175. UserService::instance()->update(['bindtime' => time()], ['id' => $userId]);
  176. }
  177. # S: APP用户绑定手机号打点
  178. $dotData = new DotObject();
  179. $userobj = $userInfo;
  180. $dotData->user_id = $userobj['id'];
  181. $dotData->channel_id = $userobj['channel_id'];
  182. $dotData->sex = $userobj['sex'];
  183. $dotData->business_line = PayConstants::BUSINESS_APP;
  184. $dotData->action_type = MqConstants:: ROUTING_KEY_APP_BIND_CODE;
  185. $dotData->type = MqConstants::MSG_TYPE_APP_BIND_CODE;
  186. $dotData->event_time = Request::instance()->server('REQUEST_TIME');
  187. LogService::info('[ codeRegister ] APP用户绑定手机号打点');
  188. MqService::instance()->sendMessage($dotData);
  189. # End: APP用户绑定手机号打点
  190. return $this->setData($userInfo)->getReturn();
  191. }
  192. /**
  193. * 获取Loading页面配置信息
  194. * @param $userInfo
  195. * @param $clientVersion
  196. * @return \app\main\model\object\ReturnObject
  197. * @throws \Exception
  198. */
  199. public function getClientConfigLoading($userInfo, $clientVersion)
  200. {
  201. $clientConfigList = $this->fetchClientConfig($userInfo, $clientVersion,
  202. ClientApiConstants::CLIENT_CONFIG_FUN_TYPE_LOADING, 1);
  203. if (count($clientConfigList) > 0) {
  204. $data = current($clientConfigList);
  205. $info = $this->ClientConfigFormat($data);
  206. return $this->setData($info)->getReturn();
  207. } else {
  208. return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
  209. }
  210. }
  211. /**
  212. * 获取书架配置信息
  213. * @param $userInfo
  214. * @param $clientVersion
  215. * @return \app\main\model\object\ReturnObject
  216. * @throws \Exception
  217. */
  218. public function getClientConfigBookShelf($userInfo, $clientVersion)
  219. {
  220. $clientConfigList = $this->fetchClientConfig($userInfo, $clientVersion,
  221. ClientApiConstants::CLIENT_CONFIG_FUN_TYPE_BOOKSHELF, 5);
  222. $result = [];
  223. foreach ($clientConfigList as $item) {
  224. $tmp = $this->ClientConfigFormat($item);
  225. $result[] = $tmp;
  226. }
  227. if (count($result) > 0) {
  228. return $this->setData($result)->getReturn();
  229. } else {
  230. return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
  231. }
  232. }
  233. /**
  234. * 获取弹窗配置信息
  235. * @param $userInfo
  236. * @param $clientVersion
  237. * @param $position
  238. * @return \app\main\model\object\ReturnObject
  239. * @throws \Exception
  240. */
  241. public function getClientConfigAlert($userInfo, $clientVersion, $position)
  242. {
  243. $clientConfigList = $this->fetchClientConfig($userInfo, $clientVersion,
  244. ClientApiConstants::CLIENT_CONFIG_FUN_TYPE_ALERT, 1, $position);
  245. if (count($clientConfigList) > 0) {
  246. $data = current($clientConfigList);
  247. return $this->setData($data)->getReturn();
  248. } else {
  249. return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
  250. }
  251. }
  252. private function ClientConfigFormat($clientConfigInfo)
  253. {
  254. $result = [
  255. 'image_url' => $clientConfigInfo['pic_url'],
  256. 'delay_time' => $clientConfigInfo['count_down'],
  257. 'start_time' => strtotime($clientConfigInfo['start_time']),
  258. 'end_time' => strtotime($clientConfigInfo['end_time']),
  259. ];
  260. if ($clientConfigInfo['type'] == ClientApiConstants::CLIENT_CONFIG_TYPE_BOOK_INFO) {
  261. $result['uri'] = $this->parseAppUrl('bookinfo', ['book_id' => $clientConfigInfo['book_id']]);
  262. } elseif ($clientConfigInfo['type'] == ClientApiConstants::CLIENT_CONFIG_TYPE_BOOK_CHAPTER) {
  263. $result['uri'] = $this->parseAppUrl('chapter', ['book_id' => $clientConfigInfo['book_id']]);
  264. } elseif ($clientConfigInfo['type'] == ClientApiConstants::CLIENT_CONFIG_TYPE_URL) {
  265. $result['uri'] = $clientConfigInfo['url'];
  266. } elseif ($clientConfigInfo['type'] == ClientApiConstants::CLIENT_CONFIG_TYPE_BOOK_ACTIVITY) {
  267. $webHost = Config::get("site.client_web_host");
  268. $result['uri'] = sprintf('%s/clientweb/activity/index?id=%s', $webHost,
  269. $clientConfigInfo['client_activity_id']);
  270. }
  271. return $result;
  272. }
  273. private function fetchClientConfig($userInfo, $clientVersion, $funType, $limit, $position = null)
  274. {
  275. $key = "APCC:$clientVersion:$funType";
  276. $userPayTypeCond = [ClientApiConstants::USER_PAY_ALL];
  277. if (!empty($userInfo)) {
  278. $userIsPay = $userInfo['is_pay'];
  279. $key .= ":$userIsPay";
  280. if ($userIsPay == 1) {
  281. $userPayTypeCond[] = ClientApiConstants::USER_PAY_PAYED;
  282. } else {
  283. $userPayTypeCond[] = ClientApiConstants::USER_PAY_UNPAY;
  284. }
  285. } else {
  286. $key .= ":0";
  287. }
  288. if (!empty($position)) {
  289. $key .= ":$position";
  290. }
  291. $redis = Redis::instance();
  292. if ($redis->exists($key)) {
  293. $res = json_decode($redis->get($key), true);
  294. } else {
  295. $model = $this->getClientConfigModel()
  296. ->where('fun_type', $funType)
  297. ->where('status', ClientApiConstants::CLIENT_CONFIG_NORMAL)
  298. ->where('start_time', '<', date('Y-m-d H:i:s'))
  299. ->where('end_time', '>', date('Y-m-d H:i:s'))
  300. ->whereIn('user_pay_type', $userPayTypeCond)
  301. ->whereIn('version', [$clientVersion, '-1'])
  302. ->order('sort', 'desc')->limit($limit);
  303. if (!empty($position)) {
  304. $model->where("find_in_set({$position},position)");
  305. }
  306. $res = $model->select();
  307. $redis->set($key, json_encode($res, JSON_UNESCAPED_UNICODE), 60);
  308. }
  309. return $res;
  310. }
  311. /**
  312. * 获取用户信息
  313. * @param $userId
  314. * @param $token
  315. * @return \app\main\model\object\ReturnObject
  316. */
  317. public function getUserInfo($userId, $token)
  318. {
  319. $userInfo = $this->getUserModel()->getUserInfo($userId);
  320. if (empty($userInfo)) {
  321. return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg('没有找到用户信息')->getReturn();
  322. }
  323. if ($userInfo['openid'] == $token) {
  324. return $this->setData($userInfo)->getReturn();
  325. } else {
  326. return $this->setCode(ErrorCodeConstants::EXCEPTION)->setMsg('用户校验出错,userId与openid不匹配')->getReturn();
  327. }
  328. }
  329. /**
  330. * 获取书籍信息
  331. * @param array $bookParams key为bookId(必须有),value为chapterKey(如果不需要请填空)
  332. * @param null $userInfo
  333. * @param bool $allRecentBookId 获取用户阅读的所有书籍
  334. * @return \app\main\model\object\ReturnObject
  335. * originalBookList 参数$bookParams的key对应的书籍列表,结构与数据库book表相同的书籍列表
  336. * bookList 参数$bookParams的key & 阅读记录的并集
  337. * recentList userId对应的阅读记录,结构与数据库recently表相同的书籍列表
  338. * @throws \Exception
  339. */
  340. public function userReadBooksInfo($bookParams, $userInfo = null, $allRecentBookId = false)
  341. {
  342. $bookIds = array_keys($bookParams);
  343. $booksInfo = BookService::instance()->getBookModel()->getBooksInfo($bookIds);
  344. $result = ['originalBookList' => $booksInfo];
  345. foreach ($booksInfo as $bookInfo) {
  346. $bookId = $bookInfo['id'];
  347. $bookInfoItem = $this->bookInfoFormat($bookInfo);
  348. $chapterKey = $bookParams[$bookId];
  349. if (empty($chapterKey)) {
  350. $bookInfoItem['state'] = BookService::makeBookStatusForClient($bookInfo);
  351. } else {
  352. $bookInfoItem['state'] = BookService::makeBookStatusForClient($bookInfo, $chapterKey);
  353. }
  354. $bookResult[$bookId] = $bookInfoItem;
  355. }
  356. $recentBookIdsFromCps = [];
  357. if (!empty($userInfo)) {
  358. $recentResult = BookService::instance()->getUserRecentlyRead()->getRecentlyRead(0, 100, $userInfo['id']);
  359. $recentList = $recentResult['totalNum'] > 0 ? $recentResult['data'] : [];
  360. foreach ($recentList as $recent) {
  361. $bookId = $recent['book_id'];
  362. if (isset($bookResult[$bookId])) {
  363. $bookResult[$bookId]['current_cid'] = $recent['chapter_id'];
  364. $bookResult[$bookId]['current_c_name'] = $recent['chapter_name'];
  365. $bookResult[$bookId]['action_time'] = $recent['updatetime'];
  366. } elseif ($allRecentBookId) {
  367. $bookResult[$bookId]['current_cid'] = $recent['chapter_id'];
  368. $bookResult[$bookId]['current_c_name'] = $recent['chapter_name'];
  369. $bookResult[$bookId]['action_time'] = $recent['updatetime'];
  370. $recentBookIdsFromCps[] = $bookId;
  371. }
  372. }
  373. }
  374. $booksInfoFromCps = BookService::instance()->getBookModel()->getBooksInfo($recentBookIdsFromCps);
  375. foreach ($booksInfoFromCps as $bookInfoFromCps) {
  376. $bookId = $bookInfoFromCps['id'];
  377. $bookInfoItem = $this->bookInfoFormat($bookInfoFromCps);
  378. $bookInfoItem['state'] = BookService::makeBookStatusForClient($bookInfoFromCps);
  379. $bookResult[$bookId] = array_merge($bookInfoItem, $bookResult[$bookId]);
  380. }
  381. $bookResult = empty($bookResult) ? [] : array_values($bookResult);
  382. $result['bookList'] = $bookResult;
  383. if (isset($recentList)) {
  384. $result['recentList'] = $recentList;
  385. }
  386. return $this->setData($result)->getReturn();
  387. }
  388. /**
  389. * 格式化书籍对象
  390. * @param $bookInfo 从db或redis中取出的书籍对象
  391. * @return array
  392. */
  393. private function bookInfoFormat($bookInfo)
  394. {
  395. $result = [
  396. 'book_id' => strval($bookInfo['id']),
  397. 'book_name' => $bookInfo['name'],
  398. 'author' => $bookInfo['author'],
  399. 'cover' => $bookInfo['image'],
  400. 'chapter_key' => strval($bookInfo['last_chapter_id']),
  401. ];
  402. return $result;
  403. }
  404. /**
  405. * @param $userId
  406. * @return \app\main\model\object\ReturnObject
  407. */
  408. public function getTodaySign($userId)
  409. {
  410. $todayDate = date('Ymd');
  411. $sign = $this->getSignModel()->setConnect($userId)->where([
  412. 'uid' => $userId,
  413. 'createdate' => $todayDate
  414. ])->find();
  415. return $this->setData(!empty($sign))->getReturn();
  416. }
  417. public function getDefaultBookIds()
  418. {
  419. $redis = Redis::instance();
  420. if ($redis->exists(ClientApiConstants::DEFAULT_RECOMMAND_KEY)) {
  421. $bookIds = $redis->sMembers(ClientApiConstants::DEFAULT_RECOMMAND_KEY);
  422. } else {
  423. $bookInfos = $this->getClientDefaultRecommandModel()
  424. ->where('status', 'normal')
  425. ->select();
  426. $bookIds = array_column($bookInfos, 'book_id');
  427. $redis->sAddArray(ClientApiConstants::DEFAULT_RECOMMAND_KEY, $bookIds);
  428. }
  429. return $this->setData($bookIds)->getReturn();
  430. }
  431. /**
  432. * 返回书城页的各个配置块的数据
  433. * @param $type
  434. * @return array|mixed
  435. */
  436. public function pageBlockResource($type)
  437. {
  438. $redis = Redis::instance();
  439. $boydata = [];
  440. $girldata = [];
  441. if ($redis->exists('CP:1') && $redis->exists('CP:2')) {
  442. $boydata = json_decode($redis->get('CP:1'), true);
  443. $girldata = json_decode($redis->get('CP:2'), true);
  444. } else {
  445. $block = collection(model('ClientManageBlock')->order('page_id asc,weigh desc')->select())->toArray();
  446. foreach ($block as $value) {
  447. $blockId = $value['id'];
  448. $sources = collection(
  449. model('ClientManageBlockResource')
  450. ->where('block_id', 'eq', $blockId)
  451. ->order('weigh desc')
  452. ->limit(4)
  453. ->select()
  454. )->toArray();
  455. foreach ($sources as $source) {
  456. $sourceId = $source['id'];
  457. $sourceType = $source['type'];
  458. $resRow = [];
  459. if ($sourceType == 1) {
  460. //书籍
  461. $bookRows = collection(
  462. model('ClientManageBlockResource')
  463. ->join('book', 'book.id= client_manage_block_resource.book_id')
  464. ->join('book_category bc','bc.id = book.book_category_id','LEFT')
  465. ->where('client_manage_block_resource.id', 'eq', $sourceId)
  466. ->field('bc.name as bc_name,book.book_category_id,book.name,book.author,book.description,book.last_chapter_name,book.last_chapter_id,book.read_num,client_manage_block_resource.*')
  467. ->where('book.state=1')
  468. ->select()
  469. )->toArray();
  470. if (!empty($bookRows)) {
  471. $bookRow = $bookRows[0];
  472. $bookRow['read_nums'] = friend_date($bookRow['read_num']);
  473. $bookRow['author'] = $bookRow['bc_name'];
  474. if (empty($bookRow['url'])) {
  475. //重整url @todo url需要重整梳理
  476. $bookRow['url'] =
  477. $this->parseAppUrl('bookinfo', ['book_id' => $bookRow['book_id']]);
  478. }
  479. $resRow = $bookRow;
  480. } else {
  481. continue;
  482. }
  483. } else if ($sourceType == 2) {
  484. //url
  485. $resRow = $urlRow = $source;
  486. } else if ($sourceType == 3) {
  487. //vip充值
  488. $resRow = $vipRow = $source;
  489. $url = Url::build('/clientweb/index/vippopup', '', '', true);
  490. $resRow['url'] = $this->parseAppUrl('dialog', ['url' => $url]);
  491. } else if ($sourceType == 4) {
  492. //活动
  493. $actRows = collection(
  494. model('ClientManageBlockResource')
  495. ->join('activity activity', 'activity.id= client_manage_block_resource.client_activity_id')
  496. ->where('client_manage_block_resource.id', 'eq', $sourceId)
  497. ->field('client_manage_block_resource.*')
  498. ->where("activity.status='1'")
  499. ->where('activity.starttime', '<', time())
  500. ->where('activity.endtime', '>', time())
  501. ->select()
  502. )->toArray();
  503. if (!empty($actRows)) {
  504. $actRow = $actRows[0];
  505. //重整url
  506. $url = Url::build('/clientweb/activity/index', 'id='.$actRow['client_activity_id'], '', true);
  507. $actRow['url'] = $this->parseAppUrl('activity', ['url' => $url]);
  508. $resRow = $actRow;
  509. } else {
  510. continue;
  511. }
  512. }
  513. $value['block_resource'][] = $resRow;
  514. }
  515. if ($value['page_id'] == 1) {
  516. $boydata[] = $value;
  517. }
  518. if ($value['page_id'] == 2) {
  519. $girldata[] = $value;
  520. }
  521. }
  522. if (!empty($boydata)) {
  523. $redis->set('CP:1', json_encode($boydata, JSON_UNESCAPED_UNICODE));
  524. }
  525. if (!empty($girldata)) {
  526. $redis->set('CP:2', json_encode($girldata, JSON_UNESCAPED_UNICODE));
  527. }
  528. }
  529. if ($type == 'boy') {
  530. return $boydata;
  531. } else {
  532. return $girldata;
  533. }
  534. }
  535. /**
  536. * 榜单列表 rank1男频 rank2女频 rank0不区分男女 按照idx排序
  537. */
  538. public function rankList($type)
  539. {
  540. $redis = Redis::instance();
  541. $boydata = [];
  542. $girldata = [];
  543. if ($redis->exists('CRANK:1') && $redis->exists('CRANK:2') && $redis->exists('CRANK:0')) {
  544. $boydata = json_decode($redis->get('CRANK:1'), true);
  545. $girldata = json_decode($redis->get('CRANK:2'), true);
  546. $idxdata = json_decode($redis->get('CRANK:0'), true);
  547. } else {
  548. $boydata['click'] = collection(
  549. model('Book')->join('book_category bc','bc.id = book.book_category_id','LEFT')
  550. ->where(['book.state' => 1, 'book.sex' => 1])
  551. ->field('book.*,bc.name as bc_name')
  552. ->order('book.read_num desc')
  553. ->limit(10)
  554. ->select()
  555. )->toArray();
  556. foreach ($boydata['click'] as &$value) {
  557. $value['read_nums'] = friend_date($value['read_num']);
  558. $value['author'] = $value['bc_name'];
  559. }
  560. $boydata['idx'] = collection(
  561. model('Book')->join('book_category bc','bc.id = book.book_category_id','LEFT')
  562. ->where(['book.state' => 1, 'book.sex' => 1])
  563. ->field('book.*,bc.name as bc_name')
  564. ->order('book.idx desc')
  565. ->limit(10)
  566. ->select()
  567. )->toArray();
  568. foreach ($boydata['idx'] as &$value) {
  569. $value['read_nums'] = friend_date($value['read_num']);
  570. $value['author'] = $value['bc_name'];
  571. }
  572. $girldata['click'] = collection(
  573. model('Book')->join('book_category bc','bc.id = book.book_category_id','LEFT')
  574. ->where(['book.state' => 1, 'book.sex' => 2])
  575. ->field('book.*,bc.name as bc_name')
  576. ->order('book.read_num desc')
  577. ->limit(10)
  578. ->select()
  579. )->toArray();
  580. foreach ($girldata['click'] as &$value) {
  581. $value['read_nums'] = friend_date($value['read_num']);
  582. $value['author'] = $value['bc_name'];
  583. }
  584. $girldata['idx'] = collection(
  585. model('Book')->join('book_category bc','bc.id = book.book_category_id','LEFT')
  586. ->where(['book.state' => 1, 'book.sex' => 2])
  587. ->field('book.*,bc.name as bc_name')
  588. ->order('book.idx desc')
  589. ->limit(10)
  590. ->select()
  591. )->toArray();
  592. foreach ($girldata['idx'] as &$value) {
  593. $value['read_nums'] = friend_date($value['read_num']);
  594. $value['author'] = $value['bc_name'];
  595. }
  596. $idxdata['idx'] = collection(
  597. model('Book')->join('book_category bc','bc.id = book.book_category_id','LEFT')
  598. ->where(['book.state' => 1])
  599. ->field('book.*,bc.name as bc_name')
  600. ->order('book.idx desc')
  601. ->limit(10)
  602. ->select()
  603. )->toArray();
  604. foreach ($idxdata['idx'] as &$value) {
  605. $value['read_nums'] = friend_date($value['read_num']);
  606. $value['author'] = $value['bc_name'];
  607. }
  608. if (!empty($boydata)) {
  609. $redis->setex('CRANK:1', $this->ranklivetime, json_encode($boydata, JSON_UNESCAPED_UNICODE));
  610. }
  611. if (!empty($girldata)) {
  612. $redis->setex('CRANK:2', $this->ranklivetime, json_encode($girldata, JSON_UNESCAPED_UNICODE));
  613. }
  614. if (!empty($idxdata)) {
  615. $redis->setex('CRANK:0', $this->ranklivetime, json_encode($idxdata, JSON_UNESCAPED_UNICODE));
  616. }
  617. }
  618. if ($type == 1) {
  619. return $boydata;
  620. } elseif ($type == 2) {
  621. return $girldata;
  622. } elseif ($type == 'boy') {
  623. return $boydata;
  624. } elseif ($type == 'girl') {
  625. return $girldata;
  626. } else {
  627. return $idxdata;
  628. }
  629. }
  630. /*
  631. * 主编推荐列表
  632. */
  633. public function recommendList($book_id, $userid = 0)
  634. {
  635. if($book_id){
  636. $bookInfo = model("book")->BookInfo($book_id);
  637. }else{
  638. return false;
  639. }
  640. $where = [];
  641. $where['state'] = '1';
  642. $where['book_category_id'] = $bookInfo['book_category_id'];
  643. //最近阅读
  644. $recentList = [];
  645. if (!empty($userid)) {
  646. $recentList = model('UserRecentlyRead')->getRecentlyRead(0, 10, $userid);
  647. }
  648. $recentIds[] = $bookInfo['id'];
  649. if ($recentList['totalNum'] > 0) {
  650. foreach ($recentList['data'] as $v) {
  651. $recentIds[] = $v['book_id'];
  652. }
  653. }
  654. if ($recentIds) {
  655. $where['id'] = ['not in', $recentIds];
  656. }
  657. $pagedata[0]['name'] = "主编推荐";
  658. $pagedata[0]['page_id'] = 1;
  659. $pagedata[0]['second_name'] = "主编推荐";
  660. $pagedata[0]['block_resource'] = collection(model("Book")
  661. ->where($where)
  662. ->order('rand()')
  663. ->limit(4)
  664. ->select())->toArray();
  665. if($pagedata[0]['block_resource']){
  666. foreach ($pagedata[0]['block_resource'] as &$v){
  667. $v['book_id'] = $v['id'];
  668. }
  669. }
  670. return $pagedata;
  671. }
  672. /**
  673. * @param $packageName
  674. * @return \app\main\model\object\ReturnObject
  675. * @throws \think\Exception
  676. */
  677. public function getPlugin($packageName)
  678. {
  679. $key = $this->_makeAppHearBookKey($packageName);
  680. $resultData = [];
  681. $redis = Redis::instance();
  682. if ($redis->exists($key)) {
  683. $resultData = json_decode($redis->get($key), true);
  684. } else {
  685. $result = $this->getHearbookModel()
  686. ->where('package_title', $packageName)
  687. ->order('version desc')
  688. ->find();
  689. if (!empty($result)) {
  690. $resultData = $result->toArray();
  691. $redis->set($key, json_encode($resultData));
  692. }
  693. }
  694. if (empty($resultData)) {
  695. return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->setMsg('没有找到语音包')->getReturn();
  696. } else {
  697. return $this->setData($resultData)->getReturn();
  698. }
  699. }
  700. /**
  701. * 组装APP要用的url
  702. * @param $urlType
  703. * @param $params
  704. * @return string
  705. */
  706. public function parseAppUrl($urlType, $params)
  707. {
  708. switch ($urlType) {
  709. case "bookinfo":
  710. //书籍详情页
  711. $uri = ClientApiConstants::APP_HOST."?page=bookDetail&param=";
  712. $paramsData = [
  713. "bookId" => $params['book_id'],
  714. ];
  715. $url = $uri . json_encode($paramsData);
  716. break;
  717. case "chapter":
  718. //阅读器
  719. $uri = ClientApiConstants::APP_HOST."?page=reader&param=";
  720. $paramsData = [
  721. "bookId" => $params['book_id'],
  722. ];
  723. if (isset($params['chapter_id'])) {
  724. $paramsData['chapterId'] = $params['chapter_id'];
  725. }
  726. $url = $uri . json_encode($paramsData);
  727. break;
  728. case "shelf":
  729. //书架
  730. $url = ClientApiConstants::APP_HOST."?page=shelf&param={}";
  731. break;
  732. case "account":
  733. //个人中心
  734. $url = ClientApiConstants::APP_HOST."?page=account&param={}";
  735. break;
  736. case "book":
  737. //书城
  738. $url = ClientApiConstants::APP_HOST."?page=store&param={}";
  739. break;
  740. case "dialog":
  741. $url = $params['url'];
  742. if (strrpos($url, 'http') === false) {
  743. $webHost = Config::get("site.client_web_host");
  744. $url = trim($webHost, '/') . DS. trim($url, '/');
  745. }
  746. $paramsData = [
  747. "url" => urlencode($url),
  748. ];
  749. $uri = ClientApiConstants::APP_HOST."?page=dialogWebView&param=";
  750. $url = $uri . json_encode($paramsData);
  751. break;
  752. case "activity":
  753. case "url":
  754. default:
  755. $url = $params['url'];
  756. if (strrpos($url, 'http') === false) {
  757. $webHost = Config::get("site.client_web_host");
  758. $url = trim($webHost, '/') . DS. trim($url, '/');
  759. }
  760. if ($urlType == "activity") {
  761. $params['showTitleBar'] = $params['showTitleBar'] ?? true;
  762. }
  763. $paramsData = [
  764. 'url' => urlencode($url),
  765. 'showTitleBar' => $params['showTitleBar'] ?? false
  766. ];
  767. $uri = ClientApiConstants::APP_HOST."?page=pageWebView&param=";
  768. $url = $uri . json_encode($paramsData);
  769. }
  770. return $url;
  771. }
  772. public function clearHearBookCache($packageName)
  773. {
  774. $key = $this->_makeAppHearBookKey($packageName);
  775. $redis = Redis::instance();
  776. $redis->del($key);
  777. }
  778. private function _makeAppHearBookKey($packageName)
  779. {
  780. return sprintf('HB:%s', $packageName);
  781. }
  782. /**
  783. * 获取app版本信息
  784. * @param $versionName
  785. * @return \app\main\model\object\ReturnObject
  786. * @throws \think\Exception
  787. */
  788. public function getAppVersion($versionName)
  789. {
  790. $key = 'JGUE:' . $versionName;
  791. $redis = Redis::instance();
  792. if ($redis->exists($key)) {
  793. $res = json_decode($redis->get($key), true);
  794. } else {
  795. $res = $this->getAppVersionModel()->where('begin_version', '<=', $versionName)
  796. ->where('end_version', '>=', $versionName)
  797. ->where('status', 'normal')
  798. ->order('sort desc')
  799. ->find();
  800. $res = empty($res) ? [] : $res->toArray();
  801. $redis->set($key, json_encode($res, JSON_UNESCAPED_UNICODE), 60);
  802. }
  803. if (!empty($res)) {
  804. return $this->setData($res)->getReturn();
  805. } else {
  806. return $this->setCode(ErrorCodeConstants::RESULT_EMPTY)->getReturn();
  807. }
  808. }
  809. }