'read', 'channelType' => 'translation', 'contentType' => "markdown", 'format' => 'react', 'debug' => [], 'studioId' => null, 'lang' => 'zh-Hans', 'footnote' => false, 'paragraph' => false, 'origin' => true, 'translation' => true, ]; /** * Create a new command instance. * string $mode 'read' | 'edit' * string $format 'react' | 'text' | 'tex' | 'unity' * @return void */ public function __construct($param, $channelInfo, $mode, $format = 'react', $studioId = '', $debug = [], $lang = 'zh-Hans') { $this->param = $param; foreach ($channelInfo as $value) { $this->channel_id[] = $value->uid; } $this->channelInfo = $channelInfo; $this->mode = $mode; $this->format = $format; $this->studioId = $studioId; $this->debug = $debug; $this->glossaryKey = 'glossary'; if (count($this->channel_id) > 0) { $channelId = $this->channel_id[0]; if (Str::isUuid($channelId)) { $lang = Channel::where('uid', $channelId)->value('lang'); } } if (!empty($lang)) { $this->lang = $lang; $this->langFamily = explode('-', $lang)[0]; } } public function options($options = []) { foreach ($options as $key => $value) { $this->options[$key] = $value; } } public function glossaryKey() { return $this->glossaryKey; } /** * TODO 设置默认语言。在渲染某些内容的时候需要语言信息 */ public function setLang($lang) { $this->lang = $lang; $this->langFamily = explode('-', $lang)[0]; } private function info($message, $debug) { if (in_array($debug, $this->debug)) { Log::info($message); } } private function error($message, $debug) { if (in_array($debug, $this->debug)) { Log::error($message); } } public function render($tpl_name) { switch ($tpl_name) { case 'term': # 术语 $result = $this->render_term(); break; case 'note': $result = $this->render_note(); break; case 'sent': $result = $this->render_sent(); break; case 'quote': $result = $this->render_quote(); break; case 'ql': $result = $this->render_quote_link(); break; case 'exercise': $result = $this->render_exercise(); break; case 'article': $result = $this->render_article(); break; case 'nissaya': $result = $this->render_nissaya(); break; case 'mermaid': $result = $this->render_mermaid(); break; case 'qa': $result = $this->render_qa(); break; case 'v': $result = $this->render_video(); break; case 'g': $result = $this->render_grammar_lookup(); break; case 'ref': $result = $this->render_ref(); break; case 'dict-pref': $result = $this->render_dict_pref(); break; case 'ai': $result = $this->render_ai(); break; default: # code... $result = [ 'props' => base64_encode(\json_encode([])), 'html' => '', 'tag' => 'span', 'tpl' => 'unknown', ]; break; } return $result; } public function getTermProps($word, $tag = null, $channel = null) { if ($channel && !empty($channel)) { $channelId = $channel; } else { if (count($this->channel_id) > 0) { $channelId = $this->channel_id[0]; } else { $channelId = null; } } if (count($this->channelInfo) === 0) { if (!empty($channel)) { $channelInfo = Channel::where('uid', $channel)->first(); if (!$channelInfo) { unset($channelInfo); } } if (!isset($channelInfo)) { Log::error('channel is null'); $output = [ "word" => $word, 'innerHtml' => '', ]; return $output; } } else { $channelInfo = $this->channelInfo[0]; } if (Str::isUuid($channelId)) { $lang = Channel::where('uid', $channelId)->value('lang'); if (!empty($lang)) { $langFamily = explode('-', $lang)[0]; } else { $langFamily = 'zh'; } $this->info("term:{$word} 先查属于这个channel 的", 'term'); $this->info('channel id' . $channelId, 'term'); $table = DhammaTerm::where("word", $word) ->where('channal', $channelId); if ($tag && !empty($tag)) { $table = $table->where('tag', $tag); } $tplParam = $table->orderBy('updated_at', 'desc') ->first(); $studioId = $channelInfo->owner_uid; } else { $tplParam = false; $lang = ''; $langFamily = ''; $studioId = $this->studioId; } if (!$tplParam) { if (Str::isUuid($studioId)) { /** * 没有,再查这个studio的 * 按照语言过滤 * 完全匹配的优先 * 语族匹配也行 */ $this->info("没有-再查这个studio的", 'term'); $table = DhammaTerm::where("word", $word); if (!empty($tag)) { $table = $table->where('tag', $tag); } $termsInStudio = $table->where('owner', $channelInfo->owner_uid) ->orderBy('updated_at', 'desc') ->get(); if (count($termsInStudio) > 0) { $list = array(); foreach ($termsInStudio as $key => $term) { if (empty($term->channal)) { if ($term->language === $lang) { $list[$term->guid] = 2; } else if (strpos($term->language, $langFamily) !== false) { $list[$term->guid] = 1; } } } if (count($list) > 0) { arsort($list); foreach ($list as $key => $one) { foreach ($termsInStudio as $term) { if ($term->guid === $key) { $tplParam = $term; break; } } break; } } } } } if (!$tplParam) { $this->info("没有,再查社区", 'term'); $community_channel = ChannelApi::getSysChannel("_community_term_zh-hans_"); $table = DhammaTerm::where("word", $word); if (!empty($tag)) { $table = $table->where('tag', $tag); } $tplParam = $table->where('channal', $community_channel) ->first(); if ($tplParam) { $isCommunity = true; } else { $this->info("查社区没有", 'term'); } } $output = [ "word" => $word, "parentChannelId" => $channelId, "parentStudioId" => $channelInfo->owner_uid, ]; $innerString = $output["word"]; if ($tplParam) { $output["id"] = $tplParam->guid; $output["meaning"] = $tplParam->meaning; $output["channel"] = $tplParam->channal; if (!empty($tplParam->note)) { $mdRender = new MdRender(['format' => $this->format]); $output['note'] = $mdRender->convert($tplParam->note, $this->channel_id); } if (isset($isCommunity)) { $output["isCommunity"] = true; } $innerString = "{$output["meaning"]}({$output["word"]})"; if (!empty($tplParam->other_meaning)) { $output["meaning2"] = $tplParam->other_meaning; } } $output['innerHtml'] = $innerString; return $output; } private function render_term() { $word = $this->get_param($this->param, "word", 1); $props = $this->getTermProps($word, ''); $output = $props['word']; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => $props['innerHtml'], 'tag' => 'span', 'tpl' => 'term', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'term', ]; break; case 'html': if (isset($props["meaning"])) { $GLOBALS[$this->glossaryKey][$props["word"]] = $props['meaning']; $key = 'term-' . $props["word"]; $termHead = "" . $props['meaning'] . ""; if (isset($GLOBALS[$key])) { $output = $termHead; } else { $GLOBALS[$key] = 1; $output = $termHead . '(' . $props["word"] . ')'; } } else { $output = $props["word"]; } break; case 'text': if (isset($props["meaning"])) { $key = 'term-' . $props["word"]; if (isset($GLOBALS[$key])) { $output = $props["meaning"]; } else { $GLOBALS[$key] = 1; $output = $props["meaning"] . '(' . $props["word"] . ')'; } } else { $output = $props["word"]; } break; case 'tex': if (isset($props["meaning"])) { $key = 'term-' . $props["word"]; if (isset($GLOBALS[$key])) { $output = $props["meaning"]; } else { $GLOBALS[$key] = 1; $output = $props["meaning"] . '(' . $props["word"] . ')'; } } else { $output = $props["word"]; } break; case 'simple': if (isset($props["meaning"])) { $output = $props["meaning"]; } else { $output = $props["word"]; } break; case 'markdown': if (isset($props["meaning"])) { $key = 'term-' . $props["word"]; if (isset($GLOBALS[$key]) && $GLOBALS[$key] === 1) { $GLOBALS[$key]++; $output = $props["meaning"]; } else { $GLOBALS[$key] = 1; $output = $props["meaning"] . '(' . $props["word"] . ')'; } } else { $output = $props["word"]; } //如果有内容且第一次出现,显示为脚注 if (!empty($props["note"]) && $GLOBALS[$key] === 1) { if (isset($GLOBALS['note_sn'])) { $GLOBALS['note_sn']++; } else { $GLOBALS['note_sn'] = 1; $GLOBALS['note'] = array(); } $content = $props["note"]; $output .= '[^' . $GLOBALS['note_sn'] . ']'; $GLOBALS['note'][] = [ 'sn' => $GLOBALS['note_sn'], 'trigger' => '', 'content' => $content, ]; } break; default: if (isset($props["meaning"])) { $output = $props["meaning"]; } else { $output = $props["word"]; } break; } return $output; } private function render_note() { $note = $this->get_param($this->param, "text", 1); $trigger = $this->get_param($this->param, "trigger", 2); $props = ["note" => $note]; $innerString = ""; if (!empty($trigger)) { $props["trigger"] = $trigger; $innerString = $props["trigger"]; } if ($this->format === 'unity') { $props["note"] = MdRender::render( $props["note"], $this->channel_id, null, 'read', 'translation', 'markdown', 'unity' ); } $output = $note; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => $innerString, 'tag' => 'span', 'tpl' => 'note', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'note', ]; break; case 'html': if (isset($GLOBALS['note_sn'])) { $GLOBALS['note_sn']++; } else { $GLOBALS['note_sn'] = 1; $GLOBALS['note'] = array(); } $GLOBALS['note'][] = [ 'sn' => $GLOBALS['note_sn'], 'trigger' => $trigger, 'content' => MdRender::render( $props["note"], $this->channel_id, null, 'read', 'translation', 'markdown', 'html' ), ]; $link = ""; if (empty($trigger)) { $output = $link . "[" . $GLOBALS['note_sn'] . "]"; } else { $output = $link . $trigger . ""; } break; case 'text': $output = $trigger; break; case 'tex': $output = $trigger; break; case 'simple': $output = ''; break; case 'markdown': if (isset($GLOBALS['note_sn'])) { $GLOBALS['note_sn']++; } else { $GLOBALS['note_sn'] = 1; $GLOBALS['note'] = array(); } $content = MdRender::render( $props["note"], $this->channel_id, null, 'read', 'translation', 'markdown', 'markdown' ); $output = '[^' . $GLOBALS['note_sn'] . ']'; $GLOBALS['note'][] = [ 'sn' => $GLOBALS['note_sn'], 'trigger' => $trigger, 'content' => $content, ]; //$output = ''.$content.''; break; default: $output = ''; break; } return $output; } private function render_nissaya() { $pali = $this->get_param($this->param, "pali", 1); $meaning = $this->get_param($this->param, "meaning", 2); $innerString = ""; $props = [ "pali" => $pali, "meaning" => $meaning, "lang" => $this->lang, ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => $innerString, 'tag' => 'span', 'tpl' => 'nissaya', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'nissaya', ]; break; case 'text': $output = $pali . '၊' . $meaning; break; case 'tex': $output = $pali . '၊' . $meaning; break; case 'simple': $output = $pali . '၊' . $meaning; break; case 'prompt': $output = Tools::MyToRm($pali) . ':' . $meaning; break; default: $output = $pali . '၊' . $meaning; break; } return $output; } private function render_exercise() { $id = $this->get_param($this->param, "id", 1); $title = $this->get_param($this->param, "title", 1); $props = [ "id" => $id, "title" => $title, "channel" => $this->channel_id[0], ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'tag' => 'span', 'tpl' => 'exercise', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'exercise', ]; break; case 'text': $output = $title; break; case 'tex': $output = $title; break; case 'simple': $output = $title; break; default: $output = ''; break; } return $output; } private function render_article() { $type = $this->get_param($this->param, "type", 1); $id = $this->get_param($this->param, "id", 2); $title = $this->get_param($this->param, "title", 3); $channel = $this->get_param($this->param, "channel", 4); $style = $this->get_param($this->param, "style", 5); $book = $this->get_param($this->param, "book", 6); $paragraphs = $this->get_param($this->param, "paragraphs", 7); $anthology = $this->get_param($this->param, "anthology", 8); if ($type === 'chapter' && empty($id)) { $book = (int)$book; $paragraphs = (int)$paragraphs; $id = "{$book}-{$paragraphs}"; } $props = [ "type" => $type, "id" => $id, 'style' => $style, ]; if (!empty($channel)) { $props['channel'] = $channel; } if (!empty($title)) { $props['title'] = $title; } if (!empty($book)) { $props['book'] = $book; } if (!empty($paragraphs)) { $props['paragraphs'] = $paragraphs; } if (!empty($anthology)) { $props['anthology'] = $anthology; } if (is_array($this->channel_id)) { $props['parentChannels'] = $this->channel_id; } switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => $title, 'tag' => 'span', 'tpl' => 'article', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'article', ]; break; case 'text': $output = $title; break; case 'tex': $output = $title; break; case 'simple': $output = $title; break; default: $output = ''; break; } return $output; } private function render_quote() { $paraId = $this->get_param($this->param, "para", 1); $channelId = $this->channel_id[0]; $props = RedisClusters::remember( "/quote/{$channelId}/{$paraId}", config('mint.cache.expire'), function () use ($paraId, $channelId) { $para = \explode('-', $paraId); $output = [ "paraId" => $paraId, "channel" => $channelId, "innerString" => $paraId, ]; if (count($para) < 2) { return $output; } $PaliText = PaliText::where("book", $para[0]) ->where("paragraph", $para[1]) ->select(['toc', 'path']) ->first(); if ($PaliText) { $output["pali"] = $PaliText->toc; $output["paliPath"] = \json_decode($PaliText->path); $output["innerString"] = $PaliText->toc; } return $output; } ); switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => $props["innerString"], 'tag' => 'span', 'tpl' => 'quote', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'quote', ]; break; case 'text': $output = $props["innerString"]; break; case 'tex': $output = $props["innerString"]; break; case 'simple': $output = $props["innerString"]; break; default: $output = $props["innerString"]; break; } return $output; } private function render_quote_link() { $type = $this->get_param($this->param, "type", 1); $title = $this->get_param($this->param, "title", 6, ''); $bookName = $this->get_param($this->param, "bookname", 2, ''); $volume = $this->get_param($this->param, "volume", 3); $page = $this->get_param($this->param, "page", 4, ''); $style = $this->get_param($this->param, "style", 5, 'modal'); $book = $this->get_param($this->param, "book", 7, false); $para = $this->get_param($this->param, "para", 8, false); $props = [ 'type' => $type, 'style' => $style, 'found' => true, ]; if (!empty($bookName) && $volume !== '' && !empty($page)) { $props['bookName'] = $bookName; $props['volume'] = (int)$volume; $props['page'] = $page; $props['found'] = true; } else if ($book && $para) { /** * 没有指定书名,根据book para 查询 */ if ($type === 'c') { //按照章节名称显示 $path = PaliTextApi::getChapterPath($book, $para); if ($path) { $path = json_decode($path, true); } if ($path && is_array($path) && count($path) > 2) { $props['bookName'] = strtolower($path[0]['title']); $props['chapter'] = strtolower(end($path)['title']); $props['found'] = true; } else { $props['found'] = false; } } else { $pageInfo = $this->pageInfoByPara($type, $book, $para); if ($pageInfo['found']) { $props['bookName'] = $pageInfo['bookName']; $props['volume'] = $pageInfo['volume']; $props['page'] = $pageInfo['page']; $props['found'] = true; } else { $props['found'] = false; } } } else if ($title) { //没有书号用title查询 //$tmpTitle = explode('။',$title); for ($i = mb_strlen($title, 'UTF-8'); $i > 0; $i--) { $mTitle = mb_substr($title, 0, $i); $has = array_search($mTitle, array_column(BookTitle::my(), 'title2')); Log::debug('run', ['title' => $mTitle, 'has' => $has]); if ($has !== false) { $tmpBookTitle = $mTitle; $tmpBookPage = mb_substr($title, $i); $tmpBookPage = $this->mb_trim($tmpBookPage, '၊။'); break; } } if (isset($tmpBookTitle)) { Log::debug('book title found', ['title' => $tmpBookTitle, 'page' => $tmpBookPage]); //$tmpBookTitle = $tmpTitle[0]; //$tmpBookPage = $tmpTitle[1]; $tmpBookPage = (int)str_replace( ['၁', '၂', '၃', '၄', '၅', '၆', '၇', '၈', '၉', '၀'], ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'], $tmpBookPage ); $found_key = array_search($tmpBookTitle, array_column(BookTitle::my(), 'title2')); if ($found_key !== false) { $props['bookName'] = BookTitle::my()[$found_key]['bookname']; $props['volume'] = BookTitle::my()[$found_key]['volume']; $props['page'] = $tmpBookPage; if (!empty($props['bookName'])) { $found_title = array_search($props['bookName'], array_column(BookTitle::my(), 'bookname')); if ($found_title === false) { $props['found'] = false; } } } else { //没找到,返回术语和页码 $props['found'] = false; $props['bookName'] = $tmpBookTitle; $props['page'] = $tmpBookPage; $props['volume'] = 0; } } } else { Log::debug('book title not found'); $props['found'] = false; } if ($book && $para) { $props['book'] = $book; $props['para'] = $para; } if ($title) { $props['title'] = $title; } $text = ''; if (isset($props['bookName'])) { $searchField = ''; switch ($type) { case 'm': $searchField = 'm_title'; break; case 'p': $searchField = 'p_title'; break; } $found_title = array_search($props['bookName'], array_column(BookTitle::get(), $searchField)); if ($found_title === false) { $props['found'] = false; } $term = $this->getTermProps($props['bookName'], ':quote:'); $props['term'] = $term; if (isset($term['id'])) { $props['bookNameLocal'] = $term['meaning']; $text .= $term['meaning']; } else { $text .= $bookName; } } if (isset($props['volume']) && isset($props['page'])) { $text .= " {$volume}.{$page}"; } switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => '', 'tag' => 'span', 'tpl' => 'quote-link', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'quote-link', ]; break; default: $output = $text; break; } return $output; } private function pageInfoByPara($type, $book, $para) { $output = array(); $pageInfo = PageNumber::where('type', strtoupper($type)) ->where('book', $book) ->where('paragraph', '<=', $para) ->orderBy('paragraph', 'desc') ->first(); if ($pageInfo) { foreach (BookTitle::get() as $value) { if ($value['id'] === $pageInfo->pcd_book_id) { switch (strtoupper($type)) { case 'M': $key = 'm_title'; break; case 'P': $key = 'p_title'; break; case 'V': $key = 'v_title'; break; default: $key = 'term'; break; } $output['bookName'] = $value[$key]; break; } } $output['volume'] = $pageInfo->volume; $output['page'] = $pageInfo->page; $output['found'] = true; } else { $output['found'] = false; } return $output; } private function render_sent() { $sid = $this->get_param($this->param, "id", 1); $channel = $this->get_param($this->param, "channel", 2); $text = $this->get_param($this->param, "text", 2, 'both'); if (!empty($channel)) { $channels = explode(',', $channel); } else { $channels = $this->channel_id; } $sentInfo = explode('@', trim($sid)); $sentId = $sentInfo[0]; if (isset($sentInfo[1])) { $channels = [$sentInfo[1]]; } $Sent = new CorpusController(); $props = $Sent->getSentTpl( $sentId, $channels, $this->mode, true, $this->format ); if ($props === false) { $props['error'] = "句子模版渲染错误。句子参数个数不符。应该是四个。"; } if ($this->mode === 'read') { $tpl = "sentread"; } else { $tpl = "sentedit"; } //输出引用 $arrSid = explode('-', $sid); $bookPara = array_slice($arrSid, 0, 2); if (!isset($GLOBALS['ref_sent'])) { $GLOBALS['ref_sent'] = array(); } $GLOBALS['ref_sent'][] = $bookPara; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'tag' => 'span', 'tpl' => $tpl, ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => $tpl, ]; break; case 'text': $output = ''; if (isset($props['origin']) && is_array($props['origin'])) { foreach ($props['origin'] as $key => $value) { $output .= $value['html']; } } if (isset($props['translation']) && is_array($props['translation'])) { foreach ($props['translation'] as $key => $value) { $output .= $value['html']; } } break; case 'prompt': $output = ''; if ($text === 'both' || $text === 'origin') { if (isset($props['origin']) && is_array($props['origin'])) { foreach ($props['origin'] as $key => $value) { $output .= $value['html']; } } } if ($text === 'both' || $text === 'translation') { if (isset($props['translation']) && is_array($props['translation'])) { foreach ($props['translation'] as $key => $value) { $output .= $value['html']; } } } break; case 'html': $output = ''; $output .= ''; if ($text === 'both' || $text === 'origin') { if (isset($props['origin']) && is_array($props['origin'])) { foreach ($props['origin'] as $key => $value) { $output .= '' . $value['html'] . ''; } } } if ($text === 'both' || $text === 'translation') { if (isset($props['translation']) && is_array($props['translation'])) { foreach ($props['translation'] as $key => $value) { $output .= '' . $value['html'] . ''; } } } $output .= ''; break; case 'tex': $output = ''; if (isset($props['translation']) && is_array($props['translation'])) { foreach ($props['translation'] as $key => $value) { $output .= $value['html']; } } break; case 'simple': $output = ''; if ($text === 'both' || $text === 'origin') { if (empty($output)) { if ( isset($props['origin']) && is_array($props['origin']) && count($props['origin']) > 0 ) { foreach ($props['origin'] as $key => $value) { $output .= trim($value['html']); } } } } if ($text === 'both' || $text === 'translation') { if ( isset($props['translation']) && is_array($props['translation']) && count($props['translation']) > 0 ) { foreach ($props['translation'] as $key => $value) { $output .= trim($value['html']); } } } break; case 'markdown': $output = ''; if ($text === 'both' || $text === 'origin') { if ( $this->options['origin'] === true || $this->options['origin'] === 'true' ) { if (isset($props['origin']) && is_array($props['origin'])) { foreach ($props['origin'] as $key => $value) { $output .= trim($value['html']); } } } } if ($text === 'both' || $text === 'translation') { if ( $this->options['translation'] === true || $this->options['translation'] === 'true' ) { if ( isset($props['translation']) && is_array($props['translation']) && count($props['translation']) > 0 ) { foreach ($props['translation'] as $key => $value) { $output .= trim($value['html']); } } else { if ($text === 'translation') { //无译文用原文代替 if (isset($props['origin']) && is_array($props['origin'])) { foreach ($props['origin'] as $key => $value) { $output .= trim($value['html']); } } } } } } break; default: $output = ''; break; } return $output; } private function render_mermaid() { $text = json_decode(base64_decode($this->get_param($this->param, "text", 1))); $props = ["text" => implode("\n", $text)]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "mermaid", 'tag' => 'div', 'tpl' => 'mermaid', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'mermaid', ]; break; case 'text': $output = 'mermaid'; break; case 'tex': $output = 'mermaid'; break; case 'simple': $output = 'mermaid'; break; default: $output = 'mermaid'; break; } return $output; } private function render_qa() { $id = $this->get_param($this->param, "id", 1); $style = $this->get_param($this->param, "style", 2); $props = [ "type" => 'qa', "id" => $id, 'title' => '', 'style' => $style, ]; $qa = Discussion::where('id', $id)->first(); if ($qa) { $props['title'] = $qa->title; $props['resId'] = $qa->res_id; $props['resType'] = $qa->res_type; } switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => $props['title'], 'tag' => 'div', 'tpl' => 'qa', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'qa', ]; break; default: $output = $props['title']; break; } return $output; } private function render_grammar_lookup() { $word = $this->get_param($this->param, "word", 1); $props = ['word' => $word]; $localTermChannel = ChannelApi::getSysChannel( "_System_Grammar_Term_" . strtolower($this->lang) . "_", "_System_Grammar_Term_en_" ); $term = $this->getTermProps($word, null, $localTermChannel); $props['term'] = $term; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => $props['word'], 'tag' => 'span', 'tpl' => 'grammar', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'grammar', ]; break; default: $output = $props['word']; break; } return $output; } private function render_video() { $url = $this->get_param($this->param, "url", 1); $style = $this->get_param($this->param, "style", 2, 'modal'); $title = $this->get_param($this->param, "title", 3); $props = [ "url" => $url, 'title' => $title, 'style' => $style, ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => $props['title'], 'tag' => 'span', 'tpl' => 'video', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'video', ]; break; default: $output = $props['title']; break; } return $output; } //论文后面的参考资料 private function render_ref() { $references = array(); $counter = 0; if (isset($GLOBALS['ref_sent'])) { $hasBooks = array(); $book_titles = BookSeries::select(['book', 'paragraph', 'title', 'sn']) ->orderBy('sn', 'DESC')->get(); $bTitles = array(); foreach ($book_titles as $key => $book) { $bTitles[] = [ 'book' => $book->book, 'paragraph' => $book->paragraph, 'title' => $book->title ]; } foreach ($GLOBALS['ref_sent'] as $key => $ref) { $books = array_filter($bTitles, function ($value) use ($ref) { return $value['book'] === (int)$ref[0]; }); if (count($books) > 0) { foreach ($books as $key => $book) { if ($book['paragraph'] < (int)$ref[1]) { if (!isset($hasBooks[$book['title']])) { $hasBooks[$book['title']] = 1; $counter++; $references[] = [ 'sn' => $counter, 'title' => $book['title'], 'copyright' => 'CSCD V4 VRI 2008' ]; } } } } } } $props = [ "pali" => $references, ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => '', 'tag' => 'div', 'tpl' => 'reference', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'reference', ]; break; case 'markdown': $output = ''; foreach ($references as $key => $reference) { $output .= '[' . $reference['sn'] . '] **' . ucfirst($reference['title']) . '** '; $output .= $reference['copyright'] . "\n\n"; } break; default: $output = ''; foreach ($references as $key => $reference) { $output .= '[' . $reference['sn'] . '] ' . ucfirst($reference['title']) . ' '; $output .= $reference['copyright'] . "\n"; } break; } return $output; } private function render_dict_pref() { $currPage = $this->get_param($this->param, "page", 1, 1); $pageSize = $this->get_param($this->param, "size", 2, 100); $props = [ "currPage" => $currPage, 'pageSize' => $pageSize, ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => '', 'tag' => 'div', 'tpl' => 'dict-pref', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'dict-pref', ]; break; default: $output = 'dict-pref'; break; } return $output; } private function render_ai() { $model = $this->get_param($this->param, "model", 1, 1); $props = [ "model" => $model, ]; switch ($this->format) { case 'react': $output = [ 'props' => base64_encode(\json_encode($props)), 'html' => "", 'text' => '', 'tag' => 'div', 'tpl' => 'ai', ]; break; case 'unity': $output = [ 'props' => base64_encode(\json_encode($props)), 'tpl' => 'ai', ]; break; case 'text': $output = 'ai'; break; case 'prompt': $output = ''; break; default: $output = 'ai'; break; } return $output; } private function get_param(array $param, string $name, int $id, string $default = '') { if (isset($param[$name])) { return trim($param[$name]); } else if (isset($param["{$id}"])) { return trim($param["{$id}"]); } else { return $default; } } private function mb_trim($str, string $character_mask = ' ', $charset = "UTF-8") { $start = 0; $end = mb_strlen($str, $charset) - 1; $chars = preg_split('//u', $character_mask, -1, PREG_SPLIT_NO_EMPTY); while ($start <= $end && in_array(mb_substr($str, $start, 1, $charset), $chars)) { $start++; } while ($end >= $start && in_array(mb_substr($str, $end, 1, $charset), $chars)) { $end--; } return mb_substr($str, $start, $end - $start + 1, $charset); } }