BookConfig.php 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599
  1. <?php
  2. namespace App\Modules\Book\Models;
  3. use App\Consts\Channel\ChannelConst;
  4. use App\Modules\Book\Services\BookTagsService;
  5. use App\Modules\Book\Services\TestBookService;
  6. use App\Modules\User\Services\ReadRecordService;
  7. use App\Modules\Book\Services\BookConfigService;
  8. use App\Modules\Channel\Services\ChannelService;
  9. use App\Modules\OfficialAccount\Services\ForceSubscribeService;
  10. use App\Modules\Promotion\Services\PromotionService;
  11. use App\Modules\User\Services\UserService;
  12. use DB;
  13. use Exception;
  14. use Hashids;
  15. use Illuminate\Database\Eloquent\Model;
  16. use Illuminate\Support\Facades\Log;
  17. use Redis;
  18. class BookConfig extends Model
  19. {
  20. protected $table = 'book_configs';
  21. protected $fillable = [
  22. 'bid', 'force_subscribe_chapter_seq', 'price', 'cover', 'book_name',
  23. 'copyright', 'charge_type', 'hot', 'is_on_shelf', 'source_domain', 'recommend_index', 'roles', 'test_status', 'plan_push_user_num', 'test_update_time',
  24. 'is_show_index_content', 'click_count', 'promotion_domain', 'copyright_limit_data', 'recommend_cid', 'is_high_quality', 'vip_seq', 'editor_recommend', 'is_current_week_promotion'
  25. ];
  26. /**
  27. * 根据条件获取图书
  28. * @param array $where
  29. * @param array $order
  30. * @param int $page_size
  31. * @return mixed
  32. */
  33. public static function getBooks(array $where = [], array $order = [], $page_size = 15)
  34. {
  35. if (!$order) {
  36. $order = ['recommend_index', 'desc'];
  37. }
  38. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  39. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  40. ->select(
  41. 'book_configs.bid',
  42. 'book_configs.roles',
  43. 'book_configs.force_subscribe_chapter_seq',
  44. 'book_configs.cp_source',
  45. 'book_configs.vip_seq',
  46. 'book_configs.price',
  47. 'book_configs.cover',
  48. 'book_configs.book_name',
  49. 'book_configs.copyright',
  50. 'book_configs.charge_type',
  51. 'book_configs.is_on_shelf',
  52. 'books.author',
  53. 'books.intro',
  54. 'book_categories.category_name',
  55. 'category_id',
  56. 'status',
  57. 'chapter_count',
  58. 'book_configs.click_count',
  59. 'first_cid',
  60. 'last_cid',
  61. 'books.size',
  62. 'last_chapter',
  63. 'books.keyword',
  64. 'book_configs.recommend_index',
  65. 'book_configs.is_show_index_content',
  66. 'book_configs.product_id',
  67. 'book_categories.channel_name',
  68. 'books.last_cid',
  69. 'books.last_chapter',
  70. 'book_configs.product_id',
  71. 'book_configs.copyright_limit_data',
  72. 'books.updated_at as last_update_time',
  73. 'book_configs.promotion_domain',
  74. 'books.name as old_name',
  75. 'book_configs.recommend_cid',
  76. 'book_configs.is_high_quality',
  77. 'is_current_week_promotion'
  78. );
  79. if ($where) {
  80. foreach ($where as $key => $v) {
  81. //关键词查询
  82. if ($key == 'key' && $v) {
  83. $res = $res->where('book_configs.book_name', 'like', '%' . $v . '%');
  84. //->orWhere('books.intro', 'like', '%' . $v . '%')
  85. //->orWhere('books.category_name', 'like', '%' . $v . '%')->orWhere('books.author', 'like', '%' . $v . '%')
  86. //->orWhere('books.keyword', 'like', '%' . $v . '%');
  87. }
  88. //分类id查询
  89. if ($key == 'category_id' && $v) {
  90. $res = $res->where('books.category_id', '=', $v);
  91. }
  92. //上架查询
  93. if ($key == 'is_on_shelf' && $v != '') {
  94. if (is_array($v)) {
  95. $res = $res->whereIn('is_on_shelf', $v);
  96. } else {
  97. $res = $res->where('is_on_shelf', '=', $v);
  98. }
  99. }
  100. //频道查询
  101. if ($key == 'channel_name' && $v) {
  102. $res = $res->where('book_categories.channel_name', '=', $v);
  103. }
  104. if ($key == 'status') {
  105. $res = $res->where('books.status', '=', $v);
  106. }
  107. if ($key == 'author') {
  108. $res = $res->where('books.author', 'like', '%' . $v . '%');
  109. }
  110. if ($key == 'roles') {
  111. $res = $res->where('book_configs.roles', 'like', '%' . $v . '%');
  112. }
  113. //旧书名查询
  114. if ($key == 'old_name') {
  115. $res = $res->where('books.name', 'like', '%' . $v . '%');
  116. }
  117. //版权日期查询
  118. if ($key == 'copy_right_date') {
  119. if (is_array($v)) {
  120. $res = $res->whereBetween('book_configs.copyright_limit_data', $v);
  121. } else {
  122. $res = $res->where('book_configs.copyright_limit_data', '<=', $v);
  123. }
  124. }
  125. if ($key == 'domain') {
  126. $res = $res->where('book_configs.promotion_domain', 'like', '%' . $v . '%');
  127. }
  128. if ($key == 'bid') {
  129. $res = $res->where('book_configs.bid', '=', $v);
  130. }
  131. if ($key == 'is_high_quality') {
  132. $res = $res->where('book_configs.is_high_quality', '=', $v);
  133. }
  134. if ($key == 'charge_type') {
  135. $res = $res->where('book_configs.charge_type', '=', $v);
  136. }
  137. if ($key == 'firstChapterContent') {
  138. $res = $res->join('chapters', function ($query) use ($v) {
  139. $query->on('book_configs.bid', '=', 'chapters.bid')
  140. ->where('chapters.sequence', 1);
  141. })->where('chapters.content', 'like', '%' . $v . '%');
  142. }
  143. if ($key == 'tags') {
  144. $tags_filter = BookTagsService::getSearchBooks($v);
  145. $res->whereIn('book_configs.bid', $tags_filter);
  146. }
  147. if ($key == 'is_current_week_promotion') {
  148. $res->where('book_configs.is_current_week_promotion', $v);
  149. }
  150. }
  151. }
  152. //$res->orderBy('book_configs.updated_at','desc');
  153. return $res->orderBy($order[0], $order[1])->orderBy('book_configs.updated_at', 'desc')->paginate($page_size);
  154. }
  155. /**
  156. * 根据条件获取图书
  157. * @param array $where
  158. * @param array $order
  159. * @param int $page_size
  160. * @return mixed
  161. */
  162. public static function getPromotionBooks(array $where = [], array $bids, array $order = [], $page_size = 15)
  163. {
  164. if (!$order) {
  165. $order = ['recommend_index', 'desc'];
  166. }
  167. $res1 = self::join('books', 'book_configs.bid', '=', 'books.id')
  168. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  169. ->select(
  170. 'book_configs.bid',
  171. 'book_configs.force_subscribe_chapter_seq',
  172. 'book_configs.cp_source',
  173. 'book_configs.vip_seq',
  174. 'book_configs.price',
  175. 'book_configs.cover',
  176. 'book_configs.book_name',
  177. 'book_configs.copyright',
  178. 'book_configs.charge_type',
  179. 'book_configs.is_on_shelf',
  180. 'books.author',
  181. 'books.intro',
  182. 'book_categories.category_name',
  183. 'category_id',
  184. 'status',
  185. 'chapter_count',
  186. 'book_configs.click_count',
  187. 'first_cid',
  188. 'last_cid',
  189. 'size',
  190. 'last_chapter',
  191. 'books.keyword',
  192. 'book_configs.recommend_index',
  193. 'book_configs.is_show_index_content',
  194. 'book_configs.product_id',
  195. 'book_categories.channel_name',
  196. 'books.last_cid',
  197. 'books.last_chapter',
  198. 'book_configs.product_id',
  199. 'book_configs.copyright_limit_data',
  200. 'books.updated_at as last_update_time',
  201. 'book_configs.promotion_domain',
  202. 'books.name as old_name',
  203. 'book_configs.recommend_cid',
  204. 'book_configs.is_high_quality'
  205. );
  206. if ($where) {
  207. foreach ($where as $key => $v) {
  208. //关键词查询
  209. if ($key == 'key' && $v) {
  210. $res1 = $res1->where('book_configs.book_name', 'like', '%' . $v . '%');
  211. }
  212. //分类id查询
  213. if ($key == 'category_id' && $v) {
  214. $res1 = $res1->where('books.category_id', '=', $v);
  215. }
  216. //上架查询
  217. if ($key == 'is_on_shelf' && $v != '') {
  218. if (is_array($v)) {
  219. $res1 = $res1->whereIn('is_on_shelf', $v);
  220. } else {
  221. $res1 = $res1->where('is_on_shelf', '=', $v);
  222. }
  223. }
  224. //频道查询
  225. if ($key == 'channel_name' && $v) {
  226. $res1 = $res1->where('book_categories.channel_name', '=', $v);
  227. }
  228. if ($key == 'status') {
  229. $res1 = $res1->where('books.status', '=', $v);
  230. }
  231. if ($key == 'author') {
  232. $res1 = $res1->where('books.author', 'like', '%' . $v . '%');
  233. }
  234. //旧书名查询
  235. if ($key == 'old_name') {
  236. $res1 = $res1->where('books.name', 'like', '%' . $v . '%');
  237. }
  238. //版权日期查询
  239. if ($key == 'copy_right_date') {
  240. if (is_array($v)) {
  241. $res1 = $res1->whereBetween('book_configs.copyright_limit_data', $v);
  242. } else {
  243. $res1 = $res1->where('book_configs.copyright_limit_data', '<=', $v);
  244. }
  245. }
  246. if ($key == 'domain') {
  247. $res1 = $res1->where('book_configs.promotion_domain', 'like', '%' . $v . '%');
  248. }
  249. if ($key == 'bid') {
  250. $res1 = $res1->where('book_configs.bid', '=', $v);
  251. }
  252. if ($key == 'is_high_quality') {
  253. $res1 = $res1->where('book_configs.is_high_quality', '=', $v);
  254. }
  255. if ($key == 'charge_type') {
  256. $res1 = $res1->where('book_configs.charge_type', '=', $v);
  257. }
  258. if ($key == 'hidden_books') {
  259. $res1 = $res1->whereNotIn('book_configs.bid', $v);
  260. }
  261. }
  262. if ($bids) {
  263. //$res1 = $res1->orwhereIn('book_configs.id', $bids);
  264. if ((isset($where['key']) && !empty($where['key'])) && (isset($where['channel_name']) && !empty($where['channel_name']))) {
  265. $res1 = $res1->orWhere(function ($query) use ($bids, $where) {
  266. $query->where('is_on_shelf', 1)
  267. ->whereIn('book_configs.bid', $bids)
  268. ->where('book_configs.book_name', 'like', '%' . $where['key'] . '%')
  269. ->where('book_categories.channel_name', '=', $where['channel_name']);;
  270. });
  271. } elseif (isset($where['key']) && !empty($where['key'])) {
  272. $res1 = $res1->orWhere(function ($query) use ($bids, $where) {
  273. $query->where('is_on_shelf', 1)
  274. ->whereIn('book_configs.bid', $bids)
  275. ->where('book_configs.book_name', 'like', '%' . $where['key'] . '%');
  276. });
  277. } elseif (isset($where['channel_name']) && !empty($where['channel_name'])) {
  278. $res1 = $res1->orWhere(function ($query) use ($bids, $where) {
  279. $query->where('is_on_shelf', 1)
  280. ->whereIn('book_configs.bid', $bids)
  281. ->where('book_categories.channel_name', '=', $where['channel_name']);
  282. });
  283. } else {
  284. $res1 = $res1->orwhereIn('book_configs.bid', $bids);
  285. }
  286. }
  287. }
  288. return $res1->orderBy($order[0], $order[1])->orderBy('book_configs.updated_at', 'desc')->paginate($page_size);
  289. }
  290. /**
  291. * 根据id数组获取图书信息
  292. * @param array $bid_arr
  293. * @param array $order
  294. * @return mixed
  295. */
  296. public static function getBooksByIds(array $bid_arr, array $order = [])
  297. {
  298. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  299. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  300. ->select(
  301. 'book_configs.bid',
  302. 'book_configs.force_subscribe_chapter_seq',
  303. 'book_configs.vip_seq',
  304. 'book_configs.price',
  305. 'book_configs.cover',
  306. 'book_configs.book_name',
  307. 'book_configs.copyright',
  308. 'book_configs.charge_type',
  309. 'book_configs.is_on_shelf',
  310. 'books.author',
  311. 'books.intro',
  312. 'book_categories.category_name',
  313. 'category_id',
  314. 'status',
  315. 'chapter_count',
  316. 'book_configs.click_count',
  317. 'first_cid',
  318. 'last_cid',
  319. 'size',
  320. 'last_chapter',
  321. 'books.keyword',
  322. 'book_configs.recommend_index',
  323. 'book_configs.is_show_index_content',
  324. 'book_configs.product_id',
  325. 'book_categories.channel_name',
  326. 'books.last_cid',
  327. 'books.last_chapter',
  328. 'book_configs.product_id',
  329. 'books.updated_at as last_update_time',
  330. 'book_configs.copyright_limit_data',
  331. 'book_configs.promotion_domain',
  332. 'books.name as old_name',
  333. 'book_configs.recommend_cid'
  334. )
  335. ->whereIn('book_configs.bid', $bid_arr);
  336. if ($order) {
  337. $res->orderBy($order[0], $order[1]);
  338. } else {
  339. $str = implode(',', $bid_arr);
  340. $field = 'bid,' . $str;
  341. $res->orderBy(DB::raw('field(' . $field . ')'));
  342. }
  343. return $res->limit(30)->get();
  344. }
  345. /**
  346. * 根据bid获取图书信息
  347. * @param $bid
  348. * @return mixed
  349. */
  350. public static function getBookById($bid)
  351. {
  352. if (empty($bid)) return null;
  353. return self::join('books', 'book_configs.bid', '=', 'books.id')
  354. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  355. ->select(
  356. 'book_configs.bid',
  357. 'book_configs.is_on_shelf',
  358. 'book_configs.force_subscribe_chapter_seq',
  359. 'book_configs.vip_seq',
  360. 'book_configs.cp_source',
  361. 'book_configs.price',
  362. 'book_configs.cover',
  363. 'book_configs.book_name',
  364. 'book_configs.copyright',
  365. 'book_configs.created_at',
  366. 'book_configs.charge_type',
  367. 'book_configs.is_on_shelf',
  368. 'books.author',
  369. 'books.intro',
  370. 'book_categories.category_name',
  371. 'category_id',
  372. 'status',
  373. 'chapter_count',
  374. 'first_cid',
  375. 'last_cid',
  376. 'size',
  377. 'last_chapter',
  378. 'books.keyword',
  379. 'book_configs.recommend_index',
  380. 'book_configs.is_show_index_content',
  381. 'book_configs.click_count',
  382. 'book_configs.product_id',
  383. 'book_categories.channel_name',
  384. 'books.last_cid',
  385. 'books.updated_at as last_update_time',
  386. 'books.last_chapter',
  387. 'book_configs.product_id',
  388. 'book_configs.copyright_limit_data',
  389. 'book_configs.promotion_domain',
  390. 'books.name as old_name',
  391. 'book_configs.recommend_cid',
  392. 'book_configs.is_high_quality'
  393. )->where('book_configs.bid', $bid)->first();
  394. }
  395. /**
  396. * 根据关键词获取图书
  397. * @param $key
  398. * @param int $page_size
  399. * @param null $is_on_shelf
  400. * @return mixed
  401. */
  402. public static function getBooksByKey($key, $page_size = 15, $is_on_shelf = null)
  403. {
  404. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  405. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  406. ->select(
  407. 'book_configs.bid',
  408. 'book_configs.force_subscribe_chapter_seq',
  409. 'book_configs.vip_seq',
  410. 'book_configs.price',
  411. 'book_configs.cover',
  412. 'book_configs.book_name',
  413. 'book_configs.copyright',
  414. 'book_configs.charge_type',
  415. 'book_configs.is_on_shelf',
  416. 'books.author',
  417. 'books.intro',
  418. 'book_categories.category_name',
  419. 'category_id',
  420. 'status',
  421. 'chapter_count',
  422. 'book_configs.click_count',
  423. 'first_cid',
  424. 'last_cid',
  425. 'size',
  426. 'last_chapter',
  427. 'books.keyword',
  428. 'book_configs.recommend_index',
  429. 'book_configs.is_show_index_content',
  430. 'book_configs.product_id',
  431. 'book_categories.channel_name',
  432. 'books.last_cid',
  433. 'books.last_chapter',
  434. 'book_configs.product_id',
  435. 'books.updated_at as last_update_time',
  436. 'book_configs.copyright_limit_data',
  437. 'book_configs.promotion_domain',
  438. 'books.name as old_name',
  439. 'book_configs.recommend_cid',
  440. 'book_configs.is_high_quality'
  441. )
  442. ->where('book_configs.book_name', 'like', '%' . $key . '%');
  443. //->orWhere('books.intro', 'like', '%' . $key . '%')
  444. //->orWhere('books.keyword', 'like', '%' . $key . '%')
  445. //->orWhere('books.category_name', 'like', '%' . $key . '%')
  446. //->orWhere('books.author', 'like', '%' . $key . '%');
  447. /*
  448. if ($is_on_shelf) {
  449. if (is_array($is_on_shelf)) {
  450. $res->whereIn('book_configs.is_on_shelf', $is_on_shelf);
  451. } else {
  452. $res->where('book_configs.is_on_shelf', '=', $is_on_shelf);
  453. }
  454. }*/
  455. $res->whereIn('book_configs.is_on_shelf', [1, 2]);
  456. $res = $res->paginate($page_size);
  457. foreach ($res as $v) {
  458. $v->book_url = '/detail?id=' . Hashids::encode($v->bid);
  459. }
  460. return $res;
  461. }
  462. /**
  463. * 根据product_id获取图书
  464. * @param $product_id
  465. * @return mixed
  466. */
  467. public static function getBookByProduct($product_id)
  468. {
  469. return self::join('books', 'book_configs.bid', '=', 'books.id')
  470. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  471. ->select(
  472. 'book_configs.bid',
  473. 'book_configs.force_subscribe_chapter_seq',
  474. 'book_configs.vip_seq',
  475. 'book_configs.price',
  476. 'book_configs.cover',
  477. 'book_configs.book_name',
  478. 'book_configs.copyright',
  479. 'book_configs.charge_type',
  480. 'book_configs.is_on_shelf',
  481. 'books.author',
  482. 'books.intro',
  483. 'book_categories.category_name',
  484. 'category_id',
  485. 'status',
  486. 'chapter_count',
  487. 'first_cid',
  488. 'last_cid',
  489. 'size',
  490. 'last_chapter',
  491. 'books.keyword',
  492. 'book_configs.recommend_index',
  493. 'book_configs.is_show_index_content',
  494. 'book_configs.click_count',
  495. 'book_configs.product_id',
  496. 'book_categories.channel_name',
  497. 'books.last_cid',
  498. 'books.last_chapter',
  499. 'book_configs.product_id',
  500. 'book_configs.recommend_cid',
  501. 'book_configs.is_high_quality'
  502. )->where('book_configs.product_id', $product_id)->first();
  503. }
  504. /**
  505. * 更新图书
  506. * @param $bid
  507. * @param array $param
  508. * @return bool
  509. */
  510. public static function updateBookInfo($bid, array $param)
  511. {
  512. $book_info = self::getBookById($bid);
  513. if (!$book_info) return false;
  514. $update_data = [];
  515. if (isset($param['force_subscribe_chapter_seq']) && !empty($param['force_subscribe_chapter_seq'])) $update_data['force_subscribe_chapter_seq'] = $param['force_subscribe_chapter_seq'];
  516. if (isset($param['product_id']) && !empty($param['product_id'])) $update_data['product_id'] = $param['product_id'];
  517. if (isset($param['book_name']) && !empty($param['book_name'])) $update_data['book_name'] = $param['book_name'];
  518. if (isset($param['price']) && !empty($param['price'])) $update_data['price'] = $param['price'];
  519. if (isset($param['cover']) && !empty($param['cover'])) $update_data['cover'] = $param['cover'];
  520. if (isset($param['charge_type']) && !empty($param['charge_type'])) {
  521. $update_data['charge_type'] = $param['charge_type'];
  522. if (is_numeric($update_data['charge_type'])) {
  523. $update_data['charge_type'] = 'CHAPTER';
  524. }
  525. }
  526. if (isset($param['hot']) && !empty($param['hot'])) $update_data['hot'] = $param['hot'];
  527. if (isset($param['roles']) && !empty($param['roles'])) $update_data['roles'] = $param['roles'];
  528. if (isset($param['is_on_shelf']) && $param['is_on_shelf'] != '') $update_data['is_on_shelf'] = $param['is_on_shelf'];
  529. if (isset($param['recommend_index']) && !empty($param['recommend_index'])) $update_data['recommend_index'] = $param['recommend_index'];
  530. if (isset($param['is_show_index_content'])) $update_data['is_show_index_content'] = $param['is_show_index_content'];
  531. if (isset($param['click_count']) && $param['click_count'] != '') $update_data['click_count'] = $param['click_count'];
  532. if (isset($param['copyright_limit_data']) && $param['copyright_limit_data'] != '') $update_data['copyright_limit_data'] = $param['copyright_limit_data'];
  533. if (isset($param['promotion_domain']) && $param['promotion_domain'] != '') $update_data['promotion_domain'] = $param['promotion_domain'];
  534. if (isset($param['copyright']) && $param['copyright'] != '') $update_data['copyright'] = $param['copyright'];
  535. $res1 = null;
  536. if (isset($param['status'])) {
  537. $res1 = Book::where('id', $bid)->update(['status' => $param['status']]);
  538. }
  539. if (isset($param['book_category_id'])) {
  540. $catagory = BookCategory::select('category_name')->where('id', $param['book_category_id'])->first();
  541. Book::where('id', $bid)->update(['category_id' => $param['book_category_id'], 'category_name' => $catagory->category_name]);
  542. }
  543. if (empty($update_data) && !$res1) return false;
  544. return self::where('bid', $bid)->update($update_data);
  545. }
  546. /*
  547. * 获取渠道,用户的全部书籍列表
  548. */
  549. public static function getLeftRecommendBook($channel_name, $is_high_quality, $force_update = false): array
  550. {
  551. if ($force_update) {
  552. Redis::set('full_book_channel_name:' . $channel_name, null);
  553. }
  554. // 存redis里面
  555. $full_book_bids = Redis::get('full_book_channel_name:' . $channel_name);
  556. $full_book_bids = json_decode($full_book_bids);
  557. if (!empty($full_book_bids)) {
  558. } else {
  559. // 获取全集
  560. $full_book_bids = self::join('books', 'book_configs.bid', '=', 'books.id')
  561. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  562. ->select('book_configs.bid')
  563. ->where('book_categories.channel_name', $channel_name)
  564. ->where('book_configs.is_high_quality', $is_high_quality)
  565. ->where('book_configs.test_status', 0) // 不含测书
  566. ->whereIn('book_configs.is_on_shelf', [2])
  567. ->orderBy('book_configs.id', 'desc')
  568. ->get()->pluck('bid')->all();
  569. if (!empty($full_book_bids)) {
  570. Log::info('set_full_book_channel_name:' . $channel_name . ' data:' . json_encode($full_book_bids));
  571. Redis::set('full_book_channel_name:' . $channel_name, json_encode($full_book_bids));
  572. }
  573. }
  574. return $full_book_bids;
  575. }
  576. /*
  577. * 获取渠道,用户的全部需要测试的书籍列表
  578. */
  579. public static function getLeftRecommendTestBook($channel_name)
  580. {
  581. // 获取test全集
  582. $test_bids = self::getLeftRecommendTestBookConfigs($channel_name);
  583. $last_bids = [];
  584. if (!empty($test_bids)) {
  585. foreach ($test_bids as $test_bid) {
  586. $bid = $test_bid->bid;
  587. $redis_bid_push_num = Redis::hget('SmartPushBookUserNum', $bid);
  588. $plan_push_user_num = $test_bid->plan_push_user_num;
  589. Log::info('left_test_book,bid:' . $bid . ' redis_bid_push_num:' . $redis_bid_push_num . ' plan_push_user_num:' . $plan_push_user_num);
  590. if ($redis_bid_push_num >= $plan_push_user_num) {
  591. Log::info('full_update_test_book,bid:' . $bid . ' redis_bid_push_num:' . $redis_bid_push_num . ' plan_push_user_num:' . $plan_push_user_num);
  592. self::where('bid', $bid)->update(['test_status' => 2, 'test_update_time' => date('Y-m-d H:i:s')]);
  593. continue;
  594. }
  595. $last_bids[] = $bid;
  596. }
  597. }
  598. return $last_bids;
  599. }
  600. /*
  601. * 获取渠道,用户的全部需要测试的书籍列表
  602. */
  603. public static function getLeftRecommendTestBookConfigs($channel_name)
  604. {
  605. // 获取全集
  606. return self::join('books', 'book_configs.bid', '=', 'books.id')
  607. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  608. ->select('book_configs.bid', 'book_configs.plan_push_user_num')
  609. ->where('book_categories.channel_name', $channel_name)
  610. ->where('book_configs.test_status', 1) // 待测
  611. ->groupBy('book_configs.bid')
  612. ->orderBy('book_configs.test_weight', 'desc')
  613. ->orderBy('book_configs.test_update_time', 'asc')
  614. ->limit(1) // 每次1本
  615. ->get();
  616. }
  617. /*
  618. * 获取用户的曾经推荐过的书籍列表
  619. */
  620. public static function getUserRecommendRecords($uid)
  621. {
  622. $recommend_bids = Redis::smembers('userRecommendBids:' . $uid);
  623. return $recommend_bids;
  624. }
  625. /*
  626. * 添加用户的曾经推荐过的书籍列表
  627. */
  628. public static function addUserRecommendRecords($uid, $bids)
  629. {
  630. foreach ($bids as $bid) {
  631. Redis::sadd('userRecommendBids:' . $uid, $bid);
  632. }
  633. }
  634. /*
  635. * 清楚用户的曾经推荐过的书籍列表
  636. */
  637. public static function truncateUserRecommendRecords($uid)
  638. {
  639. Log::info('truncateUserRecommendRecords:' . $uid);
  640. Redis::del('userRecommendBids:' . $uid);
  641. }
  642. /*
  643. * 书籍推送量+1
  644. */
  645. public static function incrBidPushNum($last_bids)
  646. {
  647. if (!empty($last_bids)) {
  648. foreach ($last_bids as $last_bid) {
  649. // Log::info('incrBidPushNum:test_bid' . $last_bid);
  650. Redis::hincrby('SmartPushBookUserNum', $last_bid, 1);
  651. }
  652. }
  653. }
  654. /*
  655. * 获取相同频道的4本高推荐图书
  656. * 1、新书倒序 2、用户推荐过的,有阅读记录的不再推荐
  657. */
  658. public static function getLeftRecommendBids($uid = '', $channel_name, $num = 4, $loop = 1)
  659. {
  660. // 获取用户阅读记录详情
  661. $read_bids = ReadRecordService::getSimpleReadRecord($uid);
  662. // 获取用户推荐过的详情
  663. $recommend_bids = self::getUserRecommendRecords($uid);
  664. // 获取全集,不含测试书籍
  665. $full_bids = $full_bid_no_tests = self::getLeftRecommendBook($channel_name, 1, false);
  666. //判断如果注册时间小于15天,不推测试书籍
  667. $test_book = null;
  668. $last_bids = array();
  669. try {
  670. if ($uid) {
  671. $user = UserService::getById($uid);
  672. if ($user && (time() - strtotime($user->created_at) > 15 * 86400)) {
  673. $channel_sex = $channel_name == '男频' ? 1 : 2;
  674. $temp = TestBookService::getTestBook($channel_sex);
  675. $test_res = false;
  676. if ($channel_sex == 2 && $guyan_test_book = TestBookService::getTestBook($channel_sex, 'GUYAN'))//女频古言优先判断
  677. {
  678. if (!in_array($guyan_test_book->bid, $read_bids)) {
  679. $user_property = NovelUserPorperty::model(date('Ymd'))->where('uid', $uid)->first();
  680. if ($user_property && in_array($user_property->category, TestBookService::gu_yan)) {
  681. $test_book = $guyan_test_book;
  682. $test_res = true;
  683. }
  684. }
  685. }
  686. if (!$test_res) if ($temp && !in_array($temp->bid, $read_bids)) $test_book = $temp;
  687. }
  688. }
  689. $test_book && $full_bids = array_merge([$test_book->bid], $full_bid_no_tests);
  690. // 得到差集
  691. $left_bids = array_diff($full_bids, $recommend_bids, $read_bids);
  692. $left_bid_num = count($left_bids);
  693. if ($left_bid_num) {
  694. $last_bids = array_slice($left_bids, 0, $num, false);
  695. } else {
  696. //判断推送的书都被阅读情况下 随机从优质书中取
  697. if (!$not_read_bids = array_diff($full_bids, $read_bids)) {
  698. $last_bids[] = $full_bid_no_tests[array_rand($full_bid_no_tests)];
  699. } else {
  700. //推送过但未阅读情况下,清空继续推
  701. self::truncateUserRecommendRecords($uid);
  702. $last_bids = array_slice($not_read_bids, 0, $num, false);
  703. }
  704. }
  705. // 加入已经推荐
  706. self::addUserRecommendRecords($uid, $last_bids);
  707. // 书籍推送量+1
  708. self::incrBidPushNum($last_bids);
  709. foreach ($last_bids as $_bid) {
  710. if ($test_book && $test_book->bid == $_bid) {
  711. $redis_bid_push_num = Redis::hget('SmartPushBookUserNum', $_bid);
  712. $plan_push_user_num = $test_book->plan_push_user_num;
  713. $uid && TestBookService::record($test_book->id, $uid);
  714. if ($redis_bid_push_num >= $plan_push_user_num) {
  715. TestBookService::finishTest($_bid);
  716. }
  717. }
  718. }
  719. } catch (Exception $e) {
  720. Log::error('get test book error:' . $e->getMessage() . $e->getLine());
  721. $last_bids = [$full_bid_no_tests[array_rand($full_bid_no_tests)]];
  722. }
  723. return $last_bids;
  724. }
  725. /*
  726. * 获取相同频道的4本高推荐图书(循环获取)
  727. * 1、新书倒序 2、用户推荐过的,有阅读记录的不再推荐
  728. */
  729. public static function getSimpleChannelBookLoop($bid, $num = 4, $uid = '', $property = '')
  730. {
  731. if (empty($uid)) {
  732. return self::getSimpleChannelBook($bid, $num, $property);
  733. }
  734. // 站点设置的属性
  735. if (in_array($property, [ChannelConst::PROPERTY_MALE, ChannelConst::PROPERTY_FEMALE], true)) {
  736. $channel_name = $property === ChannelConst::PROPERTY_MALE ? '男频' : '女频';
  737. } else {
  738. $book_info = self::getBookById($bid);
  739. $channel_name = getProp($book_info, 'channel_name', '女频');
  740. }
  741. // 获取全集,减去阅读记录和推荐过的书籍id
  742. $bids = self::getLeftRecommendBids($uid, $channel_name, $num, 1);
  743. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  744. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  745. ->select(
  746. 'book_configs.bid',
  747. 'book_configs.force_subscribe_chapter_seq',
  748. 'book_configs.vip_seq',
  749. 'book_configs.price',
  750. 'books.updated_at as last_update_time',
  751. 'book_configs.cover',
  752. 'book_configs.book_name',
  753. 'book_configs.copyright',
  754. 'book_configs.charge_type',
  755. 'book_configs.is_on_shelf',
  756. 'books.author',
  757. 'books.intro',
  758. 'book_categories.category_name',
  759. 'category_id',
  760. 'status',
  761. 'chapter_count',
  762. 'first_cid',
  763. 'last_cid',
  764. 'size',
  765. 'last_chapter',
  766. 'books.keyword',
  767. 'book_configs.recommend_index',
  768. 'book_configs.is_show_index_content',
  769. 'book_configs.click_count',
  770. 'book_configs.product_id',
  771. 'book_categories.channel_name',
  772. 'books.last_cid',
  773. 'books.last_chapter',
  774. 'book_configs.product_id',
  775. 'books.name as old_name',
  776. 'book_configs.recommend_cid',
  777. 'book_configs.is_high_quality'
  778. )
  779. ->whereIn('book_configs.bid', $bids)
  780. ->orderBy('book_configs.id', 'desc')
  781. ->get();
  782. foreach ($res as $v) {
  783. $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;
  784. }
  785. return $res;
  786. }
  787. public static function getHotRandomRecommendBooks($uid, $num = 2)
  788. {
  789. $sex = ForceSubscribeService::getSimpleSexByUid($uid);
  790. $channel_name = $sex == 1 ? '男频' : '女频';
  791. Log::info('getHotRandomRecommendBooks,uid:' . $uid . ' num:' . $num . ' channel_name:' . $channel_name);
  792. $bids = self::getRandomRecommendBooks($channel_name, $num);
  793. return $bids;
  794. }
  795. public static function getSpecialHotRandomRecommendBooks($num = 2, $channel_name = '女频')
  796. {
  797. $bids = self::getRandomRecommendBooks($channel_name, $num);
  798. return self::getBidRecommendBooks($bids);
  799. }
  800. public static function getHotRandomRecommendBookText($distribution_channel_id, $uid, $num)
  801. {
  802. $bids = self::getHotRandomRecommendBooks($uid, $num);
  803. $recomm_books = BookConfigService::getBooksByIds($bids, ['bid', 'asc']);
  804. $content = '';
  805. if ($recomm_books) {
  806. // 判断是否不展示书名
  807. $self_config = ChannelService::check_channel_account_priv($distribution_channel_id, 'hide_book_name');
  808. $hide_type = isset($self_config->type) ? $self_config->type : 'not_hide';
  809. $recommend_titles = [];
  810. if ($hide_type == 'hide_book_name') {
  811. Log::info('hide_book_name:' . $distribution_channel_id . ' uid:' . $uid);
  812. $sex = ForceSubscribeService::getSimpleSexByUid($uid);
  813. $recommend_titles = PromotionService::getRandomHeadline($sex, count($recomm_books));
  814. }
  815. $content .= "\n\n" . '热门书籍推荐';
  816. foreach ($recomm_books as $key => $book) {
  817. $book_name = $book->book_name;
  818. if ($hide_type == 'hide_book_name') {
  819. $book_name = isset($recommend_titles[$key]->title) ? $recommend_titles[$key]->title : $book->book_name;
  820. }
  821. $url = env('PROTOCOL') . '://site' . encodeDistributionChannelId($distribution_channel_id) . '.' . env('CUSTOM_HOST') . '.com/reader?bid=' . Hashids::encode($book->bid) . '&cid=' . $book->first_cid;
  822. $content .= "\n\n" . '<a href="' . $url . '"> ☞ 《' . $book_name . '》</a>';
  823. }
  824. }
  825. return $content;
  826. }
  827. /**
  828. * 获取h5推荐的图书
  829. */
  830. public static function getH5RecommendBooks($uid, $pos, $num = 4)
  831. {
  832. $sex = ForceSubscribeService::getSimpleSexByUid($uid);
  833. $channel_name = $sex == 1 ? '男频' : '女频';
  834. Log::info('getH5RecommendBooks:pos:' . $pos . ' uid:' . $uid . ' num:' . $num . ' channel_name:' . $channel_name);
  835. $bids = [];
  836. // 先从缓存取,1天有效期
  837. $h5_book_cache = Redis::get('userH5RecommendBids:' . $uid . ':' . $pos);
  838. if (!empty($h5_book_cache)) {
  839. Log::info('h5_book_cache_exist:' . $uid);
  840. return json_decode($h5_book_cache);
  841. }
  842. $bids = [];
  843. $random_recommend = true;
  844. if ($random_recommend) {
  845. $bids = self::getRandomRecommendBooks($channel_name, $num);
  846. }
  847. $forceSubscribeUser = ForceSubscribeService::forceSubscribeUsersByUid(['uid' => $uid]);
  848. $distribution_channel_id = isset($forceSubscribeUser->distribution_channel_id) ? $forceSubscribeUser->distribution_channel_id : '';
  849. Log::info('getH5RecommendBooks:uid:' . $uid . ' distribution_channel_id:' . $distribution_channel_id . ' bids:' . json_encode($bids));
  850. if (!empty($bids)) {
  851. $books = BookConfigService::getBooksByIds($bids, ['bid', 'asc']);
  852. $data = $books->toArray();
  853. // 有效期24小时
  854. $redis_key = 'userH5RecommendBids:' . $uid . ':' . $pos;
  855. Redis::set($redis_key, json_encode(object_to_array($data)));
  856. Redis::expire($redis_key, 3600 * 24);
  857. }
  858. return $books;
  859. }
  860. /**
  861. * 获取随机的推荐书籍bid
  862. */
  863. public static function getRandomRecommendBooks($channel_name, $num)
  864. {
  865. $bids = self::join('books', 'book_configs.bid', '=', 'books.id')
  866. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  867. ->select('book_configs.bid')
  868. ->where('book_categories.channel_name', $channel_name)
  869. ->where('book_configs.is_high_quality', 1)
  870. ->where('book_configs.test_status', 0) // 不含测书
  871. ->whereIn('book_configs.is_on_shelf', [2])
  872. ->inRandomOrder()
  873. ->limit($num)
  874. ->get()->pluck('bid')->all();
  875. return $bids;
  876. }
  877. /*
  878. * 获取相同频道的4本高推荐图书
  879. */
  880. public static function getSimpleChannelBook($bid, $num = 4, $property = '')
  881. {
  882. $book_info = self::getBookById($bid);
  883. if (!$book_info) return false;
  884. // 站点设置的属性
  885. $channel_name = $book_info->channel_name;
  886. if (in_array($property, [ChannelConst::PROPERTY_MALE, ChannelConst::PROPERTY_FEMALE], true)) {
  887. $channel_name = $property === ChannelConst::PROPERTY_MALE ? '男频' : '女频';
  888. }
  889. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  890. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  891. ->select(
  892. 'book_configs.bid',
  893. 'book_configs.force_subscribe_chapter_seq',
  894. 'book_configs.vip_seq',
  895. 'book_configs.price',
  896. 'books.updated_at as last_update_time',
  897. 'book_configs.cover',
  898. 'book_configs.book_name',
  899. 'book_configs.copyright',
  900. 'book_configs.charge_type',
  901. 'book_configs.is_on_shelf',
  902. 'books.author',
  903. 'books.intro',
  904. 'book_categories.category_name',
  905. 'category_id',
  906. 'status',
  907. 'chapter_count',
  908. 'first_cid',
  909. 'last_cid',
  910. 'size',
  911. 'last_chapter',
  912. 'books.keyword',
  913. 'book_configs.recommend_index',
  914. 'book_configs.is_show_index_content',
  915. 'book_configs.click_count',
  916. 'book_configs.product_id',
  917. 'book_categories.channel_name',
  918. 'books.last_cid',
  919. 'books.last_chapter',
  920. 'book_configs.product_id',
  921. 'books.name as old_name',
  922. 'book_configs.recommend_cid',
  923. 'book_configs.is_high_quality'
  924. )
  925. ->where('book_categories.channel_name', $channel_name)
  926. ->where('book_configs.is_high_quality', 1)
  927. ->whereIn('book_configs.is_on_shelf', [2])
  928. ->orderBy('recommend_index', 'desc')
  929. ->get()
  930. ->random($num);
  931. foreach ($res as $v) {
  932. $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;
  933. }
  934. return $res;
  935. }
  936. /*
  937. * 获取托管智能推送的书籍,头条要95分以上,其余4条优质书库随机,按分数倒叙排列
  938. * 新版1条
  939. */
  940. public static function getTrusteeShipChannelBook($distribution_channel_id, $channel_name, $num = 4)
  941. {
  942. // 找头条
  943. $first_res = self::join('books', 'book_configs.bid', '=', 'books.id')
  944. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  945. ->select('book_configs.bid', 'book_configs.recommend_index')
  946. ->where('book_categories.channel_name', $channel_name)
  947. ->where('book_configs.is_high_quality', 1)
  948. // ->where('book_configs.recommend_index', '>=',95)
  949. ->whereIn('book_configs.is_on_shelf', [2])
  950. ->orderBy('recommend_index', 'desc')
  951. ->limit(50)
  952. ->get()
  953. ->random(1);
  954. Log::info('$first_res');
  955. Log::info($first_res);
  956. $bids = [];
  957. $bids[] = $first_res[0]->bid;
  958. Log::info('getTrusteeShipChannelBook_bids:' . json_encode($bids));
  959. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  960. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  961. ->select(
  962. 'book_configs.bid',
  963. 'book_configs.force_subscribe_chapter_seq',
  964. 'book_configs.vip_seq',
  965. 'book_configs.price',
  966. 'books.updated_at as last_update_time',
  967. 'book_configs.cover',
  968. 'book_configs.book_name',
  969. 'book_configs.copyright',
  970. 'book_configs.charge_type',
  971. 'book_configs.is_on_shelf',
  972. 'books.author',
  973. 'books.intro',
  974. 'book_categories.category_name',
  975. 'category_id',
  976. 'status',
  977. 'chapter_count',
  978. 'first_cid',
  979. 'last_cid',
  980. 'size',
  981. 'last_chapter',
  982. 'books.keyword',
  983. 'book_configs.recommend_index',
  984. 'book_configs.is_show_index_content',
  985. 'book_configs.click_count',
  986. 'book_configs.product_id',
  987. 'book_categories.channel_name',
  988. 'books.last_cid',
  989. 'books.last_chapter',
  990. 'book_configs.product_id',
  991. 'books.name as old_name',
  992. 'book_configs.recommend_cid',
  993. 'book_configs.is_high_quality'
  994. )
  995. ->where('book_categories.channel_name', $channel_name)
  996. ->where('book_configs.is_high_quality', 1)
  997. ->whereIn('book_configs.bid', $bids)
  998. ->orderBy('recommend_index', 'desc')
  999. ->get();
  1000. foreach ($res as $v) {
  1001. $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;
  1002. }
  1003. Log::info('last_res');
  1004. Log::info($res);
  1005. return $res;
  1006. }
  1007. /*
  1008. * 获取托管智能推送的书籍,头条要95分以上,其余4条优质书库随机,按分数倒叙排列
  1009. * 老版多条
  1010. */
  1011. public static function getTrusteeShipChannelBookMulty($distribution_channel_id, $channel_name, $num = 4)
  1012. {
  1013. // TODO 内部渠道的书=内部+外部,外部渠道的书=外部
  1014. // 内部上架判断有点复杂,先统一外部上架
  1015. // 找头条
  1016. $first_res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1017. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1018. ->select('book_configs.bid', 'book_configs.recommend_index')
  1019. ->where('book_categories.channel_name', $channel_name)
  1020. ->where('book_configs.is_high_quality', 1)
  1021. // ->where('book_configs.recommend_index', '>=',95)
  1022. ->whereIn('book_configs.is_on_shelf', [2])
  1023. ->orderBy('recommend_index', 'desc')
  1024. ->limit(10)
  1025. ->get()
  1026. ->random(1);
  1027. Log::info('$first_res');
  1028. Log::info($first_res);
  1029. $bids = [];
  1030. $bids[] = $first_res[0]->bid;
  1031. // 找其余3条
  1032. $left_res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1033. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1034. ->select('book_configs.bid')
  1035. ->where('book_categories.channel_name', $channel_name)
  1036. ->where('book_configs.is_high_quality', 1)
  1037. ->whereNotIn('book_configs.bid', $bids)
  1038. ->whereIn('book_configs.is_on_shelf', [2])
  1039. ->orderBy('recommend_index', 'desc')
  1040. ->get()
  1041. ->random(3);
  1042. Log::info('left_res');
  1043. Log::info($left_res);
  1044. foreach ($left_res as $left_r) {
  1045. $bids[] = $left_r->bid;
  1046. }
  1047. Log::info('getTrusteeShipChannelBook_bids:' . json_encode($bids));
  1048. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1049. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1050. ->select(
  1051. 'book_configs.bid',
  1052. 'book_configs.force_subscribe_chapter_seq',
  1053. 'book_configs.vip_seq',
  1054. 'book_configs.price',
  1055. 'books.updated_at as last_update_time',
  1056. 'book_configs.cover',
  1057. 'book_configs.book_name',
  1058. 'book_configs.copyright',
  1059. 'book_configs.charge_type',
  1060. 'book_configs.is_on_shelf',
  1061. 'books.author',
  1062. 'books.intro',
  1063. 'book_categories.category_name',
  1064. 'category_id',
  1065. 'status',
  1066. 'chapter_count',
  1067. 'first_cid',
  1068. 'last_cid',
  1069. 'size',
  1070. 'last_chapter',
  1071. 'books.keyword',
  1072. 'book_configs.recommend_index',
  1073. 'book_configs.is_show_index_content',
  1074. 'book_configs.click_count',
  1075. 'book_configs.product_id',
  1076. 'book_categories.channel_name',
  1077. 'books.last_cid',
  1078. 'books.last_chapter',
  1079. 'book_configs.product_id',
  1080. 'books.name as old_name',
  1081. 'book_configs.recommend_cid',
  1082. 'book_configs.is_high_quality'
  1083. )
  1084. ->where('book_categories.channel_name', $channel_name)
  1085. ->where('book_configs.is_high_quality', 1)
  1086. ->whereIn('book_configs.bid', $bids)
  1087. ->orderBy('recommend_index', 'desc')
  1088. ->get();
  1089. foreach ($res as $v) {
  1090. $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;
  1091. }
  1092. Log::info('last_res');
  1093. Log::info($res);
  1094. return $res;
  1095. }
  1096. /*
  1097. * H5专用,用户阅读完推荐
  1098. * 获取相同推荐
  1099. */
  1100. public static function getRecommendBooks($bid, $channel_name, $num = 4)
  1101. {
  1102. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1103. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1104. ->select(
  1105. 'book_configs.bid',
  1106. 'book_configs.force_subscribe_chapter_seq',
  1107. 'book_configs.vip_seq',
  1108. 'book_configs.price',
  1109. 'book_configs.cover',
  1110. 'book_configs.book_name',
  1111. 'book_configs.copyright',
  1112. 'book_configs.charge_type',
  1113. 'book_configs.is_on_shelf',
  1114. 'books.author',
  1115. 'books.intro',
  1116. 'book_categories.category_name',
  1117. 'category_id',
  1118. 'status',
  1119. 'chapter_count',
  1120. 'first_cid',
  1121. 'last_cid',
  1122. 'size',
  1123. 'last_chapter',
  1124. 'books.keyword',
  1125. 'book_configs.recommend_index',
  1126. 'book_configs.is_show_index_content',
  1127. 'book_configs.click_count',
  1128. 'book_configs.product_id',
  1129. 'book_categories.channel_name',
  1130. 'books.last_cid',
  1131. 'books.last_chapter',
  1132. 'book_configs.product_id',
  1133. 'books.name as old_name',
  1134. 'book_configs.recommend_cid',
  1135. 'book_configs.is_high_quality',
  1136. 'books.updated_at as last_update_time'
  1137. )
  1138. ->where('book_categories.channel_name', $channel_name)
  1139. ->where('book_configs.bid', '!=', $bid)
  1140. ->where('book_configs.is_high_quality', 1)
  1141. ->orderBy('recommend_index', 'desc')->get();
  1142. $count = $res->count() >= $num ? $num : $res->count();
  1143. return $res->random($count);
  1144. }
  1145. /*
  1146. * 签到专用
  1147. * 获取相同推荐
  1148. */
  1149. public static function getSignRecommendBooks(array $bid, $channel_name, $num = 2)
  1150. {
  1151. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1152. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1153. ->select(
  1154. 'book_configs.bid',
  1155. 'book_configs.force_subscribe_chapter_seq',
  1156. 'book_configs.vip_seq',
  1157. 'book_configs.price',
  1158. 'book_configs.cover',
  1159. 'book_configs.book_name',
  1160. 'book_configs.copyright',
  1161. 'book_configs.charge_type',
  1162. 'book_configs.is_on_shelf',
  1163. 'books.author',
  1164. 'books.intro',
  1165. 'book_categories.category_name',
  1166. 'category_id',
  1167. 'status',
  1168. 'chapter_count',
  1169. 'first_cid',
  1170. 'last_cid',
  1171. 'size',
  1172. 'last_chapter',
  1173. 'books.keyword',
  1174. 'book_configs.recommend_index',
  1175. 'book_configs.is_show_index_content',
  1176. 'book_configs.click_count',
  1177. 'book_configs.product_id',
  1178. 'book_categories.channel_name',
  1179. 'books.last_cid',
  1180. 'books.last_chapter',
  1181. 'book_configs.product_id',
  1182. 'books.name as old_name',
  1183. 'book_configs.recommend_cid',
  1184. 'book_configs.is_high_quality',
  1185. 'books.updated_at as last_update_time'
  1186. )
  1187. ->where('book_categories.channel_name', $channel_name)
  1188. ->where('book_configs.is_on_shelf', 2)
  1189. ->whereNotIn('book_configs.bid', $bid)
  1190. ->where('book_configs.is_high_quality', 1)
  1191. ->get();
  1192. $count = $res->count() >= $num ? $num : $res->count();
  1193. return $res->random($count);
  1194. }
  1195. /*
  1196. * 获取指定bid的书籍推荐
  1197. */
  1198. public static function getBidRecommendBooks(array $bids)
  1199. {
  1200. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1201. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1202. ->select(
  1203. 'book_configs.bid',
  1204. 'book_configs.force_subscribe_chapter_seq',
  1205. 'book_configs.vip_seq',
  1206. 'book_configs.price',
  1207. 'book_configs.cover',
  1208. 'book_configs.book_name',
  1209. 'book_configs.copyright',
  1210. 'book_configs.charge_type',
  1211. 'book_configs.is_on_shelf',
  1212. 'books.author',
  1213. 'books.intro',
  1214. 'book_categories.category_name',
  1215. 'category_id',
  1216. 'status',
  1217. 'chapter_count',
  1218. 'first_cid',
  1219. 'last_cid',
  1220. 'size',
  1221. 'last_chapter',
  1222. 'books.keyword',
  1223. 'book_configs.recommend_index',
  1224. 'book_configs.is_show_index_content',
  1225. 'book_configs.click_count',
  1226. 'book_configs.product_id',
  1227. 'book_categories.channel_name',
  1228. 'books.last_cid',
  1229. 'books.last_chapter',
  1230. 'book_configs.product_id',
  1231. 'books.name as old_name',
  1232. 'book_configs.recommend_cid',
  1233. 'book_configs.is_high_quality',
  1234. 'books.updated_at as last_update_time'
  1235. )
  1236. ->whereIn('book_configs.bid', $bids)
  1237. ->get();
  1238. if (!empty($res)) {
  1239. foreach ($res as $v) {
  1240. $v->url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->first_cid;
  1241. }
  1242. }
  1243. return $res;
  1244. }
  1245. /*
  1246. * 获取指定bid的阅读链接
  1247. */
  1248. public static function getBidReadUrl($bid, $chapter_num)
  1249. {
  1250. $offset_chapter_num = $chapter_num - 2;
  1251. $res = DB::select('select chapters.bid,chapters.sequence,chapters.next_cid
  1252. from chapters where bid=' . $bid . '
  1253. order by sequence asc
  1254. limit 1
  1255. offset ' . $offset_chapter_num);
  1256. $read_url = '';
  1257. if (!empty($res)) {
  1258. foreach ($res as $v) {
  1259. $read_url = '/reader?bid=' . Hashids::encode($v->bid) . '&cid=' . $v->next_cid;
  1260. break;
  1261. }
  1262. }
  1263. if (empty($read_url)) $read_url = '?';
  1264. Log::Info('getBidReadUrl,$bid:' . $bid . ' $chapter_num:' . $chapter_num . ' $read_url:' . $read_url);
  1265. return $read_url;
  1266. }
  1267. /**
  1268. * 修改vip章节
  1269. */
  1270. public static function updateVipSeq($bid, $seq)
  1271. {
  1272. return self::where('bid', $bid)->update(['vip_seq' => $seq]);
  1273. }
  1274. public static function getAllBooks($on_shelf, $order)
  1275. {
  1276. if (!$order) {
  1277. $order = ['id', 'asc'];
  1278. }
  1279. return self::whereIn('is_on_shelf', $on_shelf)->select('bid', 'book_name')->orderBy($order[0], $order[1])->get();
  1280. }
  1281. /**
  1282. * 根据条件获取书籍,没有分页
  1283. */
  1284. public static function getBooksNoPage(array $where = [], array $order = [], array $on_shelf, $limit = 20)
  1285. {
  1286. if (!$order) {
  1287. $order = [['recommend_index', 'desc']];
  1288. }
  1289. $res = self::join('books', 'book_configs.bid', '=', 'books.id')
  1290. ->leftjoin('book_categories', 'books.category_id', 'book_categories.id')
  1291. ->select(
  1292. 'book_configs.bid',
  1293. 'book_configs.force_subscribe_chapter_seq',
  1294. 'book_configs.cp_source',
  1295. 'book_configs.vip_seq',
  1296. 'book_configs.price',
  1297. 'book_configs.cover',
  1298. 'book_configs.book_name',
  1299. 'book_configs.copyright',
  1300. 'book_configs.charge_type',
  1301. 'book_configs.is_on_shelf',
  1302. 'books.author',
  1303. 'books.intro',
  1304. 'book_categories.category_name',
  1305. 'category_id',
  1306. 'status',
  1307. 'chapter_count',
  1308. 'book_configs.click_count',
  1309. 'first_cid',
  1310. 'last_cid',
  1311. 'size',
  1312. 'last_chapter',
  1313. 'books.keyword',
  1314. 'book_configs.recommend_index',
  1315. 'book_configs.is_show_index_content',
  1316. 'book_configs.product_id',
  1317. 'book_categories.channel_name',
  1318. 'books.last_cid',
  1319. 'books.last_chapter',
  1320. 'book_configs.product_id',
  1321. 'book_configs.copyright_limit_data',
  1322. 'books.updated_at as last_update_time',
  1323. 'book_configs.promotion_domain',
  1324. 'books.name as old_name',
  1325. 'book_configs.recommend_cid',
  1326. 'book_configs.is_high_quality'
  1327. );
  1328. if ($where) {
  1329. foreach ($where as $v) {
  1330. $res->where($v[0], $v[1], $v[2]);
  1331. }
  1332. }
  1333. $res->whereIn('is_on_shelf', $on_shelf);
  1334. foreach ($order as $v) {
  1335. $res->orderBy($v[0], $v[1]);
  1336. }
  1337. return $res->limit($limit)->get();
  1338. }
  1339. public static function getAllCps()
  1340. {
  1341. $cps = self::select('cp_source')->groupBy('cp_source')->get();
  1342. $result = array();
  1343. foreach ($cps as $cp) {
  1344. if (!empty($cp['cp_source'])) {
  1345. $result[] = $cp['cp_source'];
  1346. }
  1347. }
  1348. return $result;
  1349. }
  1350. public static function getAllCpBooks()
  1351. {
  1352. $result = array();
  1353. $cp_books = self::select('cp_source', 'bid')->groupBy('cp_source')->groupBy('bid')->get();
  1354. foreach ($cp_books as $cp_book) {
  1355. $result[$cp_book['cp_source']][] = $cp_book['bid'];
  1356. }
  1357. return $result;
  1358. }
  1359. /*
  1360. * 得到cp某段时间某本书的消费
  1361. */
  1362. public static function getAllCpBookConsume($start_date, $end_date, $cps, $yestoday)
  1363. {
  1364. $result = self::leftjoin('book_order_statistical', 'book_order_statistical.bid', '=', 'book_configs.bid')
  1365. //
  1366. ->leftjoin('cp_book_time_configs', function ($join) {
  1367. $join->on('cp_book_time_configs.bid', '=', 'book_configs.bid')
  1368. ->on('cp_book_time_configs.cp_source', '=', 'book_configs.cp_source');
  1369. })
  1370. ->select(
  1371. 'book_order_statistical.bid',
  1372. DB::raw('sum(book_order_statistical.charge_balance) as charge_balance'),
  1373. DB::raw('(select book_order_statistical.charge_balance from book_order_statistical where book_order_statistical.bid=book_configs.bid and day="' . $yestoday . '" limit 1) as yestoday_charge_balance'),
  1374. 'book_configs.book_name',
  1375. 'book_configs.is_on_shelf',
  1376. 'book_configs.cp_source'
  1377. )
  1378. ->whereIn('book_configs.cp_source', $cps)
  1379. // 2个起始值取最大值
  1380. ->where('book_order_statistical.day', '>=', DB::raw("ifnull(cp_book_time_configs.start_date,'')"))
  1381. ->where('book_order_statistical.day', '>=', $start_date)
  1382. ->where('book_order_statistical.day', '<=', $end_date)
  1383. ->groupBy('book_configs.cp_source')
  1384. ->groupBy('book_order_statistical.bid')
  1385. ->get();
  1386. return $result;
  1387. }
  1388. public static function getBookByIdAndStatus($bid, $status)
  1389. {
  1390. return self::where('bid', $bid)->whereIn('is_on_shelf', $status)->first();
  1391. }
  1392. public static function get_all_test_books($is_all = false)
  1393. {
  1394. if ($is_all) {
  1395. return self::where('test_status', '<>', 0)->orderBy('test_status', 'asc')->orderBy('test_update_time', 'desc')->get();
  1396. } else {
  1397. return self::where('test_status', '<>', 0)->orderBy('test_status', 'asc')->orderBy('test_update_time', 'desc')->paginate();
  1398. }
  1399. }
  1400. public static function get_test_books($test_status)
  1401. {
  1402. return self::where('test_status', $test_status)->get();
  1403. }
  1404. public static function updateTestBook($bid, $test_status, $plan_push_user_num = 10000)
  1405. {
  1406. return self::where('bid', $bid)->update(['test_status' => $test_status, 'plan_push_user_num' => $plan_push_user_num, 'test_update_time' => date('Y-m-d H:i:s')]);
  1407. }
  1408. public static function get_all_smart_push_books($is_all = false)
  1409. {
  1410. if ($is_all) {
  1411. return self::where('is_on_shelf', 2)->where('is_high_quality', 1)->orderBy('id', 'desc')->get();
  1412. } else {
  1413. return self::where('is_on_shelf', 2)->where('is_high_quality', 1)->orderBy('id', 'desc')->paginate();
  1414. }
  1415. }
  1416. /**
  1417. * 获取书本的id,名称,作者,封面 并带分页
  1418. * @param bool $isAll 是否查询所有
  1419. * @param int $pageSize 每页的条数
  1420. * @param int $pageCount 页数
  1421. * @return mixed
  1422. */
  1423. static function getBookCoverInfos($isAll = false, $pageSize = 200, $pageCount = 0)
  1424. {
  1425. $obj = self::join('books', 'book_configs.bid', '=', 'books.id')->select('book_configs.bid', 'book_configs.book_name', 'books.author', 'book_configs.cover');
  1426. if ($isAll) {
  1427. return $obj->get();
  1428. } else {
  1429. return $obj->limit($pageSize)->offset($pageCount * $pageSize)->get();
  1430. }
  1431. }
  1432. /**
  1433. * 获取书本的总数
  1434. * @return mixed
  1435. */
  1436. static function getBooksCount()
  1437. {
  1438. return self::count();
  1439. }
  1440. /**
  1441. * 通过书名模糊搜索bid
  1442. * @param $book_name
  1443. * @return mixed
  1444. */
  1445. static function getIdByName($book_name)
  1446. {
  1447. return self::select('bid')->where('book_name', 'like', '%' . $book_name . '%')->get();
  1448. }
  1449. static function getBooksByBid($bid)
  1450. {
  1451. return self::where('id', '>', $bid)
  1452. ->where('is_on_shelf', 2)
  1453. ->where('test_status', 0)
  1454. ->orderBy('id', 'asc')->limit(500)->get();
  1455. }
  1456. static function getOneByBid($bid)
  1457. {
  1458. return self::where('bid', $bid)->first();
  1459. }
  1460. static function getBooksByOffsetTime($offset_time=30,$is_full_push=false)
  1461. {
  1462. if($is_full_push){
  1463. return self::whereIn('is_on_shelf', [1,2])
  1464. ->orderBy('id', 'asc')->get();
  1465. }else{
  1466. $start_updated_time = date("Y-m-d H:i:s",time() - $offset_time*60);
  1467. return self::where('updated_at', '>=', $start_updated_time)
  1468. ->whereIn('is_on_shelf', [1,2])
  1469. ->orderBy('id', 'asc')->limit(500)->get();
  1470. }
  1471. }
  1472. }