'', "title"=> '', "path"=>[], "sub_title"=> '', "summary"=> '', "content"=> '', "content_type"=> "html", "toc" => [], "status"=>30, "lang"=> "", "created_at"=> "", "updated_at"=> "", ]; protected $wbwChannels = []; //句子需要查询的列 protected $selectCol = [ 'uid', 'book_id', 'paragraph', 'word_start', "word_end", 'channel_uid', 'content', 'content_type', 'editor_uid', 'acceptor_uid', 'pr_edit_at', 'updated_at' ]; public function __construct() { } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index(Request $request) { // switch ($request->get('view')) { case 'para': return $this->showPara($request); break; default: # code... break; } } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { // } /** * Display the specified resource. * * @param \App\Models\Sentence $sentence * @return \Illuminate\Http\Response */ public function show(Sentence $sentence) { // } public function getSentTpl($id,$channels,$mode='edit',$onlyProps=false){ $sent = []; $sentId = \explode('-',$id); if(count($sentId) !== 4){ return false; } if($mode==='read'){ $channelId = ChannelApi::getSysChannel('_System_Pali_VRI_'); }else{ $channelId = ChannelApi::getSysChannel('_System_Wbw_VRI_'); } if($channelId !== false){ array_push($channels,$channelId); } $record = Sentence::select($this->selectCol) ->where('book_id',$sentId[0]) ->where('paragraph',$sentId[1]) ->where('word_start',(int)$sentId[2]) ->where('word_end',(int)$sentId[3]) ->whereIn('channel_uid',$channels) ->get(); $channelIndex = $this->getChannelIndex($channels); //获取wbw channel //目前默认的 wbw channel 是第一个translation channel foreach ($channels as $channel) { # code... if($channelIndex[$channel]->type==='translation'){ $this->wbwChannels[] = $channel; break; } } return $this->makeContent($record,$mode,$channelIndex,[],$onlyProps); } /** * Display the specified resource. * @param \Illuminate\Http\Request $request * @param string $id * @return \Illuminate\Http\Response */ public function showSent(Request $request, string $id) { $channels = \explode('_',$request->get('channels')); $this->result['uid'] = ""; $this->result['title'] = ""; $this->result['subtitle'] = ""; $this->result['summary'] = ""; $this->result['lang'] = ""; $this->result['status'] = 30; $this->result['content'] = $this->getSentTpl($id,$channels,$request->get('mode','edit')); return $this->ok($this->result); } /** * 获取某句子的全部译文 * @param \Illuminate\Http\Request $request * @param string $type * @param string $id * @return \Illuminate\Http\Response */ public function showSentences(Request $request, string $type, string $id){ $param = \explode('_',$id); $sentId = \explode('-',$param[0]); $channels = []; #获取channel类型 $sentChannel = Sentence::select('channel_uid') ->where('book_id',$sentId[0]) ->where('paragraph',$sentId[1]) ->where('word_start',$sentId[2]) ->where('word_end',$sentId[3]) ->get(); foreach ($sentChannel as $key => $value) { # code... $channels[] = $value->channel_uid; } $channelInfo = Channel::whereIn("uid",$channels)->select(['uid','type','name'])->get(); $indexChannel = []; $channels = []; foreach ($channelInfo as $key => $value) { # code... if($value->type === $type){ $indexChannel[$value->uid] = $value; $channels[] = $value->uid; } } //获取句子数据 $record = Sentence::select($this->selectCol) ->where('book_id',$sentId[0]) ->where('paragraph',$sentId[1]) ->where('word_start',$sentId[2]) ->where('word_end',$sentId[3]) ->whereIn('channel_uid',$channels) ->orderBy('paragraph') ->orderBy('word_start') ->get(); if(count($record) ===0){ return $this->error("no data"); } $this->result['uid'] = ""; $this->result['title'] = ""; $this->result['subtitle'] = ""; $this->result['summary'] = ""; $this->result['lang'] = ""; $this->result['status'] = 30; $this->result['content'] = $this->makeContent($record,$mode,$indexChannel); return $this->ok($this->result); } /** * Store a newly created resource in storage. * @param \Illuminate\Http\Request $request * @param string $id * @param string $mode * @return \Illuminate\Http\Response */ public function showPara(Request $request) { // $channels = []; if($request->get('mode') === 'edit'){ //翻译模式加载json格式原文 $channels[] = ChannelApi::getSysChannel('_System_Wbw_VRI_'); }else{ //阅读模式加载html格式原文 $channels[] = ChannelApi::getSysChannel('_System_Pali_VRI_'); } if($request->has('channels')){ if(strpos($request->get('channels'),',') === FALSE){ $getChannel = explode('_',$request->get('channels')); }else{ $getChannel = explode(',',$request->get('channels')); } $channels = array_merge($channels,$getChannel ); } $para = explode(",",$request->get('par')); //段落所在章节 $parent = PaliText::where('book',$request->get('book')) ->where('paragraph',$para[0])->first(); $chapter = PaliText::where('book',$request->get('book')) ->where('paragraph',$parent->parent)->first(); if($chapter){ if(empty($chapter->toc)){ $this->result['title'] = "unknown"; }else{ $this->result['title'] = $chapter->toc; $this->result['sub_title'] = $chapter->toc; $this->result['path'] = json_decode($chapter->path); } } $paraFrom = $para[0]; $paraTo = end($para); $indexedHeading = []; #获取channel索引表 $tranChannels = []; $channelInfo = Channel::whereIn("uid",$channels)->select(['uid','type','name'])->get(); foreach ($channelInfo as $key => $value) { # code... if($value->type==="translation" ){ $tranChannels[] = $value->uid; } } $indexChannel = []; $indexChannel = $this->getChannelIndex($channels); //获取wbw channel //目前默认的 wbw channel 是第一个translation channel foreach ($channels as $key => $value) { # code... if($indexChannel[$value]->type==='translation'){ $this->wbwChannels[] = $value; break; } } //章节译文标题 $title = Sentence::select($this->selectCol) ->where('book_id',$parent->book) ->where('paragraph',$parent->paragraph) ->whereIn('channel_uid',$tranChannels) ->first(); if($title){ $this->result['title'] = MdRender::render($title->content,[$title->channel_uid]); } /** * 获取句子数据 */ $record = Sentence::select($this->selectCol) ->where('book_id',$request->get('book')) ->whereIn('paragraph',$para) ->whereIn('channel_uid',$channels) ->orderBy('paragraph') ->orderBy('word_start') ->get(); if(count($record) ===0){ $this->result['content'] = "No Data"; }else{ $this->result['content'] = $this->makeContent($record,$request->get('mode','read'),$indexChannel,$indexedHeading); } return $this->ok($this->result); } /** * Store a newly created resource in storage. * @param \Illuminate\Http\Request $request * @param string $id * @return \Illuminate\Http\Response */ public function showChapter(Request $request, string $id) { // $sentId = \explode('-',$id); $channels = []; if($request->has('channels')){ if(strpos($request->get('channels'),',') === FALSE){ $channels = explode('_',$request->get('channels')); }else{ $channels = explode(',',$request->get('channels')); } } $mode = $request->get('mode','read'); if($mode === 'read'){ //阅读模式加载html格式原文 $channelId = ChannelApi::getSysChannel('_System_Pali_VRI_'); }else{ //翻译模式加载json格式原文 $channelId = ChannelApi::getSysChannel('_System_Wbw_VRI_'); } if($channelId !== false){ $channels[] = $channelId; } $chapter = PaliText::where('book',$sentId[0])->where('paragraph',$sentId[1])->first(); if(!$chapter){ return $this->error("no data"); } if(empty($chapter->toc)){ $this->result['title'] = "unknown"; }else{ $this->result['title'] = $chapter->toc; $this->result['sub_title'] = $chapter->toc; $this->result['path'] = json_decode($chapter->path); } $paraFrom = $sentId[1]; $paraTo = $sentId[1]+$chapter->chapter_len-1; //获取标题 $heading = PaliText::select(["book","paragraph","level"]) ->where('book',$sentId[0]) ->whereBetween('paragraph',[$paraFrom,$paraTo]) ->where('level','<',8) ->get(); //将标题段落转成索引数组 以便输出标题层级 $indexedHeading = []; foreach ($heading as $key => $value) { # code... $indexedHeading["{$value->book}-{$value->paragraph}"] = $value->level; } #获取channel索引表 $tranChannels = []; $channelInfo = Channel::whereIn("uid",$channels)->select(['uid','type','name'])->get(); foreach ($channelInfo as $key => $value) { # code... if($value->type==="translation" ){ $tranChannels[] = $value->uid; } } $indexChannel = []; $indexChannel = $this->getChannelIndex($channels); //获取wbw channel //目前默认的 wbw channel 是第一个translation channel foreach ($channels as $key => $value) { # code... if($indexChannel[$value]->type==='translation'){ $this->wbwChannels[] = $value; break; } } $title = Sentence::select($this->selectCol) ->where('book_id',$sentId[0]) ->where('paragraph',$sentId[1]) ->whereIn('channel_uid',$tranChannels) ->first(); if($title){ $this->result['title'] = MdRender::render($title->content,[$title->channel_uid]); } /** * 获取句子数据 * 算法: * 1. 如果标题和下一级第一个标题之间有段落。只输出这些段落和子目录 * 2. 如果标题和下一级第一个标题之间没有间隔 且 chapter 长度大于10000个字符 且有子目录,只输出子目录 * 3. 如果二者都不是,lazy load */ //1. 计算 标题和下一级第一个标题之间 是否有间隔 $nextChapter = PaliText::where('book',$sentId[0]) ->where('paragraph',">",$sentId[1]) ->where('level','<',8) ->orderBy('paragraph') ->value('paragraph'); $between = $nextChapter - $sentId[1]; //输出子目录 $chapterLen = $chapter->chapter_len; $toc = PaliText::where('book',$sentId[0]) ->whereBetween('paragraph',[$paraFrom+1,$paraFrom+$chapterLen-1]) ->where('level','<',8) ->orderBy('paragraph') ->select(['book','paragraph','level','toc']) ->get(); if($between > 1){ //有间隔 $paraTo = $nextChapter - 1; }else{ if($chapter->chapter_strlen>2000){ if(count($toc)>0){ //有子目录只输出标题和目录 $paraTo = $paraFrom; }else{ //没有子目录 全部输出 } }else{ //章节小。全部输出 不输出章节 $toc = []; } } $pFrom = $request->get('from',$paraFrom); $pTo = $request->get('to',$paraTo); //根据句子的长度找到这次应该加载的句子 $maxLen = 3000; $paliText = PaliText::select(['paragraph','lenght']) ->where('book',$sentId[0]) ->whereBetween('paragraph',[$pFrom,$pTo]) ->get(); $sumLen = 0; $currTo = $pTo; foreach ($paliText as $para) { $sumLen += $para->lenght; if($sumLen > $maxLen){ $currTo = $para->paragraph; break; } } $record = Sentence::select($this->selectCol) ->where('book_id',$sentId[0]) ->whereBetween('paragraph',[$pFrom,$currTo]) ->whereIn('channel_uid',$channels) ->orderBy('paragraph') ->orderBy('word_start') ->get(); if(count($record) ===0){ return $this->error("no data"); } $this->result['content'] = $this->makeContent($record,$mode,$indexChannel,$indexedHeading); if(!$request->has('from')){ //第一次才显示toc $this->result['toc'] = TocResource::collection($toc); } if($currTo < $pTo){ $this->result['from'] = $currTo+1; $this->result['to'] = $pTo; $this->result['paraId'] = $id; $this->result['channels'] = $request->get('channels'); $this->result['mode'] = $request->get('mode'); } return $this->ok($this->result); } private function getChannelIndex($channels,$type=null){ #获取channel索引表 $channelInfo = Channel::whereIn("uid",$channels) ->select(['uid','type','name','owner_uid'])->get(); $indexChannel = []; foreach ($channelInfo as $key => $value) { # code... if($type !== null && $value->type !== $type){ continue; } $indexChannel[$value->uid] = $value; } foreach ($indexChannel as $uid => $value) { # 查询studio $indexChannel[$uid]['studio'] = StudioApi::getById($value->owner_uid); } return $indexChannel; } /** * 根据句子库数据生成文章内容 * $record 句子数据 * $mode read | edit | wbw * $indexChannel channel索引 * $indexedHeading 标题索引 用于给段落加标题标签