SyncChaptersFromZwContent.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace App\Console\Book;
  3. use App\Models\Book\Book;
  4. use App\Models\Book\Chapter;
  5. use App\Models\Book\ChapterContent;
  6. use GuzzleHttp\Client;
  7. use Illuminate\Console\Command;
  8. use GuzzleHttp\Exception\GuzzleException;
  9. class SyncChaptersFromZwContent extends Command
  10. {
  11. /**
  12. * The name and signature of the console command.
  13. *
  14. * @var string
  15. */
  16. protected $signature = 'chapter:content:sync:from:zw {--bid=} {--after=}';
  17. /**
  18. * The console command description.
  19. *
  20. * @var string
  21. */
  22. protected $description = '从内容平台同步并更新图书章节';
  23. /**
  24. * @var Client
  25. */
  26. private $client;
  27. // 内容中台域名
  28. private $baseUrl = 'http://cp.yqsd.cn/api/book';
  29. /**
  30. * Create a new command instance.
  31. *
  32. * @return void
  33. */
  34. public function __construct()
  35. {
  36. parent::__construct();
  37. $this->client = new Client(['timeout' => 20.0, 'allow_redirects' => true]);
  38. }
  39. /**
  40. * @return void
  41. * @throws GuzzleException
  42. */
  43. public function handle()
  44. {
  45. // 传参
  46. $bid = (int)$this->option('bid');
  47. $after = (int)$this->option('after');
  48. // 获取书籍列表
  49. $books = $this->getBooks($bid, $after);
  50. // 执行更新
  51. $this->syncChapters($books);
  52. }
  53. /**
  54. * 获取待更新书籍列表
  55. *
  56. * @param $bid
  57. * @param $after
  58. * @return mixed
  59. */
  60. private function getBooks($bid, $after)
  61. {
  62. // 组装查询条件
  63. $query = Book::select('id', 'zw_id', 'name')->where('zw_id', '>', '0');
  64. // 此处bid为原创小程序bid
  65. if ($bid) {
  66. if ($after) {
  67. $query->where('books.id', '>=', $bid);
  68. }else{
  69. $query->where('books.id', $bid);
  70. }
  71. }
  72. // 查询
  73. return $query->get();
  74. }
  75. /**
  76. * @param $books
  77. * @return void
  78. * @throws GuzzleException
  79. */
  80. private function syncChapters($books): void
  81. {
  82. // 判空
  83. if ($books->isEmpty()) {
  84. return;
  85. }
  86. // 循环执行
  87. foreach ($books as $book) {
  88. $this->syncBookChapters($book->id, $book->zw_id);
  89. }
  90. }
  91. /**
  92. * @param $bid
  93. * @param $zwId
  94. * @return void
  95. * @throws GuzzleException
  96. */
  97. private function syncBookChapters($bid, $zwId): void
  98. {
  99. dLog('sync')->info('chapter:sync-start', compact('bid', 'zwId'));
  100. // 判空
  101. if (empty($bid) || empty($zwId)) {
  102. return;
  103. }
  104. // 获取最新章节信息
  105. $lastChapter = Chapter::where('bid', $bid)
  106. ->where('is_check', 1)
  107. ->where('is_draft', 0)
  108. ->where('is_deleted', 0)
  109. ->orderBy('sequence', 'desc')
  110. ->first();
  111. // 章节相关参数
  112. $maxSequence = (int)getProp($lastChapter, 'sequence', 0);
  113. $lastChapterId = (int)getProp($lastChapter, 'id', 0);
  114. $zwChapterId = (int)getProp($lastChapter, 'zw_chapter_id', 0);
  115. // 获取内容平台章节列表
  116. $zwChapters = $this->request('/chapterlist/' . $zwId);
  117. if (empty($zwChapters)) {
  118. return;
  119. }
  120. // 循环章节内容
  121. foreach ($zwChapters as $zwChapter) {
  122. $zwCid = (int)getProp($zwChapter, 'chapter_id', 0);
  123. $chapterName = getProp($zwChapter, 'chapter_name');
  124. // 从最新章节开始新增内容
  125. if ($zwChapterId && $zwChapterId !== $zwCid) {
  126. continue;
  127. }
  128. // 获取内容平台章节内容
  129. $contentData = $this->request('/chapterContent/' . $zwId . '/' . $zwCid);
  130. if (empty($contentData)) {
  131. continue;
  132. }
  133. // 先保存章节内容
  134. $obj = new ChapterContent();
  135. $obj->bid = $bid;
  136. $obj->zw_bid = $zwId;
  137. $obj->zw_chapter_id = $zwCid;
  138. $obj->chapter_name = $chapterName;
  139. $obj->content = getProp($contentData, 'content');
  140. $obj->save();
  141. // 保存章节
  142. $obj1 = new Chapter();
  143. $obj1->bid = $bid;
  144. $obj1->name = $chapterName;
  145. $obj1->sequence = (int)getProp($zwChapter, 'sequence');
  146. $obj1->size = (int)getProp($zwChapter, 'size');
  147. $obj1->is_vip = (int)getProp($zwChapter, 'is_vip');
  148. $obj1->is_check = 1;
  149. $obj1->recent_update_at = date('Y-m-d H:i:s');
  150. $obj1->post_time = date('Y-m-d H:i:s');
  151. $obj1->zw_bid = $zwId;
  152. $obj1->zw_chapter_id = $zwCid;
  153. $obj1->chapter_content_id = $obj->id;
  154. $obj1->save();
  155. }
  156. dLog('sync')->info('chapter:sync-end', compact('bid'));
  157. // 执行更新书籍数据脚本
  158. $this->call('book:after:spider', ['--bid' => $bid]);
  159. }
  160. /**
  161. * 请求
  162. *
  163. * @param $url
  164. * @return array|mixed|string
  165. * @throws \GuzzleHttp\Exception\GuzzleException
  166. */
  167. private function request($url)
  168. {
  169. $url = $this->baseUrl . $url;
  170. try {
  171. $result = $this->client->request('get', $url)->getBody()->getContents();
  172. $result = json_decode($result, true);
  173. $code = getProp($result, 'code', 0);
  174. $data = getProp($result, 'data', []);
  175. } catch (\Exception $e) {
  176. return [];
  177. }
  178. return $code ? [] : $data;
  179. }
  180. }