ChapterController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. <?php
  2. namespace App\Http\Controllers\Manage\Book;
  3. use App\Modules\Book\Models\Book;
  4. use App\Http\Controllers\Manage\Book\Transformers\ChapterListTransformer;
  5. use App\Http\Controllers\Manage\Book\Transformers\ChapterTransformer;
  6. use App\Modules\Book\Services\BookConfigService;
  7. use App\Modules\Book\Services\ChapterService;
  8. use Illuminate\Http\Request;
  9. use App\Http\Controllers\Controller;
  10. use Storage;
  11. use Hashids;
  12. use DB;
  13. class ChapterController extends Controller
  14. {
  15. /**
  16. * @apiDefine BookChapter 图书章节模块
  17. */
  18. /**
  19. * @apiVersion 1.0.0
  20. * @apiDescription 章节列表分页
  21. * @api {get} books/{bid}/chapter 章节列表分页
  22. * @apiGroup BookChapter
  23. * @apiName getChapterLists
  24. * @apiParam {Int} page_size 分页大小(默认15)
  25. * @apiSuccess {int} code 状态码
  26. * @apiSuccess {String} msg 信息
  27. * @apiSuccess {object} data 结果集
  28. * @apiSuccess {Array} data.list 分页结果集
  29. * @apiSuccess {Int} data.list.bid bid
  30. * @apiSuccess {Int} data.list.chapter_id 章节id
  31. * @apiSuccess {String} data.list.chapter_name 章节名称
  32. * @apiSuccess {Int} data.list.chapter_sequence 序号
  33. * @apiSuccess {Int} data.list.chapter_is_vip 是否vip
  34. * @apiSuccess {Int} data.list.chapter_size 章节大小
  35. * @apiSuccess {Int} data.list.prev_cid 上一章节id
  36. * @apiSuccess {Int} data.list.next_cid 下一章节
  37. * @apiSuccess {String} data.list.recent_update_at 更新时间
  38. * @apiSuccess {String} data.list.is_need_subscirbe 是否强制关注
  39. * @apiSuccess {object} data.meta 分页信息
  40. * @apiSuccess {Int} data.meta.total 总条数
  41. * @apiSuccess {Int} data.meta.per_page 每页条数
  42. * @apiSuccess {Int} data.meta.current_page 当前页
  43. * @apiSuccess {Int} data.meta.last_page 最后页
  44. * @apiSuccess {String} data.meta.next_page_url 下一页
  45. * @apiSuccess {String} data.meta.prev_page_url 上一页
  46. * @apiSuccessExample {json} Success-Response:
  47. * HTTP/1.1 200 OK
  48. * {
  49. * code: 0,
  50. * msg: "",
  51. * data:
  52. * list:[
  53. * {
  54. * bid: 5,
  55. * chapter_id: 5,
  56. * chapter_name: "第1240章 不是我",
  57. * chapter_sequence: 1239,
  58. * chapter_is_vip: 1,
  59. * chapter_size: 2422,
  60. * prev_cid: 0,
  61. * next_cid: 0,
  62. * recent_update_at: 2017-11-20 15:01:56,
  63. * is_need_subscirbe: 1,
  64. * },
  65. * {
  66. * bid: 5,
  67. * chapter_id: 5,
  68. * chapter_name: "第1240章 不是我",
  69. * chapter_sequence: 1239,
  70. * chapter_is_vip: 1,
  71. * chapter_size: 2422,
  72. * prev_cid: 0,
  73. * next_cid: 0,
  74. * recent_update_at: 2017-11-20 15:01:56,
  75. * is_need_subscirbe: 1,
  76. * },
  77. * ]
  78. * meta:{
  79. * total: 1253,
  80. * per_page: 15,
  81. * current_page: 1,
  82. * last_page: 84,
  83. * next_page_url: "http://myapi.cn/api/books/1/chapter?page=2",
  84. * prev_page_url: ""
  85. * }
  86. * }
  87. */
  88. public function getChapterLists(Request $request,$bid){
  89. $page_size = $request->input('page_size',15);
  90. $lists = ChapterService::getChapterListsPage($bid,$page_size);
  91. $book = BookConfigService::getBookById($bid);//force_subscribe_chapter_seq
  92. foreach ($lists as &$item){
  93. $item->is_recommend = 0;
  94. $item->recommend_text = '';
  95. if($item->sequence>= ($book->force_subscribe_chapter_seq)){
  96. $item->is_need_subscirbe = 1;
  97. }else{
  98. $item->is_need_subscirbe = 0;
  99. }
  100. if($item->id == $book->recommend_cid ){
  101. $item->is_recommend = 1;
  102. if( Storage::exists('RecommendChapterPositionWord.txt')){
  103. $item->recommend_text = Storage::get('RecommendChapterPositionWord.txt');
  104. }else{
  105. $item->recommend_text = '建议此章节生成推广文案(原文转化率好)';
  106. }
  107. }
  108. }
  109. return response()->pagination(new ChapterListTransformer,$lists);
  110. }
  111. /**
  112. * @apiVersion 1.0.0
  113. * @apiDescription 前5章章节内容
  114. * @api {get} books/{bid}/fivechapter 前5章章节内容
  115. * @apiGroup BookChapter
  116. * @apiName getTopFiveChapter
  117. * @apiSuccess {int} code 状态码
  118. * @apiSuccess {String} msg 信息
  119. * @apiSuccess {object} data 结果集
  120. * @apiSuccess {Int} data.chapter_id 章节id
  121. * @apiSuccess {String} data.chapter_name 章节名称
  122. * @apiSuccess {Int} data.chapter_sequence 序号
  123. * @apiSuccess {Int} data.chapter_is_vip 是否vip
  124. * @apiSuccess {Int} data.chapter_size 章节大小
  125. * @apiSuccess {Int} data.prev_cid 上一章节id
  126. * @apiSuccess {Int} data.next_cid 下一章节
  127. * @apiSuccess {String} data.recent_update_at 更新时间
  128. * @apiSuccess {String} data.chapter_content 章节内容
  129. * @apiSuccessExample {json} Success-Response:
  130. * HTTP/1.1 200 OK
  131. * {
  132. * code: 0,
  133. * msg: "",
  134. * data: [{
  135. * chapter_id: 5,
  136. * chapter_name: "第1240章 不是我",
  137. * chapter_sequence: 1239,
  138. * chapter_is_vip: 1,
  139. * chapter_size: 2422,
  140. * prev_cid: 0,
  141. * next_cid: 0,
  142. * recent_update_at: 2017-11-20 15:01:56,
  143. * chapter_content: "叶妩被司行霈的阴阳怪气一吓,思路偏得太远了。 她张口结舌,忘记了自己要说什么。",
  144. * },
  145. * ]
  146. * }
  147. */
  148. public function getTopFiveChapter($bid){
  149. $res = ChapterService::getTopFiveChapter($bid);
  150. return response()->collection(new ChapterTransformer,$res);
  151. }
  152. /**
  153. * @apiVersion 1.0.0
  154. * @apiDescription 章节列表和内容
  155. * @api {get} books/{bid}/chapter 章节列表和内容
  156. * @apiGroup BookChapter
  157. * @apiName getCatalogPagination
  158. * @apiSuccess {int} code 状态码
  159. * @apiSuccess {String} msg 信息
  160. * @apiSuccess {object} data 结果集
  161. * @apiSuccess {Int} data.chapter_id 章节id
  162. * @apiSuccess {String} data.chapter_name 章节名称
  163. * @apiSuccess {Int} data.chapter_sequence 序号
  164. * @apiSuccess {Int} data.chapter_is_vip 是否vip
  165. * @apiSuccess {Int} data.chapter_size 章节大小
  166. * @apiSuccess {Int} data.prev_cid 上一章节id
  167. * @apiSuccess {Int} data.next_cid 下一章节
  168. * @apiSuccess {String} data.recent_update_at 更新时间
  169. * @apiSuccess {String} data.chapter_content 章节内容
  170. * @apiSuccess {Int} data.is_recommend 是否是推荐章节
  171. * @apiSuccess {String} data.recommend_text 推荐章节标题
  172. * @apiSuccessExample {json} Success-Response:
  173. * HTTP/1.1 200 OK
  174. * {
  175. * code: 0,
  176. * msg: "",
  177. * data: list:[
  178. * {
  179. * bid: 5,
  180. * chapter_id: 5,
  181. * chapter_name: "第1240章 不是我",
  182. * chapter_sequence: 1239,
  183. * chapter_is_vip: 1,
  184. * chapter_size: 2422,
  185. * prev_cid: 0,
  186. * next_cid: 0,
  187. * recent_update_at: 2017-11-20 15:01:56,
  188. * is_need_subscirbe: 1,
  189. * chapter_content:"这事儿还得从2010年的暑假说起"
  190. * },
  191. * {
  192. * bid: 5,
  193. * chapter_id: 5,
  194. * chapter_name: "第1240章 不是我",
  195. * chapter_sequence: 1239,
  196. * chapter_is_vip: 1,
  197. * chapter_size: 2422,
  198. * prev_cid: 0,
  199. * next_cid: 0,
  200. * recent_update_at: 2017-11-20 15:01:56,
  201. * is_need_subscirbe: 1,
  202. * chapter_content:"这事儿还得从2010年的暑假说起"
  203. * },
  204. * ]
  205. * meta:{
  206. * total: 1253,
  207. * per_page: 15,
  208. * current_page: 1,
  209. * last_page: 84,
  210. * next_page_url: "http://myapi.cn/api/books/1/chapter?page=2",
  211. * prev_page_url: ""
  212. * }
  213. * }
  214. */
  215. function getCatalogPagination(Request $request, $bid)
  216. {
  217. if(!is_numeric($bid)){
  218. $bid = Hashids::decode($bid)[0];
  219. }
  220. $page_size = $request->input('page_size',15);
  221. $lists = ChapterService::getChapterPage($bid,$page_size);
  222. $book = BookConfigService::getBookById($bid);
  223. foreach ($lists as &$item){
  224. $item->is_recommend = '';
  225. $item->recommend_text = '';
  226. if($item->sequence>= ($book->force_subscribe_chapter_seq)){
  227. $item->is_need_subscirbe = 1;
  228. }else{
  229. $item->is_need_subscirbe = 0;
  230. }
  231. if($item->id == $book->recommend_cid ){
  232. $item->is_recommend = 1;
  233. if( Storage::exists('RecommendChapterPositionWord.txt')){
  234. $item->recommend_text = Storage::get('RecommendChapterPositionWord.txt');
  235. }else{
  236. $item->recommend_text = '建议此章节生成推广文案(原文转化率好)';
  237. }
  238. }
  239. }
  240. return response()->pagination(new ChapterListTransformer,$lists);
  241. }
  242. /**
  243. * @apiVersion 1.0.0
  244. * @apiDescription 修改vip章节
  245. * @api {get} chapter/setvip 修改vip章节
  246. * @apiGroup BookChapter
  247. * @apiName editChapterVip
  248. * @apiParam {int} bid bid
  249. * @apiParam {int} vip vip数
  250. * @apiSuccess {int} code 状态码
  251. * @apiSuccess {String} msg 信息
  252. * @apiSuccess {object} data 结果集
  253. * @apiSuccessExample {json} Success-Response:
  254. * HTTP/1.1 200 OK
  255. * {
  256. * code: 0,
  257. * msg: "",
  258. * data: {}
  259. * }
  260. */
  261. public function editChapterVip(Request $request){
  262. $bid = $request->get('bid');
  263. $vip_num = $request->get('vip');
  264. if(empty($bid) || $vip_num == ''){
  265. return response()->error('PARAM_EMPTY');
  266. }
  267. ChapterService::editVip($bid,$vip_num);
  268. BookConfigService::editVipSeq($bid,$vip_num);
  269. return response()->success();
  270. }
  271. /**
  272. * @apiVersion 1.0.0
  273. * @apiDescription 修改章节内容
  274. * @api {post} chapter/content 修改章节内容
  275. * @apiGroup BookChapter
  276. * @apiName editChapterVip
  277. * @apiParam {int} bid bid
  278. * @apiParam {int} cid 章节id
  279. * @apiParam {String} content 内容
  280. * @apiSuccess {int} code 状态码
  281. * @apiSuccess {String} msg 信息
  282. * @apiSuccess {object} data 结果集
  283. * @apiSuccessExample {json} Success-Response:
  284. * HTTP/1.1 200 OK
  285. * {
  286. * code: 0,
  287. * msg: "",
  288. * data: {}
  289. * }
  290. */
  291. public function editChapterContent(Request $request){
  292. $cid = $request->input('cid');
  293. $bid = $request->input('bid');
  294. $content = $request->input('content');
  295. if(empty($cid) || empty($bid) || empty($content)){
  296. return response()->error('PARAM_EMPTY');
  297. }
  298. $chapter = ChapterService::getChapterFromDb($bid,$cid);
  299. $chapter->content = $content;
  300. $chapter->size = ceil(strlen($content)/3);
  301. ChapterService::editChapter($chapter);
  302. return response()->success();
  303. }
  304. /**
  305. * @apiVersion 1.0.0
  306. * @apiDescription 修改章节名
  307. * @api {get} chapter/editChapterName 修改章节名
  308. * @apiGroup BookChapter
  309. * @apiName editChapterName
  310. * @apiParam {int} cid 章节id
  311. * @apiParam {String} chaper_name 章节名
  312. * @apiSuccess {int} code 状态码
  313. * @apiSuccess {String} msg 信息
  314. * @apiSuccess {object} data 结果集
  315. * @apiSuccessExample {json} Success-Response:
  316. * HTTP/1.1 200 OK
  317. * {
  318. * code: 0,
  319. * msg: "",
  320. * data: {}
  321. * }
  322. */
  323. public function editChapterName(Request $request){
  324. $cid = $request->get('cid');
  325. $chaper_name = $request->get('chaper_name');
  326. if(empty($cid) || empty($chaper_name)){
  327. return response()->error('PARAM_EMPTY');
  328. }
  329. ChapterService::updateChapterName($cid,$chaper_name);
  330. return response()->success();
  331. }
  332. /**
  333. * @apiVersion 1.0.0
  334. * @apiDescription 删除章节
  335. * @api {get} chapter/deleteChapter 删除章节
  336. * @apiGroup BookChapter
  337. * @apiName deleteChapter
  338. * @apiParam {int} cid 章节id
  339. * @apiParam {int} bid bid
  340. * @apiSuccess {int} code 状态码
  341. * @apiSuccess {String} msg 信息
  342. * @apiSuccess {object} data 结果集
  343. * @apiSuccessExample {json} Success-Response:
  344. * HTTP/1.1 200 OK
  345. * {
  346. * code: 0,
  347. * msg: "",
  348. * data: {}
  349. * }
  350. */
  351. public function deleteChapter(Request $request){
  352. $cid = $request->get('cid');
  353. $bid = $request->get('bid');
  354. if(empty($cid) || empty($bid)){
  355. return response()->error('PARAM_EMPTY');
  356. }
  357. $chapter = ChapterService::getChapterById($cid);
  358. if(!$chapter || $chapter->bid< 0){
  359. return response()->error('PARAM_EMPTY');
  360. }
  361. $book = Book::where('id',$bid)->first();
  362. $chapter->bid = -$chapter->bid;
  363. $chapter->save();
  364. ChapterService::updateSequence($bid,$chapter->sequence);
  365. $this->adjustSequentOne($bid,$chapter->sequence-1,$chapter->sequence+1);
  366. $book->size -= $chapter->size;
  367. if($chapter->sequence == 1){
  368. $next = ChapterService::getChapterInfoByBidAndSeq($bid,1);
  369. ChapterService::updateOne($chapter->next_cid,['prev_cid'=>0]);
  370. if($next){
  371. $book->first_cid = $next->id;
  372. }
  373. }
  374. if($chapter->sequence == $book->chapter_count){
  375. $prev = ChapterService::getChapterInfoByBidAndSeq($bid,$chapter->sequence-1);
  376. ChapterService::updateOne($chapter->prev_cid,['next_cid'=>0]);
  377. if($prev){
  378. $book->last_cid = $prev->id;
  379. $book->last_chapter = $prev->name;
  380. }
  381. }
  382. $book->chapter_count -= 1;
  383. $book->save();
  384. return response()->success();
  385. }
  386. /**
  387. * @apiVersion 1.0.0
  388. * @apiDescription 新增章节
  389. * @api {post} chapter/addChapter 新增章节
  390. * @apiGroup BookChapter
  391. * @apiName addChapter
  392. * @apiParam {string} name 章节名
  393. * @apiParam {string} content 内容
  394. * @apiParam {int} sequence 顺序
  395. * @apiParam {int} is_vip 是否vip
  396. * @apiParam {int} bid bid
  397. * @apiSuccess {int} code 状态码
  398. * @apiSuccess {String} msg 信息
  399. * @apiSuccess {object} data 结果集
  400. * @apiSuccessExample {json} Success-Response:
  401. * HTTP/1.1 200 OK
  402. * {
  403. * code: 0,
  404. * msg: "",
  405. * data: {}
  406. * }
  407. */
  408. public function addChapter(Request $request){
  409. $param = $request->except('_url');
  410. $res = checkParam($param,['name','content','sequence','is_vip','bid']);
  411. if($res){
  412. return response()->error('PARAM_EMPTY',['msg'=>$res]);
  413. }
  414. if(!is_numeric($param['sequence'])){
  415. return response()->error('PARAM_ERROR',['msg'=>'sequence']);
  416. }
  417. $book = Book::where('id',$param['bid'])->first();
  418. if(!$book){
  419. return response()->error('PARAM_ERROR',['msg'=>'bid not exist']);
  420. }
  421. DB::beginTransaction();
  422. try{
  423. ChapterService::updateSequenceIncr($param['bid'],$param['sequence']);
  424. $param['size'] = mb_strlen($param['content']);
  425. $param['recent_update_at'] = date('Y-m-d H:i:s');
  426. $param['prev_cid'] = 0;
  427. $param['next_cid'] = 0;
  428. $param['ly_chapter_id'] = 0;
  429. $result = ChapterService::createChapter($param);
  430. if($param['sequence'] == 1){
  431. $book->first_cid = $result->id;
  432. }
  433. if($param['sequence'] == $book->chapter_count+1){
  434. $book->last_cid = $result->id;
  435. $book->last_chapter = $param['name'];
  436. }
  437. $this->adjustSequentOne($param['bid'],$param['sequence']-1,$param['sequence']+1);
  438. $book->chapter_count++;
  439. $book->size += $param['size'] ;
  440. $book->save();
  441. DB::commit();
  442. return response()->success();
  443. }catch (\Exception $e){
  444. DB::rollBack();
  445. }
  446. return response()->error('UNKNOWN_ERROR');
  447. }
  448. private function adjustSequentOne($bid,$startsequence,$endsequence){
  449. $chapter_list = DB::table('chapters')
  450. ->whereBetween('sequence',[$startsequence,$endsequence])->orderBy('sequence')->where('bid',$bid)->get();
  451. $prev = 0;
  452. foreach ($chapter_list as $chapter){
  453. if($prev){
  454. DB::table('chapters')->where('id',$chapter->id)->update(['prev_cid'=>$prev]);
  455. DB::table('chapters')->where('id',$prev)->update(['next_cid'=>$chapter->id]);
  456. }
  457. $prev = $chapter->id;
  458. }
  459. }
  460. }