Quellcode durchsuchen

Merge pull request #2442 from visuddhinanda/development

Development
visuddhinanda vor 3 Tagen
Ursprung
Commit
3c75ed07f4
100 geänderte Dateien mit 2480 neuen und 2281 gelöschten Zeilen
  1. 7 7
      api-v13/app/Console/Commands/AiArticleTranslate.php
  2. 28 23
      api-v13/app/Console/Commands/AiTranslate.php
  3. 7 6
      api-v13/app/Console/Commands/CacheDictPreference.php
  4. 6 6
      api-v13/app/Console/Commands/CacheWbwPreference.php
  5. 1 1
      api-v13/app/Console/Commands/ClearEmbeddingsCache.php
  6. 49 44
      api-v13/app/Console/Commands/CopyUserBook.php
  7. 22 19
      api-v13/app/Console/Commands/CreateMyHanCrop.php
  8. 8 4
      api-v13/app/Console/Commands/CreateOpenSearchIndex.php
  9. 2 3
      api-v13/app/Console/Commands/CreateQueue.php
  10. 19 14
      api-v13/app/Console/Commands/ExportAiPaliWordToken.php
  11. 41 33
      api-v13/app/Console/Commands/ExportAiTrainingData.php
  12. 31 31
      api-v13/app/Console/Commands/ExportArticle.php
  13. 26 24
      api-v13/app/Console/Commands/ExportChannel.php
  14. 47 56
      api-v13/app/Console/Commands/ExportChapter.php
  15. 14 12
      api-v13/app/Console/Commands/ExportChapterIndex.php
  16. 12 11
      api-v13/app/Console/Commands/ExportCreateDb.php
  17. 27 23
      api-v13/app/Console/Commands/ExportDiscussion.php
  18. 23 23
      api-v13/app/Console/Commands/ExportFtsPali.php
  19. 25 22
      api-v13/app/Console/Commands/ExportGlossary.php
  20. 11 9
      api-v13/app/Console/Commands/ExportIKPaliTeam.php
  21. 116 104
      api-v13/app/Console/Commands/ExportNissaya.php
  22. 24 22
      api-v13/app/Console/Commands/ExportOffline.php
  23. 25 24
      api-v13/app/Console/Commands/ExportPalitext.php
  24. 19 17
      api-v13/app/Console/Commands/ExportSentence.php
  25. 10 9
      api-v13/app/Console/Commands/ExportTag.php
  26. 11 9
      api-v13/app/Console/Commands/ExportTagmap.php
  27. 31 29
      api-v13/app/Console/Commands/ExportTerm.php
  28. 30 30
      api-v13/app/Console/Commands/ExportZip.php
  29. 33 33
      api-v13/app/Console/Commands/ExportZip2.php
  30. 48 40
      api-v13/app/Console/Commands/ImportArticle.php
  31. 86 77
      api-v13/app/Console/Commands/ImportArticleMap.php
  32. 1 2
      api-v13/app/Console/Commands/IndexOpenSearch.php
  33. 1 1
      api-v13/app/Console/Commands/IndexTerm.php
  34. 60 62
      api-v13/app/Console/Commands/IndexTipitaka.php
  35. 16 14
      api-v13/app/Console/Commands/InitCommentary.php
  36. 39 37
      api-v13/app/Console/Commands/InitCs6sentence.php
  37. 15 13
      api-v13/app/Console/Commands/InitDependence.php
  38. 12 11
      api-v13/app/Console/Commands/InitSystemDict.php
  39. 18 18
      api-v13/app/Console/Commands/Install.php
  40. 36 34
      api-v13/app/Console/Commands/InstallPaliSeries.php
  41. 107 108
      api-v13/app/Console/Commands/InstallPaliText.php
  42. 71 72
      api-v13/app/Console/Commands/InstallWbwTemplate.php
  43. 47 44
      api-v13/app/Console/Commands/InstallWordAll.php
  44. 62 60
      api-v13/app/Console/Commands/InstallWordBook.php
  45. 42 40
      api-v13/app/Console/Commands/InstallWordIndex.php
  46. 44 41
      api-v13/app/Console/Commands/InstallWordStatistics.php
  47. 80 71
      api-v13/app/Console/Commands/MqAiTranslate.php
  48. 62 62
      api-v13/app/Console/Commands/MqDiscussion.php
  49. 4 2
      api-v13/app/Console/Commands/MqEmpty.php
  50. 20 17
      api-v13/app/Console/Commands/MqExport.php
  51. 20 18
      api-v13/app/Console/Commands/MqExportArticle.php
  52. 21 18
      api-v13/app/Console/Commands/MqExportPaliChapter.php
  53. 7 3
      api-v13/app/Console/Commands/MqIssues.php
  54. 24 26
      api-v13/app/Console/Commands/MqPr.php
  55. 21 17
      api-v13/app/Console/Commands/MqProgress.php
  56. 10 8
      api-v13/app/Console/Commands/MqTask.php
  57. 12 10
      api-v13/app/Console/Commands/MqWbwAnalyses.php
  58. 0 2
      api-v13/app/Console/Commands/PatchWbwPageNumber.php
  59. 4 4
      api-v13/app/Console/Commands/PostInstall.php
  60. 6 5
      api-v13/app/Console/Commands/ProcessDeadLetterQueue.php
  61. 52 40
      api-v13/app/Console/Commands/RabbitMQWorker.php
  62. 7 6
      api-v13/app/Console/Commands/RemoveTermCache.php
  63. 23 21
      api-v13/app/Console/Commands/StatisticsDict.php
  64. 20 18
      api-v13/app/Console/Commands/StatisticsExp.php
  65. 27 24
      api-v13/app/Console/Commands/StatisticsNissaya.php
  66. 15 10
      api-v13/app/Console/Commands/StatisticsNissayaCover.php
  67. 19 17
      api-v13/app/Console/Commands/StatisticsWbw.php
  68. 10 10
      api-v13/app/Console/Commands/TestAI.php
  69. 5 3
      api-v13/app/Console/Commands/TestAIArticleTranslate.php
  70. 1 1
      api-v13/app/Console/Commands/TestAITerm.php
  71. 7 4
      api-v13/app/Console/Commands/TestAiTask.php
  72. 21 20
      api-v13/app/Console/Commands/TestCaseMan.php
  73. 6 5
      api-v13/app/Console/Commands/TestJsonToXml.php
  74. 14 12
      api-v13/app/Console/Commands/TestMarkdownToTpl.php
  75. 27 22
      api-v13/app/Console/Commands/TestMdRender.php
  76. 9 6
      api-v13/app/Console/Commands/TestMq.php
  77. 3 1
      api-v13/app/Console/Commands/TestMqExit.php
  78. 17 13
      api-v13/app/Console/Commands/TestMqWorker.php
  79. 22 17
      api-v13/app/Console/Commands/TestProjectCopyTask.php
  80. 22 28
      api-v13/app/Console/Commands/TestRedis.php
  81. 3 1
      api-v13/app/Console/Commands/TestSchedule.php
  82. 16 15
      api-v13/app/Console/Commands/TestSearchPali.php
  83. 13 11
      api-v13/app/Console/Commands/TestTex.php
  84. 9 6
      api-v13/app/Console/Commands/TestWorkerStartProject.php
  85. 52 55
      api-v13/app/Console/Commands/UpdateCorpus.php
  86. 7 3
      api-v13/app/Console/Commands/UpdateOpenSearchIndex.php
  87. 12 11
      api-v13/app/Console/Commands/UpdateRelationTo.php
  88. 26 25
      api-v13/app/Console/Commands/UpdateSentenceUnique.php
  89. 8 6
      api-v13/app/Console/Commands/UpdateSentenceVer.php
  90. 4 4
      api-v13/app/Console/Commands/UpgradeAITranslation.php
  91. 4 3
      api-v13/app/Console/Commands/UpgradeAt20230227.php
  92. 23 24
      api-v13/app/Console/Commands/UpgradeChapterDynamicDaily.php
  93. 27 28
      api-v13/app/Console/Commands/UpgradeChapterDynamicWeekly.php
  94. 30 30
      api-v13/app/Console/Commands/UpgradeCommunityTerm.php
  95. 68 60
      api-v13/app/Console/Commands/UpgradeCompound.php
  96. 13 14
      api-v13/app/Console/Commands/UpgradeDaily.php
  97. 55 49
      api-v13/app/Console/Commands/UpgradeDict.php
  98. 49 46
      api-v13/app/Console/Commands/UpgradeDictDefaultMeaning.php
  99. 10 8
      api-v13/app/Console/Commands/UpgradeDictId.php
  100. 23 19
      api-v13/app/Console/Commands/UpgradeDictSysPreference.php

+ 7 - 7
api-v13/app/Console/Commands/AiArticleTranslate.php

@@ -2,12 +2,11 @@
 
 namespace App\Console\Commands;
 
+use App\Services\AIAssistant\ArticleTranslateService;
+use App\Services\ArticleService;
 use Illuminate\Console\Attributes\Description;
 use Illuminate\Console\Attributes\Signature;
 use Illuminate\Console\Command;
-use App\Services\AIAssistant\ArticleTranslateService;
-use App\Services\ArticleService;
-
 
 #[Signature('app:ai-article-translate
 {--article=}
@@ -26,10 +25,11 @@ class AiArticleTranslate extends Command
     public function handle()
     {
         if (
-            !$this->option('model') ||
-            !$this->option('channel')
+            ! $this->option('model') ||
+            ! $this->option('channel')
         ) {
             $this->error('model,article,channel is requested');
+
             return;
         }
         //
@@ -46,7 +46,7 @@ class AiArticleTranslate extends Command
                 $llm = $llm->setThinking($this->option('thinking') === 'true');
             }
 
-            $total =    $llm->translateArticle($this->option('article'))
+            $total = $llm->translateArticle($this->option('article'))
                 ->save();
             $this->info("{$total} sentences saved");
         }
@@ -68,7 +68,7 @@ class AiArticleTranslate extends Command
                 $this->info("{$total} sentences saved");
             }
 
-            $this->info(count($articleIds) . " article saved");
+            $this->info(count($articleIds).' article saved');
         }
     }
 }

+ 28 - 23
api-v13/app/Console/Commands/AiTranslate.php

@@ -2,13 +2,12 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Models\Sentence;
 use App\Models\PaliSentence;
 use App\Models\PaliText;
-
-use Illuminate\Support\Facades\Log;
+use App\Models\Sentence;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
 
 class AiTranslate extends Command
 {
@@ -16,9 +15,10 @@ class AiTranslate extends Command
      * The name and signature of the console command.
      * php artisan ai:sentence.translate --type=chapter --api=deepseek --model=deepseek-chat --sid=107-2357
      * php artisan ai:sentence.translate --type=sentence --api=kimi --model=moonshot-v1-8k --sid=107-2357-9-47
+     *
      * @var string
      */
-    protected $signature = <<<command
+    protected $signature = <<<'command'
     ai:sentence.translate 
     {--type=sentence  : sentence|paragraph|chapter} 
     {--api=  : ai engin url} 
@@ -52,8 +52,8 @@ class AiTranslate extends Command
      */
     public function handle()
     {
-        //句子号列表
-        $sentences = array();
+        // 句子号列表
+        $sentences = [];
         $totalLen = 0;
         switch ($this->option('type')) {
             case 'sentence':
@@ -83,37 +83,39 @@ class AiTranslate extends Command
                 return 1;
                 break;
         }
-        //获取句子总长度
+        // 获取句子总长度
 
         foreach ($sentences as $key => $sentence) {
             $totalLen += $this->sentLen($sentence);
         }
         //
         foreach ($sentences as $key => $sentence) {
-            # 获取巴利句子
+            // 获取巴利句子
             $pali = PaliSentence::where('book', $sentence[0])
                 ->where('paragraph', $sentence[1])
                 ->where('word_begin', $sentence[2])
                 ->where('word_end', $sentence[3])
                 ->value('text');
-            //获取nissaya
+            // 获取nissaya
             $nissaya = Sentence::where('channel_uid', $this->option('nissaya'))
                 ->where('book_id', $sentence[0])
                 ->where('paragraph', $sentence[1])
                 ->where('word_start', $sentence[2])
                 ->where('word_end', $sentence[3])
                 ->value('content');
-            //获取ai结果
+            // 获取ai结果
             $api = $this->getEngin($this->option('api'));
-            if (!$api) {
+            if (! $api) {
                 $this->error('ai translate no api');
+
                 return 1;
             }
             $json = $this->fetch($api, $this->option('model'), $pali, $nissaya);
             Log::info('ai translate', ['json' => $json]);
             $this->info($json['choices'][0]['message']['content']);
-            //写入
+            // 写入
         }
+
         return 0;
     }
 
@@ -125,41 +127,44 @@ class AiTranslate extends Command
             ->where('word_end', $id[3])
             ->value('length');
     }
+
     private function getEngin($engin)
     {
         $api = config('mint.ai.accounts');
         $selected = array_filter($api, function ($value) use ($engin) {
             return $value['name'] === $engin;
         });
-        if (!is_array($selected) || count($selected) === 0) {
+        if (! is_array($selected) || count($selected) === 0) {
             return null;
         }
+
         return $selected[0];
     }
 
-    private function fetch($api, $model, $origin,  $nissaya = null)
+    private function fetch($api, $model, $origin, $nissaya = null)
     {
         $prompt = '翻译上面的巴利文为中文';
         if ($nissaya) {
-            $prompt = '根据下面的解释,' . $prompt;
+            $prompt = '根据下面的解释,'.$prompt;
         }
         $message = "{$origin}\n\n{$prompt}\n\n{$nissaya}";
 
         $url = $api['api_url'];
         $param = [
-            "model" => $model,
-            "messages" => [
-                ["role" => "system", "content" => "你是翻译人工智能助手.bhikkhu 为专有名词,不可翻译成其他语言。"],
-                ["role" => "user", "content" => $message],
+            'model' => $model,
+            'messages' => [
+                ['role' => 'system', 'content' => '你是翻译人工智能助手.bhikkhu 为专有名词,不可翻译成其他语言。'],
+                ['role' => 'user', 'content' => $message],
             ],
-            "temperature" => 0.3,
-            "stream" => false
+            'temperature' => 0.3,
+            'stream' => false,
         ];
         $response = Http::withToken($api['token'])
             ->post($url, $param);
         if ($response->failed()) {
-            $this->error('http request error' . $response->json('message'));
+            $this->error('http request error'.$response->json('message'));
             Log::error('http request error', ['data' => $response->json()]);
+
             return null;
         } else {
             return $response->json();

+ 7 - 6
api-v13/app/Console/Commands/CacheDictPreference.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\UserDict;
-use Illuminate\Support\Facades\DB;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\DB;
 
 class CacheDictPreference extends Command
 {
@@ -40,7 +41,7 @@ class CacheDictPreference extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $prefix = 'dict-preference';
@@ -57,15 +58,15 @@ class CacheDictPreference extends Command
                 ->where('source', '_PAPER_RICH_')
                 ->whereNotNull('mean')
                 ->value('mean');
-            $meaning = trim($meaning, " $");
-            if (!empty($meaning)) {
+            $meaning = trim($meaning, ' $');
+            if (! empty($meaning)) {
                 $m = explode('$', $meaning);
                 Cache::put("{$prefix}/{$word->word}/{$word->language}", $m[0]);
             }
             $bar->advance();
             $count++;
             if ($count % 1000 === 0) {
-                if (\App\Tools\Tools::isStop()) {
+                if (Tools::isStop()) {
                     return 0;
                 }
             }

+ 6 - 6
api-v13/app/Console/Commands/CacheWbwPreference.php

@@ -2,10 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Models\WbwAnalysis;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Cache;
-use App\Models\WbwAnalysis;
 use Illuminate\Support\Facades\DB;
 
 class CacheWbwPreference extends Command
@@ -41,7 +41,7 @@ class CacheWbwPreference extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $prefix = 'wbw-preference';
@@ -78,7 +78,7 @@ class CacheWbwPreference extends Command
                 $bar->advance();
                 $count++;
                 if ($count % 1000 === 0) {
-                    if (\App\Tools\Tools::isStop()) {
+                    if (Tools::isStop()) {
                         return 0;
                     }
                 }
@@ -105,8 +105,8 @@ class CacheWbwPreference extends Command
                 $data = WbwAnalysis::where('wbw_word', $value->wbw_word)
                     ->where('type', $value->type)
                     ->selectRaw('data,count(*)')
-                    ->groupBy("data")
-                    ->orderBy("count", "desc")
+                    ->groupBy('data')
+                    ->orderBy('count', 'desc')
                     ->first();
 
                 Cache::put("{$prefix}/{$value->wbw_word}/{$value->type}/0", $data->data);

+ 1 - 1
api-v13/app/Console/Commands/ClearEmbeddingsCache.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Services\OpenSearchService;
+use Illuminate\Console\Command;
 
 class ClearEmbeddingsCache extends Command
 {

+ 49 - 44
api-v13/app/Console/Commands/CopyUserBook.php

@@ -2,20 +2,20 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Models\CustomBookSentence;
-use App\Models\CustomBook;
-
 use App\Models\Channel;
+use App\Models\CustomBook;
+use App\Models\CustomBookSentence;
 use App\Models\Sentence;
-use Illuminate\Support\Str;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
 
 class CopyUserBook extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan copy:user.book
+     *
      * @var string
      */
     protected $signature = 'copy:user.book {--lang} {--book=} {--test}';
@@ -44,16 +44,16 @@ class CopyUserBook extends Command
      */
     public function handle()
     {
-        //获取全部语言列表
+        // 获取全部语言列表
         $lang = CustomBookSentence::select('lang')->groupBy('lang')->get();
         foreach ($lang as $key => $value) {
             $this->info('language:'.$value->lang);
         }
-        if($this->option('lang')){
+        if ($this->option('lang')) {
             return 0;
         }
 
-        if($this->option('test')){
+        if ($this->option('test')) {
             $this->info('run in test mode');
         }
 
@@ -62,18 +62,18 @@ class CopyUserBook extends Command
 
         foreach (CustomBook::get() as $key => $customBook) {
             $this->info('doing book='.$customBook->book_id);
-            if(empty($customBook->channel_id)){
+            if (empty($customBook->channel_id)) {
                 $bookLang = $customBook->lang;
-                if(empty($bookLang) || $bookLang === 'false' || $bookLang === 'null'  || $bookLang === 'none'){
+                if (empty($bookLang) || $bookLang === 'false' || $bookLang === 'null' || $bookLang === 'none') {
                     $this->info('language can not be empty change to pa, book='.$customBook->book_id);
                     Log::warning('copy:user.book language can not be empty ,change to pa, book='.$customBook->book_id);
                     $bookLang = 'pa';
                 }
                 $customBook->lang = $bookLang;
                 $channelName = '_user_book_'.$bookLang;
-                $channel = Channel::where('owner_uid',$customBook->owner)
-                                ->where('name',$channelName)->first();
-                if($channel === null){
+                $channel = Channel::where('owner_uid', $customBook->owner)
+                    ->where('name', $channelName)->first();
+                if ($channel === null) {
                     $this->info('create new channel');
                     $channelUuid = Str::uuid();
                     $channel = new Channel;
@@ -85,31 +85,34 @@ class CopyUserBook extends Command
                     $channel->lang = $bookLang;
                     $channel->editor_id = 0;
                     $channel->is_system = true;
-                    $channel->create_time = time()*1000;
-                    $channel->modify_time = time()*1000;
+                    $channel->create_time = time() * 1000;
+                    $channel->modify_time = time() * 1000;
                     $channel->status = $customBook->status;
-                    if(!$this->option('test')){
+                    if (! $this->option('test')) {
                         $saveOk = $channel->save();
-                        if($saveOk){
+                        if ($saveOk) {
                             $newChannel++;
                             Log::debug('copy user book : create channel success name='.$channelName);
-                        }else{
-                            Log::error('copy user book : create channel fail.',['channel'=>$channelName,'book'=>$customBook->book_id]);
+                        } else {
+                            Log::error('copy user book : create channel fail.', ['channel' => $channelName, 'book' => $customBook->book_id]);
                             $this->error('copy user book : create channel fail.  name='.$channelName);
+
                             continue;
                         }
                     }
                 }
-                if(!Str::isUuid($channel->uid)){
-                    Log::error('copy user book : channel id error.',['channel'=>$channelName,'book'=>$customBook->book_id]);
+                if (! Str::isUuid($channel->uid)) {
+                    Log::error('copy user book : channel id error.', ['channel' => $channelName, 'book' => $customBook->book_id]);
                     $this->error('copy user book : channel id error.  name='.$channelName);
+
                     continue;
                 }
                 $customBook->channel_id = $channel->uid;
-                if(!$this->option('test')){
+                if (! $this->option('test')) {
                     $ok = $customBook->save();
-                    if(!$ok){
-                        Log::error('copy user book : create channel fail.',['book'=>$customBook->book_id]);
+                    if (! $ok) {
+                        Log::error('copy user book : create channel fail.', ['book' => $customBook->book_id]);
+
                         continue;
                     }
                 }
@@ -118,31 +121,32 @@ class CopyUserBook extends Command
         $this->info('给CustomBook 添加channel 结束');
 
         $userBooks = CustomBook::get();
-        $this->info('book '. count($userBooks));
+        $this->info('book '.count($userBooks));
         $copySent = 0;
         foreach ($userBooks as $key => $book) {
 
             $queryBook = $this->option('book');
-            if(!empty($queryBook)){
-                if($book->book_id != $queryBook){
+            if (! empty($queryBook)) {
+                if ($book->book_id != $queryBook) {
                     continue;
                 }
             }
-            if(empty($book->channel_id)){
+            if (empty($book->channel_id)) {
                 $this->error('book channel is empty');
+
                 continue;
             }
-            $this->info('doing book '. $book->book_id);
+            $this->info('doing book '.$book->book_id);
 
-            $bookSentence = CustomBookSentence::where('book',$book->book_id)->cursor();
+            $bookSentence = CustomBookSentence::where('book', $book->book_id)->cursor();
             foreach ($bookSentence as $key => $sentence) {
                 $newRow = Sentence::firstOrNew(
                     [
-                        "book_id" => $sentence->book,
-                        "paragraph" => $sentence->paragraph,
-                        "word_start" => $sentence->word_start,
-                        "word_end" => $sentence->word_end,
-                        "channel_uid" => $book->channel_id,
+                        'book_id' => $sentence->book,
+                        'paragraph' => $sentence->paragraph,
+                        'word_start' => $sentence->word_start,
+                        'word_end' => $sentence->word_end,
+                        'channel_uid' => $book->channel_id,
                     ],
                     [
                         'id' => app('snowflake')->id(),
@@ -150,21 +154,21 @@ class CopyUserBook extends Command
                         'create_time' => $sentence->create_time,
                         'modify_time' => $sentence->modify_time,
                     ]
-                    );
+                );
                 $newRow->editor_uid = $sentence->owner;
                 $newRow->content = $sentence->content;
-                $newRow->strlen = mb_strlen($sentence->content,"UTF-8");
+                $newRow->strlen = mb_strlen($sentence->content, 'UTF-8');
                 $newRow->status = $sentence->status;
                 $newRow->content_type = $sentence->content_type;
                 $newRow->language = $book->lang;
-                if(empty($newRow->channel_uid)){
-                    $this->error('channel uuid is null book='.$sentence->book .' para='.$sentence->paragraph);
-                    Log::error('channel uuid is null ',['sentence'=>$sentence->book]);
-                }else{
-                    if(!$this->option('test')){
+                if (empty($newRow->channel_uid)) {
+                    $this->error('channel uuid is null book='.$sentence->book.' para='.$sentence->paragraph);
+                    Log::error('channel uuid is null ', ['sentence' => $sentence->book]);
+                } else {
+                    if (! $this->option('test')) {
                         $ok = $newRow->save();
-                        if(!$ok){
-                            Log::error('copy fail ',['sentence'=>$sentence->id]);
+                        if (! $ok) {
+                            Log::error('copy fail ', ['sentence' => $sentence->id]);
                         }
                         $copySent++;
                     }
@@ -175,6 +179,7 @@ class CopyUserBook extends Command
         $this->info('all done ');
         $this->info('channel create '.$newChannel);
         $this->info('sentence copy '.$copySent);
+
         return 0;
     }
 }

+ 22 - 19
api-v13/app/Console/Commands/CreateMyHanCrop.php

@@ -10,6 +10,7 @@ class CreateMyHanCrop extends Command
     /**
      * The name and signature of the console command.
      * php artisan create:my.han.crop --page=10
+     *
      * @var string
      */
     protected $signature = 'create:my.han.crop {--page=}';
@@ -38,8 +39,8 @@ class CreateMyHanCrop extends Command
      */
     public function handle()
     {
-        $csvFile = config("mint.path.dict_text") . '/zh/my-han/index.csv';
-        if (($fp = fopen($csvFile, "r")) !== false) {
+        $csvFile = config('mint.path.dict_text').'/zh/my-han/index.csv';
+        if (($fp = fopen($csvFile, 'r')) !== false) {
             $row = 0;
             $currPage = 0;
             $currPageWords = [];
@@ -49,17 +50,17 @@ class CreateMyHanCrop extends Command
                     continue;
                 }
                 if ($this->option('page')) {
-                    if ($currPage >= (int)$this->option('page')) {
+                    if ($currPage >= (int) $this->option('page')) {
                         break;
                     }
                 }
-                $page = (int)$data[1];
+                $page = (int) $data[1];
                 $word = $data[2];
                 if ($page !== $currPage) {
-                    //保存上一页数据
+                    // 保存上一页数据
                     $this->save($currPage, $currPageWords);
                     $currPage = $page;
-                    //清空单词缓存
+                    // 清空单词缓存
                     $currPageWords = [];
                 }
                 $currPageWords[] = $word;
@@ -68,19 +69,21 @@ class CreateMyHanCrop extends Command
             $this->save($currPage, $currPageWords);
         }
         $this->info('done');
+
         return 0;
     }
+
     private function save($page, $words)
     {
         $basicUrl = 'https://ftp.wikipali.org/kosalla/%E7%BC%85%E6%96%87%E8%AF%8D%E5%85%B8/';
         if (count($words) > 0) {
-            $m = new \Mustache_Engine(array(
+            $m = new \Mustache_Engine([
                 'entity_flags' => ENT_QUOTES,
                 'escape' => function ($value) {
                     return $value;
-                }
-            ));
-            $tplFile = resource_path("/mustache/my_han_crop.tpl");
+                },
+            ]);
+            $tplFile = resource_path('/mustache/my_han_crop.tpl');
             $tpl = file_get_contents($tplFile);
             $wordWithIndex = [];
             foreach ($words as $key => $value) {
@@ -93,22 +96,22 @@ class CreateMyHanCrop extends Command
                 'dict' => [
                     ['index' => 'a', 'img' => "{$basicUrl}{$page}A.jpg"],
                     ['index' => 'b', 'img' => "{$basicUrl}{$page}B.jpg"],
-                    ['index' => 'a', 'img' => "{$basicUrl}" . ($page + 1) . "A.jpg"],
+                    ['index' => 'a', 'img' => "{$basicUrl}".($page + 1).'A.jpg'],
                 ],
-                'words' => $wordWithIndex
+                'words' => $wordWithIndex,
             ];
             $content = $m->render($tpl, $data);
-            //保存到临时文件夹
+            // 保存到临时文件夹
             // 使用本地磁盘
             // 创建目录]
-            $dir = '/tmp/export/myhan_crop/' . $page;
+            $dir = '/tmp/export/myhan_crop/'.$page;
             Storage::disk('local')->makeDirectory($dir);
-            Storage::disk('local')->makeDirectory($dir . '/img');
-            Storage::disk('local')->put($dir . "/index.html", $content);
-            Storage::disk('local')->put($dir . "/img/{$page}", $page);
-            $this->info("page={$page} word=" . count($words));
+            Storage::disk('local')->makeDirectory($dir.'/img');
+            Storage::disk('local')->put($dir.'/index.html', $content);
+            Storage::disk('local')->put($dir."/img/{$page}", $page);
+            $this->info("page={$page} word=".count($words));
         } else {
-            $this->error('page' . $page . 'no words');
+            $this->error('page'.$page.'no words');
         }
     }
 }

+ 8 - 4
api-v13/app/Console/Commands/CreateOpenSearchIndex.php

@@ -10,6 +10,7 @@ class CreateOpenSearchIndex extends Command
     /**
      * The name and signature of the console command.
      * php artisan create:opensearch.index
+     *
      * @var string
      */
     protected $signature = 'create:opensearch.index';
@@ -46,6 +47,7 @@ class CreateOpenSearchIndex extends Command
             $this->info($open[1]);
         } else {
             $this->error($open[1]);
+
             return 1; // Exit with error code
         }
 
@@ -54,20 +56,22 @@ class CreateOpenSearchIndex extends Command
             $this->info('create openSearch index. index name='.config('mint.opensearch.index'));
             $crate = $openSearch->createIndex();
             if ($crate['acknowledged']) {
-                $this->info('Index created successfully: ' . $crate['index']);
+                $this->info('Index created successfully: '.$crate['index']);
             }
             if ($crate['shards_acknowledged']) {
-                $this->info('Shards initialized successfully for index: ' . $crate['index']);
+                $this->info('Shards initialized successfully for index: '.$crate['index']);
             } else {
-                $this->error('Shard initialization failed for index: ' . $crate['index']);
+                $this->error('Shard initialization failed for index: '.$crate['index']);
+
                 return 1;
             }
         } catch (\Exception $e) {
             if (str_contains($e->getMessage(), 'exists')) {
                 $this->warn('Index already exists, attempting to update...');
             } else {
-                $this->error('Failed to create index: ' . $e->getMessage());
+                $this->error('Failed to create index: '.$e->getMessage());
             }
+
             return 1;
         }
 

+ 2 - 3
api-v13/app/Console/Commands/CreateQueue.php

@@ -2,12 +2,11 @@
 
 namespace App\Console\Commands;
 
+use App\Services\RabbitMQService;
 use Illuminate\Console\Attributes\Description;
 use Illuminate\Console\Attributes\Signature;
 use Illuminate\Console\Command;
 
-use App\Services\RabbitMQService;
-
 #[Signature('app:create-queue')]
 #[Description('create queues')]
 class CreateQueue extends Command
@@ -18,7 +17,7 @@ class CreateQueue extends Command
     public function handle()
     {
         //
-        $this->info("queues create start");
+        $this->info('queues create start');
         $created = app(RabbitMQService::class)->createQueue();
         $total = count($created);
         $this->info("[{$total}] queues created");

+ 19 - 14
api-v13/app/Console/Commands/ExportAiPaliWordToken.php

@@ -2,16 +2,18 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\DictApi;
-use Illuminate\Support\Facades\Log;
 use App\Models\UserDict;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
 
 class ExportAiPaliWordToken extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan export:ai.pali.word.token
+     *
      * @var string
      */
     protected $signature = 'export:ai.pali.word.token {--format=gz  : zip file format 7z,lzma,gz }';
@@ -42,31 +44,34 @@ class ExportAiPaliWordToken extends Command
     {
         Log::debug('export ai pali word token');
 
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exportDir = storage_path('app/tmp/export/offline');
-        if (!is_dir($exportDir)) {
+        if (! is_dir($exportDir)) {
             $res = mkdir($exportDir, 0755, true);
-            if (!$res) {
-                Log::error('mkdir fail path=' . $exportDir);
+            if (! $res) {
+                Log::error('mkdir fail path='.$exportDir);
+
                 return 1;
             } else {
-                Log::info('make dir successful ' . $exportDir);
+                Log::info('make dir successful '.$exportDir);
             }
         }
 
         $dict_id = DictApi::getSysDict('system_preference');
-        if (!$dict_id) {
+        if (! $dict_id) {
             Log::error('没有找到 system_preference 字典');
+
             return 1;
         }
 
-        $filename = 'ai-pali-word-token-' . date("Y-m-d") . '.tsv';
-        $exportFile = $exportDir . '/' . $filename;
+        $filename = 'ai-pali-word-token-'.date('Y-m-d').'.tsv';
+        $exportFile = $exportDir.'/'.$filename;
         $fp = fopen($exportFile, 'w');
         if ($fp === false) {
             Log::error('无法创建文件');
+
             return 1;
         }
 
@@ -78,15 +83,15 @@ class ExportAiPaliWordToken extends Command
                 'factors',
             ])->cursor();
         foreach ($words as $key => $word) {
-            $output = array($word->word, $word->factors);
-            fwrite($fp, implode("\t", $output) . "\n");
+            $output = [$word->word, $word->factors];
+            fwrite($fp, implode("\t", $output)."\n");
             if ($key % 100 === 0) {
-                $present = (int)($key * 100 / $total);
+                $present = (int) ($key * 100 / $total);
                 $this->info("[{$present}%]-{$key}");
             }
         }
         fclose($fp);
-        Log::info((time() - $start) . ' seconds');
+        Log::info((time() - $start).' seconds');
 
         $this->call('export:zip', [
             'id' => 'ai-pali-word-token',

+ 41 - 33
api-v13/app/Console/Commands/ExportAiTrainingData.php

@@ -2,21 +2,23 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
-use App\Models\Sentence;
-use App\Models\PaliSentence;
-use App\Http\Api\MdRender;
-use Illuminate\Support\Facades\File;
 use App\Http\Api\ChannelApi;
+use App\Http\Api\MdRender;
+use App\Models\PaliSentence;
+use App\Models\Sentence;
 use App\Services\PaliTextService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\File;
+use Illuminate\Support\Facades\Log;
 
 class ExportAiTrainingData extends Command
 {
     private $ShortTrans = 0.17;
+
     /**
      * The name and signature of the console command.
      * php artisan export:ai.training.data
+     *
      * @var string
      */
     protected $signature = 'export:ai.training.data {--format=gz  : zip file format 7z,lzma,gz } {--test}';
@@ -46,33 +48,35 @@ class ExportAiTrainingData extends Command
     public function handle()
     {
         Log::info('task export offline sentence-table start');
-        //创建文件夹
+        // 创建文件夹
         $base = 'app/tmp/export/offline';
         $exportDir = storage_path($base);
-        if (!is_dir($exportDir)) {
+        if (! is_dir($exportDir)) {
             $res = mkdir($exportDir, 0755, true);
-            if (!$res) {
-                $this->error('mkdir fail path=' . $exportDir);
+            if (! $res) {
+                $this->error('mkdir fail path='.$exportDir);
+
                 return 1;
             } else {
-                $this->info('make dir successful ' . $exportDir);
+                $this->info('make dir successful '.$exportDir);
             }
         }
 
-        //创建临时文件夹\
-        $dirname = $exportDir . '/' . 'wikipali-offline-ai-training-' . date("YmdHis");
+        // 创建临时文件夹\
+        $dirname = $exportDir.'/'.'wikipali-offline-ai-training-'.date('YmdHis');
 
         $tmp = mkdir($dirname, 0755, true);
-        if (!$tmp) {
-            $this->error('mkdir fail path=' . $dirname);
+        if (! $tmp) {
+            $this->error('mkdir fail path='.$dirname);
+
             return 1;
         } else {
-            $this->info('make dir successful ' . $dirname);
+            $this->info('make dir successful '.$dirname);
         }
 
-        $fpIndex = fopen($dirname . '/index.md', 'w');
+        $fpIndex = fopen($dirname.'/index.md', 'w');
         if ($fpIndex === false) {
-            die('无法创建索引文件');
+            exit('无法创建索引文件');
         }
 
         $channels = [
@@ -97,12 +101,12 @@ class ExportAiTrainingData extends Command
                 fwrite($fpIndex, "- 语言:{$channelInfo['lang']}\n");
             }
             // 创建文件
-            $this->info('export start' . $channel);
-            $filename = $channel . '.jsonl';
-            $exportFile = $dirname . '/' . $filename;
+            $this->info('export start'.$channel);
+            $filename = $channel.'.jsonl';
+            $exportFile = $dirname.'/'.$filename;
             $fp = fopen($exportFile, 'w');
             if ($fp === false) {
-                die('无法创建文件');
+                exit('无法创建文件');
             }
 
             $db = Sentence::where('channel_uid', $channel);
@@ -115,7 +119,7 @@ class ExportAiTrainingData extends Command
                 'word_end',
                 'content',
                 'content_type',
-                'updated_at'
+                'updated_at',
             ])
                 ->whereNotNull('content')
                 ->orderBy('book_id')
@@ -127,15 +131,16 @@ class ExportAiTrainingData extends Command
                 if (isset($done[$id])) {
                     continue;
                 }
-                //获取原文
+                // 获取原文
                 $origin = PaliSentence::where('book', $sent->book_id)
                     ->where('paragraph', $sent->paragraph)
                     ->where('word_begin', $sent->word_start)
                     ->where('word_end', $sent->word_end)
                     ->value('text');
-                //忽略空的原文
+                // 忽略空的原文
                 if (self::isEmpty($origin)) {
-                    Log::warning('origin is empty id=' . $id);
+                    Log::warning('origin is empty id='.$id);
+
                     continue;
                 }
                 // 渲染译文
@@ -151,20 +156,22 @@ class ExportAiTrainingData extends Command
                 $translation = trim($translation);
                 // 忽略空的译文
                 if (self::isEmpty($translation)) {
-                    Log::warning('translation is empty id=' . $id);
+                    Log::warning('translation is empty id='.$id);
+
                     continue;
                 }
 
-                //忽略过短的译文
+                // 忽略过短的译文
                 /*
                 if (mb_strlen($translation) / mb_strlen($origin) < $this->ShortTrans) {
                     Log::warning('translation is short id=' . $id);
                     continue;
                 }
                 */
-                //原文与翻译完全相同
+                // 原文与翻译完全相同
                 if ($translation === $origin) {
-                    Log::warning('translation is same id=' . $id);
+                    Log::warning('translation is same id='.$id);
+
                     continue;
                 }
                 // 获取分类标签
@@ -177,10 +184,10 @@ class ExportAiTrainingData extends Command
                     'translation' => $translation,
                     'category' => $tags,
                     'path' => $path,
-                    'updated_at' => $sent->updated_at
+                    'updated_at' => $sent->updated_at,
                 ];
 
-                fwrite($fp, json_encode($currData, JSON_UNESCAPED_UNICODE) . "\n");
+                fwrite($fp, json_encode($currData, JSON_UNESCAPED_UNICODE)."\n");
                 $bar->advance();
                 $done[$id] = 1;
             }
@@ -188,7 +195,7 @@ class ExportAiTrainingData extends Command
         }
         fclose($fpIndex);
 
-        $this->info((time() - $start) . ' seconds');
+        $this->info((time() - $start).' seconds');
         $this->call('export:zip2', [
             'id' => 'ai-translating-training-data',
             'filename' => $dirname,
@@ -208,6 +215,7 @@ class ExportAiTrainingData extends Command
             return true;
         }
         $result = preg_replace('/[\s\d\p{P}]/u', '', $input);
+
         return empty($result);
     }
 }

+ 31 - 31
api-v13/app/Console/Commands/ExportArticle.php

@@ -2,16 +2,12 @@
 
 namespace App\Console\Commands;
 
+use App\Http\Api\MdRender;
+use App\Tools\ExportDownload;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Str;
-use Illuminate\Support\Facades\Storage;
-
-use Illuminate\Support\Facades\Cache;
-use App\Tools\ExportDownload;
-use App\Http\Api\MdRender;
-
 
 class ExportArticle extends Command
 {
@@ -19,6 +15,7 @@ class ExportArticle extends Command
      * The name and signature of the console command.
      * php artisan export:article 78c22ad3-58e2-4cf0-b979-67783ca3a375 123 --channel=7fea264d-7a26-40f8-bef7-bc95102760fb --format=html
      * php artisan export:article df6c6609-6fc1-42d0-9ef1-535ef3e702c9 1234 --origin=true --channel=7fea264d-7a26-40f8-bef7-bc95102760fb  --format=docx --anthology=697c9169-cb9d-4a60-8848-92745e467bab --token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJuYmYiOjE2OTc3Mjg2ODUsImV4cCI6MTcyOTI2NDY4NSwidWlkIjoiYmE1NDYzZjMtNzJkMS00NDEwLTg1OGUtZWFkZDEwODg0NzEzIiwiaWQiOjR9.fiXhnY2LczZ9kKVHV0FfD3AJPZt-uqM5wrDe4EhToVexdd007ebPFYssZefmchfL0mx9nF0rgHSqjNhx4P0yDA
+     *
      * @var string
      */
     protected $signature = 'export:article {id} {query_id} {--token=} {--anthology=} {--channel=}  {--origin=false} {--translation=true} {--format=tex} {--debug}';
@@ -49,7 +46,7 @@ class ExportArticle extends Command
     {
         $this->info('task export chapter start');
         Log::debug('task export chapter start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $options = [
@@ -61,25 +58,24 @@ class ExportArticle extends Command
         $upload = new ExportDownload($options);
 
         MdRender::init();
-        $m = new \Mustache_Engine(array(
+        $m = new \Mustache_Engine([
             'entity_flags' => ENT_QUOTES,
             'delimiters' => '[[ ]]',
             'escape' => function ($value) {
                 return $value;
-            }
-        ));
-
-        $sections = array();
-        $articles = array();
+            },
+        ]);
 
+        $sections = [];
+        $articles = [];
 
         $article = $this->fetch($this->argument('id'));
-        if (!$article) {
+        if (! $article) {
             return 1;
         }
 
-        $bookMeta = array();
-        $bookMeta['book_author'] = "";
+        $bookMeta = [];
+        $bookMeta['book_author'] = '';
         $bookMeta['book_title'] = $article['title_text'];
 
         $articles[] = [
@@ -88,10 +84,10 @@ class ExportArticle extends Command
             'content' => isset($article['html']) ? $article['html'] : '',
         ];
         $progress = 0.1;
-        $this->info($upload->setStatus($progress, 'export article content title=' . $article['title_text']));
+        $this->info($upload->setStatus($progress, 'export article content title='.$article['title_text']));
 
         if (isset($article['toc']) && count($article['toc']) > 0) {
-            $this->info('has sub article ' . count($article['toc']));
+            $this->info('has sub article '.count($article['toc']));
             $step = 0.8 / count($article['toc']);
             $baseLevel = 0;
             foreach ($article['toc'] as $key => $value) {
@@ -99,13 +95,14 @@ class ExportArticle extends Command
                     $baseLevel = $value['level'] - 2;
                 }
                 $progress += $step;
-                $this->info($upload->setStatus($progress, 'exporting article title=' . $value['title']));
+                $this->info($upload->setStatus($progress, 'exporting article title='.$value['title']));
                 $article = $this->fetch($value['key']);
-                if (!$article) {
-                    $this->info($upload->setStatus($progress, 'exporting article fail title=' . $value['title']));
+                if (! $article) {
+                    $this->info($upload->setStatus($progress, 'exporting article fail title='.$value['title']));
+
                     continue;
                 }
-                $this->info($upload->setStatus($progress, 'exporting article success title=' . $article['title_text']));
+                $this->info($upload->setStatus($progress, 'exporting article success title='.$article['title_text']));
                 $articles[] = [
                     'level' => $value['level'] - $baseLevel,
                     'title' => $article['title_text'],
@@ -121,25 +118,25 @@ class ExportArticle extends Command
         $this->info($upload->setStatus(0.9, 'export article content done'));
         Log::debug('导出结束');
 
-
         $upload->upload('article', $sections, $bookMeta);
         $this->info($upload->setStatus(1, 'export article done'));
+
         return 0;
     }
 
     private function fetch($articleId)
     {
         $api = config('mint.server.api.bamboo');
-        $basicUrl = $api . '/v2/article/';
-        $url =  $basicUrl . $articleId;;
-        $this->info('http request url=' . $url);
+        $basicUrl = $api.'/v2/article/';
+        $url = $basicUrl.$articleId;
+        $this->info('http request url='.$url);
 
         $urlParam = [
             'mode' => 'read',
             'format' => 'markdown',
             'anthology' => $this->option('anthology'),
             'channel' => $this->option('channel'),
-            'origin' => 'true' /*$this->option('origin')*/,
+            'origin' => 'true' /* $this->option('origin') */,
             'paragraph' => true,
         ];
 
@@ -151,15 +148,18 @@ class ExportArticle extends Command
         }
 
         if ($response->failed()) {
-            $this->error('http request error' . $response->json('message'));
+            $this->error('http request error'.$response->json('message'));
             Log::error('http request error', ['error' => $response->json('message')]);
+
             return false;
         }
-        if (!$response->json('ok')) {
-            $this->error('http request error' . $response->json('message'));
+        if (! $response->json('ok')) {
+            $this->error('http request error'.$response->json('message'));
+
             return false;
         }
         $article = $response->json('data');
+
         return $article;
     }
 }

+ 26 - 24
api-v13/app/Console/Commands/ExportChannel.php

@@ -6,9 +6,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use App\Models\Channel;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportChannel extends Command
@@ -44,40 +44,41 @@ class ExportChannel extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $this->info('task export offline channel-table start');
-        $exportFile = storage_path('app/public/export/offline/' . $this->argument('db') . '-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/'.$this->argument('db').'-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO channel ( id , name , type , language ,
+        $query = 'INSERT INTO channel ( id , name , type , language ,
                                     summary , owner_id , setting,created_at )
-                                    VALUES ( ? , ? , ? , ? , ? , ? , ? , ?  )";
+                                    VALUES ( ? , ? , ? , ? , ? , ? , ? , ?  )';
         try {
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
         $total = Channel::where('status', 30)->count();
-        $channels= Channel::where('status', 30)
-                ->select([
-                    'uid',
-                    'name',
-                    'type',
-                    'lang',
-                    'summary',
-                    'owner_uid',
-                    'setting',
-                    'created_at'
-                ])
-                ->cursor();
+        $channels = Channel::where('status', 30)
+            ->select([
+                'uid',
+                'name',
+                'type',
+                'lang',
+                'summary',
+                'owner_uid',
+                'setting',
+                'created_at',
+            ])
+            ->cursor();
 
-        foreach ($channels as $key => $row  ) {
-            $currData = array(
+        foreach ($channels as $key => $row) {
+            $currData = [
                 $row->uid,
                 $row->name,
                 $row->type,
@@ -86,16 +87,17 @@ class ExportChannel extends Command
                 $row->owner_uid,
                 $row->setting,
                 $row->created_at,
-            );
+            ];
             $stmt->execute($currData);
 
-            if($key % 30 ===0){
-                $precent = (int)($key*100/$total);
+            if ($key % 30 === 0) {
+                $precent = (int) ($key * 100 / $total);
                 $this->line("[{$precent}%]");
             }
         }
         $dbh->commit();
         $this->info('task export offline channel-table finished');
+
         return 0;
     }
 }

+ 47 - 56
api-v13/app/Console/Commands/ExportChapter.php

@@ -2,22 +2,16 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Str;
-
-use App\Models\ProgressChapter;
-use App\Models\Channel;
-use App\Models\PaliText;
-use App\Models\Sentence;
-
 use App\Http\Api\ChannelApi;
 use App\Http\Api\MdRender;
+use App\Models\PaliText;
+use App\Models\ProgressChapter;
+use App\Models\Sentence;
 use App\Tools\Export;
-use Illuminate\Support\Facades\Cache;
 use App\Tools\ExportDownload;
-
+use App\Tools\Tools;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
 
 class ExportChapter extends Command
 {
@@ -26,6 +20,7 @@ class ExportChapter extends Command
      * php artisan export:chapter 213 3 a19eaf75-c63f-4b84-8125-1bce18311e23 213-3.html --format=html --origin=true
      * php artisan export:chapter 168 915 7fea264d-7a26-40f8-bef7-bc95102760fb 168-915.html --format=html --debug
      * php artisan export:chapter 168 915 7fea264d-7a26-40f8-bef7-bc95102760fb 168-915.html --format=html --origin=true
+     *
      * @var string
      */
     protected $signature = 'export:chapter {book} {para} {channel} {query_id} {--token=} {--origin=false} {--translation=true} {--debug} {--format=markdown} ';
@@ -56,7 +51,7 @@ class ExportChapter extends Command
     {
         $this->info('task export chapter start');
         Log::debug('task export chapter start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $book = $this->argument('book');
@@ -66,55 +61,54 @@ class ExportChapter extends Command
             'queryId' => $this->argument('query_id'),
             'format' => $this->option('format'),
             'debug' => $this->option('debug'),
-            'filename' => $book . '-' . $para,
+            'filename' => $book.'-'.$para,
         ]);
 
-        $m = new \Mustache_Engine(array(
+        $m = new \Mustache_Engine([
             'entity_flags' => ENT_QUOTES,
             'delimiters' => '[[ ]]',
             'escape' => function ($value) {
                 return $value;
-            }
-        ));
-        $tplFile = resource_path("mustache/chapter/md/paragraph.md");
+            },
+        ]);
+        $tplFile = resource_path('mustache/chapter/md/paragraph.md');
         $tplParagraph = file_get_contents($tplFile);
 
         MdRender::init();
 
         $renderFormat = 'markdown';
 
-        //获取原文channel
+        // 获取原文channel
         $orgChannelId = ChannelApi::getSysChannel('_System_Pali_VRI_');
 
         $tranChannelsId = explode('_', $this->argument('channel'));
 
         $channelsId = array_merge([$orgChannelId], $tranChannelsId);
 
-        $channels = array();
-        $channelsIndex = array();
+        $channels = [];
+        $channelsIndex = [];
         foreach ($channelsId as $key => $id) {
             $channels[] = ChannelApi::getById($id);
             $channelsIndex[$id] = ChannelApi::getById($id);
         }
 
-        $bookMeta = array();
-        $bookMeta['book_author'] = "";
+        $bookMeta = [];
+        $bookMeta['book_author'] = '';
         foreach ($channels as $key => $channel) {
-            $bookMeta['book_author'] .= $channel['name'] . ' ';
+            $bookMeta['book_author'] .= $channel['name'].' ';
         }
 
         $chapter = PaliText::where('book', $book)
             ->where('paragraph', $para)->first();
-        if (!$chapter) {
-            return $this->error("no data");
+        if (! $chapter) {
+            return $this->error('no data');
         }
 
         $currProgress = 0;
         $this->info($upload->setStatus($currProgress, 'start'));
 
-
         if (empty($chapter->toc)) {
-            $bookMeta['title'] = "unknown";
+            $bookMeta['title'] = 'unknown';
         } else {
             $bookMeta['book_title'] = '';
             foreach ($channelsId as $key => $id) {
@@ -131,7 +125,7 @@ class ExportChapter extends Command
             ->orderBy('paragraph')
             ->get();
         if (count($subChapter) === 0) {
-            //没有子章节
+            // 没有子章节
             $subChapter = PaliText::where('book', $book)->where('paragraph', $para)
                 ->where('level', '<', 8)
                 ->orderBy('paragraph')
@@ -154,9 +148,9 @@ class ExportChapter extends Command
             $outputChannelsId = array_merge($outputChannelsId, $tranChannelsId);
         }
 
-        $sections = array();
+        $sections = [];
         foreach ($subChapter as $key => $sub) {
-            # 看这个章节是否存在译文
+            // 看这个章节是否存在译文
             $hasChapter = false;
             if ($this->option('origin') === 'true') {
                 $hasChapter = true;
@@ -171,11 +165,11 @@ class ExportChapter extends Command
                     }
                 }
             }
-            if (!$hasChapter) {
-                //不存在需要导出的数据
+            if (! $hasChapter) {
+                // 不存在需要导出的数据
                 continue;
             }
-            $filename = "{$sub->paragraph}." . $this->option('format');
+            $filename = "{$sub->paragraph}.".$this->option('format');
             $bookMeta['sections'][] = ['filename' => $filename];
             $paliTitle = PaliText::where('book', $book)
                 ->where('paragraph', $sub->paragraph)
@@ -185,13 +179,12 @@ class ExportChapter extends Command
                 $chapter = ProgressChapter::where('book', $book)->where('para', $sub->paragraph)
                     ->where('channel_id', $tranChannelsId[0])
                     ->first();
-                if ($chapter && !empty($chapter->title)) {
+                if ($chapter && ! empty($chapter->title)) {
                     $sectionTitle = $chapter->title;
                 }
             }
 
-
-            $content = array();
+            $content = [];
 
             $chapterStart = $sub->paragraph + 1;
             $chapterEnd = $sub->paragraph + $sub->chapter_len;
@@ -199,19 +192,17 @@ class ExportChapter extends Command
                 ->whereBetween('paragraph', [$chapterStart, $chapterEnd])
                 ->orderBy('paragraph')->get();
 
-
-
             foreach ($chapterBody as $body) {
                 $currProgress += $step;
-                $this->info($upload->setStatus($currProgress, 'export chapter ' . $body->paragraph));
-                $paraData = array();
-                $paraData['translations'] = array();
+                $this->info($upload->setStatus($currProgress, 'export chapter '.$body->paragraph));
+                $paraData = [];
+                $paraData['translations'] = [];
                 foreach ($outputChannelsId as $key => $channelId) {
                     $translationData = Sentence::where('book_id', $book)
                         ->where('paragraph', $body->paragraph)
                         ->where('channel_uid', $channelId)
                         ->orderBy('word_start')->get();
-                    $sentContent = array();
+                    $sentContent = [];
                     foreach ($translationData as $sent) {
                         $texText = MdRender::render(
                             $sent->content,
@@ -247,9 +238,9 @@ class ExportChapter extends Command
                         $subSessionTitle = $paraData['translations'][0]['content'];
                     }
 
-                    //标题
+                    // 标题
                     $subStr = array_fill(0, $currLevel, '#');
-                    $content[] = implode('', $subStr) . " " . $subSessionTitle;
+                    $content[] = implode('', $subStr).' '.$subSessionTitle;
                 }
                 $content[] = "\n\n";
             }
@@ -258,14 +249,14 @@ class ExportChapter extends Command
                 'name' => $filename,
                 'body' => [
                     'title' => $sectionTitle,
-                    'content' => implode('', $content)
-                ]
+                    'content' => implode('', $content),
+                ],
             ];
         }
 
-        //导出术语表
-        $keyPali = array();
-        $keyMeaning = array();
+        // 导出术语表
+        $keyPali = [];
+        $keyMeaning = [];
         if (isset($GLOBALS['glossary'])) {
             $glossary = $GLOBALS['glossary'];
             foreach ($glossary as $word => $meaning) {
@@ -288,21 +279,21 @@ class ExportChapter extends Command
 
         Log::debug('glossary', ['data' => $glossaryData]);
 
-        $tplFile = resource_path("mustache/chapter/" . $this->option('format') . "/glossary." . $this->option('format'));
+        $tplFile = resource_path('mustache/chapter/'.$this->option('format').'/glossary.'.$this->option('format'));
         $tplGlossary = file_get_contents($tplFile);
 
         $glossaryContent = $m->render($tplGlossary, $glossaryData);
 
         $sections[] = [
-            'name' => 'glossary.' . $this->option('format'),
+            'name' => 'glossary.'.$this->option('format'),
             'body' => [
                 'title' => 'glossary',
-                'content' => $glossaryContent
-            ]
+                'content' => $glossaryContent,
+            ],
         ];
-        $this->info($upload->setStatus($currProgress, 'export glossary ' . count($keyPali)));
+        $this->info($upload->setStatus($currProgress, 'export glossary '.count($keyPali)));
 
-        $this->info($upload->setStatus(0.9, 'export content done sections=' . count($sections)));
+        $this->info($upload->setStatus(0.9, 'export content done sections='.count($sections)));
 
         Log::debug('导出结束', ['sections' => count($sections)]);
 

+ 14 - 12
api-v13/app/Console/Commands/ExportChapterIndex.php

@@ -2,10 +2,10 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use App\Models\ProgressChapter;
 use App\Models\Channel;
+use App\Models\ProgressChapter;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Log;
 
@@ -43,28 +43,29 @@ class ExportChapterIndex extends Command
     public function handle()
     {
         Log::debug('task export offline chapter-index-table start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
 
-        $exportFile = storage_path('app/public/export/offline/' . $this->argument('db') . '-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/'.$this->argument('db').'-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO chapter ( id , book , paragraph,
+        $query = 'INSERT INTO chapter ( id , book , paragraph,
                                     language , title , channel_id , progress,updated_at  )
-                                    VALUES ( ? , ? , ? , ? , ? , ? , ? , ?  )";
+                                    VALUES ( ? , ? , ? , ? , ? , ? , ? , ?  )';
         try {
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
         $publicChannels = Channel::where('status', 30)->select('uid')->get();
         $rows = ProgressChapter::whereIn('channel_id', $publicChannels)->count();
-        Cache::put("/export/chapter/count", $rows, 3600 * 10);
+        Cache::put('/export/chapter/count', $rows, 3600 * 10);
         $bar = $this->output->createProgressBar($rows);
         foreach (
             ProgressChapter::whereIn('channel_id', $publicChannels)
@@ -76,10 +77,10 @@ class ExportChapterIndex extends Command
                     'title',
                     'channel_id',
                     'progress',
-                    'updated_at'
+                    'updated_at',
                 ])->cursor() as $row
         ) {
-            $currData = array(
+            $currData = [
                 $row->uid,
                 $row->book,
                 $row->para,
@@ -88,13 +89,14 @@ class ExportChapterIndex extends Command
                 $row->channel_id,
                 $row->progress,
                 $row->updated_at,
-            );
+            ];
             $stmt->execute($currData);
             $bar->advance();
         }
         $dbh->commit();
         $bar->finish();
         Log::debug('task export offline chapter-index-table finished');
+
         return 0;
     }
 }

+ 12 - 11
api-v13/app/Console/Commands/ExportCreateDb.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Facades\Log;
 
 class ExportCreateDb extends Command
@@ -40,29 +40,30 @@ class ExportCreateDb extends Command
     public function handle()
     {
         Log::debug('task export offline create-db start');
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $this->create('sentence.sql','wikipali-offline');
-        $this->create('sentence.sql','wikipali-offline-index');
+        $this->create('sentence.sql', 'wikipali-offline');
+        $this->create('sentence.sql', 'wikipali-offline-index');
 
         return 0;
     }
 
-    private function create($sqlFile,$dbFile){
+    private function create($sqlFile, $dbFile)
+    {
         $sqlPath = database_path('export/'.$sqlFile);
         $exportDir = storage_path('app/public/export/offline');
-        $exportFile = $exportDir.'/'.$dbFile.'-'.date("Y-m-d").'.db3';
-        $file = fopen($exportFile,'w');
+        $exportFile = $exportDir.'/'.$dbFile.'-'.date('Y-m-d').'.db3';
+        $file = fopen($exportFile, 'w');
         fclose($file);
-        $dbh = new \PDO('sqlite:'.$exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
-        //建立数据库
+        // 建立数据库
         $_sql = file_get_contents($sqlPath);
         $_arr = explode(';', $_sql);
-        //执行sql语句
+        // 执行sql语句
         foreach ($_arr as $_value) {
-            $dbh->query($_value . ';');
+            $dbh->query($_value.';');
         }
         Log::debug('task export offline create-db finished');
     }

+ 27 - 23
api-v13/app/Console/Commands/ExportDiscussion.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\DB;
 use App\Http\Api\ChannelApi;
 use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Support\Collection;
+use Illuminate\Support\Facades\DB;
 
 class ExportDiscussion extends Command
 {
@@ -40,8 +41,9 @@ class ExportDiscussion extends Command
 
         // 1. 获取巴利原文 channel_uid
         $this->orgChannelId = ChannelApi::getSysChannel('_System_Pali_VRI_');
-        if (!$this->orgChannelId) {
+        if (! $this->orgChannelId) {
             $this->error('Failed to retrieve Pali source channel ID.');
+
             return self::FAILURE;
         }
         $this->info("Pali channel ID: {$this->orgChannelId}");
@@ -54,24 +56,26 @@ class ExportDiscussion extends Command
 
         if ($total === 0) {
             $this->warn("No discussions found for editor: {$editorUid}");
+
             return self::SUCCESS;
         }
 
         $this->info("Found {$total} discussion(s). Processing...");
 
         // 3. 打开文件句柄(流式写入,不在内存中拼接整个 Markdown)
-        $filename = "discussion_export_{$editorUid}_" . now()->format('YmdHis') . '.md';
+        $filename = "discussion_export_{$editorUid}_".now()->format('YmdHis').'.md';
         $this->outputPath = storage_path("app/tmp/{$filename}");
         $this->fileHandle = fopen($this->outputPath, 'w');
-        if (!$this->fileHandle) {
+        if (! $this->fileHandle) {
             $this->error("Cannot open file for writing: {$this->outputPath}");
+
             return self::FAILURE;
         }
 
         // 写文件头
         $this->writeLine("# 讨论导出报告\n");
         $this->writeLine("- **Editor UID**: {$editorUid}");
-        $this->writeLine("- **导出时间**: " . now()->toDateTimeString());
+        $this->writeLine('- **导出时间**: '.now()->toDateTimeString());
         $this->writeLine("\n---\n");
 
         // 4. 分批处理(每批 50 条),避免内存溢出
@@ -104,7 +108,7 @@ class ExportDiscussion extends Command
     /**
      * 处理一批 discussions。
      */
-    private function processChunk(\Illuminate\Support\Collection $discussions): void
+    private function processChunk(Collection $discussions): void
     {
         // --- 批量查译文 sentences ---
         $resIds = $discussions->pluck('res_id')->unique()->values()->all();
@@ -145,21 +149,21 @@ class ExportDiscussion extends Command
 
         // --- 写 Markdown ---
         foreach ($discussions as $discussion) {
-            $sentUid     = $discussion->res_id;
+            $sentUid = $discussion->res_id;
             $translation = $translationMap->get($sentUid);
-            if (!$translation) {
+            if (! $translation) {
                 continue;
             }
 
-            $coordKey    = "{$translation->book_id}_{$translation->paragraph}_{$translation->word_start}_{$translation->word_end}";
-            $pali        = $paliMap[$coordKey] ?? null;
+            $coordKey = "{$translation->book_id}_{$translation->paragraph}_{$translation->word_start}_{$translation->word_end}";
+            $pali = $paliMap[$coordKey] ?? null;
             $paliContent = $pali ? trim($pali->content ?? '(无原文)') : '(未找到巴利原文)';
 
             $discussionCreatedAt = $discussion->created_at
                 ? Carbon::parse($discussion->created_at)
                 : null;
 
-            $histories      = $historiesMap[$sentUid] ?? [];
+            $histories = $historiesMap[$sentUid] ?? [];
             $matchedHistory = $this->findClosestHistory($histories, $discussionCreatedAt);
             $translationAtTime = $matchedHistory
                 ? trim($matchedHistory->content)
@@ -167,7 +171,7 @@ class ExportDiscussion extends Command
 
             $this->writeLine("# {$paliContent}\n");
             $this->writeLine("  - **历史译文**: {$translationAtTime}");
-            $this->writeLine("  - **评论**: " . trim($discussion->title ?? '') . trim($discussion->content ?? ''));
+            $this->writeLine('  - **评论**: '.trim($discussion->title ?? '').trim($discussion->content ?? ''));
             $this->writeLine("  - **当前译文**: {$translation->content}");
             $this->writeLine('');
         }
@@ -179,7 +183,7 @@ class ExportDiscussion extends Command
     /**
      * 批量查询巴利原文,每组最多 30 个坐标,避免超大 SQL。
      *
-     * @param array<string, object> $coordKeys  key="{book_id}_{paragraph}_{word_start}_{word_end}"
+     * @param  array<string, object>  $coordKeys  key="{book_id}_{paragraph}_{word_start}_{word_end}"
      * @return array<string, object>
      */
     private function fetchPaliSentences(array $coordKeys): array
@@ -192,10 +196,10 @@ class ExportDiscussion extends Command
                 ->where(function ($q) use ($group) {
                     foreach ($group as $t) {
                         $q->orWhere(function ($sub) use ($t) {
-                            $sub->where('book_id',    $t->book_id)
-                                ->where('paragraph',  $t->paragraph)
+                            $sub->where('book_id', $t->book_id)
+                                ->where('paragraph', $t->paragraph)
                                 ->where('word_start', $t->word_start)
-                                ->where('word_end',   $t->word_end);
+                                ->where('word_end', $t->word_end);
                         });
                     }
                 })
@@ -218,15 +222,15 @@ class ExportDiscussion extends Command
      */
     private function writeLine(string $line): void
     {
-        fwrite($this->fileHandle, $line . "\n");
+        fwrite($this->fileHandle, $line."\n");
     }
 
     /**
      * 在历史记录中找评论发布时间之前最近的那条。
      * 若全部在评论之后,则退而取最早一条。
      *
-     * @param array       $histories           sent_histories(已按 create_time ASC 排序)
-     * @param Carbon|null $discussionCreatedAt 评论发布时间
+     * @param  array  $histories  sent_histories(已按 create_time ASC 排序)
+     * @param  Carbon|null  $discussionCreatedAt  评论发布时间
      */
     private function findClosestHistory(array $histories, ?Carbon $discussionCreatedAt): ?object
     {
@@ -234,12 +238,12 @@ class ExportDiscussion extends Command
             return null;
         }
 
-        if (!$discussionCreatedAt) {
+        if (! $discussionCreatedAt) {
             return end($histories) ?: null;
         }
 
         $discussionTimestamp = $discussionCreatedAt->timestamp;
-        $best     = null;
+        $best = null;
         $bestDiff = PHP_INT_MAX;
 
         foreach ($histories as $h) {
@@ -248,7 +252,7 @@ class ExportDiscussion extends Command
                 $diff = $discussionTimestamp - $historyTime;
                 if ($diff < $bestDiff) {
                     $bestDiff = $diff;
-                    $best     = $h;
+                    $best = $h;
                 }
             }
         }

+ 23 - 23
api-v13/app/Console/Commands/ExportFtsPali.php

@@ -2,11 +2,11 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\DictApi;
 use App\Models\UserDict;
-use Illuminate\Support\Facades\Redis;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Redis;
 
 class ExportFtsPali extends Command
 {
@@ -41,16 +41,17 @@ class ExportFtsPali extends Command
      */
     public function handle()
     {
-        //irregular
+        // irregular
         $dictId = ['4d3a0d92-0adc-4052-80f5-512a2603d0e8'];
-        //regular
+        // regular
         $dictId[] = DictApi::getSysDict('system_regular');
-        $long = ["ā", "ī", "ū"];
+        $long = ['ā', 'ī', 'ū'];
         $path = storage_path('app/export/fts');
-        if (!is_dir($path)) {
+        if (! is_dir($path)) {
             $res = mkdir($path, 0700, true);
-            if (!$res) {
-                Log::error('mkdir fail path=' . $path);
+            if (! $res) {
+                Log::error('mkdir fail path='.$path);
+
                 return 1;
             }
         }
@@ -58,13 +59,13 @@ class ExportFtsPali extends Command
         $pageSize = 10000;
         $currPage = 1;
         $filename = "/pali-{$currPage}.syn";
-        $fp = fopen($path . $filename, 'w') or die("Unable to open file!");
+        $fp = fopen($path.$filename, 'w') or exit('Unable to open file!');
         $count = 0;
         foreach ($dictId as $key => $value) {
             $words = UserDict::where('dict_id', $value)
                 ->select('word')
                 ->groupBy('word')->cursor();
-            $this->info('word count=' . count($words));
+            $this->info('word count='.count($words));
             foreach ($words as $key => $word) {
                 $count++;
                 if ($count % 1000 === 0) {
@@ -72,38 +73,37 @@ class ExportFtsPali extends Command
                 }
                 if ($count % 10000 === 0) {
                     fclose($fp);
-                    $redisKey = 'export/fts/pali' . $filename;
-                    $content = file_get_contents($path . $filename);
+                    $redisKey = 'export/fts/pali'.$filename;
+                    $content = file_get_contents($path.$filename);
                     Redis::set($redisKey, $content);
                     Redis::expire($redisKey, 3600 * 24 * 10);
                     $currPage++;
                     $filename = "/pali-{$currPage}.syn";
-                    $this->info('new file filename=' . $filename);
-                    $fp = fopen($path . $filename, 'w') or die("Unable to open file!");
+                    $this->info('new file filename='.$filename);
+                    $fp = fopen($path.$filename, 'w') or exit('Unable to open file!');
                 }
                 $parent = UserDict::where('dict_id', $value)
                     ->where('word', $word->word)
                     ->selectRaw('parent,char_length("parent")')
                     ->groupBy('parent')->orderBy('char_length', 'asc')->first();
 
-                if ($parent && !empty($parent->parent)) {
-                    $end = mb_substr($parent->parent, -1, null, "UTF-8");
-                    if (in_array($end, ["ā", "ī", "ū"])) {
-                        $head = mb_substr($parent->parent, 0, mb_strlen($parent->parent) - 1, "UTF-8");
-                        $newEnd = str_replace(["ā", "ī", "ū"], ["a", "i", "u"], $end);
-                        $parentWord = $head . $newEnd;
+                if ($parent && ! empty($parent->parent)) {
+                    $end = mb_substr($parent->parent, -1, null, 'UTF-8');
+                    if (in_array($end, ['ā', 'ī', 'ū'])) {
+                        $head = mb_substr($parent->parent, 0, mb_strlen($parent->parent) - 1, 'UTF-8');
+                        $newEnd = str_replace(['ā', 'ī', 'ū'], ['a', 'i', 'u'], $end);
+                        $parentWord = $head.$newEnd;
                     } else {
                         $parentWord = $parent->parent;
                     }
-                    fwrite($fp, $word->word . ' ' . $parentWord . PHP_EOL);
+                    fwrite($fp, $word->word.' '.$parentWord.PHP_EOL);
                 } else {
-                    $this->error('word no parent word=' . $word->word);
+                    $this->error('word no parent word='.$word->word);
                 }
             }
         }
         fclose($fp);
 
-
         return 0;
     }
 }

+ 25 - 22
api-v13/app/Console/Commands/ExportGlossary.php

@@ -2,17 +2,17 @@
 
 namespace App\Console\Commands;
 
+use App\Services\TermService;
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\File;
-use App\Services\TermService;
-
+use Illuminate\Support\Facades\Log;
 
 class ExportGlossary extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan export:export-glossary zh-Hans
+     *
      * @var string
      */
     protected $signature = 'export:export-glossary {lang}';
@@ -31,6 +31,7 @@ class ExportGlossary extends Command
         $this->termService = $termService;
         parent::__construct();
     }
+
     /**
      * Execute the console command.
      */
@@ -38,55 +39,57 @@ class ExportGlossary extends Command
     {
         Log::info('task export offline sentence-table start');
         $lang = $this->argument('lang');
-        //创建文件夹
+        // 创建文件夹
         $base = 'app/tmp/export/offline';
         $exportDir = storage_path($base);
-        if (!is_dir($exportDir)) {
+        if (! is_dir($exportDir)) {
             $res = mkdir($exportDir, 0755, true);
-            if (!$res) {
-                $this->error('mkdir fail path=' . $exportDir);
+            if (! $res) {
+                $this->error('mkdir fail path='.$exportDir);
+
                 return 1;
             } else {
-                $this->info('make dir successful ' . $exportDir);
+                $this->info('make dir successful '.$exportDir);
             }
         }
 
-        //创建临时文件夹\
-        $dirname = $exportDir . '/' . 'wikipali_glossary_' . date("YmdHis");
+        // 创建临时文件夹\
+        $dirname = $exportDir.'/'.'wikipali_glossary_'.date('YmdHis');
 
         $tmp = mkdir($dirname, 0755, true);
-        if (!$tmp) {
-            $this->error('mkdir fail path=' . $dirname);
+        if (! $tmp) {
+            $this->error('mkdir fail path='.$dirname);
+
             return 1;
         } else {
-            $this->info('make dir successful ' . $dirname);
+            $this->info('make dir successful '.$dirname);
         }
 
-        $fpIndex = fopen($dirname . '/index.md', 'w');
+        $fpIndex = fopen($dirname.'/index.md', 'w');
         if ($fpIndex === false) {
-            die('无法创建索引文件');
+            exit('无法创建索引文件');
         }
 
         // 创建json文件
-        $this->info('export start' . $lang);
-        $filename = 'glossary_' . $lang . '.jsonl';
-        $exportFile = $dirname . '/' . $filename;
+        $this->info('export start'.$lang);
+        $filename = 'glossary_'.$lang.'.jsonl';
+        $exportFile = $dirname.'/'.$filename;
         $fp = fopen($exportFile, 'w');
         if ($fp === false) {
-            die('无法创建文件');
+            exit('无法创建文件');
         }
         $start = time();
 
-        //**业务逻辑 */
+        // **业务逻辑 */
 
         $data = $this->termService->getCommunityGlossary($lang);
         foreach ($data['items'] as $key => $value) {
-            fwrite($fp, json_encode($value, JSON_UNESCAPED_UNICODE) . "\n");
+            fwrite($fp, json_encode($value, JSON_UNESCAPED_UNICODE)."\n");
         }
 
         fclose($fpIndex);
 
-        $this->info((time() - $start) . ' seconds');
+        $this->info((time() - $start).' seconds');
         $this->call('export:zip2', [
             'id' => 'wikipali_glossary',
             'filename' => $dirname,

+ 11 - 9
api-v13/app/Console/Commands/ExportIKPaliTeam.php

@@ -2,9 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\DhammaTerm;
-use Illuminate\Support\Facades\Redis;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportIKPaliTeam extends Command
@@ -12,6 +11,7 @@ class ExportIKPaliTeam extends Command
     /**
      * The name and signature of the console command.
      * php artisan export:ik.pali.team
+     *
      * @var string
      */
     protected $signature = 'export:ik.pali.team';
@@ -41,28 +41,30 @@ class ExportIKPaliTeam extends Command
     public function handle()
     {
         $path = storage_path('app/export/fts');
-        if (!is_dir($path)) {
+        if (! is_dir($path)) {
             $res = mkdir($path, 0700, true);
-            if (!$res) {
-                Log::error('mkdir fail path=' . $path);
+            if (! $res) {
+                Log::error('mkdir fail path='.$path);
+
                 return 1;
             }
         }
-        $filename = "/pali_term.txt";
-        $fp = fopen($path . $filename, 'w') or die("Unable to open file!");
+        $filename = '/pali_term.txt';
+        $fp = fopen($path.$filename, 'w') or exit('Unable to open file!');
         $wordsList = [];
         $teams = DhammaTerm::select(['meaning', 'other_meaning'])->get();
         foreach ($teams as $term) {
-            if (!empty($term->meaning)) {
+            if (! empty($term->meaning)) {
                 $wordsList[$term->meaning] = 1;
             }
         }
         foreach ($wordsList as $word => $value) {
-            fwrite($fp, $word . PHP_EOL);
+            fwrite($fp, $word.PHP_EOL);
         }
         // 关闭文件
         fclose($fp);
         $this->info('done');
+
         return 0;
     }
 }

+ 116 - 104
api-v13/app/Console/Commands/ExportNissaya.php

@@ -2,80 +2,84 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
+use App\Http\Api\DictApi;
 use App\Models\Channel;
-use App\Models\Sentence;
 use App\Models\NissayaEnding;
+use App\Models\Sentence;
 use App\Models\UserDict;
-use App\Http\Api\DictApi;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
 
 class SuttaType
 {
-    public static function types(){
-        return     [
-            'mula'=>[
-                69,70,71,72,73,74,
-                75,76,77,78,79,80,
-                81,82,83,84,85,86,
-                87,88,89,90,91,92,
-                93,94,95,143,144,145,
-                146,147,148,149,150,151,
-                152,153,154,155,156,157,
-                158,159,160,161,162,163,
-                164,165,166,167,168,169,
-                170,171,213,214,215,216,217,
+    public static function types()
+    {
+        return [
+            'mula' => [
+                69, 70, 71, 72, 73, 74,
+                75, 76, 77, 78, 79, 80,
+                81, 82, 83, 84, 85, 86,
+                87, 88, 89, 90, 91, 92,
+                93, 94, 95, 143, 144, 145,
+                146, 147, 148, 149, 150, 151,
+                152, 153, 154, 155, 156, 157,
+                158, 159, 160, 161, 162, 163,
+                164, 165, 166, 167, 168, 169,
+                170, 171, 213, 214, 215, 216, 217,
             ],
             'atthakatha' => [
-                64,65,96,97,98,99,
-                100,101,102,103,104,105,
-                106,107,108,109,110,111,
-                112,113,114,115,116,117,
-                118,119,120,121,122,123,
-                124,125,126,127,128,129,
-                130,131,132,133,134,135,
-                136,137,138,139,140,141,142,
+                64, 65, 96, 97, 98, 99,
+                100, 101, 102, 103, 104, 105,
+                106, 107, 108, 109, 110, 111,
+                112, 113, 114, 115, 116, 117,
+                118, 119, 120, 121, 122, 123,
+                124, 125, 126, 127, 128, 129,
+                130, 131, 132, 133, 134, 135,
+                136, 137, 138, 139, 140, 141, 142,
             ],
             'tika' => [
-                66,67,68,172,173,174,
-                175,176,177,178,179,180,
-                181,182,183,184,185,186,
-                187,188,189,190,191,192,
-                193,194,195,196,197,198,
-                199,200,201,202,203,204,
-                205,206,207,208,209,210,211,212,
+                66, 67, 68, 172, 173, 174,
+                175, 176, 177, 178, 179, 180,
+                181, 182, 183, 184, 185, 186,
+                187, 188, 189, 190, 191, 192,
+                193, 194, 195, 196, 197, 198,
+                199, 200, 201, 202, 203, 204,
+                205, 206, 207, 208, 209, 210, 211, 212,
             ],
-            'vinaya' => [138,139,140,141,142,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,],
+            'vinaya' => [138, 139, 140, 141, 142, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217],
             'sutta' => [
-                82,83,84,85,86,
-                87,88,89,90,91,92,93,
-                94,95,99,100,101,102,
-                103,104,105,106,107,108,
-                109,110,111,112,113,114,
-                115,116,117,118,119,120,
-                121,122,123,124,125,126,
-                127,128,129,130,131,132,
-                133,134,135,136,137,143,
-                144,145,146,147,148,149,
-                150,151,152,153,154,155,
-                156,157,158,159,160,161,
-                162,163,164,165,166,167,
-                168,169,170,171,181,182,
-                183,184,185,186,187,188,
-                189,190,191,192,193,194,
-                195,196,197,198,199,
+                82, 83, 84, 85, 86,
+                87, 88, 89, 90, 91, 92, 93,
+                94, 95, 99, 100, 101, 102,
+                103, 104, 105, 106, 107, 108,
+                109, 110, 111, 112, 113, 114,
+                115, 116, 117, 118, 119, 120,
+                121, 122, 123, 124, 125, 126,
+                127, 128, 129, 130, 131, 132,
+                133, 134, 135, 136, 137, 143,
+                144, 145, 146, 147, 148, 149,
+                150, 151, 152, 153, 154, 155,
+                156, 157, 158, 159, 160, 161,
+                162, 163, 164, 165, 166, 167,
+                168, 169, 170, 171, 181, 182,
+                183, 184, 185, 186, 187, 188,
+                189, 190, 191, 192, 193, 194,
+                195, 196, 197, 198, 199,
             ],
-            'abhidhamma' => [69,70,71,72,73,74,75,76,77,78,79,80,81,96,97,98,172,173,174,175,176,177,178,179,180,],
+            'abhidhamma' => [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 96, 97, 98, 172, 173, 174, 175, 176, 177, 178, 179, 180],
         ];
     }
 
-    public static function getTypeByBook($bookId){
+    public static function getTypeByBook($bookId)
+    {
         $types = [];
         foreach (SuttaType::types() as $type => $books) {
-            if(in_array($bookId,$books)){
+            if (in_array($bookId, $books)) {
                 $types[] = $type;
             }
         }
+
         return $types;
     }
 }
@@ -85,11 +89,14 @@ class ExportNissaya extends Command
     /**
      * The name and signature of the console command.
      * php artisan export:nissaya
+     *
      * @var string
      */
     protected $signature = 'export:nissaya';
-    protected $my = ["ႁႏၵ","ခ္","ဃ္","ဆ္","ဈ္","ည္","ဌ္","ဎ္","ထ္","ဓ္","ဖ္","ဘ္","က္","ဂ္","စ္","ဇ္","ဉ္","ဠ္","ဋ္","ဍ္","ဏ္","တ္","ဒ္","န္","ဟ္","ပ္","ဗ္","မ္","ယ္","ရ္","လ္","ဝ္","သ္","င္","င်္","ဿ","ခ","ဃ","ဆ","ဈ","စျ","ည","ဌ","ဎ","ထ","ဓ","ဖ","ဘ","က","ဂ","စ","ဇ","ဉ","ဠ","ဋ","ဍ","ဏ","တ","ဒ","န","ဟ","ပ","ဗ","မ","ယ","ရ","႐","လ","ဝ","သ","aျ္","aွ္","aြ္","aြ","ၱ","ၳ","ၵ","ၶ","ၬ","ၭ","ၠ","ၡ","ၢ","ၣ","ၸ","ၹ","ၺ","႓","ၥ","ၧ","ၨ","ၩ","်","ျ","ႅ","ၼ","ွ","ႇ","ႆ","ၷ","ၲ","႒","႗","ၯ","ၮ","႑","kaၤ","gaၤ","khaၤ","ghaၤ","aှ","aိံ","aုံ","aော","aေါ","aအံ","aဣံ","aဥံ","aံ","aာ","aါ","aိ","aီ","aု","aဳ","aူ","aေ","အါ","အာ","အ","ဣ","ဤ","ဥ","ဦ","ဧ","ဩ","ႏ","ၪ","a္","္","aံ","ေss","ေkh","ေgh","ေch","ေjh","ေññ","ေṭh","ေḍh","ေth","ေdh","ေph","ေbh","ေk","ေg","ေc","ေj","ေñ","ေḷ","ေṭ","ေḍ","ေṇ","ေt","ေd","ေn","ေh","ေp","ေb","ေm","ေy","ေr","ေl","ေv","ေs","ေy","ေv","ေr","ea","eā","၁","၂","၃","၄","၅","၆","၇","၈","၉","၀","း","့","။","၊"];
-    protected $en = ["ndra","kh","gh","ch","jh","ññ","ṭh","ḍh","th","dh","ph","bh","k","g","c","j","ñ","ḷ","ṭ","ḍ","ṇ","t","d","n","h","p","b","m","y","r","l","v","s","ṅ","ṅ","ssa","kha","gha","cha","jha","jha","ñña","ṭha","ḍha","tha","dha","pha","bha","ka","ga","ca","ja","ña","ḷa","ṭa","ḍa","ṇa","ta","da","na","ha","pa","ba","ma","ya","ra","ra","la","va","sa","ya","va","ra","ra","္ta","္tha","္da","္dha","္ṭa","္ṭha","္ka","္kha","္ga","္gha","္pa","္pha","္ba","္bha","္ca","္cha","္ja","္jha","္a","္ya","္la","္ma","္va","္ha","ssa","na","ta","ṭṭha","ṭṭa","ḍḍha","ḍḍa","ṇḍa","ṅka","ṅga","ṅkha","ṅgha","ha","iṃ","uṃ","o","o","aṃ","iṃ","uṃ","aṃ","ā","ā","i","ī","u","u","ū","e","ā","ā","a","i","ī","u","ū","e","o","n","ñ","","","aṃ","sse","khe","ghe","che","jhe","ññe","ṭhe","ḍhe","the","dhe","phe","bhe","ke","ge","ce","je","ñe","ḷe","ṭe","ḍe","ṇe","te","de","ne","he","pe","be","me","ye","re","le","ve","se","ye","ve","re","e","o","1","2","3","4","5","6","7","8","9","0","”","’",".",","];
+
+    protected $my = ['ႁႏၵ', 'ခ္', 'ဃ္', 'ဆ္', 'ဈ္', 'ည္', 'ဌ္', 'ဎ္', 'ထ္', 'ဓ္', 'ဖ္', 'ဘ္', 'က္', 'ဂ္', 'စ္', 'ဇ္', 'ဉ္', 'ဠ္', 'ဋ္', 'ဍ္', 'ဏ္', 'တ္', 'ဒ္', 'န္', 'ဟ္', 'ပ္', 'ဗ္', 'မ္', 'ယ္', 'ရ္', 'လ္', 'ဝ္', 'သ္', 'င္', 'င်္', 'ဿ', 'ခ', 'ဃ', 'ဆ', 'ဈ', 'စျ', 'ည', 'ဌ', 'ဎ', 'ထ', 'ဓ', 'ဖ', 'ဘ', 'က', 'ဂ', 'စ', 'ဇ', 'ဉ', 'ဠ', 'ဋ', 'ဍ', 'ဏ', 'တ', 'ဒ', 'န', 'ဟ', 'ပ', 'ဗ', 'မ', 'ယ', 'ရ', '႐', 'လ', 'ဝ', 'သ', 'aျ္', 'aွ္', 'aြ္', 'aြ', 'ၱ', 'ၳ', 'ၵ', 'ၶ', 'ၬ', 'ၭ', 'ၠ', 'ၡ', 'ၢ', 'ၣ', 'ၸ', 'ၹ', 'ၺ', '႓', 'ၥ', 'ၧ', 'ၨ', 'ၩ', '်', 'ျ', 'ႅ', 'ၼ', 'ွ', 'ႇ', 'ႆ', 'ၷ', 'ၲ', '႒', '႗', 'ၯ', 'ၮ', '႑', 'kaၤ', 'gaၤ', 'khaၤ', 'ghaၤ', 'aှ', 'aိံ', 'aုံ', 'aော', 'aေါ', 'aအံ', 'aဣံ', 'aဥံ', 'aံ', 'aာ', 'aါ', 'aိ', 'aီ', 'aု', 'aဳ', 'aူ', 'aေ', 'အါ', 'အာ', 'အ', 'ဣ', 'ဤ', 'ဥ', 'ဦ', 'ဧ', 'ဩ', 'ႏ', 'ၪ', 'a္', '္', 'aံ', 'ေss', 'ေkh', 'ေgh', 'ေch', 'ေjh', 'ေññ', 'ေṭh', 'ေḍh', 'ေth', 'ေdh', 'ေph', 'ေbh', 'ေk', 'ေg', 'ေc', 'ေj', 'ေñ', 'ေḷ', 'ေṭ', 'ေḍ', 'ေṇ', 'ေt', 'ေd', 'ေn', 'ေh', 'ေp', 'ေb', 'ေm', 'ေy', 'ေr', 'ေl', 'ေv', 'ေs', 'ေy', 'ေv', 'ေr', 'ea', 'eā', '၁', '၂', '၃', '၄', '၅', '၆', '၇', '၈', '၉', '၀', 'း', '့', '။', '၊'];
+
+    protected $en = ['ndra', 'kh', 'gh', 'ch', 'jh', 'ññ', 'ṭh', 'ḍh', 'th', 'dh', 'ph', 'bh', 'k', 'g', 'c', 'j', 'ñ', 'ḷ', 'ṭ', 'ḍ', 'ṇ', 't', 'd', 'n', 'h', 'p', 'b', 'm', 'y', 'r', 'l', 'v', 's', 'ṅ', 'ṅ', 'ssa', 'kha', 'gha', 'cha', 'jha', 'jha', 'ñña', 'ṭha', 'ḍha', 'tha', 'dha', 'pha', 'bha', 'ka', 'ga', 'ca', 'ja', 'ña', 'ḷa', 'ṭa', 'ḍa', 'ṇa', 'ta', 'da', 'na', 'ha', 'pa', 'ba', 'ma', 'ya', 'ra', 'ra', 'la', 'va', 'sa', 'ya', 'va', 'ra', 'ra', '္ta', '္tha', '္da', '္dha', '္ṭa', '္ṭha', '္ka', '္kha', '္ga', '္gha', '္pa', '္pha', '္ba', '္bha', '္ca', '္cha', '္ja', '္jha', '္a', '္ya', '္la', '္ma', '္va', '္ha', 'ssa', 'na', 'ta', 'ṭṭha', 'ṭṭa', 'ḍḍha', 'ḍḍa', 'ṇḍa', 'ṅka', 'ṅga', 'ṅkha', 'ṅgha', 'ha', 'iṃ', 'uṃ', 'o', 'o', 'aṃ', 'iṃ', 'uṃ', 'aṃ', 'ā', 'ā', 'i', 'ī', 'u', 'u', 'ū', 'e', 'ā', 'ā', 'a', 'i', 'ī', 'u', 'ū', 'e', 'o', 'n', 'ñ', '', '', 'aṃ', 'sse', 'khe', 'ghe', 'che', 'jhe', 'ññe', 'ṭhe', 'ḍhe', 'the', 'dhe', 'phe', 'bhe', 'ke', 'ge', 'ce', 'je', 'ñe', 'ḷe', 'ṭe', 'ḍe', 'ṇe', 'te', 'de', 'ne', 'he', 'pe', 'be', 'me', 'ye', 're', 'le', 've', 'se', 'ye', 've', 're', 'e', 'o', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '”', '’', '.', ','];
 
     /**
      * The console command description.
@@ -115,79 +122,80 @@ class ExportNissaya extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $nissaya_channels = Channel::where('type','nissaya')
-                            ->where('lang','my')
-                            ->select('uid')->get();
+        $nissaya_channels = Channel::where('type', 'nissaya')
+            ->where('lang', 'my')
+            ->select('uid')->get();
         $this->info('channel:'.count($nissaya_channels));
-        //system regular
+        // system regular
         $dict_id = DictApi::getSysDict('system_regular');
-        if(!$dict_id){
+        if (! $dict_id) {
             $this->error('没有找到 system_regular 字典');
+
             return 1;
-        }else{
+        } else {
             $this->info("system_regular :{$dict_id}");
         }
 
-        //获取缅文语尾表
+        // 获取缅文语尾表
         $nissayaEndings = NissayaEnding::select('ending')->groupBy('ending')->get();
         $endings = [];
         $maxLen = 0;
         foreach ($nissayaEndings as $key => $ending) {
             $endings[] = $ending->ending;
-            if(mb_strlen($ending->ending,'UTF-8')>$maxLen){
-                $maxLen = mb_strlen($ending->ending,'UTF-8');
+            if (mb_strlen($ending->ending, 'UTF-8') > $maxLen) {
+                $maxLen = mb_strlen($ending->ending, 'UTF-8');
             }
         }
         $this->info(count($endings).' ending');
 
-        $filename = "public/export/nissaya.csv";
-        Storage::disk('local')->put($filename, "");
-        $file = fopen(storage_path("app/$filename"),"w");
-        $bar = $this->output->createProgressBar(Sentence::whereIn('channel_uid',$nissaya_channels)->count());
-        foreach (Sentence::whereIn('channel_uid',$nissaya_channels)->select(['content','book_id'])->cursor() as $sent) {
-            $lines = explode("\n",$sent->content);
+        $filename = 'public/export/nissaya.csv';
+        Storage::disk('local')->put($filename, '');
+        $file = fopen(storage_path("app/$filename"), 'w');
+        $bar = $this->output->createProgressBar(Sentence::whereIn('channel_uid', $nissaya_channels)->count());
+        foreach (Sentence::whereIn('channel_uid', $nissaya_channels)->select(['content', 'book_id'])->cursor() as $sent) {
+            $lines = explode("\n", $sent->content);
             foreach ($lines as $key => $line) {
-                # code...
-                if(substr_count(trim($line),'=') === 1){
-                    $nissaya_str = explode('=',$line);
+                // code...
+                if (substr_count(trim($line), '=') === 1) {
+                    $nissaya_str = explode('=', $line);
                     $pali = $this->my2en($nissaya_str[0]);
                     $types = SuttaType::getTypeByBook($sent->book_id);
-                    $strTypes = implode(",",$types);
-                    //拆分
-                    $factors = UserDict::where('dict_id',$dict_id)->where('word',$pali)->value('factors');
-                    $factors = explode('+',$factors);
-                    if(count($factors)>1){
+                    $strTypes = implode(',', $types);
+                    // 拆分
+                    $factors = UserDict::where('dict_id', $dict_id)->where('word', $pali)->value('factors');
+                    $factors = explode('+', $factors);
+                    if (count($factors) > 1) {
                         $paliEnding = end($factors);
-                    }else{
+                    } else {
                         $paliEnding = '';
                     }
                     $nissaya_my = trim($nissaya_str[1]);
-                    $mEnding1 = $this->matchEnding($nissaya_my,$endings,$maxLen);
-                    if(!empty($paliEnding) && !empty($mEnding1[1])){
+                    $mEnding1 = $this->matchEnding($nissaya_my, $endings, $maxLen);
+                    if (! empty($paliEnding) && ! empty($mEnding1[1])) {
                         $mixed = $paliEnding.$mEnding1[1];
-                        fputcsv($file,[$strTypes, $pali,$paliEnding,$nissaya_my,$mEnding1[1],$mixed]);
+                        fputcsv($file, [$strTypes, $pali, $paliEnding, $nissaya_my, $mEnding1[1], $mixed]);
                     }
-                    $mEnding2= ['',''];
-                    if(!empty($mEnding1[1])){
-                        $mEnding2 = $this->matchEnding($mEnding1[0],$endings,$maxLen);
-                        if(!empty($paliEnding) && !empty($mEnding2[1])){
+                    $mEnding2 = ['', ''];
+                    if (! empty($mEnding1[1])) {
+                        $mEnding2 = $this->matchEnding($mEnding1[0], $endings, $maxLen);
+                        if (! empty($paliEnding) && ! empty($mEnding2[1])) {
                             $mixed = $paliEnding.$mEnding2[1];
-                            fputcsv($file,[$strTypes, $pali,$paliEnding,$nissaya_my,$mEnding2[1],$mixed]);
+                            fputcsv($file, [$strTypes, $pali, $paliEnding, $nissaya_my, $mEnding2[1], $mixed]);
                         }
                     }
-                    $mEnding3= ['',''];
-                    if(!empty($mEnding2[1])){
-                        $mEnding3 = $this->matchEnding($mEnding2[0],$endings,$maxLen);
-                        if(!empty($paliEnding) && !empty($mEnding3[1])){
+                    $mEnding3 = ['', ''];
+                    if (! empty($mEnding2[1])) {
+                        $mEnding3 = $this->matchEnding($mEnding2[0], $endings, $maxLen);
+                        if (! empty($paliEnding) && ! empty($mEnding3[1])) {
                             $mixed = $paliEnding.$mEnding3[1];
-                            fputcsv($file,[$strTypes, $pali,$paliEnding,$nissaya_my,$mEnding3[1],$mixed]);
+                            fputcsv($file, [$strTypes, $pali, $paliEnding, $nissaya_my, $mEnding3[1], $mixed]);
                         }
                     }
 
-                    //fputcsv($file,[$strTypes, $pali,$paliEnding,$nissaya_my,$mEnding1[1],$mEnding2[1],$mEnding3[1]]);
+                    // fputcsv($file,[$strTypes, $pali,$paliEnding,$nissaya_my,$mEnding1[1],$mEnding2[1],$mEnding3[1]]);
                 }
             }
             $bar->advance();
@@ -196,24 +204,28 @@ class ExportNissaya extends Command
         $bar->finish();
         $this->info('done');
         $this->info($filename);
+
         return 0;
     }
 
-    public function my2en($my){
-        return str_replace($this->my,$this->en,$my);
+    public function my2en($my)
+    {
+        return str_replace($this->my, $this->en, $my);
     }
 
-    private function matchEnding($needle,$endings,$maxLen){
+    private function matchEnding($needle, $endings, $maxLen)
+    {
         $needle = trim($needle);
-        if(mb_substr($needle,-1,1,'UTF-8') === '။'){
-            $needle = mb_substr($needle,0,-1);
+        if (mb_substr($needle, -1, 1, 'UTF-8') === '။') {
+            $needle = mb_substr($needle, 0, -1);
         }
-        for ($i=1; $i <= $maxLen ; $i++) {
-            $mEnding = mb_substr($needle,-$i);
-            if(in_array($mEnding,$endings)){
-                return [mb_substr($needle,0,mb_strlen($needle,'UTF-8')-$i),$mEnding];
+        for ($i = 1; $i <= $maxLen; $i++) {
+            $mEnding = mb_substr($needle, -$i);
+            if (in_array($mEnding, $endings)) {
+                return [mb_substr($needle, 0, mb_strlen($needle,'UTF-8') - $i), $mEnding];
             }
         }
-        return [$needle,''];
+
+        return [$needle, ''];
     }
 }

+ 24 - 22
api-v13/app/Console/Commands/ExportOffline.php

@@ -2,17 +2,17 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Facades\Redis;
 
 class ExportOffline extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan export:offline lzma
+     *
      * @var string
      */
     protected $signature = 'export:offline {format?  : zip file format 7z,lzma,gz } {--test}  {--driver=str}';
@@ -41,60 +41,61 @@ class ExportOffline extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exportDir = storage_path('app/public/export/offline');
-        if (!is_dir($exportDir)) {
+        if (! is_dir($exportDir)) {
             $res = mkdir($exportDir, 0755, true);
-            if (!$res) {
-                Log::error('mkdir fail path=' . $exportDir);
+            if (! $res) {
+                Log::error('mkdir fail path='.$exportDir);
+
                 return 1;
             }
         }
 
-        //清空redis
+        // 清空redis
         Cache::put('/offline/index', []);
 
-        //删除全部的旧文件
+        // 删除全部的旧文件
         foreach (scandir($exportDir) as $key => $file) {
-            if (is_file($exportDir . '/' . $file)) {
-                unlink($exportDir . '/' . $file);
+            if (is_file($exportDir.'/'.$file)) {
+                unlink($exportDir.'/'.$file);
             }
         }
-        //添加 .stop
-        $exportStop = $exportDir . '/.stop';
+        // 添加 .stop
+        $exportStop = $exportDir.'/.stop';
         $file = fopen($exportStop, 'w');
         fclose($file);
 
-        //建表
+        // 建表
         $this->info('create db');
         $this->call('export:create.db');
 
-        //term
+        // term
         $this->info('export term start');
         $this->call('export:term');
 
-        //导出channel
+        // 导出channel
         $this->call('export:channel', ['db' => 'wikipali-offline']);
         $this->call('export:channel', ['db' => 'wikipali-offline-index']);
 
-        if (!$this->option('test')) {
-            //tag
+        if (! $this->option('test')) {
+            // tag
             $this->call('export:tag', ['db' => 'wikipali-offline']);
             $this->call('export:tag.map', ['db' => 'wikipali-offline']);
             //
             $this->info('export pali text start');
             $this->call('export:pali.text');
-            //导出章节索引
+            // 导出章节索引
             $this->info('export chapter start');
             $this->call('export:chapter.index', ['db' => 'wikipali-offline']);
             $this->call('export:chapter.index', ['db' => 'wikipali-offline-index']);
-            //导出译文
+            // 导出译文
             $this->info('export sentence start');
             $this->call('export:sentence', ['--type' => 'translation', '--driver' => $this->option('driver')]);
             $this->call('export:sentence', ['--type' => 'nissaya', '--driver' => $this->option('driver')]);
-            //导出原文
+            // 导出原文
             $this->call('export:sentence', ['--type' => 'original', '--driver' => $this->option('driver')]);
         }
 
@@ -103,13 +104,13 @@ class ExportOffline extends Command
         sleep(5);
         $this->call('export:zip', [
             'id' => 'index',
-            'filename' => 'wikipali-offline-index' . '-' . date("Y-m-d") . '.db3',
+            'filename' => 'wikipali-offline-index'.'-'.date('Y-m-d').'.db3',
             'title' => 'wikipali 离线包索引',
             'format' => $this->argument('format'),
         ]);
         $this->call('export:zip', [
             'id' => 'date-package',
-            'filename' => 'wikipali-offline' . '-' . date("Y-m-d") . '.db3',
+            'filename' => 'wikipali-offline'.'-'.date('Y-m-d').'.db3',
             'title' => 'wikipali 离线包',
             'format' => $this->argument('format'),
         ]);
@@ -117,6 +118,7 @@ class ExportOffline extends Command
         $this->call('export:ai.training.data');
         $this->call('export:ai.pali.word.token');
         unlink($exportStop);
+
         return 0;
     }
 }

+ 25 - 24
api-v13/app/Console/Commands/ExportPalitext.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use App\Models\PaliText;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportPalitext extends Command
@@ -41,40 +41,41 @@ class ExportPalitext extends Command
     public function handle()
     {
         Log::debug('task export offline palitext-table start');
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $exportFile = storage_path('app/public/export/offline/wikipali-offline-'.date("Y-m-d").'.db3');
-        $dbh = new \PDO('sqlite:'.$exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/wikipali-offline-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO pali_text ( id , book , paragraph, level, toc,
+        $query = 'INSERT INTO pali_text ( id , book , paragraph, level, toc,
                                     chapter_len , parent   )
-                                    VALUES ( ? , ? , ? , ? , ? , ? , ? )";
-        try{
+                                    VALUES ( ? , ? , ? , ? , ? , ? , ? )';
+        try {
             $stmt = $dbh->prepare($query);
-        }catch(PDOException $e){
+        } catch (PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
         $bar = $this->output->createProgressBar(PaliText::count());
-        foreach (PaliText::select(['uid','book','paragraph',
-                    'level','toc','lenght','chapter_len',
-                    'next_chapter','prev_chapter','parent','chapter_strlen'])
-                    ->orderBy('book')
-                    ->orderBy('paragraph')
-                    ->cursor() as $chapter) {
-            $currData = array(
-                            $chapter->uid,
-                            $chapter->book,
-                            $chapter->paragraph,
-                            $chapter->level,
-                            $chapter->toc,
-                            $chapter->chapter_len,
-                            $chapter->parent,
-                            );
+        foreach (PaliText::select(['uid', 'book', 'paragraph',
+            'level', 'toc', 'lenght', 'chapter_len',
+            'next_chapter', 'prev_chapter', 'parent', 'chapter_strlen'])
+            ->orderBy('book')
+            ->orderBy('paragraph')
+            ->cursor() as $chapter) {
+            $currData = [
+                $chapter->uid,
+                $chapter->book,
+                $chapter->paragraph,
+                $chapter->level,
+                $chapter->toc,
+                $chapter->chapter_len,
+                $chapter->parent,
+            ];
             $stmt->execute($currData);
             $bar->advance();
         }

+ 19 - 17
api-v13/app/Console/Commands/ExportSentence.php

@@ -2,14 +2,15 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use App\Models\Sentence;
-use App\Models\Channel;
 use App\Http\Api\ChannelApi;
+use App\Http\Api\MdRender;
+use App\Models\Channel;
+use App\Models\Sentence;
+use App\Tools\Markdown;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Str;
-use App\Http\Api\MdRender;
 
 class ExportSentence extends Command
 {
@@ -45,10 +46,10 @@ class ExportSentence extends Command
     public function handle()
     {
         Log::debug('task export offline sentence-table start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        \App\Tools\Markdown::driver($this->option('driver'));
+        Markdown::driver($this->option('driver'));
         $channels = [];
         $channel_id = $this->option('channel');
         if ($channel_id) {
@@ -57,8 +58,8 @@ class ExportSentence extends Command
         } else {
             $channel_type = $this->option('type');
             $file_suf = $channel_type;
-            if ($channel_type === "original") {
-                $pali_channel = ChannelApi::getSysChannel("_System_Pali_VRI_");
+            if ($channel_type === 'original') {
+                $pali_channel = ChannelApi::getSysChannel('_System_Pali_VRI_');
                 if ($pali_channel === false) {
                     return 0;
                 }
@@ -66,19 +67,18 @@ class ExportSentence extends Command
             } else {
                 $nissaya_channel = Channel::where('type', $channel_type)->where('status', 30)->select('uid')->get();
                 foreach ($nissaya_channel as $key => $value) {
-                    # code...
+                    // code...
                     $channels[] = $value->uid;
                 }
             }
         }
 
-
-        $exportFile = storage_path('app/public/export/offline/wikipali-offline-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/wikipali-offline-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        if ($channel_type === "original") {
+        if ($channel_type === 'original') {
             $table = 'sentence';
         } else {
             $table = 'sentence_translation';
@@ -91,6 +91,7 @@ class ExportSentence extends Command
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
@@ -107,12 +108,12 @@ class ExportSentence extends Command
             'channel_uid',
             'editor_uid',
             'language',
-            'updated_at'
+            'updated_at',
         ])->cursor();
         foreach ($srcDb as $sent) {
             if (Str::isUuid($sent->channel_uid)) {
                 $channel = ChannelApi::getById($sent->channel_uid);
-                $currData = array(
+                $currData = [
                     $sent->book_id,
                     $sent->paragraph,
                     $sent->word_start,
@@ -127,7 +128,7 @@ class ExportSentence extends Command
                         'unity',
                     ),
                     $sent->channel_uid,
-                );
+                ];
                 $stmt->execute($currData);
             }
             $bar->advance();
@@ -135,6 +136,7 @@ class ExportSentence extends Command
         $dbh->commit();
         $bar->finish();
         Log::debug('task export sentence finished');
+
         return 0;
     }
 }

+ 10 - 9
api-v13/app/Console/Commands/ExportTag.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use App\Models\Tag;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportTag extends Command
@@ -41,33 +41,34 @@ class ExportTag extends Command
     public function handle()
     {
         $this->info('task: export offline data tag-table start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $exportFile = storage_path('app/public/export/offline/' . $this->argument('db') . '-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/'.$this->argument('db').'-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO tag ( id , name ,
+        $query = 'INSERT INTO tag ( id , name ,
                                     description , color , owner_id  )
-                                    VALUES ( ? , ? , ? , ? , ?  )";
+                                    VALUES ( ? , ? , ? , ? , ?  )';
         try {
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
         $bar = $this->output->createProgressBar(Tag::count());
         foreach (Tag::select(['id', 'name', 'description', 'color', 'owner_id'])->cursor() as $row) {
-            $currData = array(
+            $currData = [
                 $row->id,
                 $row->name,
                 $row->description,
                 $row->color,
                 $row->owner_id,
-            );
+            ];
             $stmt->execute($currData);
             $bar->advance();
         }

+ 11 - 9
api-v13/app/Console/Commands/ExportTagmap.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use App\Models\TagMap;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportTagmap extends Command
@@ -41,35 +41,37 @@ class ExportTagmap extends Command
     public function handle()
     {
         $this->info('task: export offline tagmap-table start');
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $exportFile = storage_path('app/public/export/offline/' . $this->argument('db') . '-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/'.$this->argument('db').'-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO tag_map ( anchor_id , tag_id )
-                                    VALUES ( ? , ? )";
+        $query = 'INSERT INTO tag_map ( anchor_id , tag_id )
+                                    VALUES ( ? , ? )';
         try {
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
         $bar = $this->output->createProgressBar(TagMap::count());
         foreach (TagMap::select(['id', 'table_name', 'anchor_id', 'tag_id'])->cursor() as $row) {
-            $currData = array(
+            $currData = [
                 $row->anchor_id,
                 $row->tag_id,
-            );
+            ];
             $stmt->execute($currData);
             $bar->advance();
         }
         $dbh->commit();
         $bar->finish();
         Log::debug('task: export offline tagmap-table finished');
+
         return 0;
     }
 }

+ 31 - 29
api-v13/app/Console/Commands/ExportTerm.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
 use App\Models\DhammaTerm;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class ExportTerm extends Command
@@ -42,49 +42,50 @@ class ExportTerm extends Command
     {
         Log::info('task export offline term-table start');
         $startAt = time();
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $exportFile = storage_path('app/public/export/offline/wikipali-offline-' . date("Y-m-d") . '.db3');
-        $dbh = new \PDO('sqlite:' . $exportFile, "", "", array(\PDO::ATTR_PERSISTENT => true));
+        $exportFile = storage_path('app/public/export/offline/wikipali-offline-'.date('Y-m-d').'.db3');
+        $dbh = new \PDO('sqlite:'.$exportFile, '', '', [\PDO::ATTR_PERSISTENT => true]);
         $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_WARNING);
         $dbh->beginTransaction();
 
-        $query = "INSERT INTO dhamma_terms ( uuid , word , word_en , meaning ,
+        $query = 'INSERT INTO dhamma_terms ( uuid , word , word_en , meaning ,
                                     other_meaning , note , tag , channel_id,
                                     language, owner, editor_id,
                                     created_at,updated_at,deleted_at)
                                     VALUES ( ? , ? , ? , ? ,
                                             ? , ? , ? , ? ,
                                             ?, ?, ?,
-                                            ?, ?, ? )";
+                                            ?, ?, ? )';
         try {
             $stmt = $dbh->prepare($query);
         } catch (\PDOException $e) {
             Log::error($e->getMessage(), ['exception' => $e]);
+
             return 1;
         }
 
         $total = DhammaTerm::count();
         $channels = DhammaTerm::select([
-                'guid',
-                'word',
-                'word_en',
-                'meaning',
-                'other_meaning',
-                'note',
-                'tag',
-                'channal',
-                'language',
-                "owner",
-                "editor_id",
-                "created_at",
-                "updated_at",
-                "deleted_at"
-            ])
-                ->cursor();
+            'guid',
+            'word',
+            'word_en',
+            'meaning',
+            'other_meaning',
+            'note',
+            'tag',
+            'channal',
+            'language',
+            'owner',
+            'editor_id',
+            'created_at',
+            'updated_at',
+            'deleted_at',
+        ])
+            ->cursor();
         foreach ($channels as $key => $row) {
-            $currData = array(
+            $currData = [
                 $row->guid,
                 $row->word,
                 $row->word_en,
@@ -99,18 +100,19 @@ class ExportTerm extends Command
                 $row->created_at,
                 $row->updated_at,
                 $row->deleted_at,
-            );
+            ];
             $stmt->execute($currData);
-            
-            if($key % 1000 ===0){
-                $precent = (int)($key*100/$total);
+
+            if ($key % 1000 === 0) {
+                $precent = (int) ($key * 100 / $total);
                 $this->line("[{$precent}%]");
             }
         }
         $dbh->commit();
         $bar->finish();
-        $this->info(' time=' . (time() - $startAt) . 's');
+        $this->info(' time='.(time() - $startAt).'s');
         Log::info('task export offline term-table finished');
+
         return 0;
     }
 }

+ 30 - 30
api-v13/app/Console/Commands/ExportZip.php

@@ -3,13 +3,11 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\App;
-
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
 use Symfony\Component\Process\Process;
-use Symfony\Component\Process\Exception\ProcessFailedException;
 
 class ExportZip extends Command
 {
@@ -49,7 +47,7 @@ class ExportZip extends Command
         $exportFile = $this->argument('filename');
         $filename = basename($exportFile);
         if ($filename === $exportFile) {
-            $exportFullFileName = $defaultExportPath . '/' . $filename;
+            $exportFullFileName = $defaultExportPath.'/'.$filename;
             $exportPath = $defaultExportPath;
         } else {
             $exportFullFileName = $exportFile;
@@ -66,29 +64,30 @@ class ExportZip extends Command
         );
         switch ($this->argument('format')) {
             case '7z':
-                $zipFile = $filename . ".7z";
+                $zipFile = $filename.'.7z';
                 break;
             case 'lzma':
-                $zipFile = $filename . ".lzma";
+                $zipFile = $filename.'.lzma';
                 break;
             default:
-                $zipFile = $filename . ".gz";
+                $zipFile = $filename.'.gz';
                 break;
         }
         //
-        if (!file_exists($exportFullFileName)) {
+        if (! file_exists($exportFullFileName)) {
             Log::error('export offline: no  file {filename}', ['filename' => $exportFullFileName]);
-            $this->error('export offline: no  file {filename}' . $exportFullFileName);
+            $this->error('export offline: no  file {filename}'.$exportFullFileName);
+
             return 1;
         }
 
-        $zipFullFileName = $exportPath . '/' . $zipFile;
+        $zipFullFileName = $exportPath.'/'.$zipFile;
         if (file_exists($zipFullFileName)) {
-            Log::debug('export offline: delete old zip file:' . $zipFullFileName);
+            Log::debug('export offline: delete old zip file:'.$zipFullFileName);
             unlink($zipFullFileName);
         }
 
-        shell_exec("cd " . $exportPath);
+        shell_exec('cd '.$exportPath);
         switch ($this->argument('format')) {
             case '7z':
                 $command = [
@@ -101,7 +100,7 @@ class ExportZip extends Command
                     '-md=32m',
                     '-ms=on',
                     $zipFullFileName,
-                    $exportFullFileName
+                    $exportFullFileName,
                 ];
                 break;
             case 'lzma':
@@ -123,27 +122,27 @@ class ExportZip extends Command
             'zip file {filename} in {format} saved.',
             [
                 'filename' => $exportFile,
-                'format' => $this->argument('format')
+                'format' => $this->argument('format'),
             ]
         );
 
-        $url = array();
+        $url = [];
         foreach (config('mint.server.cdn_urls') as $key => $cdn) {
             $url[] = [
-                'link' => $cdn . '/' . $zipFile,
-                'hostname' => 'china cdn-' . $key,
+                'link' => $cdn.'/'.$zipFile,
+                'hostname' => 'china cdn-'.$key,
             ];
         }
 
         $bucket = config('mint.attachments.bucket_name.temporary');
-        $tmpFile =  $bucket . '/' . $zipFile;
+        $tmpFile = $bucket.'/'.$zipFile;
 
-        $this->info('upload file=' . $tmpFile);
+        $this->info('upload file='.$tmpFile);
         Log::debug('export offline: upload file {filename}', ['filename' => $tmpFile]);
 
         Storage::put($tmpFile, file_get_contents($zipFullFileName));
 
-        $this->info('upload done file=' . $tmpFile);
+        $this->info('upload done file='.$tmpFile);
         Log::debug('export offline: upload done {filename}', ['filename' => $tmpFile]);
 
         if (App::environment('local')) {
@@ -157,30 +156,31 @@ class ExportZip extends Command
                     'export offline: generate temporaryUrl fail {Exception}',
                     [
                         'exception' => $e,
-                        'file' => $tmpFile
+                        'file' => $tmpFile,
                     ]
                 );
+
                 return 1;
             }
         }
-        $this->info('link = ' . $link);
-        Log::info('export offline: link=' . $link);
+        $this->info('link = '.$link);
+        Log::info('export offline: link='.$link);
 
         $url[] = [
             'link' => $link,
             'hostname' => 'Amazon cloud storage(Hongkong)',
         ];
         $info = Cache::get('/offline/index');
-        if (!is_array($info)) {
-            $info = array();
+        if (! is_array($info)) {
+            $info = [];
         }
         $info[] = [
             'id' => $this->argument('id'),
             'title' => $this->argument('title'),
             'filename' => $zipFile,
             'url' => $url,
-            'create_at' => date("Y-m-d H:i:s"),
-            'chapter' => Cache::get("/export/chapter/count"),
+            'create_at' => date('Y-m-d H:i:s'),
+            'chapter' => Cache::get('/export/chapter/count'),
             'filesize' => filesize($zipFullFileName),
             'min_app_ver' => '1.3',
         ];
@@ -193,7 +193,7 @@ class ExportZip extends Command
                 'export offline: delete  file fail {Exception}',
                 [
                     'exception' => $th,
-                    'file' => $exportFullFileName
+                    'file' => $exportFullFileName,
                 ]
             );
         }

+ 33 - 33
api-v13/app/Console/Commands/ExportZip2.php

@@ -3,11 +3,10 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\App;
-
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
 use Symfony\Component\Process\Process;
 
 class ExportZip2 extends Command
@@ -30,7 +29,7 @@ class ExportZip2 extends Command
         $filename = basename($exportFile);
 
         if ($filename === $exportFile) {
-            $exportFullFileName = $defaultExportPath . '/' . $filename;
+            $exportFullFileName = $defaultExportPath.'/'.$filename;
             $exportPath = $defaultExportPath;
         } else {
             $exportFullFileName = $exportFile;
@@ -39,19 +38,19 @@ class ExportZip2 extends Command
 
         $format = $this->argument('format') ?? 'gz';
 
-        if (!file_exists($exportFullFileName)) {
+        if (! file_exists($exportFullFileName)) {
 
             Log::error('export offline: file not exists', [
-                'file' => $exportFullFileName
+                'file' => $exportFullFileName,
             ]);
 
-            $this->error('file not exists: ' . $exportFullFileName);
+            $this->error('file not exists: '.$exportFullFileName);
 
             return 1;
         }
 
         $zipFile = $this->getZipFileName($filename, $format);
-        $zipFullFileName = $exportPath . '/' . $zipFile;
+        $zipFullFileName = $exportPath.'/'.$zipFile;
 
         if (file_exists($zipFullFileName)) {
             unlink($zipFullFileName);
@@ -60,7 +59,7 @@ class ExportZip2 extends Command
         $this->info("start compress: {$exportFullFileName}");
         Log::debug('export offline zip start', [
             'file' => $exportFullFileName,
-            'format' => $format
+            'format' => $format,
         ]);
 
         $this->compress($exportFullFileName, $zipFullFileName, $format);
@@ -68,7 +67,7 @@ class ExportZip2 extends Command
         $this->info('压缩完成');
 
         Log::debug('zip done', [
-            'zip' => $zipFullFileName
+            'zip' => $zipFullFileName,
         ]);
 
         /*
@@ -78,12 +77,12 @@ class ExportZip2 extends Command
         */
 
         $bucket = config('mint.attachments.bucket_name.temporary');
-        $tmpFile = $bucket . '/' . $zipFile;
+        $tmpFile = $bucket.'/'.$zipFile;
 
-        $this->info('upload file=' . $tmpFile);
+        $this->info('upload file='.$tmpFile);
 
         Log::debug('export offline upload', [
-            'file' => $tmpFile
+            'file' => $tmpFile,
         ]);
 
         Storage::put($tmpFile, fopen($zipFullFileName, 'r'));
@@ -108,14 +107,15 @@ class ExportZip2 extends Command
                 );
             } catch (\Exception $e) {
                 Log::error('temporaryUrl fail', [
-                    'exception' => $e
+                    'exception' => $e,
                 ]);
                 $this->error('generate temporaryUrl fail');
+
                 return 1;
             }
         }
 
-        $this->info('link=' . $link);
+        $this->info('link='.$link);
 
         /*
         |--------------------------------------------------------------------------
@@ -126,14 +126,14 @@ class ExportZip2 extends Command
         $url = [];
         foreach (config('mint.server.cdn_urls') as $key => $cdn) {
             $url[] = [
-                'link' => $cdn . '/' . $zipFile,
-                'hostname' => 'china cdn-' . $key
+                'link' => $cdn.'/'.$zipFile,
+                'hostname' => 'china cdn-'.$key,
             ];
         }
 
         $url[] = [
             'link' => $link,
-            'hostname' => 'Amazon cloud storage(Hongkong)'
+            'hostname' => 'Amazon cloud storage(Hongkong)',
         ];
 
         /*
@@ -143,13 +143,13 @@ class ExportZip2 extends Command
         */
 
         $info = Cache::get('/offline/index', []);
-        if (!is_array($info)) {
+        if (! is_array($info)) {
             $info = [];
         }
         $id = $this->argument('id');
         // 先移除已有相同 id 的记录
         $info = array_values(array_filter($info, function ($item) use ($id) {
-            return !isset($item['id']) || $item['id'] != $id;
+            return ! isset($item['id']) || $item['id'] != $id;
         }));
         // 再追加新数据
         $info[] = [
@@ -158,7 +158,7 @@ class ExportZip2 extends Command
             'filename' => $zipFile,
             'url' => $url,
             'create_at' => now()->toDateTimeString(),
-            'chapter' => Cache::get("/export/chapter/count"),
+            'chapter' => Cache::get('/export/chapter/count'),
             'filesize' => filesize($zipFullFileName),
             'min_app_ver' => '1.3',
         ];
@@ -181,7 +181,7 @@ class ExportZip2 extends Command
             }
         } catch (\Throwable $e) {
             Log::error('delete source fail', [
-                'exception' => $e
+                'exception' => $e,
             ]);
         }
 
@@ -197,9 +197,9 @@ class ExportZip2 extends Command
     protected function getZipFileName(string $filename, string $format): string
     {
         return match ($format) {
-            '7z' => $filename . '.7z',
-            'lzma' => $filename . '.lzma',
-            default => $filename . '.tar.gz'
+            '7z' => $filename.'.7z',
+            'lzma' => $filename.'.lzma',
+            default => $filename.'.tar.gz'
         };
     }
 
@@ -220,20 +220,20 @@ class ExportZip2 extends Command
                     '-t7z',
                     '-mx=9',
                     $target,
-                    $source
+                    $source,
                 ];
                 break;
 
             case 'lzma':
                 if ($isDir) {
-                    $tmpTar = $source . '.tar';
+                    $tmpTar = $source.'.tar';
                     $tar = new Process([
                         'tar',
                         '-cf',
                         $tmpTar,
                         '-C',
                         dirname($source),
-                        basename($source)
+                        basename($source),
                     ]);
                     $tar->run();
                     $source = $tmpTar;
@@ -243,7 +243,7 @@ class ExportZip2 extends Command
                     '-k',
                     '-9',
                     '--format=lzma',
-                    $source
+                    $source,
                 ];
                 break;
 
@@ -254,7 +254,7 @@ class ExportZip2 extends Command
                     $target,
                     '-C',
                     dirname($source),
-                    basename($source)
+                    basename($source),
                 ];
         }
 
@@ -265,10 +265,10 @@ class ExportZip2 extends Command
 
         $this->info($process->getOutput());
 
-        if (!$process->isSuccessful()) {
+        if (! $process->isSuccessful()) {
 
             Log::error('compress fail', [
-                'error' => $process->getErrorOutput()
+                'error' => $process->getErrorOutput(),
             ]);
 
             throw new \RuntimeException($process->getErrorOutput());

+ 48 - 40
api-v13/app/Console/Commands/ImportArticle.php

@@ -2,17 +2,18 @@
 
 namespace App\Console\Commands;
 
+use App\Http\Api\StudioApi;
+use App\Models\Article;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Log;
-use App\Http\Api\StudioApi;
-use App\Models\Article;
 
 class ImportArticle extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan import:article --studio=visuddhinanda --anthology=eb9e3f7f-b942-4ca4-bd6f-b7876b59a523 --token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJuYmYiOjE2OTc3Mjg2ODUsImV4cCI6MTcyOTI2NDY4NSwidWlkIjoiYmE1NDYzZjMtNzJkMS00NDEwLTg1OGUtZWFkZDEwODg0NzEzIiwiaWQiOjR9.fiXhnY2LczZ9kKVHV0FfD3AJPZt-uqM5wrDe4EhToVexdd007ebPFYssZefmchfL0mx9nF0rgHSqjNhx4P0yDA
+     *
      * @var string
      */
     protected $signature = 'import:article {--studio=} {--anthology=} {--token=}';
@@ -39,37 +40,41 @@ class ImportArticle extends Command
      * 分两个步骤导入
      * 1. 导入文章到文集
      * 2. 重新生成目录结构
+     *
      * @return int
      */
     public function handle()
     {
-        if (!$this->confirm('Do you wish to continue?')) {
+        if (! $this->confirm('Do you wish to continue?')) {
             return 0;
         }
         $token = $this->option('token');
         $studioName = $this->option('studio');
         $anthologyId = $this->option('anthology');
 
-        //先获取文章列表,建立全部目录
-        $head = array();
-        $strFileName = __DIR__."/tipitaka-sarupa.csv";
-        if(!file_exists($strFileName)){
+        // 先获取文章列表,建立全部目录
+        $head = [];
+        $strFileName = __DIR__.'/tipitaka-sarupa.csv';
+        if (! file_exists($strFileName)) {
             $this->error($strFileName.'文件不存在');
+
             return 1;
         }
 
-        if (($fp = fopen($strFileName, "r")) === false) {
+        if (($fp = fopen($strFileName, 'r')) === false) {
             $this->error("can not open csv {$strFileName}");
+
             return 0;
         }
         $this->info('打开csv文件成功');
 
         $studioId = StudioApi::getIdByName($studioName);
-        if(!$studioId){
+        if (! $studioId) {
             $this->error("can not found studio name {$studioName}");
+
             return 0;
         }
-        //导入文章
+        // 导入文章
         $url = config('app.url').'/api/v2/article';
         $inputRow = 0;
         fseek($fp, 0);
@@ -77,62 +82,64 @@ class ImportArticle extends Command
         $success = 0;
         $fail = 0;
         while (($data = fgetcsv($fp, 0, ',')) !== false) {
-            if($inputRow>0){
+            if ($inputRow > 0) {
                 $id = $data[0];
                 $dir = $data[1];
                 $title = $data[2];
                 $realTitle = "[{$id}]{$title}";
-                $content = str_replace('\n',"\n",$data[4]) ;
-                $reference = str_replace(['(',')'],['({{ql|type=m|title=','}})'],$data[5]);
+                $content = str_replace('\n', "\n", $data[4]);
+                $reference = str_replace(['(', ')'], ['({{ql|type=m|title=', '}})'], $data[5]);
                 $contentCombine = "{$title}\n\n{$content}\n\n{$reference}";
-                $percent = (int)($inputRow*100/7000);
+                $percent = (int) ($inputRow * 100 / 7000);
                 $this->info("[{$percent}%] doing ".$realTitle);
-                //先查是否有
-                $hasArticle = Article::where('owner',$studioId)
-                              ->where('title',$realTitle)
-                              ->exists();
-                if($hasArticle){
+                // 先查是否有
+                $hasArticle = Article::where('owner', $studioId)
+                    ->where('title', $realTitle)
+                    ->exists();
+                if ($hasArticle) {
                     $this->error('文章已经存在 title='.$realTitle);
+
                     continue;
                 }
                 $count++;
                 $this->info('新建 title='.$realTitle);
                 sleep(2);
                 $response = Http::withToken($token)->post($url,
-                                [
-                                    'title'=> $realTitle,
-                                    'lang'=> 'my',
-                                    'studio'=> $studioName,
-                                    'anthologyId'=> $anthologyId,
-                                ]);
-                if($response->ok()){
+                    [
+                        'title' => $realTitle,
+                        'lang' => 'my',
+                        'studio' => $studioName,
+                        'anthologyId' => $anthologyId,
+                    ]);
+                if ($response->ok()) {
                     $this->info('create ok');
                     $articleId = $response->json('data')['uid'];
-                }else{
+                } else {
                     $this->error('create article fail.'.$realTitle);
                     Log::error('create article fail title='.$realTitle);
                     $fail++;
+
                     continue;
                 }
                 sleep(2);
                 $this->info('修改 id='.$articleId);
                 $response = Http::withToken($token)->put($url.'/'.$articleId,
-                                    [
-                                        'title'=> $realTitle,
-                                        'summary'=> $title.'#'.$id,
-                                        'lang'=> 'my',
-                                        'content'=> $contentCombine,
-                                        'anthology_id'=>$anthologyId,
-                                        'to_tpl'=>true,
-                                        'status'=>30,
-                                    ]);
-
-                if($response->ok()){
+                    [
+                        'title' => $realTitle,
+                        'summary' => $title.'#'.$id,
+                        'lang' => 'my',
+                        'content' => $contentCombine,
+                        'anthology_id' => $anthologyId,
+                        'to_tpl' => true,
+                        'status' => 30,
+                    ]);
+
+                if ($response->ok()) {
                     $this->info('edit ok');
                     $success++;
-                }else{
+                } else {
                     $this->error('edit article fail');
-                    Log::error('edit article fail ',['id'=>$articleId,'title'=>$realTitle]);
+                    Log::error('edit article fail ', ['id' => $articleId, 'title' => $realTitle]);
                     $fail++;
                 }
             }
@@ -142,6 +149,7 @@ class ImportArticle extends Command
         fclose($fp);
 
         $this->info('成功='.$success.' 失败='.$fail);
+
         return 0;
     }
 }

+ 86 - 77
api-v13/app/Console/Commands/ImportArticleMap.php

@@ -2,12 +2,12 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Http;
-use Illuminate\Support\Facades\Log;
 use App\Http\Api\StudioApi;
 use App\Models\Article;
 use App\Models\Collection;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
 
 class ImportArticleMap extends Command
 {
@@ -47,167 +47,176 @@ class ImportArticleMap extends Command
         $studioName = $this->option('studio');
         $anthologyId = $this->option('anthology');
         $srcStudio = $this->argument('src_studio');
-        if (!$this->confirm('Do you wish to continue?')) {
+        if (! $this->confirm('Do you wish to continue?')) {
             return 0;
         }
         $studioId = StudioApi::getIdByName($studioName);
-        if(!$studioId){
+        if (! $studioId) {
             $this->error("can not found studio name {$studioName}");
+
             return 0;
         }
         $srcStudioId = StudioApi::getIdByName($srcStudio);
-        if(!$srcStudioId){
+        if (! $srcStudioId) {
             $this->error("can not found src studio name {$srcStudio}");
+
             return 0;
         }
 
-        //先获取文章列表,建立全部目录
+        // 先获取文章列表,建立全部目录
         $url = config('app.url').'/api/v2/article-map';
 
         $this->info('打开csv文件并读取数据');
-        $head = array();
-        $strFileName = __DIR__."/tipitaka-sarupa.csv";
-        if(!file_exists($strFileName)){
+        $head = [];
+        $strFileName = __DIR__.'/tipitaka-sarupa.csv';
+        if (! file_exists($strFileName)) {
             $this->error($strFileName.'文件不存在');
+
             return 1;
         }
 
-        if (($fp = fopen($strFileName, "r")) === false) {
+        if (($fp = fopen($strFileName, 'r')) === false) {
             $this->error("can not open csv {$strFileName}");
+
             return 0;
         }
-        //查询文集语言
-        $srcAnthology = Collection::where('uid',$anthologyId)->first();
-        if(!$srcAnthology){
-            $this->error("文集不存在 anthologyId=".$anthologyId);
+        // 查询文集语言
+        $srcAnthology = Collection::where('uid', $anthologyId)->first();
+        if (! $srcAnthology) {
+            $this->error('文集不存在 anthologyId='.$anthologyId);
+
             return 0;
         }
         $lang = $srcAnthology->lang;
-        if(empty($lang)){
-            $this->error("文集语言不能为空 anthologyId=".$anthologyId);
+        if (empty($lang)) {
+            $this->error('文集语言不能为空 anthologyId='.$anthologyId);
+
             return 0;
         }
         $inputRow = 0;
-        $currSize=0;
-        $currBlock=1;
-        $currDir='';
+        $currSize = 0;
+        $currBlock = 1;
+        $currDir = '';
         $success = 0;
         $fail = 0;
-        $articleMap = array();
+        $articleMap = [];
         while (($data = fgetcsv($fp, 0, ',')) !== false) {
-            if($inputRow>0){
+            if ($inputRow > 0) {
                 $id = $data[0];
                 $dir = $data[1];
                 $title = $data[2];
                 $realTitle = "[{$id}]{$title}";
-                $realTitle = mb_substr($realTitle,0,128,'UTF-8');
+                $realTitle = mb_substr($realTitle, 0, 128, 'UTF-8');
                 $reference = $data[5];
 
-                $percent = (int)($inputRow*100/6984);
+                $percent = (int) ($inputRow * 100 / 6984);
                 $this->info("[{$percent}%] doing ".$realTitle);
 
-                if($this->option('size')){
-                    $currDir = $srcAnthology->title . '-' . $currBlock;
-                    if($currSize > $this->option('size')){
+                if ($this->option('size')) {
+                    $currDir = $srcAnthology->title.'-'.$currBlock;
+                    if ($currSize > $this->option('size')) {
                         $currBlock++;
-                        $currSize=0;
+                        $currSize = 0;
                     }
-                }else{
+                } else {
                     $currDir = $dir;
                 }
-                //查找目录文章是否存在
-                $dirArticle = Article::where('owner',$studioId)
-                              ->where('title',$currDir)
-                              ->first();
-                if($dirArticle){
+                // 查找目录文章是否存在
+                $dirArticle = Article::where('owner', $studioId)
+                    ->where('title', $currDir)
+                    ->first();
+                if ($dirArticle) {
                     $dirId = $dirArticle->uid;
-                }else{
+                } else {
                     $this->info('不存在目录'.$currDir.'新建');
                     $url = config('app.url').'/api/v2/article';
                     sleep(2);
                     $response = Http::withToken($token)->post($url,
-                    [
-                        'title'=> $currDir,
-                        'lang'=> $lang,
-                        'studio'=> $studioName,
-                        'anthologyId'=> $anthologyId,
-                    ]);
-                    if($response->ok()){
+                        [
+                            'title' => $currDir,
+                            'lang' => $lang,
+                            'studio' => $studioName,
+                            'anthologyId' => $anthologyId,
+                        ]);
+                    if ($response->ok()) {
                         $this->info('dir create ok title='.$currDir);
                         $dirId = $response->json('data.uid');
-                    }else{
+                    } else {
                         $this->error('create dir fail.'.$currDir);
                         Log::error('create dir fail title='.$currDir);
                         $fail++;
+
                         continue;
                     }
                 }
-                //创建目录结束
-                if(!isset($articleMap[$dirId])){
-                    $articleMap[$dirId] = ['name'=>$currDir,'children'=>[]];
+                // 创建目录结束
+                if (! isset($articleMap[$dirId])) {
+                    $articleMap[$dirId] = ['name' => $currDir, 'children' => []];
                 }
-                //查找文章
-                $article = Article::where('owner',$srcStudioId)
-                              ->where('title',$realTitle)
-                              ->first();
-                if(!$article){
+                // 查找文章
+                $article = Article::where('owner', $srcStudioId)
+                    ->where('title', $realTitle)
+                    ->first();
+                if (! $article) {
                     $this->error('文章没找到.'.$realTitle);
                     Log::error('文章没找到 title='.$realTitle);
                     $fail++;
+
                     continue;
                 }
                 $articleMap[$dirId]['children'][] = [
-                    'id'=>$article->uid,
-                    'title'=>$article->title,
+                    'id' => $article->uid,
+                    'title' => $article->title,
                 ];
-                if($this->option('size')){
-                    $currSize += mb_strlen($title,'UTF-8') +
-                                mb_strlen($data[4],'UTF-8') +
-                                mb_strlen($reference,'UTF-8');
+                if ($this->option('size')) {
+                    $currSize += mb_strlen($title, 'UTF-8') +
+                                mb_strlen($data[4], 'UTF-8') +
+                                mb_strlen($reference, 'UTF-8');
                 }
                 $success++;
             }
             $inputRow++;
         }
-        $this->info("找到文章=" .$success);
-        $this->info("目录=" .count($articleMap));
+        $this->info('找到文章='.$success);
+        $this->info('目录='.count($articleMap));
 
         $this->info('正在准备map数据');
 
-        $data = array();
+        $data = [];
         foreach ($articleMap as $dirId => $dir) {
             $data[] = [
-                    'article_id'=> $dirId,
-                    'level'=> 1,
-                    'title'=> $dir['name'],
-                    'children'=> count($dir['children']),
-                    'deleted_at'=> null,
+                'article_id' => $dirId,
+                'level' => 1,
+                'title' => $dir['name'],
+                'children' => count($dir['children']),
+                'deleted_at' => null,
             ];
             foreach ($dir['children'] as $key => $child) {
                 $data[] = [
-                        'article_id'=> $child['id'],
-                        'level'=> 2,
-                        'title'=> $child['title'],
-                        'children'=> 0,
-                        'deleted_at'=> null,
+                    'article_id' => $child['id'],
+                    'level' => 2,
+                    'title' => $child['title'],
+                    'children' => 0,
+                    'deleted_at' => null,
                 ];
             }
         }
         $this->info('map data='.count($data));
 
-        //目录写入db
+        // 目录写入db
         $url = config('app.url').'/api/v2/article-map/'.$anthologyId;
         $response = Http::withToken($token)->put($url,
-        [
-            'data'=> $data,
-            'operation' => "anthology",
-        ]);
-        if($response->ok()){
+            [
+                'data' => $data,
+                'operation' => 'anthology',
+            ]);
+        if ($response->ok()) {
             $this->info('map update ok ');
-        }else{
+        } else {
             $this->error('map update  fail.');
             Log::error('map update  fail ');
         }
+
         return 0;
     }
 }

+ 1 - 2
api-v13/app/Console/Commands/IndexOpenSearch.php

@@ -2,11 +2,10 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Services\OpenSearchService;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\App;
 
-
 class IndexOpenSearch extends Command
 {
     /**

+ 1 - 1
api-v13/app/Console/Commands/IndexTerm.php

@@ -163,7 +163,7 @@ class IndexTerm extends Command
 
         if ($this->isTest) {
             $this->info($document['title']['text']['pali']);
-            //$this->info($document['summary']['text']);
+            // $this->info($document['summary']['text']);
         } else {
             $this->openSearchService->create($document['id'], $document);
         }

+ 60 - 62
api-v13/app/Console/Commands/IndexTipitaka.php

@@ -2,23 +2,24 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Services\SearchPaliDataService;
+use App\Http\Api\ChannelApi;
+use App\Models\PaliText;
+use App\Models\ProgressChapter;
+use App\Models\Sentence;
 use App\Services\OpenSearchService;
+use App\Services\PaliContentService;
+use App\Services\SearchPaliDataService;
 use App\Services\SummaryService;
 use App\Services\TagService;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
-use App\Models\PaliText;
-use App\Models\Sentence;
-use App\Services\PaliContentService;
-use App\Http\Api\ChannelApi;
-use App\Models\ProgressChapter;
 
 class IndexTipitaka extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan opensearch:index-tipitaka 93 --para=6 --granularity=paragraph
+     *
      * @var string
      */
     protected $signature = 'opensearch:index-tipitaka
@@ -37,8 +38,8 @@ class IndexTipitaka extends Command
      */
     protected $description = 'Index Pali data into OpenSearch for a specified book and optional granularity (all granularities if not specified)';
 
-
     private $isTest = false;
+
     private $summary = false;
 
     /**
@@ -63,11 +64,11 @@ class IndexTipitaka extends Command
     public function handle()
     {
         $this->line('index tipitaka start');
-        $book = (int)$this->argument('book');
+        $book = (int) $this->argument('book');
         $paragraph = $this->option('para');
         $channel = $this->option('channel');
         if ($channel) {
-            $this->line('channel=' . $channel);
+            $this->line('channel='.$channel);
         }
         $granularity = $this->option('granularity');
         $this->summary = $this->option('summary') === 'on';
@@ -77,20 +78,20 @@ class IndexTipitaka extends Command
             $this->info('test mode');
         }
 
-
         try {
             // Test OpenSearch connection
             [$connected, $message] = $this->openSearchService->testConnection();
-            if (!$connected) {
+            if (! $connected) {
                 $this->error($message);
                 Log::error($message);
+
                 return 1;
             }
             $overallStatus = 0; // Track overall command status (0 for success, 1 for any failure)
             $maxBookId = PaliText::max('book');
             if ($book === 0) {
                 $booksId = range(1, $maxBookId);
-            } else if ($this->option('resume')) {
+            } elseif ($this->option('resume')) {
                 $booksId = range($book, $maxBookId);
             } else {
                 $booksId = [$book];
@@ -112,8 +113,9 @@ class IndexTipitaka extends Command
 
             return $overallStatus;
         } catch (\Exception $e) {
-            $this->error("Failed to index Pali data: " . $e->getMessage());
-            Log::error("Failed to index Pali data for book: $book, granularity: " . ($granularity ?: 'all'), ['error' => $e]);
+            $this->error('Failed to index Pali data: '.$e->getMessage());
+            Log::error("Failed to index Pali data for book: $book, granularity: ".($granularity ?: 'all'), ['error' => $e]);
+
             return 1;
         }
     }
@@ -121,7 +123,7 @@ class IndexTipitaka extends Command
     /**
      * Index Pali paragraphs for a given book.
      *
-     * @param int $book
+     * @param  int  $book
      * @return int
      */
     protected function indexTipitakaParagraph($book, $paragraph = null)
@@ -152,12 +154,12 @@ class IndexTipitaka extends Command
             }
             $paraContent = $this->searchPaliDataService
                 ->getParaContent($para['book'], $para['paragraph']);
-            if (!empty($commentaryId)) {
+            if (! empty($commentaryId)) {
                 $currSession[] = $paraContent;
             }
             if (isset($paraContent['commentary'])) {
-                if (!empty($commentaryId)) {
-                    //保存 session
+                if (! empty($commentaryId)) {
+                    // 保存 session
                     $this->indexPaliSession($para->toArray(), $currSession, $currChapterTitle, $commentaryId);
                     $currSession = [];
                 }
@@ -172,12 +174,10 @@ class IndexTipitaka extends Command
 
         return 0;
     }
-    /**
-     *
-     */
+
     protected function indexParagraph($paraInfo, $paraContent, $related_id, array $category)
     {
-        $paraId = $paraInfo['book'] . '-' . $paraInfo['paragraph'];
+        $paraId = $paraInfo['book'].'-'.$paraInfo['paragraph'];
         $resource_id = $paraInfo['uid'];
         $path = json_decode($paraInfo['path']);
         if (is_array($path) && count($path) > 0) {
@@ -190,10 +190,10 @@ class IndexTipitaka extends Command
             'resource_id' => $resource_id, // Use uid from getPaliData for resource_id
             'resource_type' => 'tipitaka',
             'title' => [
-                'text' => ['pali' => $title,],
+                'text' => ['pali' => $title],
             ],
             'summary' => [
-                'text' => $this->summary  ? $this->summaryService->summarize($paraContent['markdown']) : ''
+                'text' => $this->summary ? $this->summaryService->summarize($paraContent['markdown']) : '',
             ],
             'content' => [
                 'text' => ['pali' => $paraContent['text']],
@@ -217,12 +217,9 @@ class IndexTipitaka extends Command
         } else {
             $this->openSearchService->create($document['id'], $document);
         }
-        return;
+
     }
 
-    /**
-     *
-     */
     protected function indexPaliSession($paraInfo, $contents, $currChapter, $related_id)
     {
         $markdown = [];
@@ -240,17 +237,17 @@ class IndexTipitaka extends Command
             'resource_id' => $paraInfo['uid'], // Use uid from getPaliData for resource_id
             'resource_type' => 'original_text',
             'title' => [
-                ['text' => ['pali' => "{$currChapter} paragraph {$paraInfo['paragraph']}"]]
+                ['text' => ['pali' => "{$currChapter} paragraph {$paraInfo['paragraph']}"]],
 
             ],
             'summary' => [
-                'text' => $this->summary ? $this->summaryService->summarize($content['markdown']) : ''
+                'text' => $this->summary ? $this->summaryService->summarize($content['markdown']) : '',
             ],
             'content' => [
-                ['text' => ['pali' => implode("\n\n", $markdown)]]
+                ['text' => ['pali' => implode("\n\n", $markdown)]],
             ],
-            'bold_single' => implode(" ", $bold_single),
-            'bold_multi' => implode(" ", $bold_multi),
+            'bold_single' => implode(' ', $bold_single),
+            'bold_multi' => implode(' ', $bold_multi),
             'related_id' => $related_id,
             'category' => 'pali', // Assuming Pali paragraphs are sutta; adjust as needed
             'language' => 'pi',
@@ -264,16 +261,14 @@ class IndexTipitaka extends Command
         } else {
             $this->openSearchService->create($document['id'], $document);
         }
-        return;
-    }
-
 
+    }
 
     /**
      * Index Pali suttas for a given book (placeholder for future implementation).
      *
-     * @param int $book
-     * @param ?string $channel
+     * @param  int  $book
+     * @param  ?string  $channel
      * @return int
      */
     protected function indexChapter($book, $channelId = null)
@@ -299,7 +294,7 @@ class IndexTipitaka extends Command
             } else {
                 $end = $chapters[$key + 1]->paragraph - 1;
             }
-            //获取这个段落之间的全部channel
+            // 获取这个段落之间的全部channel
             $table = Sentence::where('book_id', $book)
                 ->whereBetween('paragraph', [$start, $end]);
             if ($channelId) {
@@ -314,13 +309,15 @@ class IndexTipitaka extends Command
                 $display = [];
                 $content = [];
                 $channelInfo = ChannelApi::getById($channel->channel_uid);
-                if (!$channelInfo) {
+                if (! $channelInfo) {
                     Log::error('invalid channel', ['id' => $channel->channel_uid]);
+
                     continue;
                 }
-                $this->info('channel =' . $channelInfo['name']);
+                $this->info('channel ='.$channelInfo['name']);
                 if ($channelInfo['type'] === 'wbw') {
                     $this->info('wbw channel skip');
+
                     continue;
                 }
                 $paragraphsData = app(PaliContentService::class)->paragraphs(
@@ -330,20 +327,20 @@ class IndexTipitaka extends Command
                     [$channel->channel_uid],
                     ['mode' => 'read', 'format' => 'html', 'original' => false]
                 );
-                //生成html数据
+                // 生成html数据
 
                 $title = '';
                 foreach ($paragraphsData as $paragraph) {
                     $translation = [];
                     $original = [];
-                    foreach ($paragraph['children'] as  $sent) {
+                    foreach ($paragraph['children'] as $sent) {
                         $sid = "{$sent['book']}-{$sent['para']}-{$sent['wordStart']}-{$sent['wordEnd']}";
                         if (isset($sent['translation'])) {
-                            foreach ($sent['translation'] as  $tran) {
+                            foreach ($sent['translation'] as $tran) {
                                 if ($tran['channel']['id'] === $channel->channel_uid) {
                                     $html = $tran['html'] ?? $tran['content'];
                                     $translation[] = "<div class='sentence' data-sid='{$sid}'>{$html}</div>";
-                                    if ($tran['para'] === $start && !empty($html)) {
+                                    if ($tran['para'] === $start && ! empty($html)) {
                                         $title = $html;
                                     }
                                 }
@@ -354,11 +351,11 @@ class IndexTipitaka extends Command
                             is_array($sent['origin']) ||
                             count($sent['origin']) > 0
                         ) {
-                            foreach ($sent['origin'] as  $origin) {
+                            foreach ($sent['origin'] as $origin) {
                                 if ($origin['channel']['id'] === $channel->channel_uid) {
                                     $html = $origin['html'] ?? $origin['content'];
                                     $original[] = "<div class='sentence origin'  data-sid='{$sid}'>{$html}</div>";
-                                    if (empty($title) && $origin['para'] === $start && !empty($html)) {
+                                    if (empty($title) && $origin['para'] === $start && ! empty($html)) {
                                         $title = $html;
                                     }
                                 }
@@ -391,12 +388,11 @@ class IndexTipitaka extends Command
                     'channel' => $channel->channel_uid,
                     'content' => implode('', $display),
                     'title' => strip_tags($title),
-                    'cat' => $category ?? null
+                    'cat' => $category ?? null,
                 ]);
             }
         }
 
-
         return 0;
     }
 
@@ -408,18 +404,18 @@ class IndexTipitaka extends Command
             ->first();
         $channel = ChannelApi::getById($param['channel']);
         $document = [
-            'id'            => "tipitaka_chapter_{$param['book']}-{$param['para']}_{$param['channel']}",
-            'resource_id'   => $progress ? $progress->uid : "{$param['book']}-{$param['para']}_{$param['channel']}",
+            'id' => "tipitaka_chapter_{$param['book']}-{$param['para']}_{$param['channel']}",
+            'resource_id' => $progress ? $progress->uid : "{$param['book']}-{$param['para']}_{$param['channel']}",
             'resource_type' => 'tipitaka',
-            'title'         => [],
+            'title' => [],
             'summary' => [
                 'text' => '',
             ],
-            'content'     => [],
-            'related_id'  => "{$param['book']}-{$param['para']}",
-            'category'    => $param['cat'],
-            'language'    => $channel['lang'],
-            'updated_at'  => now()->toIso8601String(),
+            'content' => [],
+            'related_id' => "{$param['book']}-{$param['para']}",
+            'category' => $param['cat'],
+            'language' => $channel['lang'],
+            'updated_at' => now()->toIso8601String(),
             'granularity' => $param['level'] === 1 ? 'book' : 'chapter',
         ];
 
@@ -433,35 +429,37 @@ class IndexTipitaka extends Command
             $document['content']['text']['pali'] = $plainText;
             $document['title']['text']['pali'] = $title;
         }
-        $document['content']['display']    = $param['content'];             // 展示
+        $document['content']['display'] = $param['content'];             // 展示
 
         if ($this->isTest) {
             $this->info($param['content']);
         } else {
             $this->openSearchService->create($document['id'], $document);
-            $this->info("create index {$document['id']} size=" . strlen($param['content']));
+            $this->info("create index {$document['id']} size=".strlen($param['content']));
         }
     }
+
     /**
      * Index Pali sentences for a given book (placeholder for future implementation).
      *
-     * @param int $book
+     * @param  int  $book
      * @return int
      */
     protected function indexPaliSentences($book)
     {
         $this->warn("Sentence indexing is not yet implemented for book: $book");
         Log::warning("Sentence indexing not implemented for book: $book");
+
         return 1;
     }
 
-
     private function getPathTitle(array $input)
     {
         $output = [];
         foreach ($input as $key => $node) {
             $output[] = $node->title;
         }
+
         return implode('/', $output);
     }
 }

+ 16 - 14
api-v13/app/Console/Commands/InitCommentary.php

@@ -2,19 +2,20 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Models\Tag;
-use App\Models\TagMap;
-use App\Models\PaliText;
-use App\Models\PaliSentence;
 use App\Models\Commentary;
+use App\Models\PaliSentence;
+use App\Models\PaliText;
 use App\Models\RelatedParagraph;
+use App\Models\Tag;
+use App\Models\TagMap;
+use Illuminate\Console\Command;
 
 class InitCommentary extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan init:commentary
+     *
      * @var string
      */
     protected $signature = 'init:commentary {--book=}';
@@ -43,43 +44,43 @@ class InitCommentary extends Command
      */
     public function handle()
     {
-        //查询注释书标签
+        // 查询注释书标签
         $tags = Tag::whereIn('name', ['aṭṭhakathā', 'ṭīkā'])->select('id')->get();
-        //查询段落编号
+        // 查询段落编号
         $paliId = TagMap::whereIn('tag_id', $tags)
             ->where('table_name', 'pali_texts')
             ->cursor();
         foreach ($paliId as $key => $paraId) {
             $book = PaliText::where('uid', $paraId->anchor_id)
                 ->where('level', 1)->first();
-            if (!$book) {
+            if (! $book) {
                 continue;
             }
             $paragraphs = PaliText::where('book', $book->book)
                 ->whereBetween('paragraph', [$book->paragraph, $book->paragraph + $book->chapter_len - 1])
                 ->get();
             foreach ($paragraphs as $key => $para) {
-                $this->info($para->book . '-' . $para->paragraph);
+                $this->info($para->book.'-'.$para->paragraph);
                 $sentences = PaliSentence::where('book', $para->book)
                     ->where('paragraph', $para->paragraph)
                     ->get();
                 $del = Commentary::where('book1', $para->book)
                     ->where('paragraph1', $para->paragraph)
-                    ->where('owner_id', config("mint.admin.root_uuid"))
+                    ->where('owner_id', config('mint.admin.root_uuid'))
                     ->delete();
                 $csPara = RelatedParagraph::where('book', $para->book)
                     ->where('para', $para->paragraph)
                     ->first();
                 if ($csPara) {
                     foreach ($sentences as $key => $sentence) {
-                        $new = new Commentary();
+                        $new = new Commentary;
                         $new->book1 = $sentence->book;
                         $new->paragraph1 = $sentence->paragraph;
                         $new->start1 = $sentence->word_begin;
                         $new->end1 = $sentence->word_end;
-                        $new->editor_id = config("mint.admin.root_uuid");
-                        $new->owner_id = config("mint.admin.root_uuid");
-                        $new->p_number = $csPara->book_name . '-' . $csPara->para;
+                        $new->editor_id = config('mint.admin.root_uuid');
+                        $new->owner_id = config('mint.admin.root_uuid');
+                        $new->p_number = $csPara->book_name.'-'.$csPara->para;
                         $new->save();
                     }
                 } else {
@@ -88,6 +89,7 @@ class InitCommentary extends Command
             }
         }
         $this->info('all done');
+
         return 0;
     }
 }

+ 39 - 37
api-v13/app/Console/Commands/InitCs6sentence.php

@@ -2,13 +2,13 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
+use App\Http\Api\ChannelApi;
 use App\Models\PaliSentence;
-use App\Models\WbwTemplate;
 use App\Models\Sentence;
+use App\Models\WbwTemplate;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Str;
-use App\Http\Api\ChannelApi;
-
 
 class InitCs6sentence extends Command
 {
@@ -43,32 +43,33 @@ class InitCs6sentence extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $start = time();
         $channelId = ChannelApi::getSysChannel('_System_Pali_VRI_');
         if ($channelId === false) {
             $this->error('no channel');
+
             return 1;
         }
         $this->info($channelId);
         $pali = new PaliSentence;
-        if (!empty($this->argument('book'))) {
+        if (! empty($this->argument('book'))) {
             $pali = $pali->where('book', $this->argument('book'));
         }
-        if (!empty($this->argument('para'))) {
+        if (! empty($this->argument('para'))) {
             $pali = $pali->where('paragraph', $this->argument('para'));
         }
         $bar = $this->output->createProgressBar($pali->count());
         $pali = $pali->select('book', 'paragraph', 'word_begin', 'word_end')->cursor();
         $pageHead = ['M', 'P', 'T', 'V', 'O'];
         foreach ($pali as $value) {
-            # code...
-            $words = WbwTemplate::where("book", $value->book)
-                ->where("paragraph", $value->paragraph)
-                ->where("wid", ">=", $value->word_begin)
-                ->where("wid", "<=", $value->word_end)
+            // code...
+            $words = WbwTemplate::where('book', $value->book)
+                ->where('paragraph', $value->paragraph)
+                ->where('wid', '>=', $value->word_begin)
+                ->where('wid', '<=', $value->word_end)
                 ->orderBy('wid', 'asc')
                 ->get();
             $sent = '';
@@ -76,23 +77,23 @@ class InitCs6sentence extends Command
             $boldCount = 0;
             $lastWord = null;
             foreach ($words as $word) {
-                # code...
-                //if($word->style != "note" && $word->type != '.ctl.')
+                // code...
+                // if($word->style != "note" && $word->type != '.ctl.')
                 if ($word->type != '.ctl.') {
                     if ($lastWord !== null) {
-                        if ($word->real !== "ti") {
+                        if ($word->real !== 'ti') {
 
-                            if (!(empty($word->real) && empty($lastWord->real))) {
-                                #如果不是标点符号,在词的前面加空格 。
-                                $sent .= " ";
+                            if (! (empty($word->real) && empty($lastWord->real))) {
+                                // 如果不是标点符号,在词的前面加空格 。
+                                $sent .= ' ';
                             }
                         }
                     }
 
                     if (strpos($word->word, '{') !== false) {
-                        //一个单词里面含有黑体字的
-                        $paliWord = \str_replace("{", "<strong>", $word->word);
-                        $paliWord = \str_replace("}", "</strong>", $paliWord);
+                        // 一个单词里面含有黑体字的
+                        $paliWord = \str_replace('{', '<strong>', $word->word);
+                        $paliWord = \str_replace('}', '</strong>', $paliWord);
                         $sent .= $paliWord;
                     } else {
                         if ($word->style == 'bld') {
@@ -106,7 +107,7 @@ class InitCs6sentence extends Command
                     if (in_array($type, $pageHead)) {
                         $arrPage = explode('.', $word->word);
                         if (count($arrPage) === 2) {
-                            $pageNumber = $arrPage[0] . '.' . (int)$arrPage[1];
+                            $pageNumber = $arrPage[0].'.'.(int) $arrPage[1];
                             $sent .= "<code>{$pageNumber}</code>";
                         }
                     }
@@ -114,23 +115,23 @@ class InitCs6sentence extends Command
                 $lastWord = $word;
             }
 
-            #将wikipali风格的引用 改为缅文风格
+            // 将wikipali风格的引用 改为缅文风格
             /*
-			$sent = \str_replace('n’’’ ti','’’’nti',$sent);
-			$sent = \str_replace('n’’ ti','’’nti',$sent);
-			$sent = \str_replace('n’ ti','’nti',$sent);
-			$sent = \str_replace('**ti**','**ti',$sent);
-			$sent = \str_replace('‘ ','‘',$sent);
+            $sent = \str_replace('n’’’ ti','’’’nti',$sent);
+            $sent = \str_replace('n’’ ti','’’nti',$sent);
+            $sent = \str_replace('n’ ti','’nti',$sent);
+            $sent = \str_replace('**ti**','**ti',$sent);
+            $sent = \str_replace('‘ ','‘',$sent);
             */
             $sent = \str_replace(' ti', 'ti', $sent);
 
             $newRow = Sentence::firstOrNew(
                 [
-                    "book_id" => $value->book,
-                    "paragraph" => $value->paragraph,
-                    "word_start" => $value->word_begin,
-                    "word_end" => $value->word_end,
-                    "channel_uid" => $channelId,
+                    'book_id' => $value->book,
+                    'paragraph' => $value->paragraph,
+                    'word_start' => $value->word_begin,
+                    'word_end' => $value->word_end,
+                    'channel_uid' => $channelId,
                 ],
                 [
                     'id' => app('snowflake')->id(),
@@ -138,11 +139,11 @@ class InitCs6sentence extends Command
                     'create_time' => time() * 1000,
                 ]
             );
-            $newRow->editor_uid = config("mint.admin.root_uuid");
+            $newRow->editor_uid = config('mint.admin.root_uuid');
             $newRow->content = "<span>{$sent}</span>";
-            $newRow->strlen = mb_strlen($sent, "UTF-8");
+            $newRow->strlen = mb_strlen($sent, 'UTF-8');
             $newRow->status = 10;
-            $newRow->content_type = "html";
+            $newRow->content_type = 'html';
             $newRow->modify_time = time() * 1000;
             $newRow->language = 'en';
             $newRow->save();
@@ -150,7 +151,8 @@ class InitCs6sentence extends Command
             $bar->advance();
         }
         $bar->finish();
-        $this->info("finished " . (time() - $start) . "s");
+        $this->info('finished '.(time() - $start).'s');
+
         return 0;
     }
 }

+ 15 - 13
api-v13/app/Console/Commands/InitDependence.php

@@ -2,9 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
-use Symfony\Component\Process\Process;
 use Symfony\Component\Process\Exception\ProcessFailedException;
+use Symfony\Component\Process\Process;
 
 class InitDependence extends Command
 {
@@ -39,20 +40,21 @@ class InitDependence extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		#克隆依赖的数据仓库到本地
-		$depDir = $this->info(config("mint.path.dependence"));
-		foreach ($this->info(config("mint.dependence")) as $key => $value) {
-			# code...
-			$process = new Process(['git','clone',$value->url,$depDir.'/'.$value->path]);
-			$process->run();
-			if(!$process->isSuccessful()){
-				throw new ProcessFailedException($process);
-			}
-			$this->info($process->getOutput());
-		}
+        // 克隆依赖的数据仓库到本地
+        $depDir = $this->info(config('mint.path.dependence'));
+        foreach ($this->info(config('mint.dependence')) as $key => $value) {
+            // code...
+            $process = new Process(['git', 'clone', $value->url, $depDir.'/'.$value->path]);
+            $process->run();
+            if (! $process->isSuccessful()) {
+                throw new ProcessFailedException($process);
+            }
+            $this->info($process->getOutput());
+        }
+
         return 0;
     }
 }

+ 12 - 11
api-v13/app/Console/Commands/InitSystemDict.php

@@ -3,6 +3,7 @@
 namespace App\Console\Commands;
 
 use App\Models\DictInfo;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 
 class InitSystemDict extends Command
@@ -11,7 +12,7 @@ class InitSystemDict extends Command
      * The name and signature of the console command.
      *
      * @var string
-     * php artisan init:system.dict
+     *             php artisan init:system.dict
      */
     protected $signature = 'init:system.dict';
 
@@ -27,35 +28,35 @@ class InitSystemDict extends Command
      */
     protected $dictionary = [
         [
-            "name" => 'robot_compound',
+            'name' => 'robot_compound',
             'shortname' => 'compound',
             'description' => 'split compound by AI',
             'src_lang' => 'pa',
             'dest_lang' => 'cm',
         ],
         [
-            "name" => 'system_regular',
+            'name' => 'system_regular',
             'shortname' => 'regular',
             'description' => 'system regular',
             'src_lang' => 'pa',
             'dest_lang' => 'cm',
         ],
         [
-            "name" => 'community',
+            'name' => 'community',
             'shortname' => '社区',
             'description' => '由用户贡献词条的社区字典',
             'src_lang' => 'pa',
             'dest_lang' => 'cm',
         ],
         [
-            "name" => 'community_extract',
+            'name' => 'community_extract',
             'shortname' => '社区汇总',
             'description' => '由用户贡献词条的社区字典汇总统计',
             'src_lang' => 'pa',
             'dest_lang' => 'cm',
         ],
         [
-            "name" => 'system_preference',
+            'name' => 'system_preference',
             'shortname' => '系统单词首选项',
             'description' => '通过系统筛选出的首选项,只包含语法信息',
             'src_lang' => 'pa',
@@ -80,15 +81,15 @@ class InitSystemDict extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $this->info("init:system.dict start");
+        $this->info('init:system.dict start');
         foreach ($this->dictionary as $key => $value) {
-            # code...
+            // code...
             $channel = DictInfo::firstOrNew([
                 'name' => $value['name'],
-                'owner_id' => config("mint.admin.root_uuid"),
+                'owner_id' => config('mint.admin.root_uuid'),
             ]);
             $channel->shortname = $value['shortname'];
             $channel->description = $value['description'];
@@ -98,7 +99,7 @@ class InitSystemDict extends Command
             $channel->save();
             $this->line("updated {$value['name']}");
         }
-        $this->info("init:system.dict successful");
+        $this->info('init:system.dict successful');
 
         return 0;
     }

+ 18 - 18
api-v13/app/Console/Commands/Install.php

@@ -2,6 +2,7 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 
 class Install extends Command
@@ -35,31 +36,30 @@ class Install extends Command
      *
      * @return int
      */
-
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$isTest = $this->option('test');
-		if($isTest){
-			$this->call('install:wbwtemplate', ['from' => 1]);
-		}else{
-			$this->call('install:wbwtemplate');
-			$this->call('install:palitext');
-			$this->call('install:wordbook');
-			$this->call('install:wordall');
-			$this->call('install:wordindex');
+        $isTest = $this->option('test');
+        if ($isTest) {
+            $this->call('install:wbwtemplate', ['from' => 1]);
+        } else {
+            $this->call('install:wbwtemplate');
+            $this->call('install:palitext');
+            $this->call('install:wordbook');
+            $this->call('install:wordall');
+            $this->call('install:wordindex');
 
-			$this->call('upgrade:palitext');
-			$this->call('upgrade:palitoc',['lang'=>'pali']);
-			$this->call('upgrade:palitoc',['lang'=>'zh-hans']);
-			$this->call('upgrade:palitoc',['lang'=>'zh-hant']);
+            $this->call('upgrade:palitext');
+            $this->call('upgrade:palitoc', ['lang' => 'pali']);
+            $this->call('upgrade:palitoc', ['lang' => 'zh-hans']);
+            $this->call('upgrade:palitoc', ['lang' => 'zh-hant']);
 
-			$this->call('install:paliseries');
-			$this->call('install:wordstatistics');
+            $this->call('install:paliseries');
+            $this->call('install:wordstatistics');
 
-		}
+        }
 
         return 0;
     }

+ 36 - 34
api-v13/app/Console/Commands/InstallPaliSeries.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\BookTitle;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,44 +41,45 @@ class InstallPaliSeries extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$this->info("upgrade pali serieses");
-		$startTime = time();
+        $this->info('upgrade pali serieses');
+        $startTime = time();
+
+        DB::transaction(function () {
+            // 删除目标数据库中数据
+            BookTitle::where('book', '>', 0)->delete();
 
-		DB::transaction(function () {
-			#删除目标数据库中数据
-			BookTitle::where('book','>',0)->delete();
+            // 打开csv文件并读取数据
+            $strFileName = config('mint.path.pali_title').'/pali_serieses.csv';
+            if (! file_exists($strFileName)) {
+                return 1;
+            }
+            $inputRow = 0;
+            if (($fp = fopen($strFileName, 'r')) !== false) {
+                while (($data = fgetcsv($fp, 0, ',')) !== false) {
+                    if ($inputRow > 0) {
+                        $newData = [
+                            'sn' => $data[0],
+                            'book' => $data[1],
+                            'paragraph' => $data[2],
+                            'title' => $data[3],
+                        ];
 
-		// 打开csv文件并读取数据
-			$strFileName = config("mint.path.pali_title") . "/pali_serieses.csv";
-			if(!file_exists($strFileName)){
-				return 1;
-			}
-			$inputRow = 0;
-			if (($fp = fopen($strFileName, "r")) !== false) {
-				while (($data = fgetcsv($fp, 0, ',')) !== false) {
-					if($inputRow>0){
-						$newData = [
-							'sn'=>$data[0],
-							'book'=>$data[1],
-							'paragraph'=>$data[2],
-							'title'=>$data[3],
-						];
+                        BookTitle::create($newData);
+                    }
+                    $inputRow++;
+                }
+                fclose($fp);
+                Log::info('res load:'.$strFileName);
+            } else {
+                $this->error("can not open csv $strFileName");
+                Log::error("can not open csv $strFileName");
+            }
+        });
+        $this->info('ok');
 
-						BookTitle::create($newData);
-					}
-					$inputRow++;
-				}
-				fclose($fp);
-				Log::info("res load:" .$strFileName);
-			} else {
-				$this->error("can not open csv $strFileName");
-				Log::error("can not open csv $strFileName");
-			}
-		});
-		$this->info("ok");
         return 0;
     }
 }

+ 107 - 108
api-v13/app/Console/Commands/InstallPaliText.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\PaliText;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,115 +41,113 @@ class InstallPaliText extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$this->info("instert pali text");
-		$startTime = time();
-
-		$_from = $this->argument('from');
-		$_to = $this->argument('to');
-		if(empty($_from) && empty($_to)){
-			$_from = 1;
-			$_to = 217;
-		}else if(empty($_to)){
-			$_to = $_from;
-		}
-		$fileListFileName = config("mint.path.palitext_filelist");
-
-		$filelist = array();
-
-		if (($handle = fopen($fileListFileName, 'r')) !== false) {
-			while (($filelist[] = fgetcsv($handle, 0, ',')) !== false) {
-			}
-		}
-		$bar = $this->output->createProgressBar($_to-$_from+1);
-
-		for ($from=$_from; $from <=$_to ; $from++) {
-			# code...
-
-			$fileSn = $from-1;
-			$FileName = $filelist[$fileSn][1];
-
-			$dirXmlBase = config("mint.path.palicsv") . "/";
-			$GLOBALS['data'] = array();
-
-			// 打开vri html文件并读取数据
-			$pali_text_array = array();
-			$htmlFile = config("mint.path.palitext") .'/'. $FileName.'.htm';
-			if (($fpPaliText = fopen($htmlFile, "r")) !== false) {
-				while (($data = fgets($fpPaliText)) !== false) {
-					if (substr($data, 0, 2) === "<p") {
-						array_push($pali_text_array, $data);
-					}
-				}
-				fclose($fpPaliText);
-				//$this->info("pali text load:" . $htmlFile . PHP_EOL);
-			} else {
-				$this->error( "can not pali text file. filename=" . $htmlFile . PHP_EOL) ;
-				Log::error( "can not pali text file. filename=" . $htmlFile . PHP_EOL) ;
-			}
-
-			$inputRow = 0;
-			$csvFile = config("mint.path.palicsv") .'/'. $FileName .'/'. $FileName.'_pali.csv';
-			if (($fp = fopen($csvFile, "r")) !== false) {
-				while (($data = fgetcsv($fp, 0, ',')) !== false) {
-					if ($inputRow > 0) {
-						if (($inputRow - 1) < count($pali_text_array)) {
-							$data[5] = $pali_text_array[$inputRow - 1];
-						}
-						$data[1] = mb_substr($data[1],1,null,"UTF-8");
-						$GLOBALS['data'][] = $data;
-					}
-					$inputRow++;
-				}
-				fclose($fp);
-				//$this->info("单词表load:" . $csvFile.PHP_EOL);
-			} else {
-				$this->error( "can not open csv file. filename=" . $csvFile. PHP_EOL) ;
-				Log::error( "can not open csv file. filename=" . $csvFile. PHP_EOL) ;
-				continue;
-			}
-
-			if (($inputRow - 1) != count($pali_text_array)) {
-				$this->error( "line count error $FileName ".PHP_EOL);
-				Log::error( "line count error $FileName ".PHP_EOL);
-			}
-
-
-			#删除目标数据库中数据
-			PaliText::where('book', $from)->delete();
-
-
-			// 打开文件并读取数据
-
-
-			DB::transaction(function () {
-				foreach ($GLOBALS['data'] as $oneParam) {
-					if ($oneParam[3] < 100) {
-						$toc = $oneParam[6];
-					} else {
-						$toc = "";
-					}
-					$params = [
-						'book'=>$oneParam[1],
-						'paragraph'=>$oneParam[2],
-						'level'=>$oneParam[3],
-						'class'=> $oneParam[4],
-						'toc'=>$toc,
-						'text'=>$oneParam[6],
-						'html'=>$oneParam[5],
-						'lenght'=>mb_strlen($oneParam[6], "UTF-8"),
-					];
-					PaliText::create($params);
-				}
-
-			});
-
-			$bar->advance();
-		}
-		$bar->finish();
-		$this->info("instert pali text finished. in ". time()-$startTime . "s" .PHP_EOL);
+        $this->info('instert pali text');
+        $startTime = time();
+
+        $_from = $this->argument('from');
+        $_to = $this->argument('to');
+        if (empty($_from) && empty($_to)) {
+            $_from = 1;
+            $_to = 217;
+        } elseif (empty($_to)) {
+            $_to = $_from;
+        }
+        $fileListFileName = config('mint.path.palitext_filelist');
+
+        $filelist = [];
+
+        if (($handle = fopen($fileListFileName, 'r')) !== false) {
+            while (($filelist[] = fgetcsv($handle, 0, ',')) !== false) {
+            }
+        }
+        $bar = $this->output->createProgressBar($_to - $_from + 1);
+
+        for ($from = $_from; $from <= $_to; $from++) {
+            // code...
+
+            $fileSn = $from - 1;
+            $FileName = $filelist[$fileSn][1];
+
+            $dirXmlBase = config('mint.path.palicsv').'/';
+            $GLOBALS['data'] = [];
+
+            // 打开vri html文件并读取数据
+            $pali_text_array = [];
+            $htmlFile = config('mint.path.palitext').'/'.$FileName.'.htm';
+            if (($fpPaliText = fopen($htmlFile, 'r')) !== false) {
+                while (($data = fgets($fpPaliText)) !== false) {
+                    if (substr($data, 0, 2) === '<p') {
+                        array_push($pali_text_array, $data);
+                    }
+                }
+                fclose($fpPaliText);
+                // $this->info("pali text load:" . $htmlFile . PHP_EOL);
+            } else {
+                $this->error('can not pali text file. filename='.$htmlFile.PHP_EOL);
+                Log::error('can not pali text file. filename='.$htmlFile.PHP_EOL);
+            }
+
+            $inputRow = 0;
+            $csvFile = config('mint.path.palicsv').'/'.$FileName.'/'.$FileName.'_pali.csv';
+            if (($fp = fopen($csvFile, 'r')) !== false) {
+                while (($data = fgetcsv($fp, 0, ',')) !== false) {
+                    if ($inputRow > 0) {
+                        if (($inputRow - 1) < count($pali_text_array)) {
+                            $data[5] = $pali_text_array[$inputRow - 1];
+                        }
+                        $data[1] = mb_substr($data[1], 1, null, 'UTF-8');
+                        $GLOBALS['data'][] = $data;
+                    }
+                    $inputRow++;
+                }
+                fclose($fp);
+                // $this->info("单词表load:" . $csvFile.PHP_EOL);
+            } else {
+                $this->error('can not open csv file. filename='.$csvFile.PHP_EOL);
+                Log::error('can not open csv file. filename='.$csvFile.PHP_EOL);
+
+                continue;
+            }
+
+            if (($inputRow - 1) != count($pali_text_array)) {
+                $this->error("line count error $FileName ".PHP_EOL);
+                Log::error("line count error $FileName ".PHP_EOL);
+            }
+
+            // 删除目标数据库中数据
+            PaliText::where('book', $from)->delete();
+
+            // 打开文件并读取数据
+
+            DB::transaction(function () {
+                foreach ($GLOBALS['data'] as $oneParam) {
+                    if ($oneParam[3] < 100) {
+                        $toc = $oneParam[6];
+                    } else {
+                        $toc = '';
+                    }
+                    $params = [
+                        'book' => $oneParam[1],
+                        'paragraph' => $oneParam[2],
+                        'level' => $oneParam[3],
+                        'class' => $oneParam[4],
+                        'toc' => $toc,
+                        'text' => $oneParam[6],
+                        'html' => $oneParam[5],
+                        'lenght' => mb_strlen($oneParam[6], 'UTF-8'),
+                    ];
+                    PaliText::create($params);
+                }
+
+            });
+
+            $bar->advance();
+        }
+        $bar->finish();
+        $this->info('instert pali text finished. in '.time() - $startTime.'s'.PHP_EOL);
 
         return 0;
 

+ 71 - 72
api-v13/app/Console/Commands/InstallWbwTemplate.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\WbwTemplate;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,79 +41,77 @@ class InstallWbwTemplate extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$this->info("instert wbw template");
-
-
-		$_from = $this->argument('from');
-		$_to = $this->argument('to');
-		if(empty($_from) && empty($_to)){
-			$_from = 1;
-			$_to = 217;
-		}else if(empty($_to)){
-			$_to = $_from;
-		}
-		$fileListFileName = public_path('/palihtml/filelist.csv');
-
-		$filelist = array();
-
-		if (($handle = fopen($fileListFileName, 'r')) !== false) {
-			while (($filelist[] = fgetcsv($handle, 0, ',')) !== false) {
-			}
-		}
-		$bar = $this->output->createProgressBar($_to-$_from+1);
-
-		for ($from=$_from; $from <=$_to ; $from++) {
-			# code...
-
-			$fileSn = $from-1;
-			$outputFileNameHead = $filelist[$fileSn][1];
-
-			$dirXmlBase = public_path('/tmp/palicsv') . "/";
-			$dirXml = $outputFileNameHead . "/";
-
-
-			#删除目标数据库中数据
-			WbwTemplate::where('book', $from)->delete();
-
-
-			// 打开文件并读取数据
-
-			if (($GLOBALS["fp"] = fopen($dirXmlBase . $dirXml . $outputFileNameHead . ".csv", "r")) !== false) {
-				$GLOBALS["row"]=0;
-				DB::transaction(function () {
-					while (($data = fgetcsv($GLOBALS["fp"], 0, ',')) !== false) {
-						$GLOBALS["row"]++;
-						if($GLOBALS["row"]==1){
-							continue;
-						}
-						#或略第一行 标题行
-						$params = [
-							'book'=>mb_substr($data[2], 1),
-							'paragraph'=>$data[3],
-							'wid'=>$data[16],
-							'word'=>$data[4],
-							'real'=>$data[5],
-							'type'=>$data[6],
-							'gramma'=>$data[7],
-							'part'=>$data[10],
-							'style'=>$data[15]
-						];
-						WbwTemplate::insert($params);
-					}
-				});
-				fclose($GLOBALS["fp"]);
-			} else {
-				$this->error("can not open csv file. filename=" . $dirXmlBase . $dirXml . $outputFileNameHead . ".csv".PHP_EOL) ;
-				Log::error("can not open csv file. filename=" . $dirXmlBase . $dirXml . $outputFileNameHead . ".csv".PHP_EOL) ;
-			}
-
-			$bar->advance();
-		}
-		$bar->finish();
+        $this->info('instert wbw template');
+
+        $_from = $this->argument('from');
+        $_to = $this->argument('to');
+        if (empty($_from) && empty($_to)) {
+            $_from = 1;
+            $_to = 217;
+        } elseif (empty($_to)) {
+            $_to = $_from;
+        }
+        $fileListFileName = public_path('/palihtml/filelist.csv');
+
+        $filelist = [];
+
+        if (($handle = fopen($fileListFileName, 'r')) !== false) {
+            while (($filelist[] = fgetcsv($handle, 0, ',')) !== false) {
+            }
+        }
+        $bar = $this->output->createProgressBar($_to - $_from + 1);
+
+        for ($from = $_from; $from <= $_to; $from++) {
+            // code...
+
+            $fileSn = $from - 1;
+            $outputFileNameHead = $filelist[$fileSn][1];
+
+            $dirXmlBase = public_path('/tmp/palicsv').'/';
+            $dirXml = $outputFileNameHead.'/';
+
+            // 删除目标数据库中数据
+            WbwTemplate::where('book', $from)->delete();
+
+            // 打开文件并读取数据
+
+            if (($GLOBALS['fp'] = fopen($dirXmlBase.$dirXml.$outputFileNameHead.'.csv', 'r')) !== false) {
+                $GLOBALS['row'] = 0;
+                DB::transaction(function () {
+                    while (($data = fgetcsv($GLOBALS['fp'], 0, ',')) !== false) {
+                        $GLOBALS['row']++;
+                        if ($GLOBALS['row'] == 1) {
+                            continue;
+                        }
+                        // 或略第一行 标题行
+                        $params = [
+                            'book' => mb_substr($data[2], 1),
+                            'paragraph' => $data[3],
+                            'wid' => $data[16],
+                            'word' => $data[4],
+                            'real' => $data[5],
+                            'type' => $data[6],
+                            'gramma' => $data[7],
+                            'part' => $data[10],
+                            'style' => $data[15],
+                        ];
+                        WbwTemplate::insert($params);
+                    }
+                });
+                fclose($GLOBALS['fp']);
+            } else {
+                $this->error('can not open csv file. filename='.$dirXmlBase.$dirXml.$outputFileNameHead.'.csv'.PHP_EOL);
+                Log::error('can not open csv file. filename='.$dirXmlBase.$dirXml.$outputFileNameHead.'.csv'.PHP_EOL);
+            }
+
+            $bar->advance();
+        }
+        $bar->finish();
+
         return 0;
 
-	}
+    }
 }

+ 47 - 44
api-v13/app/Console/Commands/InstallWordAll.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\WordList;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,56 +41,58 @@ class InstallWordAll extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$startTime = time();
+        $startTime = time();
 
-		$this->info("instert word in palibook ");
-		Log::info("instert word in palibook ");
+        $this->info('instert word in palibook ');
+        Log::info('instert word in palibook ');
+
+        $_from = $this->argument('from');
+        $_to = $this->argument('to');
+        if (empty($_from) && empty($_to)) {
+            $_from = 1;
+            $_to = 217;
+        } elseif (empty($_to)) {
+            $_to = $_from;
+        }
 
-		$_from = $this->argument('from');
-		$_to = $this->argument('to');
-		if(empty($_from) && empty($_to)){
-			$_from = 1;
-			$_to = 217;
-		}else if(empty($_to)){
-			$_to = $_from;
-		}
+        $bar = $this->output->createProgressBar($_to - $_from + 1);
 
-		$bar = $this->output->createProgressBar($_to-$_from+1);
+        for ($book = $_from; $book <= $_to; $book++) {
+            Log::info('doing '.($book));
+            DB::transaction(function () use ($book) {
+                $fileSn = $book - 1;
+                if (($fpoutput = fopen(config('mint.path.paliword_book')."/{$fileSn}_words.csv", 'r')) !== false) {
+                    // 删除目标数据库中数据
+                    WordList::where('book', $book)->delete();
+                    while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
+                        $newData = [
+                            'sn' => $data[0],
+                            'book' => $data[1],
+                            'paragraph' => $data[2],
+                            'wordindex' => $data[3],
+                            'bold' => $data[4],
+                        ];
+                        WordList::create($newData);
+                    }
+
+                    return 0;
+                } else {
+                    Log::error('open csv fail');
+
+                    return 1;
+                }
+            });
+            $bar->advance();
+        }
+        $bar->finish();
 
-		for ($book=$_from; $book <= $_to; $book++) {
-			Log::info("doing ".($book));
-			DB::transaction(function ()use($book) {
-				$fileSn = $book-1;
-				if (($fpoutput = fopen(config("mint.path.paliword_book") . "/{$fileSn}_words.csv", "r")) !== false){
-					#删除目标数据库中数据
-					WordList::where('book', $book)->delete();
-					while (($data = fgetcsv($fpoutput, 0, ',')) !== false)
-					{
-						$newData = [
-							'sn'=>$data[0],
-							'book'=>$data[1],
-							'paragraph'=>$data[2],
-							'wordindex'=>$data[3],
-							'bold'=>$data[4],
-						];
-						WordList::create($newData);
-					}
-					return 0;
-				}else{
-					Log::error("open csv fail");
-					return 1;
-				}
-			});
-			$bar->advance();
-		}
-		$bar->finish();
+        $msg = 'all done in '.time() - $startTime.'s';
+        $this->info($msg.PHP_EOL);
+        Log::info($msg);
 
-		$msg = "all done in ". time()-$startTime . "s";
-		$this->info($msg.PHP_EOL);
-		Log::info($msg);
         return 0;
     }
 }

+ 62 - 60
api-v13/app/Console/Commands/InstallWordBook.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\BookWord;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,67 +41,68 @@ class InstallWordBook extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$startTime = time();
-
-		$this->info("instert word in palibook ");
-		Log::info("instert word in palibook ");
-
-		$_from = $this->argument('from');
-		$_to = $this->argument('to');
-		if(empty($_from) && empty($_to)){
-			$_from = 1;
-			$_to = 217;
-		}else if(empty($_to)){
-			$_to = $_from;
-		}
-
-		$bar = $this->output->createProgressBar($_to-$_from+1);
-
-		for ($book=$_from; $book <= $_to; $book++) {
-			Log::info("doing ".($book));
-
-			#删除目标数据库中数据
-			BookWord::where('book', $book)->delete();
-
-			//分类汇总得到单词表
-			$bookword = array();
-			$fileId = $book-1;
-			if (($fpoutput = fopen(config("mint.path.paliword_book") . "/{$fileId}_words.csv", "r")) !== false) {
-				$count = 0;
-				while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
-					$book = $data[1];
-					if (isset($bookword[$data[3]])) {
-						$bookword[$data[3]]++;
-					} else {
-						$bookword[$data[3]] = 1;
-					}
-
-					$count++;
-				}
-			}else{
-				Log::error("open csv fail");
-				continue;
-			}
-			DB::transaction(function ()use($book,$bookword) {
-				foreach ($bookword as $key => $value) {
-					$newData = [
-						'book'=>$book,
-						'wordindex'=>$key,
-						'count'=>$value,
-					];
-					BookWord::create($newData);
-				}
-			});
-			$bar->advance();
-		}
-		$bar->finish();
-
-		$msg = "all done in ". time()-$startTime . "s";
-		$this->info($msg.PHP_EOL);
-		Log::info($msg);
+        $startTime = time();
+
+        $this->info('instert word in palibook ');
+        Log::info('instert word in palibook ');
+
+        $_from = $this->argument('from');
+        $_to = $this->argument('to');
+        if (empty($_from) && empty($_to)) {
+            $_from = 1;
+            $_to = 217;
+        } elseif (empty($_to)) {
+            $_to = $_from;
+        }
+
+        $bar = $this->output->createProgressBar($_to - $_from + 1);
+
+        for ($book = $_from; $book <= $_to; $book++) {
+            Log::info('doing '.($book));
+
+            // 删除目标数据库中数据
+            BookWord::where('book', $book)->delete();
+
+            // 分类汇总得到单词表
+            $bookword = [];
+            $fileId = $book - 1;
+            if (($fpoutput = fopen(config('mint.path.paliword_book')."/{$fileId}_words.csv", 'r')) !== false) {
+                $count = 0;
+                while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
+                    $book = $data[1];
+                    if (isset($bookword[$data[3]])) {
+                        $bookword[$data[3]]++;
+                    } else {
+                        $bookword[$data[3]] = 1;
+                    }
+
+                    $count++;
+                }
+            } else {
+                Log::error('open csv fail');
+
+                continue;
+            }
+            DB::transaction(function () use ($book, $bookword) {
+                foreach ($bookword as $key => $value) {
+                    $newData = [
+                        'book' => $book,
+                        'wordindex' => $key,
+                        'count' => $value,
+                    ];
+                    BookWord::create($newData);
+                }
+            });
+            $bar->advance();
+        }
+        $bar->finish();
+
+        $msg = 'all done in '.time() - $startTime.'s';
+        $this->info($msg.PHP_EOL);
+        Log::info($msg);
 
         return 0;
     }

+ 42 - 40
api-v13/app/Console/Commands/InstallWordIndex.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\WordIndex;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,50 +41,51 @@ class InstallWordIndex extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$startTime = time();
+        $startTime = time();
 
-		$info = "instert word in palibook ";
-		$this->info($info);
-		Log::info($info);
+        $info = 'instert word in palibook ';
+        $this->info($info);
+        Log::info($info);
 
-		#删除目标数据库中数据
-		WordIndex::where('id', '>',-1)->delete();
+        // 删除目标数据库中数据
+        WordIndex::where('id', '>', -1)->delete();
+
+        $scan = scandir(config('mint.path.paliword_index'));
+        $bar = $this->output->createProgressBar(count($scan));
+        foreach ($scan as $filename) {
+            $bar->advance();
+            $filename = config('mint.path.paliword_index').'/'.$filename;
+            if (is_file($filename)) {
+                Log::info('doing '.$filename);
+                DB::transaction(function () use ($filename) {
+                    if (($fpoutput = fopen($filename, 'r')) !== false) {
+                        $count = 0;
+                        while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
+                            $newData = [
+                                'id' => $data[0],
+                                'word' => $data[1],
+                                'word_en' => $data[2],
+                                'normal' => $data[3],
+                                'bold' => $data[4],
+                                'is_base' => $data[5],
+                                'len' => $data[6],
+                            ];
+                            WordIndex::create($newData);
+                            $count++;
+                        }
+                        Log::info('insert '.$count);
+                    }
+                });
+            }
+        }
+        $bar->finish();
+        $msg = 'all done in '.time() - $startTime.'s';
+        Log::info($msg);
+        $this->info($msg);
 
-		$scan = scandir(config("mint.path.paliword_index"));
-		$bar = $this->output->createProgressBar(count($scan));
-		foreach($scan as $filename) {
-			$bar->advance();
-			$filename = config("mint.path.paliword_index")."/".$filename;
-			if (is_file($filename)) {
-				Log::info("doing ".$filename);
-				DB::transaction(function ()use($filename) {
-				if (($fpoutput = fopen($filename, "r")) !== false) {
-						$count = 0;
-						while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
-							$newData = [
-								'id'=>$data[0],
-								'word'=>$data[1],
-								'word_en'=>$data[2],
-								'normal'=>$data[3],
-								'bold'=>$data[4],
-								'is_base'=>$data[5],
-								'len'=>$data[6],
-							];
-							WordIndex::create($newData);
-							$count++;
-						}
-						Log::info("insert ".$count);
-					}
-				});
-			}
-		}
-		$bar->finish();
-		$msg = "all done in ". time()-$startTime . "s";
-		Log::info($msg);
-		$this->info($msg);
         return 0;
     }
 }

+ 44 - 41
api-v13/app/Console/Commands/InstallWordStatistics.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\WordStatistic;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Log;
 
@@ -40,52 +41,54 @@ class InstallWordStatistics extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$startTime = time();
+        $startTime = time();
 
-		$info = "instert wordstatistics ";
-		$this->info($info.PHP_EOL);
-		Log::info($info);
+        $info = 'instert wordstatistics ';
+        $this->info($info.PHP_EOL);
+        Log::info($info);
 
-		#删除目标数据库中数据
-		WordStatistic::where('id', '>',-1)->delete();
+        // 删除目标数据库中数据
+        WordStatistic::where('id', '>', -1)->delete();
+
+        $scan = scandir(config('mint.path.word_statistics'));
+        $bar = $this->output->createProgressBar(count($scan));
+        foreach ($scan as $filename) {
+            $bar->advance();
+            $filename = config('mint.path.word_statistics').'/'.$filename;
+            if (is_file($filename)) {
+                Log::info('doing '.$filename);
+                DB::transaction(function () use ($filename) {
+                    if (($fpoutput = fopen($filename, 'r')) !== false) {
+                        $count = 0;
+                        while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
+                            $newData = [
+                                'bookid' => $data[0],
+                                'word' => $data[1],
+                                'count' => $data[2],
+                                'base' => $data[3],
+                                'end1' => $data[4],
+                                'end2' => $data[5],
+                                'type' => $data[6],
+                                'length' => $data[7],
+                            ];
+                            WordStatistic::create($newData);
+                            $count++;
+                        }
+                        Log::info('insert '.$count);
+                    }
+                });
+            }
+        }
+        $bar->finish();
+        $msg = 'all done in '.time() - $startTime.'s';
+        Log::info($msg);
+        $this->info($msg);
 
-		$scan = scandir(config("mint.path.word_statistics"));
-		$bar = $this->output->createProgressBar(count($scan));
-		foreach($scan as $filename) {
-			$bar->advance();
-			$filename = config("mint.path.word_statistics")."/".$filename;
-			if (is_file($filename)) {
-				Log::info("doing ".$filename);
-				DB::transaction(function ()use($filename) {
-				if (($fpoutput = fopen($filename, "r")) !== false) {
-						$count = 0;
-						while (($data = fgetcsv($fpoutput, 0, ',')) !== false) {
-							$newData = [
-								'bookid'=>$data[0],
-								'word'=>$data[1],
-								'count'=>$data[2],
-								'base'=>$data[3],
-								'end1'=>$data[4],
-								'end2'=>$data[5],
-								'type'=>$data[6],
-								'length'=>$data[7],
-							];
-							WordStatistic::create($newData);
-							$count++;
-						}
-						Log::info("insert ".$count);
-					}
-				});
-			}
-		}
-		$bar->finish();
-		$msg = "all done in ". time()-$startTime . "s";
-		Log::info($msg);
-		$this->info($msg);
         return 0;
+
         return 0;
     }
 }

+ 80 - 71
api-v13/app/Console/Commands/MqAiTranslate.php

@@ -2,18 +2,20 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Facades\Http;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Http\Client\RequestException;
 use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
 
 class MqAiTranslate extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan mq:ai.translate
+     *
      * @var string
      */
     protected $signature = 'mq:ai.translate';
@@ -42,7 +44,7 @@ class MqAiTranslate extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
@@ -51,20 +53,21 @@ class MqAiTranslate extends Command
         Log::debug("mq worker {$queue} start.");
         Mq::worker($exchange, $queue, function ($messages, $messageId) use ($queue) {
             Log::debug('ai translate start', ['message' => count($messages)]);
-            $this->info('ai translate task start task=' . count($messages));
-            if (!is_array($messages) || count($messages) === 0) {
+            $this->info('ai translate task start task='.count($messages));
+            if (! is_array($messages) || count($messages) === 0) {
                 Log::error('message is not array');
+
                 return 1;
             }
 
-            //获取model token
+            // 获取model token
             $first = $messages[0];
             $taskId = $first->task->info->id;
             Cache::put("/task/{$taskId}/message_id", $messageId);
             $pointerKey = "/message/{$messageId}/pointer";
             $pointer = 0;
             if (Cache::has($pointerKey)) {
-                //回到上次中断的点
+                // 回到上次中断的点
                 $pointer = Cache::get($pointerKey);
             }
 
@@ -72,7 +75,7 @@ class MqAiTranslate extends Command
 
             $this->setTaskStatus($first->task->info->id, 'running', $modelToken);
 
-            $discussionUrl = config('app.url') . '/api/v2/discussion';
+            $discussionUrl = config('app.url').'/api/v2/discussion';
             $taskDiscussionData = [
                 'res_id' => $first->task->info->id,
                 'res_type' => 'task',
@@ -84,7 +87,7 @@ class MqAiTranslate extends Command
             ];
             $response = Http::timeout(10)->withToken($modelToken)->post($discussionUrl, $taskDiscussionData);
             if ($response->failed()) {
-                Log::error($queue . ' discussion create topic error', ['data' => $response->json()]);
+                Log::error($queue.' discussion create topic error', ['data' => $response->json()]);
             } else {
                 if (isset($response->json()['data']['id'])) {
                     $taskDiscussionData['parent'] = $response->json()['data']['id'];
@@ -96,22 +99,22 @@ class MqAiTranslate extends Command
                 $message = $messages[$i];
                 $taskDiscussionContent = [];
                 $param = [
-                    "model" => $message->model->model,
-                    "messages" => [
-                        ["role" => "system", "content" => $message->model->system_prompt ?? ''],
-                        ["role" => "user", "content" => $message->prompt],
+                    'model' => $message->model->model,
+                    'messages' => [
+                        ['role' => 'system', 'content' => $message->model->system_prompt ?? ''],
+                        ['role' => 'user', 'content' => $message->prompt],
                     ],
-                    "temperature" => 0.7,
-                    "stream" => false
+                    'temperature' => 0.7,
+                    'stream' => false,
                 ];
-                Log::info($queue . ' LLM request' . $message->model->url);
-                Log::info($queue . ' model:' . $param['model']);
-                Log::debug($queue . ' LLM api request', [
+                Log::info($queue.' LLM request'.$message->model->url);
+                Log::info($queue.' model:'.$param['model']);
+                Log::debug($queue.' LLM api request', [
                     'url' => $message->model->url,
-                    'data' => $param
+                    'data' => $param,
                 ]);
 
-                //写入 model log
+                // 写入 model log
                 $modelLogData = [
                     'model_id' => $message->model->uid,
                     'request_at' => now(),
@@ -125,7 +128,7 @@ class MqAiTranslate extends Command
 
                     $response->throw(); // 触发异常(如果请求失败)
                     $taskDiscussionContent[] = '- LLM request successful';
-                    Log::info($queue . ' LLM request successful');
+                    Log::info($queue.' LLM request successful');
 
                     $modelLogData['request_headers'] = json_encode($response->handlerStats(), JSON_UNESCAPED_UNICODE);
                     $modelLogData['response_headers'] = json_encode($response->headers(), JSON_UNESCAPED_UNICODE);
@@ -140,7 +143,7 @@ class MqAiTranslate extends Command
                     return 1;
                 }*/
                 } catch (RequestException $e) {
-                    Log::error($queue . ' LLM request exception: ' . $e->getMessage());
+                    Log::error($queue.' LLM request exception: '.$e->getMessage());
                     $failResponse = $e->response;
 
                     $modelLogData['request_headers'] = json_encode($failResponse->handlerStats(), JSON_UNESCAPED_UNICODE);
@@ -149,41 +152,41 @@ class MqAiTranslate extends Command
                     $modelLogData['response_data'] = $response->body();
                     $modelLogData['success'] = false;
                     self::saveModelLog($modelToken, $modelLogData);
+
                     continue;
                 }
-                Log::info($queue . ' model log saved');
+                Log::info($queue.' model log saved');
 
                 $aiData = $response->json();
-                Log::debug($queue . ' LLM http response', ['data' => $response->json()]);
+                Log::debug($queue.' LLM http response', ['data' => $response->json()]);
                 $responseContent = $aiData['choices'][0]['message']['content'];
                 if (isset($aiData['choices'][0]['message']['reasoning_content'])) {
                     $reasoningContent = $aiData['choices'][0]['message']['reasoning_content'];
                 }
 
-                Log::debug($queue . ' LLM response content=' . $responseContent);
+                Log::debug($queue.' LLM response content='.$responseContent);
                 if (empty($reasoningContent)) {
-                    Log::debug($queue . ' no reasoningContent');
+                    Log::debug($queue.' no reasoningContent');
                 } else {
-                    Log::debug($queue . ' reasoning=' . $reasoningContent);
+                    Log::debug($queue.' reasoning='.$reasoningContent);
                 }
 
-
-
                 if ($message->task->info->category === 'translate') {
-                    //写入句子库
-                    $url = config('app.url') . '/api/v2/sentence';
+                    // 写入句子库
+                    $url = config('app.url').'/api/v2/sentence';
                     $sentData = [];
                     $message->sentence->content = $responseContent;
                     $sentData[] = $message->sentence;
-                    Log::info($queue . " sentence update {$url}");
+                    Log::info($queue." sentence update {$url}");
                     $response = Http::timeout(10)->withToken($modelToken)->post($url, [
                         'sentences' => $sentData,
                     ]);
                     if ($response->failed()) {
-                        Log::error($queue . ' sentence update failed', [
+                        Log::error($queue.' sentence update failed', [
                             'url' => $url,
                             'data' => $response->json(),
                         ]);
+
                         continue;
                     } else {
                         $count = $response->json()['data']['count'];
@@ -191,9 +194,9 @@ class MqAiTranslate extends Command
                     }
                 }
                 if ($message->task->info->category === 'suggest') {
-                    //写入pr
-                    $url = config('app.url') . '/api/v2/sentpr';
-                    Log::info($queue . " sentence update {$url}");
+                    // 写入pr
+                    $url = config('app.url').'/api/v2/sentpr';
+                    Log::info($queue." sentence update {$url}");
                     $response = Http::timeout(10)->withToken($modelToken)->post($url, [
                         'book' => $message->sentence->book_id,
                         'para' => $message->sentence->paragraph,
@@ -205,10 +208,11 @@ class MqAiTranslate extends Command
                         'webhook' => false,
                     ]);
                     if ($response->failed()) {
-                        Log::error($queue . ' sentence update failed', [
+                        Log::error($queue.' sentence update failed', [
                             'url' => $url,
                             'data' => $response->json(),
                         ]);
+
                         continue;
                     } else {
                         if ($response->json()['ok']) {
@@ -222,24 +226,25 @@ class MqAiTranslate extends Command
                     }
                 }
 
-                //写入discussion
-                #获取句子id
-                $url = config('app.url') . '/api/v2/sentence-info/aa';
+                // 写入discussion
+                // 获取句子id
+                $url = config('app.url').'/api/v2/sentence-info/aa';
                 Log::info('ai translate', ['url' => $url]);
                 $response = Http::timeout(10)->withToken($modelToken)->get($url, [
                     'book' => $message->sentence->book_id,
                     'par' => $message->sentence->paragraph,
                     'start' => $message->sentence->word_start,
                     'end' => $message->sentence->word_end,
-                    'channel' => $message->sentence->channel_uid
+                    'channel' => $message->sentence->channel_uid,
                 ]);
                 if ($response->json()['ok']) {
                     $sUid = $response->json()['data']['id'];
                 } else {
-                    Log::error($queue . ' sentence id error', ['data' => $response->json()]);
+                    Log::error($queue.' sentence id error', ['data' => $response->json()]);
+
                     return 1;
                 }
-                $url = config('app.url') . '/api/v2/discussion';
+                $url = config('app.url').'/api/v2/discussion';
                 $data = [
                     'res_id' => $sUid,
                     'res_type' => 'sentence',
@@ -251,92 +256,94 @@ class MqAiTranslate extends Command
                 ];
                 $response = Http::timeout(10)->withToken($modelToken)->post($url, $data);
                 if ($response->failed()) {
-                    Log::error($queue . ' discussion create topic error', ['data' => $response->json()]);
+                    Log::error($queue.' discussion create topic error', ['data' => $response->json()]);
                 } else {
                     if (isset($response->json()['data']['id'])) {
-                        Log::info($queue . ' discussion create topic successful');
+                        Log::info($queue.' discussion create topic successful');
                         $data['parent'] = $response->json()['data']['id'];
                         unset($data['title']);
                         $topicChildren = [];
-                        //提示词
+                        // 提示词
                         $topicChildren[] = $message->prompt;
-                        //任务结果
+                        // 任务结果
                         $topicChildren[] = $responseContent;
-                        //推理过程写入discussion
-                        if (isset($reasoningContent) && !empty($reasoningContent)) {
+                        // 推理过程写入discussion
+                        if (isset($reasoningContent) && ! empty($reasoningContent)) {
                             $topicChildren[] = $reasoningContent;
                         }
-                        foreach ($topicChildren as  $content) {
+                        foreach ($topicChildren as $content) {
                             $data['content'] = $content;
-                            Log::debug($queue . ' discussion child request', ['url' => $url, 'data' => $data]);
+                            Log::debug($queue.' discussion child request', ['url' => $url, 'data' => $data]);
                             $response = Http::timeout(10)->withToken($modelToken)->post($url, $data);
                             if ($response->failed()) {
-                                Log::error($queue . ' discussion error', ['data' => $response->json()]);
+                                Log::error($queue.' discussion error', ['data' => $response->json()]);
                             } else {
-                                Log::info($queue . ' discussion child successful');
+                                Log::info($queue.' discussion child successful');
                             }
                         }
                     } else {
-                        Log::error($queue . ' discussion create topic response is null');
+                        Log::error($queue.' discussion create topic response is null');
                     }
                 }
 
-
-                //修改task 完成度
+                // 修改task 完成度
                 $taskProgress = $message->task->progress;
                 if ($taskProgress->total > 0) {
-                    $progress = (int)($taskProgress->current * 100 / $taskProgress->total);
+                    $progress = (int) ($taskProgress->current * 100 / $taskProgress->total);
                 } else {
                     $progress = 100;
-                    Log::error($queue . ' progress total is zero', ['task_id' => $message->task->info->id]);
+                    Log::error($queue.' progress total is zero', ['task_id' => $message->task->info->id]);
                 }
-                $url = config('app.url') . '/api/v2/task/' . $message->task->info->id;
+                $url = config('app.url').'/api/v2/task/'.$message->task->info->id;
                 $data = [
                     'progress' => $progress,
                 ];
-                Log::debug($queue . ' task progress request', ['url' => $url, 'data' => $data]);
+                Log::debug($queue.' task progress request', ['url' => $url, 'data' => $data]);
                 $response = Http::timeout(10)->withToken($modelToken)->patch($url, $data);
                 if ($response->failed()) {
-                    Log::error($queue . ' task progress error', ['data' => $response->json()]);
+                    Log::error($queue.' task progress error', ['data' => $response->json()]);
                 } else {
-                    $taskDiscussionContent[] = "- progress=" . $response->json()['data']['progress'];
-                    Log::info($queue . ' task progress successful progress=' . $response->json()['data']['progress']);
+                    $taskDiscussionContent[] = '- progress='.$response->json()['data']['progress'];
+                    Log::info($queue.' task progress successful progress='.$response->json()['data']['progress']);
                 }
 
                 if (isset($taskDiscussionData['parent'])) {
                     unset($taskDiscussionData['title']);
                     $taskDiscussionData['content'] = implode('\n', $taskDiscussionContent);
-                    Log::debug($queue . ' task discussion child request', ['url' => $discussionUrl, 'data' => $data]);
+                    Log::debug($queue.' task discussion child request', ['url' => $discussionUrl, 'data' => $data]);
                     $response = Http::timeout(10)->withToken($modelToken)->post($discussionUrl, $taskDiscussionData);
                     if ($response->failed()) {
-                        Log::error($queue . ' task discussion error', ['data' => $response->json()]);
+                        Log::error($queue.' task discussion error', ['data' => $response->json()]);
                     } else {
-                        Log::info($queue . ' task discussion child successful');
+                        Log::info($queue.' task discussion child successful');
                     }
                 } else {
                     Log::error('no task discussion root');
                 }
 
-                //任务完成 修改任务状态为 done
+                // 任务完成 修改任务状态为 done
                 if ($progress === 100) {
                     $this->setTaskStatus($message->task->info->id, 'done', $modelToken);
                 }
             }
             Cache::forget($pointerKey);
             $this->info('ai translate task complete');
+
             return 0;
         });
+
         return 0;
     }
+
     private function setTaskStatus($taskId, $status, $token)
     {
-        $url = config('app.url') . '/api/v2/task-status/' . $taskId;
+        $url = config('app.url').'/api/v2/task-status/'.$taskId;
         $data = [
             'status' => $status,
         ];
         Log::debug('ai_translate task status request', ['url' => $url, 'data' => $data]);
         $response = Http::timeout(10)->withToken($token)->patch($url, $data);
-        //判断状态码
+        // 判断状态码
         if ($response->failed()) {
             Log::error('ai_translate task status error', ['data' => $response->json()]);
         } else {
@@ -346,13 +353,15 @@ class MqAiTranslate extends Command
 
     private function saveModelLog($token, $data)
     {
-        $url = config('app.url') . '/api/v2/model-log';
+        $url = config('app.url').'/api/v2/model-log';
 
         $response = Http::timeout(10)->withToken($token)->post($url, $data);
         if ($response->failed()) {
             Log::error('ai-translate model log create failed', ['data' => $response->json()]);
+
             return false;
         }
+
         return true;
     }
 }

+ 62 - 62
api-v13/app/Console/Commands/MqDiscussion.php

@@ -2,29 +2,29 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Str;
-
-use App\Models\Sentence;
-use App\Models\WebHook;
-use App\Models\Discussion;
+use App\Http\Api\MdRender;
+use App\Http\Api\Mq;
+use App\Http\Api\UserApi;
+use App\Http\Controllers\NotificationController;
 use App\Models\Article;
 use App\Models\DhammaTerm;
+use App\Models\Discussion;
+use App\Models\Sentence;
 use App\Models\Wbw;
 use App\Models\WbwBlock;
-use App\Http\Api\Mq;
+use App\Models\WebHook;
+use App\Tools\Tools;
 use App\Tools\WebHook as WebHookSend;
-use App\Http\Api\MdRender;
-use App\Http\Api\UserApi;
-use App\Http\Controllers\NotificationController;
-
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
 
 class MqDiscussion extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan mq:discussion
+     *
      * @var string
      */
     protected $signature = 'mq:discussion';
@@ -53,29 +53,29 @@ class MqDiscussion extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'discussion';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::info("discussion worker start .");
+        Log::info('discussion worker start .');
         Mq::worker($exchange, $queue, function ($message) {
             Log::info('mq discussion receive {message}', ['message' => json_encode($message, JSON_UNESCAPED_UNICODE)]);
             $result = 0;
-            $msgParam = array();
+            $msgParam = [];
             $msgParam['nickname'] = $message->editor->nickName;
-            $link = config('app.url') . "/pcd/discussion/topic/";
+            $link = config('app.url').'/pcd/discussion/topic/';
             if ($message->parent) {
                 $msgParam['topic-title'] = Discussion::where('id', $message->parent)->value('title');
                 $id = $message->id;
-                $msgParam['link'] = $link . $message->parent . '#' . $id;
-                $msgParam['card_title'] = "回复讨论";
+                $msgParam['link'] = $link.$message->parent.'#'.$id;
+                $msgParam['card_title'] = '回复讨论';
                 $type = 'reply';
             } else {
                 $msgParam['title'] = $message->title;
-                $msgParam['link'] = $link . $message->id;
-                $msgParam['card_title'] = "创建讨论";
+                $msgParam['link'] = $link.$message->id;
+                $msgParam['card_title'] = '创建讨论';
                 $type = 'create';
             }
             if ($message->content) {
@@ -85,23 +85,23 @@ class MqDiscussion extends Command
             switch ($message->res_type) {
                 case 'sentence':
                     $sentence = Sentence::where('uid', $message->res_id)->first();
-                    if (!$sentence) {
-                        Log::error('invalid sentence id ' . $message->res_id);
+                    if (! $sentence) {
+                        Log::error('invalid sentence id '.$message->res_id);
                         $result = 1;
                         break;
                     }
 
-                    //站内信
+                    // 站内信
                     try {
-                        $sendTo = array();
-                        //句子的channel拥有者
-                        //$sendTo[] = $prData->channel->studio_id;
-                        //句子的作者
-                        if (!in_array($sentence->editor_uid, $sendTo)) {
+                        $sendTo = [];
+                        // 句子的channel拥有者
+                        // $sendTo[] = $prData->channel->studio_id;
+                        // 句子的作者
+                        if (! in_array($sentence->editor_uid, $sendTo)) {
                             $sendTo[] = $sentence->editor_uid;
                         }
-                        //句子的采纳者
-                        if (!empty($sentence->acceptor_uid) && !in_array($sentence->acceptor_uid, $sendTo)) {
+                        // 句子的采纳者
+                        if (! empty($sentence->acceptor_uid) && ! in_array($sentence->acceptor_uid, $sendTo)) {
                             $sendTo[] = $sentence->acceptor_uid;
                         }
                         $this->notification(
@@ -115,7 +115,7 @@ class MqDiscussion extends Command
                         Log::error('send notification failed', ['exception' => $e]);
                     }
 
-                    //webhook
+                    // webhook
                     $contentHtml = MdRender::render(
                         $sentence->content,
                         [$sentence->channel_uid],
@@ -134,32 +134,32 @@ class MqDiscussion extends Command
                     break;
                 case 'wbw':
                     $wbw = Wbw::where('uid', $message->res_id)->first();
-                    if (!$wbw) {
-                        Log::error('invalid wbw id ' . $message->res_id);
+                    if (! $wbw) {
+                        Log::error('invalid wbw id '.$message->res_id);
                         $result = 1;
                         break;
                     }
                     $wbwBlock = WbwBlock::where('uid', $wbw->block_uid)->first();
-                    if (!$wbwBlock) {
-                        Log::error('invalid wbw-block id ' . $message->res_id);
+                    if (! $wbwBlock) {
+                        Log::error('invalid wbw-block id '.$message->res_id);
                         $result = 1;
                         break;
                     }
 
-                    //站内信
+                    // 站内信
                     try {
-                        $sendTo = array();
-                        //channel拥有者
-                        //$sendTo[] = $prData->channel->studio_id;
-                        //作者
-                        if (!in_array($wbw->creator_uid, $sendTo)) {
+                        $sendTo = [];
+                        // channel拥有者
+                        // $sendTo[] = $prData->channel->studio_id;
+                        // 作者
+                        if (! in_array($wbw->creator_uid, $sendTo)) {
                             $sendTo[] = $wbw->creator_uid;
                         }
-                        //提问者
-                        if (!empty($message->parent)) {
+                        // 提问者
+                        if (! empty($message->parent)) {
                             $topicEditor = Discussion::where('id', $message->parent)
                                 ->value('editor_uid');
-                            if (!empty($topicEditor) && !in_array($topicEditor, $sendTo)) {
+                            if (! empty($topicEditor) && ! in_array($topicEditor, $sendTo)) {
                                 $sendTo[] = $topicEditor;
                                 Log::debug('发送给提问者', ['data' => $topicEditor]);
                             }
@@ -182,24 +182,23 @@ class MqDiscussion extends Command
                     break;
                 case 'term':
                     $term = DhammaTerm::where('guid', $message->res_id)->first();
-                    if (!$term) {
-                        Log::error('invalid term id ' . $message->res_id);
+                    if (! $term) {
+                        Log::error('invalid term id '.$message->res_id);
                         $result = 1;
                         break;
                     }
-                    if (empty($term->channal) || !Str::isUuid($term->channal)) {
+                    if (empty($term->channal) || ! Str::isUuid($term->channal)) {
                         break;
                     }
 
-
-                    //站内信
+                    // 站内信
                     try {
-                        $sendTo = array();
-                        //拥有者
+                        $sendTo = [];
+                        // 拥有者
                         $sendTo[] = $term->term;
-                        //作者
+                        // 作者
                         $editor = UserApi::getById($term->editor_id);
-                        if ($editor['id'] !== 0 && !in_array($editor['id'], $sendTo)) {
+                        if ($editor['id'] !== 0 && ! in_array($editor['id'], $sendTo)) {
                             $sendTo[] = $editor['id'];
                         }
                         $this->notification(
@@ -212,14 +211,14 @@ class MqDiscussion extends Command
                     } catch (\Exception $e) {
                         Log::error('send notification failed', ['exception' => $e]);
                     }
-                    //webhook
-                    $msgParam['anchor-content'] = $term->meaning . '(' . $term->word . ')';
+                    // webhook
+                    $msgParam['anchor-content'] = $term->meaning.'('.$term->word.')';
                     $WebHookResId = $term->channal;
                     $this->WebHook($msgParam, 'term', $WebHookResId);
 
                     break;
                 default:
-                    # code...
+                    // code...
                     break;
             }
 
@@ -238,12 +237,13 @@ class MqDiscussion extends Command
             ->value('content');
         if (empty($tpl)) {
             Log::error('mq:discussion 模版不能为空', ['tpl_title' => $articleTitle]);
+
             return 1;
         }
-        $m = new \Mustache_Engine(array(
+        $m = new \Mustache_Engine([
             'entity_flags' => ENT_QUOTES,
             'delimiters' => '{% %}',
-        ));
+        ]);
         $msgContent = $m->render($tpl, $msgParam);
 
         $webhooks = WebHook::where('res_id', $resId)
@@ -254,7 +254,7 @@ class MqDiscussion extends Command
             $event = json_decode($hook->event);
 
             if (is_array($event)) {
-                if (!in_array('discussion', $event)) {
+                if (! in_array('discussion', $event)) {
                     continue;
                 }
             } else {
@@ -294,7 +294,7 @@ class MqDiscussion extends Command
 
     private function notification($from, $to, $resType, $resId, $channel)
     {
-        //发送站内信
+        // 发送站内信
         try {
 
             $sendCount = NotificationController::insert(
@@ -304,10 +304,10 @@ class MqDiscussion extends Command
                 $resId,
                 $channel
             );
-            $this->info("send notification success to [" . $sendCount . '] users');
+            $this->info('send notification success to ['.$sendCount.'] users');
         } catch (\Exception $e) {
             Log::error('send notification failed', ['exception' => $e]);
         }
-        return;
+
     }
 }

+ 4 - 2
api-v13/app/Console/Commands/MqEmpty.php

@@ -2,9 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Http\Api\Mq;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
-use App\Http\Api\Mq;
 
 class MqEmpty extends Command
 {
@@ -39,7 +40,7 @@ class MqEmpty extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
@@ -52,6 +53,7 @@ class MqEmpty extends Command
             function ($message) {
                 $this->info('new message');
                 sleep(3);
+
                 return 0;
             }
         );

+ 20 - 17
api-v13/app/Console/Commands/MqExport.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class MqExport extends Command
@@ -11,6 +11,7 @@ class MqExport extends Command
     /**
      * The name and signature of the console command.
      * php artisan mq:export
+     *
      * @var string
      */
     protected $signature = 'mq:export';
@@ -42,30 +43,32 @@ class MqExport extends Command
         $exchange = 'router';
         $queue = 'export';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::debug("mq:progress start.");
-        Mq::worker($exchange,$queue,function ($message){
+        Log::debug('mq:progress start.');
+        Mq::worker($exchange, $queue, function ($message) {
             $data = [
-                        'book'=>$message->book,
-                        'para'=>$message->para,
-                        'channel'=>$message->channel,
-                        '--format'=>$message->format,
-                        'filename'=>$message->filename,
-                    ];
-            if(isset($message->origin) && is_string($message->origin)){
+                'book' => $message->book,
+                'para' => $message->para,
+                'channel' => $message->channel,
+                '--format' => $message->format,
+                'filename' => $message->filename,
+            ];
+            if (isset($message->origin) && is_string($message->origin)) {
                 $data['--origin'] = $message->origin;
             }
-            if(isset($message->translation) && is_string($message->translation)){
+            if (isset($message->translation) && is_string($message->translation)) {
                 $data['--translation'] = $message->translation;
             }
-            $ok = $this->call('export:chapter',$data);
-            if($ok !== 0){
-                Log::error('mq:progress upgrade:progress fail',$data);
-            }else{
-                $this->info("Received book=".$message->book.' result='.$ok);
-                Log::debug("mq:export: done ",$data);
+            $ok = $this->call('export:chapter', $data);
+            if ($ok !== 0) {
+                Log::error('mq:progress upgrade:progress fail', $data);
+            } else {
+                $this->info('Received book='.$message->book.' result='.$ok);
+                Log::debug('mq:export: done ', $data);
+
                 return $ok;
             }
         });
+
         return 0;
     }
 }

+ 20 - 18
api-v13/app/Console/Commands/MqExportArticle.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class MqExportArticle extends Command
@@ -11,6 +11,7 @@ class MqExportArticle extends Command
     /**
      * The name and signature of the console command.
      * php artisan mq:export.article
+     *
      * @var string
      */
     protected $signature = 'mq:export.article';
@@ -42,30 +43,31 @@ class MqExportArticle extends Command
         $exchange = 'router';
         $queue = 'export_article';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::debug("mq:export_article start.");
-        Mq::worker($exchange,$queue,function ($message){
+        Log::debug('mq:export_article start.');
+        Mq::worker($exchange, $queue, function ($message) {
             $data = [
-                        'id'=>$message->id,
-                        '--format'=>$message->format,
-                        'query_id'=>$message->queryId,
-                        '--origin'=>$message->origin,
-                        '--translation'=>$message->translation,
-                    ];
-            if(isset($message->token) && is_string($message->token)){
+                'id' => $message->id,
+                '--format' => $message->format,
+                'query_id' => $message->queryId,
+                '--origin' => $message->origin,
+                '--translation' => $message->translation,
+            ];
+            if (isset($message->token) && is_string($message->token)) {
                 $data['--token'] = $message->token;
             }
-            if(isset($message->anthology) && is_string($message->anthology)){
+            if (isset($message->anthology) && is_string($message->anthology)) {
                 $data['--anthology'] = $message->anthology;
             }
-            if(isset($message->channel) && is_string($message->channel)){
+            if (isset($message->channel) && is_string($message->channel)) {
                 $data['--channel'] = $message->channel;
             }
-            $ok = $this->call('export:article',$data);
-            if($ok !== 0){
-                Log::error('mq:export.article fail',$data);
-            }else{
-                $this->info("Received article id=".$message->id.' result='.$ok);
-                Log::debug("mq:export.article done ",$data);
+            $ok = $this->call('export:article', $data);
+            if ($ok !== 0) {
+                Log::error('mq:export.article fail', $data);
+            } else {
+                $this->info('Received article id='.$message->id.' result='.$ok);
+                Log::debug('mq:export.article done ', $data);
+
                 return $ok;
             }
         });

+ 21 - 18
api-v13/app/Console/Commands/MqExportPaliChapter.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class MqExportPaliChapter extends Command
@@ -11,6 +11,7 @@ class MqExportPaliChapter extends Command
     /**
      * The name and signature of the console command.
      * php artisan mq:export.pali.chapter
+     *
      * @var string
      */
     protected $signature = 'mq:export.pali.chapter';
@@ -42,33 +43,35 @@ class MqExportPaliChapter extends Command
         $exchange = 'router';
         $queue = 'export_pali_chapter';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::debug("mq:export_pali_chapter start.");
-        Mq::worker($exchange,$queue,function ($message){
+        Log::debug('mq:export_pali_chapter start.');
+        Mq::worker($exchange, $queue, function ($message) {
             $data = [
-                        'book'=>$message->book,
-                        'para'=>$message->para,
-                        'channel'=>$message->channel,
-                        '--format'=>$message->format,
-                        'query_id'=>$message->queryId,
-                    ];
-            if(isset($message->origin) && is_string($message->origin)){
+                'book' => $message->book,
+                'para' => $message->para,
+                'channel' => $message->channel,
+                '--format' => $message->format,
+                'query_id' => $message->queryId,
+            ];
+            if (isset($message->origin) && is_string($message->origin)) {
                 $data['--origin'] = $message->origin;
             }
-            if(isset($message->translation) && is_string($message->translation)){
+            if (isset($message->translation) && is_string($message->translation)) {
                 $data['--translation'] = $message->translation;
             }
-            if(isset($message->token) && is_string($message->token)){
+            if (isset($message->token) && is_string($message->token)) {
                 $data['--token'] = $message->token;
             }
-            $ok = $this->call('export:chapter',$data);
-            if($ok !== 0){
-                Log::error('mq:export.pali.chapter upgrade:progress fail',$data);
-            }else{
-                $this->info("Received book=".$message->book.' result='.$ok);
-                Log::debug("mq:export.pali.chapter done ",$data);
+            $ok = $this->call('export:chapter', $data);
+            if ($ok !== 0) {
+                Log::error('mq:export.pali.chapter upgrade:progress fail', $data);
+            } else {
+                $this->info('Received book='.$message->book.' result='.$ok);
+                Log::debug('mq:export.pali.chapter done ', $data);
+
                 return $ok;
             }
         });
+
         return 0;
     }
 }

+ 7 - 3
api-v13/app/Console/Commands/MqIssues.php

@@ -2,14 +2,16 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 
 class MqIssues extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan mq:issues
+     *
      * @var string
      */
     protected $signature = 'mq:issues';
@@ -38,16 +40,18 @@ class MqIssues extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'issues';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Mq::worker($exchange,$queue,function ($message){
+        Mq::worker($exchange, $queue, function ($message) {
             print_r($message);
+
             return 0;
         });
+
         return 0;
     }
 }

+ 24 - 26
api-v13/app/Console/Commands/MqPr.php

@@ -2,29 +2,28 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Http;
-use Illuminate\Support\Facades\Log;
-
 use App\Http\Api\Mq;
+use App\Http\Controllers\NotificationController;
+use App\Models\PaliSentence;
 use App\Models\Sentence;
 use App\Models\WebHook;
-use App\Models\PaliSentence;
+use App\Tools\Tools;
 use App\Tools\WebHook as WebHookSend;
-use App\Http\Api\MdRender;
-use App\Http\Api\PaliTextApi;
-use App\Http\Controllers\NotificationController;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
 
 class MqPr extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan mq:pr
+     *
      * @var string
      */
     protected $signature = 'mq:pr';
 
     protected $ver = '2024-1-2';
+
     /**
      * The console command description.
      *
@@ -49,20 +48,20 @@ class MqPr extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'suggestion';
-        $this->info(" [*] Waiting for {$queue}. Ver. " . $this->ver);
-        Log::debug("mq:pr start. ver=" . $this->ver);
+        $this->info(" [*] Waiting for {$queue}. Ver. ".$this->ver);
+        Log::debug('mq:pr start. ver='.$this->ver);
         Mq::worker($exchange, $queue, function ($message) {
             /**生成消息内容 */
 
             $msgTitle = '修改建议';
             $prData = $message->data;
             $sent_num = "{$prData->book}-{$prData->paragraph}-{$prData->word_start}-{$prData->word_end}";
-            $this->info('ver=' . $this->ver . ' request' . $sent_num);
+            $this->info('ver='.$this->ver.' request'.$sent_num);
 
             $username = $prData->editor->nickName;
             $palitext = PaliSentence::where('book', $prData->book)
@@ -76,9 +75,9 @@ class MqPr extends Command
                 ->where('word_end', $prData->word_end)
                 ->where('channel_uid', $prData->channel->id)
                 ->first();
-            $prtext = mb_substr($prData->content, 0, 140, "UTF-8");
+            $prtext = mb_substr($prData->content, 0, 140, 'UTF-8');
 
-            $link = config('app.url') . "/pcd/article/para/{$prData->book}-{$prData->paragraph}";
+            $link = config('app.url')."/pcd/article/para/{$prData->book}-{$prData->paragraph}";
             $link .= "?book={$prData->book}&par={$prData->paragraph}&channel={$prData->channel->id}";
 
             $msgContent = "{$username} 就文句`{$palitext}`提出了修改建议:\n";
@@ -86,28 +85,27 @@ class MqPr extends Command
             $msgContent .= ">句子编号:<font color=\"info\">{$sent_num}</font>\n";
             $msgContent .= "欢迎大家[点击链接]({$link})查看并讨论。";
 
-
             $result = 0;
-            //发送站内信
+            // 发送站内信
             if ($message->webhook) {
 
                 try {
-                    $sendTo = array();
+                    $sendTo = [];
                     if ($prData->editor->id !== $prData->channel->studio_id) {
                         $sendTo[] = $prData->channel->studio_id;
                     }
                     if ($orgText) {
-                        //原文作者
+                        // 原文作者
                         if (
-                            !in_array($orgText->editor_uid, $sendTo) &&
+                            ! in_array($orgText->editor_uid, $sendTo) &&
                             $orgText->editor_uid !== $prData->editor->id
                         ) {
                             $sendTo[] = $orgText->editor_uid;
                         }
-                        //原文采纳者
+                        // 原文采纳者
                         if (
-                            !empty($orgText->acceptor_uid) &&
-                            !in_array($orgText->acceptor_uid, $sendTo) &&
+                            ! empty($orgText->acceptor_uid) &&
+                            ! in_array($orgText->acceptor_uid, $sendTo) &&
                             $orgText->acceptor_uid !== $prData->editor->id
                         ) {
                             $sendTo[] = $orgText->acceptor_uid;
@@ -123,23 +121,22 @@ class MqPr extends Command
                         );
                     }
 
-                    $this->info("send notification success to [" . count($sendTo) . '] users');
+                    $this->info('send notification success to ['.count($sendTo).'] users');
                 } catch (\Exception $e) {
                     $this->error('send notification failed');
                     Log::error('send notification failed', ['exception' => $e]);
                 }
             }
 
-            //发送webhook
+            // 发送webhook
             if ($message->webhook) {
                 $webhooks = WebHook::where('res_id', $prData->channel->id)
                     ->where('status', 'active')
                     ->get();
 
-
                 foreach ($webhooks as $key => $hook) {
                     $event = json_decode($hook->event);
-                    if (!in_array('pr', $event)) {
+                    if (! in_array('pr', $event)) {
                         continue;
                     }
                     $command = '';
@@ -169,6 +166,7 @@ class MqPr extends Command
 
             return $result;
         });
+
         return 0;
     }
 }

+ 21 - 17
api-v13/app/Console/Commands/MqProgress.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class MqProgress extends Command
@@ -11,6 +12,7 @@ class MqProgress extends Command
     /**
      * The name and signature of the console command.
      * php artisan mq:progress
+     *
      * @var string
      */
     protected $signature = 'mq:progress';
@@ -39,31 +41,33 @@ class MqProgress extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'progress';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::debug("mq:progress start.");
-        Mq::worker($exchange,$queue,function ($message){
+        Log::debug('mq:progress start.');
+        Mq::worker($exchange, $queue, function ($message) {
             $data = [
-                        '--book'=>$message->book,
-                        '--para'=>$message->para,
-                        '--channel'=>$message->channel,
-                    ];
-            $ok1 = $this->call('upgrade:progress',$data);
-            if($ok1 !== 0){
-                Log::error('mq:progress upgrade:progress fail',$data);
+                '--book' => $message->book,
+                '--para' => $message->para,
+                '--channel' => $message->channel,
+            ];
+            $ok1 = $this->call('upgrade:progress', $data);
+            if ($ok1 !== 0) {
+                Log::error('mq:progress upgrade:progress fail', $data);
             }
-            $ok2 = $this->call('upgrade:progress.chapter',$data);
-            if($ok2 !== 0){
-                Log::error('mq:progress upgrade:progress.chapter fail',$data);
+            $ok2 = $this->call('upgrade:progress.chapter', $data);
+            if ($ok2 !== 0) {
+                Log::error('mq:progress upgrade:progress.chapter fail', $data);
             }
-            $this->info("Received book=".$message->book.' progress='.$ok1.' chapter='.$ok2);
-            Log::debug("mq:progress: done book=".$message->book.' progress='.$ok1.' chapter='.$ok2);
-            return $ok1+$ok2;
+            $this->info('Received book='.$message->book.' progress='.$ok1.' chapter='.$ok2);
+            Log::debug('mq:progress: done book='.$message->book.' progress='.$ok1.' chapter='.$ok2);
+
+            return $ok1 + $ok2;
         });
+
         return 0;
 
     }

+ 10 - 8
api-v13/app/Console/Commands/MqTask.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
-use Illuminate\Support\Facades\Log;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 
 class MqTask extends Command
 {
@@ -39,19 +39,21 @@ class MqTask extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $this->info('env='.env("RABBITMQ_HOST"));
-        $this->info('config='.config("queue.connections.rabbitmq.host"));
+        $this->info('env='.env('RABBITMQ_HOST'));
+        $this->info('config='.config('queue.connections.rabbitmq.host'));
         $exchange = 'router';
         $queue = 'task';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Mq::worker($exchange,$queue,function ($message){
+        Mq::worker($exchange, $queue, function ($message) {
             $message = json_decode(json_encode($message), true);
-            $this->info('name=',$message['name']);
-            return $this->call($message['name'],$message['param']);
+            $this->info('name=', $message['name']);
+
+            return $this->call($message['name'], $message['param']);
         });
+
         return 0;
     }
 }

+ 12 - 10
api-v13/app/Console/Commands/MqWbwAnalyses.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class MqWbwAnalyses extends Command
@@ -39,22 +40,23 @@ class MqWbwAnalyses extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'wbw-analyses';
         $this->info(" [*] Waiting for {$queue}. To exit press CTRL+C");
-        Log::debug("mq:wbw.analyses start.");
-        Mq::worker($exchange,$queue,function ($message){
-            $data = ['id'=>implode(',',$message)];
-            $ok = $this->call('upgrade:wbw.analyses',$data);
-            if($ok === 0){
-                $this->info("Received count=".count($message).' ok='.$ok);
+        Log::debug('mq:wbw.analyses start.');
+        Mq::worker($exchange, $queue, function ($message) {
+            $data = ['id' => implode(',', $message)];
+            $ok = $this->call('upgrade:wbw.analyses', $data);
+            if ($ok === 0) {
+                $this->info('Received count='.count($message).' ok='.$ok);
                 Log::debug('mq:wbw.analyses done count='.count($message));
-            }else{
-                Log::error('mq:wbw.analyses',$data);
+            } else {
+                Log::error('mq:wbw.analyses', $data);
             }
+
             return $ok;
         });
 

+ 0 - 2
api-v13/app/Console/Commands/PatchWbwPageNumber.php

@@ -37,8 +37,6 @@ class PatchWbwPageNumber extends Command
      */
     public function handle()
     {
-        /**
-         */
         return 0;
     }
 }

+ 4 - 4
api-v13/app/Console/Commands/PostInstall.php

@@ -28,16 +28,16 @@ class PostInstall extends Command
         //
         $this->info('post install start');
 
-        #openSearch
+        // openSearch
         $this->call('create:opensearch.index');
 
-        #rabbitmq
+        // rabbitmq
         $this->call('app:create-queue');
 
-        # system channel
+        // system channel
         $this->call('init:system.channel');
 
-        # system dictionary
+        // system dictionary
         $this->call('init:system.dict');
 
         $this->info('post install done');

+ 6 - 5
api-v13/app/Console/Commands/ProcessDeadLetterQueue.php

@@ -5,7 +5,6 @@ namespace App\Console\Commands;
 use Illuminate\Console\Command;
 use PhpAmqpLib\Connection\AMQPStreamConnection;
 use PhpAmqpLib\Message\AMQPMessage;
-use Illuminate\Support\Facades\Log;
 
 class ProcessDeadLetterQueue extends Command
 {
@@ -19,9 +18,11 @@ class ProcessDeadLetterQueue extends Command
      *
      * 删除死信消息
      * php artisan rabbitmq:process-dlq orders_dlq --delete
+     *
      * @var string
      */
     protected $signature = 'rabbitmq:process-dlq {dlq_name} {--requeue} {--delete}';
+
     protected $description = '处理死信队列中的消息';
 
     public function handle()
@@ -48,7 +49,7 @@ class ProcessDeadLetterQueue extends Command
         while (true) {
             $msg = $channel->basic_get($dlqName, false);
 
-            if (!$msg) {
+            if (! $msg) {
                 break; // 队列为空
             }
 
@@ -56,9 +57,9 @@ class ProcessDeadLetterQueue extends Command
             $data = json_decode($msg->body, true);
 
             $this->info("处理第 {$messageCount} 条死信消息");
-            $this->line("原始队列: " . ($data['queue'] ?? 'unknown'));
-            $this->line("失败原因: " . ($data['failure_reason'] ?? 'unknown'));
-            $this->line("失败时间: " . ($data['failed_at'] ?? 'unknown'));
+            $this->line('原始队列: '.($data['queue'] ?? 'unknown'));
+            $this->line('失败原因: '.($data['failure_reason'] ?? 'unknown'));
+            $this->line('失败时间: '.($data['failed_at'] ?? 'unknown'));
 
             if ($requeue) {
                 // 重新入队到原始队列

+ 52 - 40
api-v13/app/Console/Commands/RabbitMQWorker.php

@@ -2,53 +2,65 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use PhpAmqpLib\Message\AMQPMessage;
-use App\Jobs\ProcessAITranslateJob;
+use App\Exceptions\SectionTimeoutException;
+use App\Exceptions\TaskFailException;
 use App\Jobs\BaseRabbitMQJob;
+use App\Jobs\ProcessAITranslateJob;
+use App\Services\RabbitMQService;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 use PhpAmqpLib\Exception\AMQPTimeoutException;
+use PhpAmqpLib\Message\AMQPMessage;
 use PhpAmqpLib\Wire\AMQPTable;
-use App\Services\RabbitMQService;
-use App\Exceptions\SectionTimeoutException;
-use App\Exceptions\TaskFailException;
 
 class RabbitMQWorker extends Command
 {
     /**
      * The name and signature of the console command.
      * php -d memory_limit=128M artisan rabbitmq:consume ai_translate
+     *
      * @var string
      */
     protected $signature = 'rabbitmq:consume {queue} {--reset-loop-count}';
+
     protected $description = '消费 RabbitMQ 队列消息';
 
     private $connection;
+
     private $channel;
+
     private $processedCount = 0;
+
     private $maxLoopCount = 0;
+
     private $queueName;
+
     private $queueConfig;
+
     private $shouldStop = false;
+
     private $timeout = 15;
+
     private $job = null;
 
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $this->queueName = $this->argument('queue');
         $this->queueConfig = config("mint.rabbitmq.queues.{$this->queueName}");
 
-        if (!$this->queueConfig) {
+        if (! $this->queueConfig) {
             $this->error("队列 {$this->queueName} 的配置不存在");
+
             return 1;
         }
 
         $this->maxLoopCount = $this->queueConfig['max_loop_count'];
 
-        $this->info("启动 RabbitMQ Worker");
+        $this->info('启动 RabbitMQ Worker');
         $this->info("队列: {$this->queueName}");
         $this->info("最大循环次数: {$this->maxLoopCount}");
         $this->info("重试次数: {$this->queueConfig['retry_times']}");
@@ -58,11 +70,12 @@ class RabbitMQWorker extends Command
             $this->channel = $consume->getChannel();
             $this->startConsuming();
         } catch (\Exception $e) {
-            $this->error("Worker 启动失败: " . $e->getMessage());
-            Log::error("RabbitMQ Worker 启动失败", [
+            $this->error('Worker 启动失败: '.$e->getMessage());
+            Log::error('RabbitMQ Worker 启动失败', [
                 'queue' => $this->queueName,
-                'error' => $e->getMessage()
+                'error' => $e->getMessage(),
             ]);
+
             return 1;
         } finally {
             $this->cleanup();
@@ -87,7 +100,7 @@ class RabbitMQWorker extends Command
             $callback
         );
 
-        $this->info("开始消费消息... 按 Ctrl+C 退出");
+        $this->info('开始消费消息... 按 Ctrl+C 退出');
 
         // 设置信号处理
         if (extension_loaded('pcntl')) {
@@ -95,17 +108,16 @@ class RabbitMQWorker extends Command
             pcntl_signal(SIGINT, [$this, 'handleSignal']);
         }
 
-        while ($this->channel->is_consuming() && !$this->shouldStop) {
+        while ($this->channel->is_consuming() && ! $this->shouldStop) {
             try {
                 $this->channel->wait(null, false, $this->timeout);
             } catch (AMQPTimeoutException $e) {
-                //忽略
+                // 忽略
             } catch (\Exception $e) {
                 $this->error($e->getMessage());
                 throw $e;
             }
 
-
             if (extension_loaded('pcntl')) {
                 pcntl_signal_dispatch();
             }
@@ -115,8 +127,8 @@ class RabbitMQWorker extends Command
                 $this->info("达到最大循环次数 ({$this->maxLoopCount}),Worker 自动退出");
                 break;
             }
-            if (\App\Tools\Tools::isStop()) {
-                //检测到停止标记
+            if (Tools::isStop()) {
+                // 检测到停止标记
                 break;
             }
         }
@@ -129,10 +141,10 @@ class RabbitMQWorker extends Command
             Log::info('processMessage start', ['message_id' => $msg->get('message_id')]);
 
             $data = json_decode($msg->getBody());
-            $this->info("processMessage start " . $msg->get('message_id') . '[' . count($data) . ']');
+            $this->info('processMessage start '.$msg->get('message_id').'['.count($data).']');
 
             if (json_last_error() !== JSON_ERROR_NONE) {
-                throw new \Exception("JSON 解析失败: " . json_last_error_msg());
+                throw new \Exception('JSON 解析失败: '.json_last_error_msg());
             }
 
             // 获取重试次数(从消息头中获取)
@@ -156,26 +168,26 @@ class RabbitMQWorker extends Command
                 $this->info("消息处理成功 [{$this->processedCount}/{$this->maxLoopCount}]");
             } catch (SectionTimeoutException $e) {
                 $msg->nack(true, false);
-                Log::warning('attempt to requeue the message message_id:' . $msg->get('message_id'));
+                Log::warning('attempt to requeue the message message_id:'.$msg->get('message_id'));
             } catch (TaskFailException $e) {
                 $msg->nack(false, false);
             } catch (\Exception $e) {
-                //requeue
+                // requeue
                 $this->handleJobException($msg, $data, $retryCount, $e);
             }
         } catch (\Exception $e) {
-            $this->error("消息处理异常: " . $e->getMessage());
-            Log::error("RabbitMQ 消息处理异常", [
+            $this->error('消息处理异常: '.$e->getMessage());
+            Log::error('RabbitMQ 消息处理异常', [
                 'queue' => $this->queueName,
                 'error' => $e->getMessage(),
-                'message_body' => $msg->getBody()
+                'message_body' => $msg->getBody(),
             ]);
 
             // 拒绝消息并发送到死信队列
-            //$msg->nack(false, false);
+            // $msg->nack(false, false);
             $this->sendToDeadLetterQueue($data, $e);
             $msg->ack(); // 确认原消息以避免重复
-            $this->error("已发送到死信队列");
+            $this->error('已发送到死信队列');
             $this->processedCount++;
         }
     }
@@ -204,13 +216,13 @@ class RabbitMQWorker extends Command
         if ($retryCount < $maxRetries - 1) {
             // 还有重试机会,重新入队
             $this->requeueMessage($msg, $data, $retryCount + 1);
-            $this->info("消息重新入队,重试次数: " . ($retryCount + 1) . "/{$maxRetries}");
+            $this->info('消息重新入队,重试次数: '.($retryCount + 1)."/{$maxRetries}");
         } else {
             // 超过重试次数,发送到死信队列
             $this->sendToDeadLetterQueue($data, $e);
             $msg->ack(); // 确认原消息以避免重复
-            $this->error("消息超过最大重试次数,已发送到死信队列 ");
-            Log::error("消息超过最大重试次数,已发送到死信队列 message_id=" . $msg->get('message_id'));
+            $this->error('消息超过最大重试次数,已发送到死信队列 ');
+            Log::error('消息超过最大重试次数,已发送到死信队列 message_id='.$msg->get('message_id'));
         }
 
         $this->processedCount++;
@@ -223,7 +235,7 @@ class RabbitMQWorker extends Command
         $headers = new AMQPTable([
             'retry_count' => $newRetryCount,
             'original_queue' => $this->queueName,
-            'retry_timestamp' => time()
+            'retry_timestamp' => time(),
         ]);
 
         $newMsg = new AMQPMessage(
@@ -233,7 +245,7 @@ class RabbitMQWorker extends Command
                 'timestamp' => time(),
                 'message_id' => $msg->get('message_id'),
                 'application_headers' => $headers,
-                "content_type" => 'application/json; charset=utf-8'
+                'content_type' => 'application/json; charset=utf-8',
             ]
         );
 
@@ -253,7 +265,7 @@ class RabbitMQWorker extends Command
             'failure_reason' => $e->getMessage(),
             'failed_at' => date('Y-m-d H:i:s'),
             'queue' => $this->queueName,
-            'max_retries' => $this->queueConfig['retry_times']
+            'max_retries' => $this->queueConfig['retry_times'],
         ];
 
         $dlqMsg = new AMQPMessage(
@@ -263,23 +275,23 @@ class RabbitMQWorker extends Command
 
         $this->channel->basic_publish($dlqMsg, '', $dlqName);
 
-        Log::error("消息发送到死信队列", [
+        Log::error('消息发送到死信队列', [
             'original_queue' => $this->queueName,
             'dead_letter_queue' => $dlqName,
-            'error' => $e->getMessage()
+            'error' => $e->getMessage(),
         ]);
     }
 
     /**
      * 处理系统信号
      *
-     * @param int $signal 信号类型
-     * @param int|false $previousExitCode 上一个退出码
+     * @param  int  $signal  信号类型
+     * @param  int|false  $previousExitCode  上一个退出码
      * @return int|false 返回退出码或 false
      */
     public function handleSignal(int $signal, int|false $previousExitCode = 0): int|false
     {
-        $this->info("接收到退出信号,正在优雅关闭...");
+        $this->info('接收到退出信号,正在优雅关闭...');
         $this->shouldStop = true;
 
         if ($this->job) {
@@ -287,7 +299,7 @@ class RabbitMQWorker extends Command
         }
 
         if ($this->channel && $this->channel->is_consuming()) {
-            //$this->channel->basic_cancel_on_shutdown(true);
+            // $this->channel->basic_cancel_on_shutdown(true);
             $this->channel->basic_cancel('');
         }
 
@@ -307,7 +319,7 @@ class RabbitMQWorker extends Command
 
             $this->info("连接已关闭,处理了 {$this->processedCount} 条消息");
         } catch (\Exception $e) {
-            $this->error("清理资源时出错: " . $e->getMessage());
+            $this->error('清理资源时出错: '.$e->getMessage());
         }
     }
 }

+ 7 - 6
api-v13/app/Console/Commands/RemoveTermCache.php

@@ -2,9 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Models\DhammaTerm;
 use App\Models\Channel;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 
 class RemoveTermCache extends Command
@@ -40,22 +40,23 @@ class RemoveTermCache extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $word = $this->argument('word');
         $channels = Channel::select('uid')->get();
-        if(empty($word)){
+        if (empty($word)) {
 
-        }else{
+        } else {
             foreach ($channels as $key => $channel) {
                 $key = "/term/{$channel}/{$word}";
-                if(Cache::has($key)){
+                if (Cache::has($key)) {
                     $this->info('has:'.$key);
                     Cache::forget($key);
                 }
             }
         }
+
         return 0;
     }
 }

+ 23 - 21
api-v13/app/Console/Commands/StatisticsDict.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
+use App\Models\UserOperationLog;
+use App\Tools\Tools;
+use Carbon\Carbon;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Storage;
-use Carbon\Carbon;
-use App\Models\UserOperationLog;
 
 class StatisticsDict extends Command
 {
@@ -40,41 +41,42 @@ class StatisticsDict extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $file = "public/statistics/lookup-monthly.csv";
-        Storage::disk('local')->put($file, "");
-        #按月获取数据
-        $firstDay = UserOperationLog::where('op_type','dict_lookup')
-                            ->orderBy('created_at')
-                            ->select('created_at')
-                            ->first();
+        $file = 'public/statistics/lookup-monthly.csv';
+        Storage::disk('local')->put($file, '');
+        // 按月获取数据
+        $firstDay = UserOperationLog::where('op_type', 'dict_lookup')
+            ->orderBy('created_at')
+            ->select('created_at')
+            ->first();
         $firstDay = strtotime($firstDay->created_at);
-        $firstMonth = Carbon::create(date("Y-m",$firstDay));
+        $firstMonth = Carbon::create(date('Y-m', $firstDay));
         $now = Carbon::now();
         $current = $firstMonth;
         $sumCount = 0;
         while ($current <= $now) {
-            # code...
+            // code...
             $start = Carbon::create($current)->startOfMonth();
             $end = Carbon::create($current)->endOfMonth();
             $date = $current->format('Y-m');
-            $count = UserOperationLog::where('op_type','dict_lookup')
-                              ->whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->count();
+            $count = UserOperationLog::where('op_type', 'dict_lookup')
+                ->whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->count();
             $sumCount += $count;
-            $editor = UserOperationLog::where('op_type','dict_lookup')
-                              ->whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->groupBy('user_id')
-                              ->select('user_id')->get();
+            $editor = UserOperationLog::where('op_type', 'dict_lookup')
+                ->whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->groupBy('user_id')
+                ->select('user_id')->get();
             $info = $date.','.$count.','.$sumCount.','.count($editor);
             $this->info($info);
             Storage::disk('local')->append($file, $info);
             $current->addMonth(1);
         }
+
         return 0;
     }
 }

+ 20 - 18
api-v13/app/Console/Commands/StatisticsExp.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
+use App\Models\UserOperationDaily;
+use App\Tools\Tools;
+use Carbon\Carbon;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Storage;
-use Carbon\Carbon;
-use App\Models\UserOperationDaily;
 
 class StatisticsExp extends Command
 {
@@ -40,38 +41,39 @@ class StatisticsExp extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $file = "public/statistics/exp-monthly.csv";
-        Storage::disk('local')->put($file, "");
-        #按月获取数据
+        $file = 'public/statistics/exp-monthly.csv';
+        Storage::disk('local')->put($file, '');
+        // 按月获取数据
         $firstDay = UserOperationDaily::select('created_at')
-                            ->orderBy('created_at')
-                            ->first();
+            ->orderBy('created_at')
+            ->first();
         $firstDay = strtotime($firstDay->created_at);
-        $firstMonth = Carbon::create(date("Y-m",$firstDay));
+        $firstMonth = Carbon::create(date('Y-m', $firstDay));
         $now = Carbon::now();
         $current = $firstMonth;
         $sumTime = 0;
         while ($current <= $now) {
-            # code...
+            // code...
             $start = Carbon::create($current)->startOfMonth();
             $end = Carbon::create($current)->endOfMonth();
             $date = $current->format('Y-m');
-            $time = UserOperationDaily::whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->sum('duration')/1000;
+            $time = UserOperationDaily::whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->sum('duration') / 1000;
             $sumTime += $time;
-            $editor = UserOperationDaily::whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->groupBy('user_id')
-                              ->select('user_id')->get();
-            $info = $date.','.(int)($time/3600).','.(int)($sumTime/3600).','.count($editor);
+            $editor = UserOperationDaily::whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->groupBy('user_id')
+                ->select('user_id')->get();
+            $info = $date.','.(int) ($time / 3600).','.(int) ($sumTime / 3600).','.count($editor);
             $this->info($info);
             Storage::disk('local')->append($file, $info);
             $current->addMonth(1);
         }
+
         return 0;
     }
 }

+ 27 - 24
api-v13/app/Console/Commands/StatisticsNissaya.php

@@ -2,17 +2,19 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\Channel;
 use App\Models\Sentence;
-use Illuminate\Support\Facades\Storage;
+use App\Tools\Tools;
 use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
 
 class StatisticsNissaya extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan statistics:nissaya
+     *
      * @var string
      */
     protected $signature = 'statistics:nissaya';
@@ -41,50 +43,51 @@ class StatisticsNissaya extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $nissaya_channels = Channel::where('type','nissaya')
-                            ->where('lang','my')
-                            ->select('uid')->get();
+        $nissaya_channels = Channel::where('type', 'nissaya')
+            ->where('lang', 'my')
+            ->select('uid')->get();
         $this->info('channel:'.count($nissaya_channels));
-        $file = "public/statistics/nissaya-monthly.csv";
+        $file = 'public/statistics/nissaya-monthly.csv';
 
-        Storage::disk('local')->put($file, "");
-        #按月获取数据
-        $firstDay = Sentence::whereIn('channel_uid',$nissaya_channels)
-                            ->orderBy('created_at')
-                            ->select('created_at')
-                            ->first();
+        Storage::disk('local')->put($file, '');
+        // 按月获取数据
+        $firstDay = Sentence::whereIn('channel_uid', $nissaya_channels)
+            ->orderBy('created_at')
+            ->select('created_at')
+            ->first();
         $firstDay = strtotime($firstDay->created_at);
-        $firstMonth = Carbon::create(date("Y-m",$firstDay));
+        $firstMonth = Carbon::create(date('Y-m', $firstDay));
         $now = Carbon::now();
         $current = $firstMonth;
         $sumStrlen = 0;
         $sumCount = 0;
         while ($current <= $now) {
-            # code...
+            // code...
             $start = Carbon::create($current)->startOfMonth();
             $end = Carbon::create($current)->endOfMonth();
             $date = $current->format('Y-m');
-            $table = Sentence::whereIn('channel_uid',$nissaya_channels)
-                              ->whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end);
-            $strlen =  $table->sum('strlen');
+            $table = Sentence::whereIn('channel_uid', $nissaya_channels)
+                ->whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end);
+            $strlen = $table->sum('strlen');
             $sumStrlen += $strlen;
             $count = $table->count();
             $sumCount += $count;
-            $editor = Sentence::whereIn('channel_uid',$nissaya_channels)
-                              ->whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->groupBy('editor_uid')
-                              ->select('editor_uid')->get();
+            $editor = Sentence::whereIn('channel_uid', $nissaya_channels)
+                ->whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->groupBy('editor_uid')
+                ->select('editor_uid')->get();
             $info = "{$date},{$strlen},{$sumStrlen},{$count},{$sumCount},".count($editor);
             $this->info($info);
             Storage::disk('local')->append($file, $info);
             $current->addMonth(1);
         }
         $this->info('path='.$file);
+
         return 0;
     }
 }

+ 15 - 10
api-v13/app/Console/Commands/StatisticsNissayaCover.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\Channel;
-use App\Models\Sentence;
 use App\Models\PaliSentence;
+use App\Models\Sentence;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 
 class StatisticsNissayaCover extends Command
@@ -13,9 +14,11 @@ class StatisticsNissayaCover extends Command
     /**
      * The name and signature of the console command.
      * php artisan statistics:nissaya.cover
+     *
      * @var string
      */
     protected $signature = 'statistics:nissaya.cover';
+
     protected $types = [
         'mula' => [
             69,
@@ -177,7 +180,7 @@ class StatisticsNissayaCover extends Command
             211,
             212,
         ],
-        'vinaya' => [138, 139, 140, 141, 142, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217,],
+        'vinaya' => [138, 139, 140, 141, 142, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217],
         'sutta' => [
             82,
             83,
@@ -281,8 +284,9 @@ class StatisticsNissayaCover extends Command
             198,
             199,
         ],
-        'abhidhamma' => [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 96, 97, 98, 172, 173, 174, 175, 176, 177, 178, 179, 180,],
+        'abhidhamma' => [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 96, 97, 98, 172, 173, 174, 175, 176, 177, 178, 179, 180],
     ];
+
     /**
      * The console command description.
      *
@@ -307,16 +311,16 @@ class StatisticsNissayaCover extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $nissaya_channels = Channel::where('type', 'nissaya')
             ->where('lang', 'my')
             ->select('uid')->get();
-        $this->info('channel:' . count($nissaya_channels));
+        $this->info('channel:'.count($nissaya_channels));
         $output = [];
         foreach ($this->types as $type => $books) {
-            # code...
+            // code...
             $pali = PaliSentence::whereIn('book', $books)->sum('length');
             $nissayaSentences = Sentence::whereIn('channel_uid', $nissaya_channels)
                 ->whereIn('book_id', $books)
@@ -325,10 +329,10 @@ class StatisticsNissayaCover extends Command
                 ->get();
             $sentences = [];
             $final = 0;
-            $this->info($type . count($nissayaSentences) . " sentences");
+            $this->info($type.count($nissayaSentences).' sentences');
             if (count($nissayaSentences) > 0) {
                 $count = 0;
-                foreach ($nissayaSentences as  $value) {
+                foreach ($nissayaSentences as $value) {
                     $sentences[] = [
                         $value->book_id,
                         $value->paragraph,
@@ -346,10 +350,11 @@ class StatisticsNissayaCover extends Command
                 }
             }
 
-            $this->info($type . '=' . $pali . '=' . $final);
+            $this->info($type.'='.$pali.'='.$final);
             $output[] = ['type' => $type, 'total' => $pali, 'final' => $final];
         }
         Cache::put('/statistics/nissaya/cover', $output, 48 * 3600);
+
         return 0;
     }
 }

+ 19 - 17
api-v13/app/Console/Commands/StatisticsWbw.php

@@ -2,10 +2,11 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\Wbw;
-use Illuminate\Support\Facades\Storage;
+use App\Tools\Tools;
 use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Storage;
 
 class StatisticsWbw extends Command
 {
@@ -40,38 +41,39 @@ class StatisticsWbw extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $file = "public/statistics/wbw-monthly.csv";
-        Storage::disk('local')->put($file, "");
-        #按月获取数据
+        $file = 'public/statistics/wbw-monthly.csv';
+        Storage::disk('local')->put($file, '');
+        // 按月获取数据
         $firstDay = Wbw::select('created_at')
-                        ->orderBy('created_at')
-                        ->first();
+            ->orderBy('created_at')
+            ->first();
         $firstDay = strtotime($firstDay->created_at);
-        $firstMonth = Carbon::create(date("Y-m",$firstDay));
+        $firstMonth = Carbon::create(date('Y-m', $firstDay));
         $now = Carbon::now();
         $current = $firstMonth;
         $sumCount = 0;
         while ($current <= $now) {
-            # code...
+            // code...
             $start = Carbon::create($current)->startOfMonth();
             $end = Carbon::create($current)->endOfMonth();
             $date = $current->format('Y-m');
-            $count = Wbw::whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->count();
+            $count = Wbw::whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->count();
             $sumCount += $count;
-            $editor = Wbw::whereDate('created_at','>=',$start)
-                              ->whereDate('created_at','<=',$end)
-                              ->groupBy('editor_id')
-                              ->select('editor_id')->get();
+            $editor = Wbw::whereDate('created_at', '>=', $start)
+                ->whereDate('created_at', '<=', $end)
+                ->groupBy('editor_id')
+                ->select('editor_id')->get();
             $info = $date.','.$count.','.$sumCount.','.count($editor);
             $this->info($info);
             Storage::disk('local')->append($file, $info);
             $current->addMonth(1);
         }
+
         return 0;
     }
 }

+ 10 - 10
api-v13/app/Console/Commands/TestAI.php

@@ -4,7 +4,6 @@ namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Http;
-use Illuminate\Support\Facades\Log;
 
 class TestAI extends Command
 {
@@ -41,20 +40,21 @@ class TestAI extends Command
     {
         $url = 'https://api.moonshot.cn/v1/chat/completions';
         $param = [
-                "model" => "moonshot-v1-8k",
-                "messages" => [
-                    ["role" => "system","content" => "你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。"],
-                    ["role" => "user","content" => "你好,我叫李雷,1+1等于多少?"],
-                ],
-                "temperature" => 0.3,
+            'model' => 'moonshot-v1-8k',
+            'messages' => [
+                ['role' => 'system', 'content' => '你是 Kimi,由 Moonshot AI 提供的人工智能助手,你更擅长中文和英文的对话。你会为用户提供安全,有帮助,准确的回答。同时,你会拒绝一切涉及恐怖主义,种族歧视,黄色暴力等问题的回答。Moonshot AI 为专有名词,不可翻译成其他语言。'],
+                ['role' => 'user', 'content' => '你好,我叫李雷,1+1等于多少?'],
+            ],
+            'temperature' => 0.3,
         ];
         $response = Http::withToken('sk-kwjHIMh3PoWwUwQyKdT3KHvNe8Es19SUiujGrxtH09uDQCui')
-                        ->post($url,$param);
-        if($response->failed()){
+            ->post($url, $param);
+        if ($response->failed()) {
             $this->error('http request error'.$response->json('message'));
-        }else{
+        } else {
             $this->info(json_encode($response->json()));
         }
+
         return 0;
     }
 }

+ 5 - 3
api-v13/app/Console/Commands/TestAIArticleTranslate.php

@@ -2,14 +2,15 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Services\AIAssistant\ArticleTranslateService;
+use Illuminate\Console\Command;
 
 class TestAIArticleTranslate extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:ai.article.translate
+     *
      * @var string
      */
     protected $signature = 'test:ai.article.translate {--article=} {--anthology=} {--model=}  {--channel=}';
@@ -27,10 +28,11 @@ class TestAIArticleTranslate extends Command
     public function handle()
     {
         if (
-            !$this->option('model') ||
-            !$this->option('channel')
+            ! $this->option('model') ||
+            ! $this->option('channel')
         ) {
             $this->error('model,article,channel is requested');
+
             return;
         }
         //

+ 1 - 1
api-v13/app/Console/Commands/TestAITerm.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Services\AIAssistant\AITermService;
+use Illuminate\Console\Command;
 
 class TestAITerm extends Command
 {

+ 7 - 4
api-v13/app/Console/Commands/TestAiTask.php

@@ -2,9 +2,10 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Models\TaskAssignee;
+use App\Jobs\ProcessAITranslateJob;
 use App\Models\AiModel;
+use App\Models\TaskAssignee;
+use Illuminate\Console\Command;
 
 class TestAiTask extends Command
 {
@@ -12,6 +13,7 @@ class TestAiTask extends Command
      * The name and signature of the console command.
      * php artisan test:ai.task c77af42f-ffb5-48ae-af71-4c32e1c30dab
      * php artisan test:ai.task f42fa690-c590-400f-9de9-fbc81e838a5a
+     *
      * @var string
      */
     protected $signature = 'test:ai.task {id} {--test}';
@@ -45,11 +47,12 @@ class TestAiTask extends Command
             ->select('assignee_id')->get();
         $aiAssistant = AiModel::whereIn('uid', $taskAssignee)->first();
         if ($aiAssistant) {
-            $count = \App\Jobs\ProcessAITranslateJob::publish($taskId, $aiAssistant->uid);
-            $this->info('publish total:' . $count);
+            $count = ProcessAITranslateJob::publish($taskId, $aiAssistant->uid);
+            $this->info('publish total:'.$count);
         } else {
             $this->error('no ai assistant');
         }
+
         return 0;
     }
 }

+ 21 - 20
api-v13/app/Console/Commands/TestCaseMan.php

@@ -2,10 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Tools\CaseMan;
-use App\Models\UserDict;
-
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 
 class TestCaseMan extends Command
 {
@@ -40,30 +39,32 @@ class TestCaseMan extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-		$caseMan = new CaseMan();
-        $case = $caseMan->Declension($this->argument('word'),'.n:base.','.nt.',0.5);
+        $caseMan = new CaseMan;
+        $case = $caseMan->Declension($this->argument('word'), '.n:base.', '.nt.', 0.5);
         print_r($case);
+
         return 0;
 
-		$parents = $caseMan->WordToBase($this->argument('word'),1);
-			# code...
+        $parents = $caseMan->WordToBase($this->argument('word'), 1);
+        // code...
+
+        foreach ($parents as $base => $rows) {
+            // code...
+            if (count($rows) == 0) {
+                $this->error("base={$base}-(".count($rows).')');
+            } else {
+                $this->warn("base={$base}-(".count($rows).')');
+            }
 
-		foreach ($parents as $base => $rows) {
-			# code...
-			if(count($rows)==0){
-				$this->error("base={$base}-(".count($rows).")");
-			}else{
-				$this->warn("base={$base}-(".count($rows).")");
-			}
+            foreach ($rows as $value) {
+                // code...
+                $this->info($value['word'].'-'.$value['type'].'-'.$value['grammar'].'-'.$base);
+            }
+        }
 
-			foreach ($rows as $value) {
-				# code...
-				$this->info($value['word'].'-'.$value['type'].'-'.$value['grammar'].'-'.$base);
-			}
-		}
         return 0;
     }
 }

+ 6 - 5
api-v13/app/Console/Commands/TestJsonToXml.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Tools\Tools;
+use Illuminate\Console\Command;
 
 class TestJsonToXml extends Command
 {
@@ -38,16 +38,17 @@ class TestJsonToXml extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $array = [
-            'pali'=>['status'=>'7','value'=>'bārāṇasiyaṃ'],
-            'real'=>['status'=>'7','value'=>'bārāṇasiyaṃ'],
-            'id'=>'p171-2475-10'
+            'pali' => ['status' => '7', 'value' => 'bārāṇasiyaṃ'],
+            'real' => ['status' => '7', 'value' => 'bārāṇasiyaṃ'],
+            'id' => 'p171-2475-10',
         ];
         $xml = Tools::JsonToXml($array);
         $this->info($xml);
+
         return 0;
     }
 }

+ 14 - 12
api-v13/app/Console/Commands/TestMarkdownToTpl.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Controllers\ArticleController;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
 class TestMarkdownToTpl extends Command
@@ -39,12 +40,12 @@ class TestMarkdownToTpl extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         Log::info('md render start item='.$this->argument('item'));
-        $data = array();
-        $data['basic'] = <<<md
+        $data = [];
+        $data['basic'] = <<<'md'
         # 去除烦恼的五种方法(一种分类)
 
         1 为了自己的利益而从别人处听法;
@@ -56,7 +57,7 @@ class TestMarkdownToTpl extends Command
         (无碍解道,义注,1,63)
         md;
 
-        $data['tpl'] = <<<md
+        $data['tpl'] = <<<'md'
         为了自己的利益而从别人处听法;
 
         {{168-916-2-9}}
@@ -66,18 +67,19 @@ class TestMarkdownToTpl extends Command
 
         foreach ($data as $key => $value) {
             $_item = $this->argument('item');
-            if(!empty($_item) && $key !==$_item){
+            if (! empty($_item) && $key !== $_item) {
                 continue;
             }
             $tpl = $article->toTpl($value,
-                        'eb9e3f7f-b942-4ca4-bd6f-b7876b59a523',
-                        [
-                            'user_uid'=>'ba5463f3-72d1-4410-858e-eadd10884713',
-                            'user_id'=>4,
-                        ]
-                    );
+                'eb9e3f7f-b942-4ca4-bd6f-b7876b59a523',
+                [
+                    'user_uid' => 'ba5463f3-72d1-4410-858e-eadd10884713',
+                    'user_id' => 4,
+                ]
+            );
             var_dump($tpl);
         }
+
         return 0;
     }
 }

+ 27 - 22
api-v13/app/Console/Commands/TestMdRender.php

@@ -2,17 +2,20 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\MdRender;
-use Illuminate\Support\Str;
-use Illuminate\Support\Facades\Log;
+use App\Services\Template\TemplateService;
 use App\Tools\Markdown;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
 
 class TestMdRender extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:md.render term --format=unity --driver=str
+     *
      * @var string
      */
     protected $signature = 'test:md.render {item?} {--format=html} {--driver=morus}';
@@ -41,11 +44,11 @@ class TestMdRender extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
 
-        $content = <<<md
+        $content = <<<'md'
         # 测试
         ## 测试
 
@@ -66,30 +69,31 @@ class TestMdRender extends Command
 
         **粗体文本** 和 *斜体文本* 也被支持。
         md;
-        $parser = new \App\Services\Template\TemplateService(false);
+        $parser = new TemplateService(false);
         $render = $parser->parseAndRender($content, 'json');
         var_dump($render);
+
         return 0;
 
-        Log::info('md render start item=' . $this->argument('item'));
-        $data = array();
-        $data['bold'] = <<<md
+        Log::info('md render start item='.$this->argument('item'));
+        $data = [];
+        $data['bold'] = <<<'md'
         **三十位** 经在[中间]六处为**[licchavi]**,在极果为**慧解脱**
         md;
 
-        $data['sentence'] = <<<md
+        $data['sentence'] = <<<'md'
         {{168-916-2-9}}
         md;
 
-        $data['link'] = <<<md
+        $data['link'] = <<<'md'
         aa `[link](wikipali.org/aa.php?view=b&c=d)` bb
         md;
 
-        $data['term'] = <<<md
+        $data['term'] = <<<'md'
         ## term
         [[bhagavantu]]
         md;
-        $data['noteMulti'] = <<<md
+        $data['noteMulti'] = <<<'md'
         ## heading
 
         [点击](http://127.0.0.1:3000/my/article/para/168-876?mode=edit&channel=00ae2c48-c204-4082-ae79-79ba2740d506&book=168&par=876)
@@ -106,15 +110,15 @@ class TestMdRender extends Command
         md;
 
         $data['note'] = '`bla **bold** _em_ bla`';
-        $data['noteTpl'] = <<<md
+        $data['noteTpl'] = <<<'md'
         {{note|trigger=kacayana|text=bla **bold** _em_ bla}}
         md;
 
-        $data['noteTpl2'] = <<<md
+        $data['noteTpl2'] = <<<'md'
         {{note|trigger=kacayana|text={{99-556-8-12}}}}
         md;
 
-        $data['trigger'] = <<<md
+        $data['trigger'] = <<<'md'
         ## heading
         ddd
         - title
@@ -125,7 +129,7 @@ class TestMdRender extends Command
 
         aaa bbb
         md;
-        $data['exercise'] = <<<md
+        $data['exercise'] = <<<'md'
         {{168-916-10-37}}
         {{exercise|1|((168-916-10-37))}}
         {{exercise|
@@ -137,7 +141,7 @@ class TestMdRender extends Command
         content=# ddd}}
         md;
 
-        $data['article'] = <<<md
+        $data['article'] = <<<'md'
         {{article|
         type=article|
         id=27ade9ad-2d0c-4f66-b857-e9335252cc08|
@@ -145,12 +149,12 @@ class TestMdRender extends Command
         style=modal}}
         md;
 
-        $data['footnote'] = <<<md
+        $data['footnote'] = <<<'md'
         # title
         content `note content` `note2 content`
         md;
 
-        $data['paragraph'] = <<<md
+        $data['paragraph'] = <<<'md'
         # title
         content
 
@@ -160,7 +164,7 @@ class TestMdRender extends Command
         the end
         md;
 
-        $data['img'] = <<<md
+        $data['img'] = <<<'md'
         # title
         content
 
@@ -183,7 +187,7 @@ class TestMdRender extends Command
             $this->info("format:{$format}");
             foreach ($data as $key => $value) {
                 $_item = $this->argument('item');
-                if (!empty($_item) && $key !== $_item) {
+                if (! empty($_item) && $key !== $_item) {
                     continue;
                 }
                 $mdRender = new MdRender([
@@ -195,6 +199,7 @@ class TestMdRender extends Command
                 echo $output;
             }
         }
+
         return 0;
     }
 }

+ 9 - 6
api-v13/app/Console/Commands/TestMq.php

@@ -2,25 +2,28 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use Illuminate\Support\Str;
-
 use App\Http\Api\Mq;
-use App\Models\Discussion;
 use App\Http\Resources\DiscussionResource;
-use App\Models\SentPr;
 use App\Http\Resources\SentPrResource;
+use App\Models\Discussion;
+use App\Models\SentPr;
 use App\Services\RabbitMQService;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
+use Illuminate\Support\Str;
 
 class TestMq extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:mq
+     *
      * @var string
      */
     protected $signature = 'test:mq {--discussion=} {--pr=}';
+
     protected $publish;
+
     /**
      * The console command description.
      *
@@ -45,7 +48,7 @@ class TestMq extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $publish = app(RabbitMQService::class);

+ 3 - 1
api-v13/app/Console/Commands/TestMqExit.php

@@ -2,14 +2,15 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\Mq;
+use Illuminate\Console\Command;
 
 class TestMqExit extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:mq.exit
+     *
      * @var string
      */
     protected $signature = 'test:mq.exit';
@@ -41,6 +42,7 @@ class TestMqExit extends Command
         for ($i = 0; $i < 10; $i++) {
             Mq::publish('ai_translate', ['hello world']);
         }
+
         return 0;
     }
 }

+ 17 - 13
api-v13/app/Console/Commands/TestMqWorker.php

@@ -2,15 +2,20 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
+use PhpAmqpLib\Channel\AMQPChannel;
+use PhpAmqpLib\Connection\AbstractConnection;
 use PhpAmqpLib\Connection\AMQPStreamConnection;
 use PhpAmqpLib\Exchange\AMQPExchangeType;
+use PhpAmqpLib\Message\AMQPMessage;
 
 class TestMqWorker extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:mq.worker
+     *
      * @var string
      */
     protected $signature = 'test:mq.worker';
@@ -39,17 +44,17 @@ class TestMqWorker extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $exchange = 'router';
         $queue = 'hello';
         $consumerTag = 'consumer';
-        $connection = new AMQPStreamConnection(config("queue.connections.rabbitmq.host"),
-                                            config("queue.connections.rabbitmq.port"),
-                                            config("queue.connections.rabbitmq.user"),
-                                            config("queue.connections.rabbitmq.password"),
-                                            config("queue.connections.rabbitmq.virtual_host"));
+        $connection = new AMQPStreamConnection(config('queue.connections.rabbitmq.host'),
+            config('queue.connections.rabbitmq.port'),
+            config('queue.connections.rabbitmq.user'),
+            config('queue.connections.rabbitmq.password'),
+            config('queue.connections.rabbitmq.virtual_host'));
         $channel = $connection->channel();
 
         /*
@@ -80,10 +85,9 @@ class TestMqWorker extends Command
         $channel->queue_bind($queue, $exchange);
 
         /**
-         * @param \PhpAmqpLib\Message\AMQPMessage $message
+         * @param  AMQPMessage  $message
          */
-        $process_message = function ($message)
-        {
+        $process_message = function ($message) {
             echo "\n--------\n";
             echo $message->body;
             echo "\n--------\n";
@@ -109,11 +113,10 @@ class TestMqWorker extends Command
         $channel->basic_consume($queue, $consumerTag, false, false, false, false, $process_message);
 
         /**
-         * @param \PhpAmqpLib\Channel\AMQPChannel $channel
-         * @param \PhpAmqpLib\Connection\AbstractConnection $connection
+         * @param  AMQPChannel  $channel
+         * @param  AbstractConnection  $connection
          */
-        $shutdown = function ($channel, $connection)
-        {
+        $shutdown = function ($channel, $connection) {
             $channel->close();
             $connection->close();
         };
@@ -126,6 +129,7 @@ class TestMqWorker extends Command
             // do something else
             usleep(300000);
         }
+
         return 0;
     }
 }

+ 22 - 17
api-v13/app/Console/Commands/TestProjectCopyTask.php

@@ -3,8 +3,8 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Str;
 
 class TestProjectCopyTask extends Command
@@ -12,6 +12,7 @@ class TestProjectCopyTask extends Command
     /**
      * The name and signature of the console command.
      * php artisan test:project.copy.task project-50 dd9bcba8-ad3f-4082-9b52-4f5f8acdbd5f visuddhinanda
+     *
      * @var string
      */
     protected $signature = 'test:project.copy.task {project} {task} {studio} {--token=}';
@@ -52,14 +53,14 @@ class TestProjectCopyTask extends Command
         }
 
         $taskCount = $this->ask('Please enter the task count:');
-        $url = $appUrl . '/api/v2/project-tree';
-        $this->info('create project ' . $url);
-        $projects = array();
+        $url = $appUrl.'/api/v2/project-tree';
+        $this->info('create project '.$url);
+        $projects = [];
         $rootId = Str::uuid();
         $projects[] = [
             'id' => $rootId,
             'title' => $projectTitle,
-            'type' => "instance",
+            'type' => 'instance',
             'parent_id' => '',
             'weight' => 0,
             'res_id' => $rootId,
@@ -69,7 +70,7 @@ class TestProjectCopyTask extends Command
             $projects[] = [
                 'id' => $uid,
                 'title' => "{$projectTitle}_{$i}",
-                'type' => "instance",
+                'type' => 'instance',
                 'parent_id' => $rootId,
                 'weight' => 0,
                 'res_id' => $uid,
@@ -81,46 +82,50 @@ class TestProjectCopyTask extends Command
                 'data' => $projects,
             ]);
         if ($response->failed()) {
-            $this->error('project create fail' . $response->json('message'));
+            $this->error('project create fail'.$response->json('message'));
             Log::error('project create fail', ['data' => $response->body()]);
+
             return 1;
         }
 
         $projectsData = $response->json()['data']['rows'];
-        $this->info('project :' . count($projectsData));
-        //获取task
+        $this->info('project :'.count($projectsData));
+        // 获取task
         $response = Http::withToken($token)
-            ->get($appUrl . '/api/v2/task/' . $taskId);
+            ->get($appUrl.'/api/v2/task/'.$taskId);
         if ($response->failed()) {
-            $this->error('task read fail' . $response->json('message'));
+            $this->error('task read fail'.$response->json('message'));
             Log::error('task read fail', ['data' => $response->body()]);
+
             return 1;
         }
 
-        //建立task
+        // 建立task
         $task = $response->json()['data'];
         $taskTitle = $task['title'];
-        $this->info('task title:' . $task['title']);
-        $tasks = array();
+        $this->info('task title:'.$task['title']);
+        $tasks = [];
         foreach ($projectsData as $key => $project) {
             if ($project['isLeaf']) {
                 $task['title'] = "{$taskTitle}_{$key}";
                 $tasks[] = [
                     'project_id' => $project['id'],
-                    'tasks' => [$task]
+                    'tasks' => [$task],
                 ];
             }
         }
 
         $response = Http::withToken($token)
-            ->post($appUrl . '/api/v2/task-group', [
+            ->post($appUrl.'/api/v2/task-group', [
                 'data' => $tasks,
             ]);
         if ($response->failed()) {
-            $this->error('task create fail' . $response->json('message'));
+            $this->error('task create fail'.$response->json('message'));
             Log::error('task create fail', ['data' => $response->body()]);
+
             return 1;
         }
+
         return 0;
     }
 }

+ 22 - 28
api-v13/app/Console/Commands/TestRedis.php

@@ -3,8 +3,8 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Redis;
 use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Redis;
 
 class TestRedis extends Command
 {
@@ -40,78 +40,72 @@ class TestRedis extends Command
     public function handle()
     {
         $value = 'this is a test';
-        $this->info("test redis start");
+        $this->info('test redis start');
 
-
-        $key = "test-redis";
+        $key = 'test-redis';
         Redis::set($key, $value);
         if (Redis::exists($key)) {
-            $this->info("has key " . $key);
+            $this->info('has key '.$key);
         } else {
-            $this->error("no key " . $key);
+            $this->error('no key '.$key);
         }
         $expire = Redis::expire($key, 10);
-        $this->info("key expire " . $expire);
-        $this->info('del key ' . Redis::del($key));
+        $this->info('key expire '.$expire);
+        $this->info('del key '.Redis::del($key));
         Redis::set($key, $value);
         $getValue = Redis::get($key);
         if ($getValue === $value) {
-            $this->info("redis set ok ");
+            $this->info('redis set ok ');
         } else {
-            $this->error("redis set fail ");
+            $this->error('redis set fail ');
         }
 
-
-        Redis::hSet("test-redis-hash", 'hash', $value);
-        if (Redis::hGet("test-redis-hash", 'hash') == $value) {
-            $this->info("redis hash set ok ");
+        Redis::hSet('test-redis-hash', 'hash', $value);
+        if (Redis::hGet('test-redis-hash', 'hash') == $value) {
+            $this->info('redis hash set ok ');
         } else {
-            $this->error("redis hash set fail ");
+            $this->error('redis hash set fail ');
         }
 
-
-        $this->info("test cache start");
-        $this->info("testing cache put");
+        $this->info('test cache start');
+        $this->info('testing cache put');
         $key = 'cache-key';
 
-
-
         Cache::put($key, $value, 1000);
         if (Cache::has($key)) {
             $this->info("cache::put() exist key={$key}");
             if (Cache::get($key) == $value) {
                 $this->info("cache::get() ok value={$value}");
             } else {
-                $this->error("cache::get() fail ");
+                $this->error('cache::get() fail ');
             }
         } else {
             $this->error('no key cache-key');
         }
 
-
         $key = 'cache-key-2';
-        $this->info("testing cache() function");
+        $this->info('testing cache() function');
         $this->info("cache() key={$key} value={$value}");
-        cache(["cache-key-2" => $value]);
+        cache(['cache-key-2' => $value]);
         if (Cache::has($key)) {
             if (Cache::get($key) == $value) {
                 $this->info("cache() get ok value={$value}");
             } else {
-                $this->error("cache::get() fail ");
+                $this->error('cache::get() fail ');
             }
         } else {
             $this->error('no key cache-key-2');
         }
 
         $key = 'cache-key-3';
-        $this->info("testing cache remember()");
+        $this->info('testing cache remember()');
         $value = Cache::remember($key, 600, function () {
             return 'cache-value-3';
         });
         if (Cache::has($key)) {
-            $this->info("{$key} exist value=" . Cache::get($key));
+            $this->info("{$key} exist value=".Cache::get($key));
         } else {
-            $this->error("cache::remember() fail.");
+            $this->error('cache::remember() fail.');
         }
     }
 }

+ 3 - 1
api-v13/app/Console/Commands/TestSchedule.php

@@ -2,6 +2,7 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Log;
 
@@ -38,11 +39,12 @@ class TestSchedule extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         Log::info('schedule test start');
         $this->info('schedule test start');
+
         return 0;
     }
 }

+ 16 - 15
api-v13/app/Console/Commands/TestSearchPali.php

@@ -2,14 +2,15 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Tools\PaliSearch;
+use Illuminate\Console\Command;
 
 class TestSearchPali extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:search.pali
+     *
      * @var string
      */
     protected $signature = 'test:search.pali {word?}';
@@ -39,36 +40,36 @@ class TestSearchPali extends Command
     public function handle()
     {
         $word = $this->argument('word');
-        if(empty($word)){
+        if (empty($word)) {
             $word = 'citta';
         }
-        $words = str_replace('_',' ',$word);
-        $words = explode(',',$words);
+        $words = str_replace('_', ' ', $word);
+        $words = explode(',', $words);
         $this->info("searching word={$word} limit=10,offset=0");
-        $result = PaliSearch::search($words,[],'case',0,10);
-        if($result){
+        $result = PaliSearch::search($words, [], 'case', 0, 10);
+        if ($result) {
             $this->info("word={$word} total=".$result['total']);
-        }else{
+        } else {
             $this->error("word={$word} search fail");
         }
 
         $rpc_result = PaliSearch::book_list($words,
-                                            [],
-                                            'case');
+            [],
+            'case');
         $this->info('book list count='.count($rpc_result['rows']));
 
         $this->info("searching word={$word} limit=10,offset=10");
-        $result = PaliSearch::search($words,[],'case',10,10);
-        if($result){
+        $result = PaliSearch::search($words, [], 'case', 10, 10);
+        if ($result) {
             $this->info("word={$word} total=".$result['total']);
-        }else{
+        } else {
             $this->error("word={$word} search fail");
         }
         $this->info("searching word={$word} book=267");
-        $result = PaliSearch::search($words,[267],'case',0,3);
-        if($result){
+        $result = PaliSearch::search($words, [267], 'case', 0, 3);
+        if ($result) {
             $this->info("word={$word} book=267 total=".$result['total']);
-        }else{
+        } else {
             $this->error("word={$word} book=267 search fail");
         }
 

+ 13 - 11
api-v13/app/Console/Commands/TestTex.php

@@ -2,9 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Export;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Storage;
-use App\Tools\Export;
 
 class TestTex extends Command
 {
@@ -39,10 +40,10 @@ class TestTex extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $tex = array();
+        $tex = [];
         $content = <<<'EOF'
 % 导言区
 \documentclass[a4paper, 12pt, fontset=ubuntu]{article} % book, report, letter
@@ -65,8 +66,8 @@ class TestTex extends Command
 \end{document}
 
 EOF;
-$tex[] = ['name'=>'main.tex','content'=>$content];
-$content = <<<'EOF'
+        $tex[] = ['name' => 'main.tex', 'content' => $content];
+        $content = <<<'EOF'
 \section{三十位经}
 
 住在王舍城的竹林园。
@@ -76,9 +77,9 @@ $content = <<<'EOF'
 \subsection{子章节1.2 标题}
 子章节1-2 正文
 EOF;
-$tex[] = ['name'=>'section-1.tex','content'=>$content];
+        $tex[] = ['name' => 'section-1.tex', 'content' => $content];
 
-$content = <<<'EOF'
+        $content = <<<'EOF'
 \section{章节2 标题}
 章节2 正文
 \subsection{子章节2.1 标题}
@@ -87,16 +88,17 @@ $content = <<<'EOF'
 子章节2-2 正文
 EOF;
 
-$tex[] = ['name'=>'section-2.tex','content'=>$content];
+        $tex[] = ['name' => 'section-2.tex', 'content' => $content];
 
         $data = Export::ToPdf($tex);
-        if($data['ok']){
-            $filename = "export/test.pdf";
+        if ($data['ok']) {
+            $filename = 'export/test.pdf';
             $this->info($data['content-type']);
             Storage::disk('local')->put($filename, $data['data']);
-        }else{
+        } else {
             $this->error($data['code'].'-'.$data['message']);
         }
+
         return 0;
     }
 }

+ 9 - 6
api-v13/app/Console/Commands/TestWorkerStartProject.php

@@ -3,14 +3,15 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
 use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
 
 class TestWorkerStartProject extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan test:worker.start.project 0c3d2f69-1098-428b-95db-f1183667c799
+     *
      * @var string
      */
     protected $signature = 'test:worker.start.project {project} {--token=}';
@@ -54,23 +55,25 @@ class TestWorkerStartProject extends Command
         );
 
         $response = Http::withToken($token)
-            ->get($appUrl . "/api/v2/task?view=project&project_id={$projectId}&status=all&order=order&dir=asc");
+            ->get($appUrl."/api/v2/task?view=project&project_id={$projectId}&status=all&order=order&dir=asc");
         if ($response->failed()) {
-            $this->error('task read fail' . $response->json('message'));
+            $this->error('task read fail'.$response->json('message'));
             Log::error('task read fail', ['data' => $response->body()]);
+
             return 1;
         }
         $tasks = $response->json()['data']['rows'];
         foreach ($tasks as $key => $task) {
-            $this->info("[{$key}]task " . $task['title'] . ' status ' . $task['status']);
+            $this->info("[{$key}]task ".$task['title'].' status '.$task['status']);
             $response = Http::withToken($token)
-                ->patch($appUrl . "/api/v2/task-status/" . $task['id'], ['status' => $status]);
+                ->patch($appUrl.'/api/v2/task-status/'.$task['id'], ['status' => $status]);
             if ($response->failed()) {
-                $this->error('task status fail' . $response->json('message'));
+                $this->error('task status fail'.$response->json('message'));
                 Log::error('task status fail', ['data' => $response->body()]);
             }
             $this->info("[{$key}]task status changed {$status}");
         }
+
         return 0;
     }
 }

+ 52 - 55
api-v13/app/Console/Commands/UpdateCorpus.php

@@ -2,19 +2,16 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Support\Facades\Log;
-
-
+use App\Http\Api\UserApi;
+use App\Models\Channel;
 use App\Services\SentenceService;
 use App\Services\TermService;
 use Illuminate\Console\Attributes\Description;
 use Illuminate\Console\Attributes\Signature;
 use Illuminate\Console\Command;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Support\Facades\DB;
-use App\Models\Channel;
-
-use App\Http\Api\UserApi;
-
+use Illuminate\Support\Facades\Log;
 
 #[Signature('app:update-corpus {--dir=} {--es}')]
 #[Description('Update corpus from JSONL files in corpus directory')]
@@ -22,8 +19,6 @@ class UpdateCorpus extends Command
 {
     /**
      * The SentenceService instance.
-     *
-     * @var SentenceService
      */
     protected SentenceService $sentenceService;
 
@@ -31,8 +26,6 @@ class UpdateCorpus extends Command
 
     /**
      * Create a new command instance.
-     *
-     * @param SentenceService $sentenceService
      */
     public function __construct(SentenceService $sentenceService, TermService $termService)
     {
@@ -43,8 +36,6 @@ class UpdateCorpus extends Command
 
     /**
      * Execute the console command.
-     *
-     * @return int
      */
     public function handle(): int
     {
@@ -57,8 +48,9 @@ class UpdateCorpus extends Command
             $corpusBasePath = config('mint.path.corpus');
         }
 
-        if (!is_dir($corpusBasePath)) {
+        if (! is_dir($corpusBasePath)) {
             $this->error("Corpus directory not found: {$corpusBasePath}");
+
             return self::FAILURE;
         }
 
@@ -67,10 +59,11 @@ class UpdateCorpus extends Command
 
         if (empty($stores)) {
             $this->warn('No subdirectories found in corpus path.');
+
             return self::SUCCESS;
         }
 
-        $this->info("Found " . count($stores) . " subdirectories to process.");
+        $this->info('Found '.count($stores).' subdirectories to process.');
 
         $totalProcessed = 0;
         $totalErrors = 0;
@@ -91,18 +84,18 @@ class UpdateCorpus extends Command
                             'book' => 0,
                             '--channel' => $channelId,
                             '--granularity' => 'chapter',
-                            '--summary' => 'off'
+                            '--summary' => 'off',
                         ]);
                     }
                 }
             } catch (\Exception $e) {
                 $this->error("Failed to process directory {$store}: {$e->getMessage()}");
-                Log::error("Failed to process directory", [
-                    'dir'        => $store,
-                    'message'    => $e->getMessage(),
-                    'file'       => $e->getFile(),
-                    'line'       => $e->getLine(),
-                    'trace'      => $e->getTraceAsString(),
+                Log::error('Failed to process directory', [
+                    'dir' => $store,
+                    'message' => $e->getMessage(),
+                    'file' => $e->getFile(),
+                    'line' => $e->getLine(),
+                    'trace' => $e->getTraceAsString(),
                 ]);
                 $totalErrors++;
             }
@@ -110,16 +103,11 @@ class UpdateCorpus extends Command
 
         $this->info("Corpus update completed. Total processed: {$totalProcessed}, Total errors: {$totalErrors}");
 
-
-
         return $totalErrors > 0 ? self::FAILURE : self::SUCCESS;
     }
 
     /**
      * Get all subdirectories of a given directory.
-     *
-     * @param string $path
-     * @return array
      */
     protected function getSubdirectories(string $path): array
     {
@@ -131,7 +119,7 @@ class UpdateCorpus extends Command
                 continue;
             }
 
-            $fullPath = $path . DIRECTORY_SEPARATOR . $item;
+            $fullPath = $path.DIRECTORY_SEPARATOR.$item;
             if (is_dir($fullPath)) {
                 $directories[] = $fullPath;
             }
@@ -143,8 +131,6 @@ class UpdateCorpus extends Command
     /**
      * Process a single corpus directory.
      *
-     * @param string $directoryPath
-     * @return array
      * @throws \Exception
      */
     protected function processCorpusDirectory(string $directoryPath): array
@@ -155,17 +141,19 @@ class UpdateCorpus extends Command
         ];
 
         // Read meta.json file
-        $metaFile = $directoryPath . DIRECTORY_SEPARATOR . 'meta.json';
+        $metaFile = $directoryPath.DIRECTORY_SEPARATOR.'meta.json';
 
-        if (!file_exists($metaFile)) {
+        if (! file_exists($metaFile)) {
             $this->warn("meta.json not found in directory: {$directoryPath}");
+
             return $stats;
         }
 
         $metaData = json_decode(file_get_contents($metaFile), true);
 
-        if (!isset($metaData['id'])) {
+        if (! isset($metaData['id'])) {
             $this->error("Invalid meta.json: missing 'id' field in {$directoryPath}");
+
             return $stats;
         }
 
@@ -177,12 +165,13 @@ class UpdateCorpus extends Command
 
         if ($channels->isEmpty()) {
             $this->warn("No channels found with source_id: {$sourceId}");
+
             return $stats;
         }
 
         $this->info("Found {$channels->count()} channel(s) for source ID: {$sourceId}");
 
-        $glossaryFile = $directoryPath . DIRECTORY_SEPARATOR . 'glossary.csv';
+        $glossaryFile = $directoryPath.DIRECTORY_SEPARATOR.'glossary.csv';
 
         if (file_exists($glossaryFile)) {
             $status = $this->processGlossary($glossaryFile, $channels);
@@ -194,7 +183,7 @@ class UpdateCorpus extends Command
 
         foreach ($childDirectories as $childDir) {
             $this->info("Scanning directory for JSONL files: {$childDir}");
-            $jsonlFiles = glob($childDir . DIRECTORY_SEPARATOR . '*.jsonl');
+            $jsonlFiles = glob($childDir.DIRECTORY_SEPARATOR.'*.jsonl');
 
             foreach ($jsonlFiles as $jsonlFile) {
                 $this->line("Processing file: {$jsonlFile}");
@@ -203,35 +192,37 @@ class UpdateCorpus extends Command
                 $stats['errors'] += $fileStats['errors'];
             }
         }
-        $stats['channels'] = array_map(fn($item) => $item['uid'], $channels->toArray());
+        $stats['channels'] = array_map(fn ($item) => $item['uid'], $channels->toArray());
+
         return $stats;
     }
+
     /**
      * Process a glossary csv file and save glossary for each channel.
      *
-     * @param string $filePath
-     * @param \Illuminate\Database\Eloquent\Collection $channels
-     * @return array
+     * @param  Collection  $channels
      */
     protected function processGlossary(string $filePath, $channels): array
     {
         $stats = [
             'processed' => 0,
-            'errors'    => 0,
+            'errors' => 0,
         ];
 
         $handle = fopen($filePath, 'r');
 
-        if (!$handle) {
+        if (! $handle) {
             $this->error("Failed to open file: {$filePath}");
+
             return $stats;
         }
 
         $robotUid = config('mint.admin.robot_uuid');
 
-        if (!$robotUid) {
+        if (! $robotUid) {
             $this->error('robot_uuid not configured in mint.admin.robot_uid');
             fclose($handle);
+
             return $stats;
         }
 
@@ -241,6 +232,7 @@ class UpdateCorpus extends Command
         if ($headers === false) {
             $this->error("Failed to read CSV headers from: {$filePath}");
             fclose($handle);
+
             return $stats;
         }
 
@@ -252,6 +244,7 @@ class UpdateCorpus extends Command
             if (count($row) !== count($headers)) {
                 $this->error("Column count mismatch at line {$lineNumber} in file: {$filePath}");
                 $stats['errors']++;
+
                 continue;
             }
 
@@ -260,14 +253,14 @@ class UpdateCorpus extends Command
             foreach ($channels as $channel) {
                 try {
                     $saveData = [
-                        'word'          => $data['pali_word'],
-                        'tag'           => $data['tag'] ?? null,
-                        'channel_id'    => $channel->uid,
-                        'meaning'       => $data['meaning'],
-                        'redirect'       => $data['redirect'] ?? null,
+                        'word' => $data['pali_word'],
+                        'tag' => $data['tag'] ?? null,
+                        'channel_id' => $channel->uid,
+                        'meaning' => $data['meaning'],
+                        'redirect' => $data['redirect'] ?? null,
                         'other_meaning' => $data['meaning2'] ?: null,
-                        'note'          => $data['note'] ?: null,
-                        'editor_id'     => $editor_id,
+                        'note' => $data['note'] ?: null,
+                        'editor_id' => $editor_id,
                     ];
 
                     DB::transaction(function () use ($saveData) {
@@ -284,14 +277,14 @@ class UpdateCorpus extends Command
 
         fclose($handle);
         $this->line("glossary {$lineNumber} lines processed");
+
         return $stats;
     }
+
     /**
      * Process a single JSONL file and save records for each channel.
      *
-     * @param string $filePath
-     * @param \Illuminate\Database\Eloquent\Collection $channels
-     * @return array
+     * @param  Collection  $channels
      */
     protected function processJsonlFile(string $filePath, $channels): array
     {
@@ -302,17 +295,19 @@ class UpdateCorpus extends Command
 
         $handle = fopen($filePath, 'r');
 
-        if (!$handle) {
+        if (! $handle) {
             $this->error("Failed to open file: {$filePath}");
+
             return $stats;
         }
 
         $lineNumber = 0;
         $robotUid = config('mint.admin.robot_uuid');
 
-        if (!$robotUid) {
+        if (! $robotUid) {
             $this->error('robot_uuid not configured in mint.admin.robot_uuid');
             fclose($handle);
+
             return $stats;
         }
 
@@ -330,6 +325,7 @@ class UpdateCorpus extends Command
             if ($data === null) {
                 $this->error("Failed to parse JSON at line {$lineNumber} in file: {$filePath}");
                 $stats['errors']++;
+
                 continue;
             }
 
@@ -352,7 +348,7 @@ class UpdateCorpus extends Command
                     });
 
                     $stats['processed']++;
-                    //$this->line("Saved record for channel: {$channel->uid}");
+                    // $this->line("Saved record for channel: {$channel->uid}");
                 } catch (\Exception $e) {
                     $this->error("Failed to save record for channel {$channel->uid} at line {$lineNumber}: {$e->getMessage()}");
                     $stats['errors']++;
@@ -362,6 +358,7 @@ class UpdateCorpus extends Command
 
         fclose($handle);
         $this->line("$lineNumber lines write");
+
         return $stats;
     }
 }

+ 7 - 3
api-v13/app/Console/Commands/UpdateOpenSearchIndex.php

@@ -10,6 +10,7 @@ class UpdateOpenSearchIndex extends Command
     /**
      * The name and signature of the console command.
      * php artisan create:opensearch.index
+     *
      * @var string
      */
     protected $signature = 'update:opensearch.index';
@@ -46,6 +47,7 @@ class UpdateOpenSearchIndex extends Command
             $this->info($open[1]);
         } else {
             $this->error($open[1]);
+
             return 1; // Exit with error code
         }
 
@@ -53,19 +55,21 @@ class UpdateOpenSearchIndex extends Command
         $this->warn('Index already exists, attempting to update...');
         try {
             $update = $openSearch->updateIndex();
-            if (!empty($update['settings']) && $update['settings']['acknowledged']) {
+            if (! empty($update['settings']) && $update['settings']['acknowledged']) {
                 $this->info('Index settings updated successfully');
             }
-            if (!empty($update['mappings']) && $update['mappings']['acknowledged']) {
+            if (! empty($update['mappings']) && $update['mappings']['acknowledged']) {
                 $this->info('Index mappings updated successfully');
             }
             if (empty($update['settings']) && empty($update['mappings'])) {
                 $this->warn('No settings or mappings provided for update');
             }
         } catch (\Exception $updateException) {
-            $this->error('Failed to update index: ' . $updateException->getMessage());
+            $this->error('Failed to update index: '.$updateException->getMessage());
+
             return 1;
         }
+
         return 0;
     }
 }

+ 12 - 11
api-v13/app/Console/Commands/UpdateRelationTo.php

@@ -2,8 +2,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\Relation;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 
 class UpdateRelationTo extends Command
 {
@@ -38,19 +39,19 @@ class UpdateRelationTo extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
-        $count=0;
-        $all=0;
-        foreach (Relation::select(['id','to'])->cursor() as $relation) {
+        $count = 0;
+        $all = 0;
+        foreach (Relation::select(['id', 'to'])->cursor() as $relation) {
             $all++;
-            if(!empty($relation->to)){
-                $old = json_decode($relation->to,true);
-                if(count(array_filter(array_keys($old),'is_string'))===0){
-                    //索引数组,需要转换
-                    $new = ['case'=>$old];
-                    Relation::where('id',$relation->id)->update(['to'=>json_encode($new)]);
+            if (! empty($relation->to)) {
+                $old = json_decode($relation->to, true);
+                if (count(array_filter(array_keys($old), 'is_string')) === 0) {
+                    // 索引数组,需要转换
+                    $new = ['case' => $old];
+                    Relation::where('id', $relation->id)->update(['to' => json_encode($new)]);
                     $count++;
                 }
             }

+ 26 - 25
api-v13/app/Console/Commands/UpdateSentenceUnique.php

@@ -2,11 +2,10 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
+use App\Models\Discussion;
 use App\Models\Sentence;
 use App\Models\SentHistory;
-use App\Models\Discussion;
-
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 
 class UpdateSentenceUnique extends Command
@@ -16,6 +15,7 @@ class UpdateSentenceUnique extends Command
      * 与此句相关的资源也要合并,包括,pr,history,discussion
      * 多的句子软删除
      * php artisan update:sentence.unique
+     *
      * @var string
      */
     protected $signature = 'update:sentence.unique';
@@ -44,46 +44,47 @@ class UpdateSentenceUnique extends Command
      */
     public function handle()
     {
-        $queryCount = "SELECT count(*) from (SELECT * from (SELECT book_id ,paragraph ,word_start ,word_end ,channel_uid , count(*) as co from sentences s where ver = 2  group by book_id ,paragraph ,word_start ,word_end ,channel_uid) T where co>1) TT ";
+        $queryCount = 'SELECT count(*) from (SELECT * from (SELECT book_id ,paragraph ,word_start ,word_end ,channel_uid , count(*) as co from sentences s where ver = 2  group by book_id ,paragraph ,word_start ,word_end ,channel_uid) T where co>1) TT ';
         $total = DB::select($queryCount);
-        $querySame = "SELECT * from (SELECT book_id ,paragraph ,word_start ,word_end ,channel_uid , count(*) as co from sentences s where ver = 2  group by book_id ,paragraph ,word_start ,word_end ,channel_uid) T where co>1";
+        $querySame = 'SELECT * from (SELECT book_id ,paragraph ,word_start ,word_end ,channel_uid , count(*) as co from sentences s where ver = 2  group by book_id ,paragraph ,word_start ,word_end ,channel_uid) T where co>1';
         $query = DB::select($querySame);
 
         $count = 0;
         foreach ($query as $key => $value) {
             $count++;
-            $same = Sentence::where('book_id',$value->book_id)
-                            ->where('paragraph',$value->paragraph)
-                            ->where('word_start',$value->word_start)
-                            ->where('word_end',$value->word_end)
-                            ->where('channel_uid',$value->channel_uid)
-                            ->orderBy('updated_at','desc')
-                            ->get();
-            $per = (int)($count*100 / $total[0]->count);
+            $same = Sentence::where('book_id', $value->book_id)
+                ->where('paragraph', $value->paragraph)
+                ->where('word_start', $value->word_start)
+                ->where('word_end', $value->word_end)
+                ->where('channel_uid', $value->channel_uid)
+                ->orderBy('updated_at', 'desc')
+                ->get();
+            $per = (int) ($count * 100 / $total[0]->count);
             $this->info("[{$per}]-{$count} ".$same[0]->updated_at.' '.$same[1]->updated_at.' '.count($same));
 
-            for ($i=1; $i < count($same); $i++) {
-                //将旧数据的历史记录 重新定位到新数据
-                $history = SentHistory::where('sent_uid',$same[$i]->uid)
-                                      ->update(['sent_uid'=>$same[0]->uid]);
-                //将旧数据的discussion 重新定位到新数据
-                $discussion = Discussion::where('res_id',$same[$i]->uid)
-                                        ->update(['res_id'=>$same[0]->uid]);
+            for ($i = 1; $i < count($same); $i++) {
+                // 将旧数据的历史记录 重新定位到新数据
+                $history = SentHistory::where('sent_uid', $same[$i]->uid)
+                    ->update(['sent_uid' => $same[0]->uid]);
+                // 将旧数据的discussion 重新定位到新数据
+                $discussion = Discussion::where('res_id', $same[$i]->uid)
+                    ->update(['res_id' => $same[0]->uid]);
                 $this->info("{$history}-$discussion");
-                //将旧数据的 pr 重新定位到新数据
-                //删除旧数据
+                // 将旧数据的 pr 重新定位到新数据
+                // 删除旧数据
                 $same[$i]->delete();
-                if($same[$i]->trashed()){
+                if ($same[$i]->trashed()) {
                     $this->info('软删除成功!');
-                }else{
+                } else {
                     $this->error('软删除失败!');
                 }
             }
 
-            if($count >= 1){
+            if ($count >= 1) {
                 break;
             }
         }
+
         return 0;
     }
 }

+ 8 - 6
api-v13/app/Console/Commands/UpdateSentenceVer.php

@@ -2,8 +2,8 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\Sentence;
+use Illuminate\Console\Command;
 use Illuminate\Support\Str;
 
 class UpdateSentenceVer extends Command
@@ -11,6 +11,7 @@ class UpdateSentenceVer extends Command
     /**
      * 将无channel_uid的旧版句子数据的ver修改为1.
      * php artisan update:sentence.ver
+     *
      * @var string
      */
     protected $signature = 'update:sentence.ver';
@@ -40,19 +41,20 @@ class UpdateSentenceVer extends Command
     public function handle()
     {
         $count = 0;
-        $total = Sentence::whereNull('channel_uid')->orWhere('channel_uid','')->count();
-        foreach (Sentence::whereNull('channel_uid')->orWhere('channel_uid','')->cursor() as $key => $value) {
-            # code...
+        $total = Sentence::whereNull('channel_uid')->orWhere('channel_uid', '')->count();
+        foreach (Sentence::whereNull('channel_uid')->orWhere('channel_uid', '')->cursor() as $key => $value) {
+            // code...
             $value->ver = 1;
             $value->channel_uid = Str::uuid();
             $value->save();
             $count++;
-            if($count % 1000 === 0){
-                $per = (int)($count*100 / $total);
+            if ($count % 1000 === 0) {
+                $per = (int) ($count * 100 / $total);
                 $this->info("[{$per}%]-{$count}");
             }
         }
         $this->info("all done [{$count}]");
+
         return 0;
     }
 }

+ 4 - 4
api-v13/app/Console/Commands/UpgradeAITranslation.php

@@ -146,7 +146,7 @@ class UpgradeAITranslation extends Command
         $cacheKey = self::CACHE_KEY_PREFIX.':'.$type.':'.$channelId;
 
         if ($this->option('fresh')) {
-            //Cache::forget($cacheKey);
+            // Cache::forget($cacheKey);
             $this->info('Cleared cached cursor.');
         }
 
@@ -154,7 +154,7 @@ class UpgradeAITranslation extends Command
         $isFullRun = ! $this->option('book') && ! $this->option('para');
 
         // 从缓存恢复已完成的 (book, para) 集合,作为重入时的稳定游标
-        $done = [];// Cache::get($cacheKey, []);
+        $done = []; // Cache::get($cacheKey, []);
 
         $books = [];
         if ($this->option('book')) {
@@ -209,7 +209,7 @@ class UpgradeAITranslation extends Command
                 $this->info($this->argument('type')." {$book}-{$paragraph} ".count($data).' sentences time='.$time);
                 // 该处理单元全部写库完成后再标记游标,确保中途中断不会误跳过
                 $done[$cursor] = true;
-                //Cache::put($cacheKey, $done, now()->addHours(24));
+                // Cache::put($cacheKey, $done, now()->addHours(24));
             }
 
             $param = [
@@ -236,7 +236,7 @@ class UpgradeAITranslation extends Command
 
         // 完整遍历正常结束,清空断点缓存
         if ($isFullRun) {
-            //Cache::forget($cacheKey);
+            // Cache::forget($cacheKey);
         }
 
         return 0;

+ 4 - 3
api-v13/app/Console/Commands/UpgradeAt20230227.php

@@ -2,6 +2,7 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 
 class UpgradeAt20230227 extends Command
@@ -37,7 +38,7 @@ class UpgradeAt20230227 extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $this->call('init:system.channel');
@@ -46,13 +47,13 @@ class UpgradeAt20230227 extends Command
         $this->call('upgrade:dict.vocabulary');
         $this->call('upgrade:dict.default.meaning');
 
-        //语料库
+        // 语料库
         $this->call('init:cs6sentence');
         $this->call('upgrade:palitext');
         $this->call('upgrade:wbw.template');
 
         $this->call('upgrade:related.paragraph');
-        $this->call('upgrade:fts',['--content'=>true]);
+        $this->call('upgrade:fts', ['--content' => true]);
         $this->call('upgrade:pcd.book.id');
 
         return 0;

+ 23 - 24
api-v13/app/Console/Commands/UpgradeChapterDynamicDaily.php

@@ -2,13 +2,13 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Support\Facades\Storage;
+use App\Models\PaliText;
+use App\Models\ProgressChapter;
+use App\Models\SentHistory;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Carbon;
-use App\Models\SentHistory;
-use App\Models\Sentence;
-use App\Models\ProgressChapter;
-use App\Models\PaliText;
+use Illuminate\Support\Facades\Storage;
 
 class UpgradeChapterDynamicDaily extends Command
 {
@@ -43,7 +43,7 @@ class UpgradeChapterDynamicDaily extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $this->info('upgrade:chapterdynamic start.');
@@ -51,22 +51,21 @@ class UpgradeChapterDynamicDaily extends Command
         $startAt = time();
         $img_width = 600;
         $img_height = 120;
-        $days = 300; //统计多少天
+        $days = 300; // 统计多少天
         $min = 30;
         $linewidth = 2;
 
-
-        //更新总动态
-        $this->info("更新总动态");
+        // 更新总动态
+        $this->info('更新总动态');
         $chapters = ProgressChapter::select('book', 'para')
             ->groupBy('book', 'para')
             ->orderBy('book')
             ->get();
         $bar = $this->output->createProgressBar(count($chapters));
         foreach ($chapters as $key => $chapter) {
-            # code...
+            // code...
             $max = 0;
-            #章节长度
+            // 章节长度
             $paraEnd = PaliText::where('book', $chapter->book)
                 ->where('paragraph', $chapter->para)
                 ->value('chapter_len') + $chapter->para - 1;
@@ -74,9 +73,9 @@ class UpgradeChapterDynamicDaily extends Command
             $svg = "<svg xmlns='http://www.w3.org/2000/svg'  fill='currentColor' viewBox='0 0 $img_width $img_height'>";
             $svg .= "<polyline points='";
             for ($i = $days; $i > 0; $i--) {
-                # code...
+                // code...
 
-                #这一天有多少次更新
+                // 这一天有多少次更新
                 $count = SentHistory::whereDate('sent_histories.created_at', '=', Carbon::today()->subDays($i)->toDateString())
                     ->leftJoin('sentences', 'sent_histories.sent_uid', '=', 'sentences.uid')
                     ->where('book_id', $chapter->book)
@@ -92,7 +91,7 @@ class UpgradeChapterDynamicDaily extends Command
             $bar->advance();
 
             if ($this->option('test')) {
-                break; //调试代码
+                break; // 调试代码
             }
         }
         $bar->finish();
@@ -111,13 +110,13 @@ class UpgradeChapterDynamicDaily extends Command
         $svg = "<svg xmlns='http://www.w3.org/2000/svg'  fill='currentColor' viewBox='0 0 $img_width $img_height'></svg>";
         foreach ($chapters as $key => $chapter) {
             $filename = "{$chapter->book}/{$chapter->paragraph}/globle.svg";
-            if (!Storage::disk('local')->exists("public/images/chapter_dynamic/{$filename}")) {
+            if (! Storage::disk('local')->exists("public/images/chapter_dynamic/{$filename}")) {
                 Storage::disk('local')->put("public/images/chapter_dynamic/{$filename}", $svg);
             }
             $bar->advance();
 
             if ($this->option('test')) {
-                break; //调试代码
+                break; // 调试代码
             }
         }
         $bar->finish();
@@ -125,14 +124,14 @@ class UpgradeChapterDynamicDaily extends Command
         $this->info("用时 {$time}");
 
         $startAt = time();
-        //更新chennel动态
+        // 更新chennel动态
         $this->info('更新chennel动态');
         $bar = $this->output->createProgressBar(ProgressChapter::count());
 
         foreach (ProgressChapter::select('book', 'para', 'channel_id')->cursor() as $chapter) {
-            # code...
+            // code...
             $max = 0;
-            #章节长度
+            // 章节长度
             $paraEnd = PaliText::where('book', $chapter->book)
                 ->where('paragraph', $chapter->para)
                 ->value('chapter_len') + $chapter->para - 1;
@@ -140,9 +139,9 @@ class UpgradeChapterDynamicDaily extends Command
             $svg = "<svg xmlns='http://www.w3.org/2000/svg'  fill='currentColor' viewBox='0 0 $img_width $img_height'>";
             $svg .= "<polyline points='";
             for ($i = $days; $i > 0; $i--) {
-                # code...
+                // code...
 
-                #这一天有多少次更新
+                // 这一天有多少次更新
                 $count = SentHistory::whereDate('sent_histories.created_at', '=', Carbon::today()->subDays($i)->toDateString())
                     ->leftJoin('sentences', 'sent_histories.sent_uid', '=', 'sentences.uid')
                     ->where('book_id', $chapter->book)
@@ -159,14 +158,14 @@ class UpgradeChapterDynamicDaily extends Command
             $bar->advance();
 
             if ($this->option('test')) {
-                break; //调试代码
+                break; // 调试代码
             }
         }
         $bar->finish();
         $time = time() - $startAt;
         $this->info("用时 {$time}");
 
-        $this->info("upgrade:chapterdynamic done");
+        $this->info('upgrade:chapterdynamic done');
 
         return 0;
     }

+ 27 - 28
api-v13/app/Console/Commands/UpgradeChapterDynamicWeekly.php

@@ -2,13 +2,12 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Support\Facades\Storage;
+use App\Models\PaliText;
+use App\Models\ProgressChapter;
+use App\Models\SentHistory;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Carbon;
-use App\Models\SentHistory;
-use App\Models\Sentence;
-use App\Models\ProgressChapter;
-use App\Models\PaliText;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Log;
 
@@ -45,18 +44,18 @@ class UpgradeChapterDynamicWeekly extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         Log::debug('upgrade:chapter.dynamic.weekly start.');
         $this->info('upgrade:chapter.dynamic.weekly start.');
 
         $startAt = time();
-        $weeks = 60; //统计多少周
+        $weeks = 60; // 统计多少周
 
-        //更新总动态
-        $this->info("更新总动态");
-        Log::debug("task:更新总动态开始");
+        // 更新总动态
+        $this->info('更新总动态');
+        Log::debug('task:更新总动态开始');
         $table = ProgressChapter::select('book', 'para')
             ->groupBy('book', 'para')
             ->orderBy('book');
@@ -67,20 +66,20 @@ class UpgradeChapterDynamicWeekly extends Command
         $bar = $this->output->createProgressBar(count($chapters));
         Log::debug('chapter {count} ', ['count', count($chapters)]);
         foreach ($chapters as $key => $chapter) {
-            #章节长度
+            // 章节长度
             $paraEnd = PaliText::where('book', $chapter->book)
                 ->where('paragraph', $chapter->para)
                 ->value('chapter_len') + $chapter->para - 1;
 
             $progress = [];
             for ($i = $weeks; $i > 0; $i--) {
-                #这一周有多少次更新
+                // 这一周有多少次更新
                 $currDay = $i * 7 + $this->option('offset', 0);
                 $count = SentHistory::whereBetween(
                     'sent_histories.created_at',
                     [
                         Carbon::today()->subDays($currDay)->startOfWeek(),
-                        Carbon::today()->subDays($currDay)->endOfWeek()
+                        Carbon::today()->subDays($currDay)->endOfWeek(),
                     ]
                 )
                     ->leftJoin('sentences', 'sent_histories.sent_uid', '=', 'sentences.uid')
@@ -97,13 +96,13 @@ class UpgradeChapterDynamicWeekly extends Command
             if ($this->option('test')) {
                 $this->info("key:{$key}");
                 if (Cache::has($key)) {
-                    $this->info('has key ' . $key);
+                    $this->info('has key '.$key);
                 }
-                break; //调试代码
+                break; // 调试代码
             }
         }
         $bar->finish();
-        Log::debug("task:更新总动态结束");
+        Log::debug('task:更新总动态结束');
 
         $time = time() - $startAt;
         $this->info("用时 {$time}");
@@ -111,32 +110,32 @@ class UpgradeChapterDynamicWeekly extends Command
         $startAt = time();
 
         $startAt = time();
-        //更新chennel动态
+        // 更新chennel动态
         $this->info('更新channel动态');
-        Log::debug("task:更新channel动态开始");
+        Log::debug('task:更新channel动态开始');
 
         $table = ProgressChapter::select('book', 'para', 'channel_id');
         if ($this->option('book')) {
             $table = $table->where('book', $this->option('book'));
         }
         $bar = $this->output->createProgressBar($table->count());
-        Log::debug("更新channel动态 {count}", ['count' => $table->count()]);
+        Log::debug('更新channel动态 {count}', ['count' => $table->count()]);
         foreach ($table->cursor() as $chapter) {
-            # code...
+            // code...
             $max = 0;
-            #章节长度
+            // 章节长度
             $paraEnd = PaliText::where('book', $chapter->book)
                 ->where('paragraph', $chapter->para)
                 ->value('chapter_len') + $chapter->para - 1;
             $progress = [];
             for ($i = $weeks; $i > 0; $i--) {
-                #这一周有多少次更新
+                // 这一周有多少次更新
                 $currDay = $i * 7 + $this->option('offset', 0);
                 $count = SentHistory::whereBetween(
                     'sent_histories.created_at',
                     [
                         Carbon::today()->subDays($currDay)->startOfWeek(),
-                        Carbon::today()->subDays($currDay)->endOfWeek()
+                        Carbon::today()->subDays($currDay)->endOfWeek(),
                     ]
                 )
                     ->leftJoin('sentences', 'sent_histories.sent_uid', '=', 'sentences.uid')
@@ -153,19 +152,19 @@ class UpgradeChapterDynamicWeekly extends Command
             if ($this->option('test')) {
                 $this->info("key:{$key}");
                 if (Cache::has($key)) {
-                    $this->info('has key ' . $key);
+                    $this->info('has key '.$key);
                 }
-                break; //调试代码
+                break; // 调试代码
             }
         }
         $bar->finish();
-        Log::debug("task:更新channel动态结束");
+        Log::debug('task:更新channel动态结束');
 
         $time = time() - $startAt;
         $this->info("用时 {$time}");
 
-        $this->info("upgrade:chapter.dynamic done");
-        Log::debug("task: upgrade:chapter.dynamic done");
+        $this->info('upgrade:chapter.dynamic done');
+        Log::debug('task: upgrade:chapter.dynamic done');
 
         return 0;
     }

+ 30 - 30
api-v13/app/Console/Commands/UpgradeCommunityTerm.php

@@ -2,13 +2,12 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
-use App\Tools\Tools;
+use App\Http\Api\ChannelApi;
 use App\Models\DhammaTerm;
-use App\Models\UserOperationDaily;
 use App\Models\Sentence;
-
-use App\Http\Api\ChannelApi;
+use App\Models\UserOperationDaily;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Str;
 
 class UpgradeCommunityTerm extends Command
@@ -44,19 +43,20 @@ class UpgradeCommunityTerm extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $lang = strtolower($this->argument('lang'));
         $langFamily = explode('-', $lang)[0];
         $localTerm = ChannelApi::getSysChannel("_community_term_{$lang}_");
-        if (!$localTerm) {
+        if (! $localTerm) {
             return 1;
         }
 
         $channelId = ChannelApi::getSysChannel('_System_Pali_VRI_');
         if ($channelId === false) {
             $this->error('no channel');
+
             return 1;
         }
         $table = DhammaTerm::select(['word', 'tag'])
@@ -74,34 +74,34 @@ class UpgradeCommunityTerm extends Command
              * 1. 找到最常见的意思
              * 2. 找到分数最高的
              */
-            $bestNote = "";
+            $bestNote = '';
             $allTerm = DhammaTerm::where('word', $word->word)
                 ->where('tag', $word->tag)
                 ->whereIn('language', [$this->argument('lang'), $lang, $langFamily])
                 ->get();
             $score = [];
-            //$term_exp = [];
+            // $term_exp = [];
             foreach ($allTerm as $key => $term) {
-                //获取经验值
+                // 获取经验值
                 $exp = UserOperationDaily::where('user_id', $term->editor_id)
                     ->where('date_int', '<=', date_timestamp_get(date_create($term->updated_at)) * 1000)
                     ->sum('duration');
-                $iExp = (int)($exp / 1000);
+                $iExp = (int) ($exp / 1000);
                 $noteStrLen = $term->note ? mb_strlen($term->note, 'UTF-8') : 0;
                 $paliStrLen = 0;
                 $tranStrLen = 0;
-                $noteWithoutPali = "";
-                if ($term->note && !empty(trim($term->note))) {
-                    //计算note得分
-                    //查找句子模版
+                $noteWithoutPali = '';
+                if ($term->note && ! empty(trim($term->note))) {
+                    // 计算note得分
+                    // 查找句子模版
                     $pattern = "/\{\{[0-9].+?\}\}/";
-                    //获取去掉句子模版的剩余部分
-                    $noteWithoutPali = preg_replace($pattern, "", $term->note);
+                    // 获取去掉句子模版的剩余部分
+                    $noteWithoutPali = preg_replace($pattern, '', $term->note);
                     $sentences = [];
                     $iSent = preg_match_all($pattern, $term->note, $sentences);
                     if ($iSent > 0) {
-                        foreach ($sentences[0] as  $sentence) {
-                            $sentId = explode("-", trim($sentence, "{}"));
+                        foreach ($sentences[0] as $sentence) {
+                            $sentId = explode('-', trim($sentence, '{}'));
                             if (count($sentId) === 4) {
                                 $hasTran = Sentence::where('book_id', $sentId[0])
                                     ->where('paragraph', $sentId[1])
@@ -113,7 +113,7 @@ class UpgradeCommunityTerm extends Command
                                     ->where('paragraph', $sentId[1])
                                     ->where('word_start', $sentId[2])
                                     ->where('word_end', $sentId[3])
-                                    ->where("channel_uid", $channelId)
+                                    ->where('channel_uid', $channelId)
                                     ->value('strlen');
                                 if ($sentLen) {
                                     $paliStrLen += $sentLen;
@@ -125,14 +125,14 @@ class UpgradeCommunityTerm extends Command
                         }
                     }
                 }
-                //计算该术语note的总得分
+                // 计算该术语note的总得分
                 $score["{$key}"] = $iExp * $noteStrLen;
-                //$term_exp["{$key}"] = $iExp;
-                //$updated_time["{$key}"] = $term->updated_at 先提取,具体如何使用待定
+                // $term_exp["{$key}"] = $iExp;
+                // $updated_time["{$key}"] = $term->updated_at 先提取,具体如何使用待定
 
             }
 
-            //需要过滤掉system_term的数量,把count(*)替换为经验值加合作为基础得分,(基础经验得分之和转化为标准活动周,再加上最近的更新时间,为最终得分)
+            // 需要过滤掉system_term的数量,把count(*)替换为经验值加合作为基础得分,(基础经验得分之和转化为标准活动周,再加上最近的更新时间,为最终得分)
             $hotMeaning = DhammaTerm::selectRaw('meaning,count(*) as co')
                 ->where('word', $word->word)
                 ->whereIn('language', [$this->argument('lang'), $lang, $langFamily])
@@ -140,17 +140,17 @@ class UpgradeCommunityTerm extends Command
                 ->orderBy('co', 'desc')
                 ->first();
             if ($hotMeaning) {
-                $bestNote = "";
+                $bestNote = '';
                 if (count($score) > 0) {
                     arsort($score);
-                    $bestNote = $allTerm[(int)key($score)]->note;
+                    $bestNote = $allTerm[(int) key($score)]->note;
                 }
 
                 $term = DhammaTerm::where('channal', $localTerm)->firstOrNew(
                     [
-                        "word" => $word->word,
-                        "tag" => $word->tag,
-                        "channal" => $localTerm,
+                        'word' => $word->word,
+                        'tag' => $word->tag,
+                        'channal' => $localTerm,
                     ],
                     [
                         'id' => app('snowflake')->id(),
@@ -158,7 +158,7 @@ class UpgradeCommunityTerm extends Command
                         'word_en' => Tools::getWordEn($word->word),
                         'meaning' => '',
                         'language' => $this->argument('lang'),
-                        'owner' => config("mint.admin.root_uuid"),
+                        'owner' => config('mint.admin.root_uuid'),
                         'editor_id' => 0,
                         'create_time' => time() * 1000,
                     ]

+ 68 - 60
api-v13/app/Console/Commands/UpgradeCompound.php

@@ -2,26 +2,26 @@
 
 namespace App\Console\Commands;
 
-use Exception;
-use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Storage;
-use App\Models\WordIndex;
-use App\Models\WbwTemplate;
+use App\Http\Api\DictApi;
 use App\Models\UserDict;
-use Illuminate\Support\Facades\Log;
-
+use App\Models\WbwTemplate;
+use App\Models\WordIndex;
+use App\Tools\Tools;
 use App\Tools\TurboSplit;
-use App\Http\Api\DictApi;
+use Exception;
 use GuzzleHttp\Exception\GuzzleException;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Http;
-
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
 
 class UpgradeCompound extends Command
 {
     /**
      * The name and signature of the console command.
      * php -d memory_limit=2024M artisan upgrade:compound  --api=https://next.wikipali.org/api --from=0 --to=500000
+     *
      * @var string
      */
     protected $signature = 'upgrade:compound {word?} {--book=} {--debug} {--test} {--continue} {--api=} {--from=0} {--to=0} {--min=7} {--max=50} {--timeout=600}';
@@ -52,40 +52,40 @@ class UpgradeCompound extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             $this->info('.stop exists');
+
             return 0;
         }
         $confirm = '';
         if ($this->option('api')) {
-            $confirm .= 'api=' . $this->option('api') . PHP_EOL;
+            $confirm .= 'api='.$this->option('api').PHP_EOL;
         }
-        $confirm .= "min=" . $this->option('min') . PHP_EOL;
-        $confirm .= "max="  . $this->option('max') . PHP_EOL;
-        $confirm .= "from="  . $this->option('from') . PHP_EOL;
-        $confirm .= "to="  . $this->option('to') . PHP_EOL;
+        $confirm .= 'min='.$this->option('min').PHP_EOL;
+        $confirm .= 'max='.$this->option('max').PHP_EOL;
+        $confirm .= 'from='.$this->option('from').PHP_EOL;
+        $confirm .= 'to='.$this->option('to').PHP_EOL;
 
-        if (!$this->confirm($confirm)) {
+        if (! $this->confirm($confirm)) {
             return 0;
         }
-        $this->info('[' . date('Y-m-d H:i:s', time()) . '] upgrade:compound start');
+        $this->info('['.date('Y-m-d H:i:s', time()).'] upgrade:compound start');
 
         $dict_id = DictApi::getSysDict('robot_compound');
-        if (!$dict_id) {
+        if (! $dict_id) {
             $this->error('没有找到 robot_compound 字典');
+
             return 1;
         }
 
         $start = \microtime(true);
 
-
-
         //
         if ($this->option('test')) {
-            //调试代码
+            // 调试代码
             $ts = new TurboSplit(['timeout' => $this->option('timeout')]);
-            Storage::disk('local')->put("tmp/compound.md", "# Turbo Split");
-            //获取需要拆的词
+            Storage::disk('local')->put('tmp/compound.md', '# Turbo Split');
+            // 获取需要拆的词
             $list = [
                 [5, 20, 20],
                 [21, 30, 20],
@@ -93,32 +93,33 @@ class UpgradeCompound extends Command
                 [41, 60, 10],
             ];
             foreach ($list as $take) {
-                # code...
+                // code...
                 $words = WordIndex::where('final', 0)
                     ->whereBetween('len', [$take[0], $take[1]])
                     ->select('word')
                     ->take($take[2])->get();
                 foreach ($words as $word) {
                     $this->info($word->word);
-                    Storage::disk('local')->append("tmp/compound.md", "## {$word->word}");
+                    Storage::disk('local')->append('tmp/compound.md', "## {$word->word}");
                     $parts = $ts->splitA($word->word);
                     foreach ($parts as $part) {
-                        # code...
+                        // code...
                         $info = "`{$part['word']}`,{$part['factors']},{$part['confidence']}";
                         $this->info($info);
-                        Storage::disk('local')->append("tmp/compound.md", "- {$info}");
+                        Storage::disk('local')->append('tmp/compound.md', "- {$info}");
                     }
                 }
             }
-            $this->info("耗时:" . \microtime(true) - $start);
+            $this->info('耗时:'.\microtime(true) - $start);
+
             return 0;
         }
 
         $_word = $this->argument('word');
-        if (!empty($_word)) {
-            $words = array((object)array('real' => $_word, 'id' => 0));
+        if (! empty($_word)) {
+            $words = [(object) ['real' => $_word, 'id' => 0]];
             $total = 1;
-        } else if ($this->option('book')) {
+        } elseif ($this->option('book')) {
             $words = WbwTemplate::select('real')
                 ->where('book', $this->option('book'))
                 ->where('type', '<>', '.ctl.')
@@ -157,27 +158,30 @@ class UpgradeCompound extends Command
                 ->cursor();
         }
 
-        $wordIndex = array();
-        $result = array();
+        $wordIndex = [];
+        $result = [];
 
         $loopTime = 0;
         foreach ($words as $key => $word) {
             $startAt = microtime(true);
-            if (\App\Tools\Tools::isStop()) {
+            if (Tools::isStop()) {
                 $this->info('system stop');
+
                 return 0;
             }
-            $percent = (int)($key * 100 / $total);
+            $percent = (int) ($key * 100 / $total);
             if (preg_match('/\d/', $word->real)) {
                 $this->info("[{$percent}%] {$word->real} 数字不处理");
+
                 continue;
             }
-            //判断数据库里面是否有
+            // 判断数据库里面是否有
             $exists = UserDict::where('dict_id', $dict_id)
                 ->where('word', $word->real)
                 ->exists();
             if ($exists) {
                 $this->info("[{$percent}%]-{$key}-{$word->real}数据库中已经有了");
+
                 continue;
             }
 
@@ -185,19 +189,19 @@ class UpgradeCompound extends Command
             $this->info("[{$percent}%]-[{$now}]{$word->real} start id={$word->id}");
             $wordIndex[] = $word->real;
 
-            //先查询vir数据有没有拆分
-            $parts = array();
+            // 先查询vir数据有没有拆分
+            $parts = [];
             $wbwWords = WbwTemplate::where('real', $word->real)
                 ->select('word')->groupBy('word')->get();
             foreach ($wbwWords as $key => $wbwWord) {
                 if (strpos($wbwWord->word, '-') !== false) {
                     $wbwFactors = explode('-', $wbwWord->word);
-                    //看词尾是否能找到语尾
+                    // 看词尾是否能找到语尾
                     $endWord = end($wbwFactors);
                     $endWordInDict = UserDict::where('word', $endWord)->get();
                     foreach ($endWordInDict as $key => $oneWord) {
                         if (
-                            !empty($oneWord->type) &&
+                            ! empty($oneWord->type) &&
                             strpos($oneWord->type, 'base') === false &&
                             $oneWord->type !== '.cp.'
                         ) {
@@ -206,7 +210,7 @@ class UpgradeCompound extends Command
                                 'type' => $oneWord->type,
                                 'grammar' => $oneWord->grammar,
                                 'parent' => $oneWord->parent,
-                                'factors' => implode('+', array_slice($wbwFactors, 0, -1)) . '+' . $oneWord->factors,
+                                'factors' => implode('+', array_slice($wbwFactors, 0, -1)).'+'.$oneWord->factors,
                                 'confidence' => 100,
                             ];
                         }
@@ -220,25 +224,25 @@ class UpgradeCompound extends Command
                 }
                 $parts = $ts->splitA($word->real);
             } else {
-                $this->info("找到vri拆分数据:" . count($parts));
+                $this->info('找到vri拆分数据:'.count($parts));
             }
 
             $resultCount = 0;
             foreach ($parts as $part) {
-                if (isset($part['type']) && $part['type'] === ".v.") {
+                if (isset($part['type']) && $part['type'] === '.v.') {
                     continue;
                 }
                 if (empty($part['word'])) {
                     continue;
                 }
                 $resultCount++;
-                $new = array();
+                $new = [];
                 $new['word'] = $part['word'];
                 $new['factors'] = $part['factors'];
                 if (isset($part['type'])) {
                     $new['type'] = $part['type'];
                 } else {
-                    $new['type'] = ".cp.";
+                    $new['type'] = '.cp.';
                 }
                 if (isset($part['grammar'])) {
                     $new['grammar'] = $part['grammar'];
@@ -253,8 +257,8 @@ class UpgradeCompound extends Command
                 $new['confidence'] = 50 * $part['confidence'];
                 $result[] = $new;
 
-                if (!empty($_word)) {
-                    //指定拆分单词输出结果
+                if (! empty($_word)) {
+                    // 指定拆分单词输出结果
                     $debugOutput = [
                         $resultCount,
                         $part['word'],
@@ -262,7 +266,7 @@ class UpgradeCompound extends Command
                         $part['grammar'],
                         $part['parent'],
                         $part['factors'],
-                        $part['confidence']
+                        $part['confidence'],
                     ];
                     $this->info(implode(',', $debugOutput));
                 }
@@ -273,20 +277,21 @@ class UpgradeCompound extends Command
             $this->info("[{$percent}%][{$key}] {$word->real}  {$time}s total{$loopTime}");
 
             if ($loopTime > $this->MaxOneLoopTime) {
-                //到时间上传
+                // 到时间上传
                 $ok = $this->upload($wordIndex, $result, $this->option('api'));
-                if (!$ok) {
-                    Log::error('break on ' . $word->id);
+                if (! $ok) {
+                    Log::error('break on '.$word->id);
+
                     return 1;
                 }
-                $wordIndex = array();
-                $result = array();
+                $wordIndex = [];
+                $result = [];
                 $loopTime = 0;
             }
         }
         $this->upload($wordIndex, $result, $this->option('api'));
 
-        $this->info('[' . date('Y-m-d H:i:s', time()) . '] upgrade:compound finished');
+        $this->info('['.date('Y-m-d H:i:s', time()).'] upgrade:compound finished');
 
         return 0;
     }
@@ -296,13 +301,13 @@ class UpgradeCompound extends Command
         if (count($words) === 0) {
             return;
         }
-        if (!$url) {
-            $url = config('app.url') . '/api/v2/compound';
+        if (! $url) {
+            $url = config('app.url').'/api/v2/compound';
         } else {
-            $url = $url . '/v2/compound';
+            $url = $url.'/v2/compound';
         }
-        $this->info('url = ' . $url);
-        $this->info('uploading size=' . strlen(json_encode($words, JSON_UNESCAPED_UNICODE)));
+        $this->info('url = '.$url);
+        $this->info('uploading size='.strlen(json_encode($words, JSON_UNESCAPED_UNICODE)));
 
         $httpError = false;
         $Max_Loop = 10;
@@ -311,6 +316,7 @@ class UpgradeCompound extends Command
             $response = Http::retry($Max_Loop, 100, function (Exception $exception) {
                 Log::error('upload fail.', ['error' => $exception]);
                 $this->error('upload fail. try again');
+
                 return true;
             })
                 ->post(
@@ -325,7 +331,7 @@ class UpgradeCompound extends Command
                 $httpError = false;
             } else {
                 $this->error('upload fail.');
-                Log::error('upload fail.' . $response->body());
+                Log::error('upload fail.'.$response->body());
             }
         } catch (GuzzleException $e) {
             Log::error('send data failed', ['exception' => $e]);
@@ -334,8 +340,10 @@ class UpgradeCompound extends Command
 
         if ($httpError) {
             Log::error('upload fail.try max');
+
             return false;
         }
+
         return true;
     }
 }

+ 13 - 14
api-v13/app/Console/Commands/UpgradeDaily.php

@@ -2,11 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Tools\Tools;
 use Illuminate\Console\Command;
-use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\Log;
 
-
 class UpgradeDaily extends Command
 {
     /**
@@ -40,7 +39,7 @@ class UpgradeDaily extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $env = config('app.env');
@@ -51,28 +50,28 @@ class UpgradeDaily extends Command
             $this->call('message:webhook', [
                 'listener' => 'dingtalk',
                 'url' => 'dingtalk1',
-                'title' => "后台任务",
-                'message' => " wikipali: 每日统计后台任务开始执行。app.env=" . $env,
+                'title' => '后台任务',
+                'message' => ' wikipali: 每日统计后台任务开始执行。app.env='.$env,
             ]);
         }
         Log::info('wikipali: 每日统计后台任务开始执行{app.env}', ['app.env' => $env]);
-        $message = "wikipali: 每日统计后台任务执行完毕。" . $env;
+        $message = 'wikipali: 每日统计后台任务执行完毕。'.$env;
 
-        //更新单词首选意思
+        // 更新单词首选意思
         $this->call('upgrade:dict.default.meaning');
         $time = time() - $start;
         $message .= "dict.default.meaning:{$time}; ";
         $currTime = time();
-        Log::info('更新单词首选意思完毕' . $env);
+        Log::info('更新单词首选意思完毕'.$env);
 
-        //社区术语表
+        // 社区术语表
         $this->call('upgrade:community.term', ['lang' => 'zh-Hans']);
         $time = time() - $currTime;
         $message .= "community.term:{$time}; ";
         $currTime = time();
         Log::info('社区术语表完毕 {app.env}', ['app.env' => $env]);
 
-        # 导出离线数据
+        // 导出离线数据
 
         $this->call('export:offline', ['format' => 'lzma', '--driver' => 'str']);
         $time = time() - $currTime;
@@ -86,15 +85,15 @@ class UpgradeDaily extends Command
             $this->call('message:webhook', [
                 'listener' => 'dingtalk',
                 'url' => 'dingtalk1',
-                'title' => "后台任务",
-                'message' => $message . ' app.env=' . $env,
+                'title' => '后台任务',
+                'message' => $message.' app.env='.$env,
             ]);
-            //发送dingding消息
+            // 发送dingding消息
             $this->call('message:webhookarticlenew', [
                 'host' => 'https://oapi.dingtalk.com/robot/send?access_token=34143dbec80a8fc09c1cb5897a5639ee3a9a32ecfe31835ad29bf7013bdb9fdf',
                 'type' => 'dingtalk',
             ]);
-            //发送微信消息
+            // 发送微信消息
             $this->call('message:webhookarticlenew', [
                 'host' => 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=25dbd74f-c89c-40e5-8cbc-48b1ef7710b8',
                 'type' => 'wechat',

+ 55 - 49
api-v13/app/Console/Commands/UpgradeDict.php

@@ -2,19 +2,20 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Support\Str;
+use App\Models\DictInfo;
+use App\Models\UserDict;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Storage;
-
-use App\Models\UserDict;
-use App\Models\DictInfo;
+use Illuminate\Support\Str;
 
 class UpgradeDict extends Command
 {
     /**
      * The name and signature of the console command.
      * php artisan upgrade:dict
+     *
      * @var string
      */
     protected $signature = 'upgrade:dict {uuid?} {--part}';
@@ -27,6 +28,7 @@ class UpgradeDict extends Command
     protected $description = '导入csv字典';
 
     protected $dictInfo;
+
     protected $cols;
 
     /**
@@ -42,41 +44,42 @@ class UpgradeDict extends Command
     private function scanDict(string $dir)
     {
         if (is_dir($dir)) {
-            $this->info("scan:" . $dir);
+            $this->info('scan:'.$dir);
             if ($files = scandir($dir)) {
-                //进入目录搜索字典或子目录
+                // 进入目录搜索字典或子目录
                 foreach ($files as $file) {
-                    //进入语言目录循环搜索
-                    $fullPath = $dir . "/" . $file;
+                    // 进入语言目录循环搜索
+                    $fullPath = $dir.'/'.$file;
                     if (is_dir($fullPath) && $file !== '.' && $file !== '..') {
-                        //是目录继续搜索
+                        // 是目录继续搜索
                         $this->scanDict($fullPath);
                     } else {
-                        //是文件,查看是否是字典信息文件
+                        // 是文件,查看是否是字典信息文件
                         $infoFile = $fullPath;
                         if (pathinfo($infoFile, PATHINFO_EXTENSION) === 'ini') {
                             $this->dictInfo = parse_ini_file($infoFile, true);
                             if (isset($this->dictInfo['meta']['dictname'])) {
-                                //是字典信息文件
+                                // 是字典信息文件
                                 $this->info($this->dictInfo['meta']['dictname']);
                                 if (Str::isUuid($this->argument('uuid'))) {
                                     if ($this->argument('uuid') !== $this->dictInfo['meta']['uuid']) {
                                         continue;
                                     }
                                 }
-                                if (!Str::isUuid($this->dictInfo['meta']['uuid'])) {
-                                    $this->error("not uuid");
+                                if (! Str::isUuid($this->dictInfo['meta']['uuid'])) {
+                                    $this->error('not uuid');
+
                                     continue;
                                 }
-                                //读取 description
-                                $desFile = $dir . "/description.md";
+                                // 读取 description
+                                $desFile = $dir.'/description.md';
                                 if (file_exists($desFile)) {
                                     $description = file_get_contents($desFile);
                                 } else {
                                     $description = $this->dictInfo['meta']['description'];
                                 }
                                 $tableDict = DictInfo::firstOrNew([
-                                    "id" => $this->dictInfo['meta']['uuid']
+                                    'id' => $this->dictInfo['meta']['uuid'],
                                 ]);
                                 $tableDict->id = $this->dictInfo['meta']['uuid'];
                                 $tableDict->name = $this->dictInfo['meta']['dictname'];
@@ -85,55 +88,54 @@ class UpgradeDict extends Command
                                 $tableDict->src_lang = $this->dictInfo['meta']['src_lang'];
                                 $tableDict->dest_lang = $this->dictInfo['meta']['dest_lang'];
                                 $tableDict->rows = $this->dictInfo['meta']['rows'];
-                                $tableDict->owner_id = config("mint.admin.root_uuid");
+                                $tableDict->owner_id = config('mint.admin.root_uuid');
                                 $tableDict->meta = json_encode($this->dictInfo['meta']);
                                 $tableDict->save();
 
                                 if ($this->option('part')) {
-                                    $this->info(" dict id = " . $this->dictInfo['meta']['uuid']);
+                                    $this->info(' dict id = '.$this->dictInfo['meta']['uuid']);
                                 } else {
-                                    $del = UserDict::where("dict_id", $this->dictInfo['meta']['uuid'])->delete();
-                                    $this->info("delete {$del} rows dict id = " . $this->dictInfo['meta']['uuid']);
+                                    $del = UserDict::where('dict_id', $this->dictInfo['meta']['uuid'])->delete();
+                                    $this->info("delete {$del} rows dict id = ".$this->dictInfo['meta']['uuid']);
                                 }
                                 /**
                                  * 允许一个字典拆成若干个小文件
                                  * 文件名 为 ***.csv , ***-1.csv , ***-2.csv
-                                 *
                                  */
-                                $filename = $dir . '/' . pathinfo($infoFile, PATHINFO_FILENAME);
-                                $csvFile = $filename . ".csv";
+                                $filename = $dir.'/'.pathinfo($infoFile, PATHINFO_FILENAME);
+                                $csvFile = $filename.'.csv';
                                 $count = 0;
                                 $bar = $this->output->createProgressBar($this->dictInfo['meta']['rows']);
                                 while (file_exists($csvFile)) {
-                                    # code...
+                                    // code...
                                     $this->info("runing:{$csvFile}");
                                     $inputRow = 0;
-                                    if (($fp = fopen($csvFile, "r")) !== false) {
-                                        $this->cols = array();
+                                    if (($fp = fopen($csvFile, 'r')) !== false) {
+                                        $this->cols = [];
                                         while (($data = fgetcsv($fp, 0, ',')) !== false) {
                                             if ($inputRow == 0) {
                                                 foreach ($data as $key => $colname) {
-                                                    # 列名列表
+                                                    // 列名列表
                                                     $this->cols[$colname] = $key;
                                                 }
                                             } else {
                                                 if ($this->option('part')) {
-                                                    //仅仅提取拆分零件
+                                                    // 仅仅提取拆分零件
                                                     $word = $this->get($data, 'word');
                                                     $factor1 = $this->get($data, 'factors');
-                                                    $factor1 = \str_replace([' ', '(', ')', '=', '-', '$'], "+", $factor1);
-                                                    foreach (\explode('+', $factor1)  as $part) {
-                                                        # code...
+                                                    $factor1 = \str_replace([' ', '(', ')', '=', '-', '$'], '+', $factor1);
+                                                    foreach (\explode('+', $factor1) as $part) {
+                                                        // code...
                                                         if (empty($part)) {
                                                             continue;
                                                         }
                                                         if (isset($newPart[$part])) {
                                                             $newPart[$part][0]++;
                                                         } else {
-                                                            $partExists = Cache::remember('dict/part/' . $part, config('cache.expire', 1000), function () use ($part) {
+                                                            $partExists = Cache::remember('dict/part/'.$part, config('cache.expire', 1000), function () use ($part) {
                                                                 return UserDict::where('word', $part)->exists();
                                                             });
-                                                            if (!$partExists) {
+                                                            if (! $partExists) {
                                                                 $count++;
                                                                 $newPart[$part] = [1, $word];
                                                                 $this->info("{$count}:{$part}-{$word}");
@@ -141,7 +143,7 @@ class UpgradeDict extends Command
                                                         }
                                                     }
                                                 } else {
-                                                    $newDict = new UserDict();
+                                                    $newDict = new UserDict;
                                                     $newDict->id = app('snowflake')->id();
                                                     $newDict->word = $data[$this->cols['word']];
                                                     $newDict->type = $this->get($data, 'type');
@@ -155,7 +157,7 @@ class UpgradeDict extends Command
                                                     $newDict->language = $this->get($data, 'language');
                                                     $newDict->confidence = $this->get($data, 'confidence');
                                                     $newDict->source = $this->get($data, 'source');
-                                                    $newDict->create_time = (int)(microtime(true) * 1000);
+                                                    $newDict->create_time = (int) (microtime(true) * 1000);
                                                     $newDict->creator_id = 0;
                                                     $newDict->dict_id = $this->dictInfo['meta']['uuid'];
                                                     $newDict->save();
@@ -167,30 +169,33 @@ class UpgradeDict extends Command
                                         }
                                     }
                                     $count++;
-                                    $csvFile = $filename . "-{$count}.csv";
+                                    $csvFile = $filename."-{$count}.csv";
                                 }
                                 $bar->finish();
-                                Storage::disk('local')->put("tmp/pm-part.csv", "part,count,word");
+                                Storage::disk('local')->put('tmp/pm-part.csv', 'part,count,word');
                                 if (isset($newPart)) {
                                     foreach ($newPart as $part => $info) {
-                                        # 写入磁盘文件
-                                        Storage::disk('local')->append("tmp/pm-part.csv", "{$part},{$info[0]},{$info[1]}");
+                                        // 写入磁盘文件
+                                        Storage::disk('local')->append('tmp/pm-part.csv', "{$part},{$info[0]},{$info[1]}");
                                     }
                                 }
-                                $this->info("done");
+                                $this->info('done');
                             }
                         }
                     }
                 }
-                //子目录搜素完毕
+
+                // 子目录搜素完毕
                 return;
             } else {
-                //获取子目录失败
-                $this->error("scandir fail");
+                // 获取子目录失败
+                $this->error('scandir fail');
+
                 return;
             }
         } else {
             $this->error("this is not dir input={$dir}");
+
             return;
         }
     }
@@ -198,16 +203,17 @@ class UpgradeDict extends Command
     /**
      * 获取列的值
      */
-    protected function get(array $data, string $colName, $default = "")
+    protected function get(array $data, string $colName, $default = '')
     {
         if (isset($this->cols[$colName])) {
             return $data[$this->cols[$colName]];
-        } else if (isset($this->dictInfo['cols'][$colName])) {
+        } elseif (isset($this->dictInfo['cols'][$colName])) {
             return $this->dictInfo['cols'][$colName];
         } else {
             return $default;
         }
     }
+
     /**
      * Execute the console command.
      *
@@ -215,12 +221,12 @@ class UpgradeDict extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $this->info("upgrade dict start");
-        $this->scanDict(config("mint.path.dict_text"));
-        $this->info("upgrade dict done");
+        $this->info('upgrade dict start');
+        $this->scanDict(config('mint.path.dict_text'));
+        $this->info('upgrade dict done');
 
         return 0;
     }

+ 49 - 46
api-v13/app/Console/Commands/UpgradeDictDefaultMeaning.php

@@ -11,8 +11,9 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Models\UserDict;
+use App\Tools\Tools;
+use Illuminate\Console\Command;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Log;
 
@@ -24,47 +25,49 @@ class UpgradeDictDefaultMeaning extends Command
      * @var string
      */
     protected $signature = 'upgrade:dict.default.meaning {word?}';
+
     protected $dict = [
-        "zh-Hans" => [
-            "8833de18-0978-434c-b281-a2e7387f69be",    /*巴汉字典明法尊者修订版*/
-            "f364d3dc-b611-471b-9a4f-531286b8c2c3",    /*《巴汉词典》Mahāñāṇo Bhikkhu编著*/
-            "0e4dc5c8-a228-4693-92ba-7d42918d8a91",    /*汉译パーリ语辞典-黃秉榮*/
-            "6aa9ec8b-bba4-4bcd-abd2-9eae015bad2b",    /*汉译パーリ语辞典-李瑩*/
-            "eb99f8b4-c3e5-43af-9102-6a93fcb97db6",    /*パーリ语辞典--勘误表*/
-            "0d79e8e8-1430-4c99-a0f1-b74f2b4b26d8",    /*《巴汉词典》增订*/
+        'zh-Hans' => [
+            '8833de18-0978-434c-b281-a2e7387f69be',    /* 巴汉字典明法尊者修订版 */
+            'f364d3dc-b611-471b-9a4f-531286b8c2c3',    /* 《巴汉词典》Mahāñāṇo Bhikkhu编著 */
+            '0e4dc5c8-a228-4693-92ba-7d42918d8a91',    /* 汉译パーリ语辞典-黃秉榮 */
+            '6aa9ec8b-bba4-4bcd-abd2-9eae015bad2b',    /* 汉译パーリ语辞典-李瑩 */
+            'eb99f8b4-c3e5-43af-9102-6a93fcb97db6',    /* パーリ语辞典--勘误表 */
+            '0d79e8e8-1430-4c99-a0f1-b74f2b4b26d8',    /* 《巴汉词典》增订 */
         ],
-        "zh-Hant" => [
-            "3acf0c0f-59a7-4d25-a3d9-bf394a266ebd",    /*汉译パーリ语辞典-黃秉榮*/
-            "5293ffb9-887e-4cf2-af78-48bf52a85304",    /*巴利詞根*/
+        'zh-Hant' => [
+            '3acf0c0f-59a7-4d25-a3d9-bf394a266ebd',    /* 汉译パーリ语辞典-黃秉榮 */
+            '5293ffb9-887e-4cf2-af78-48bf52a85304',    /* 巴利詞根 */
         ],
-        "jp" => [
-            "91d3ec93-3811-4973-8d84-ced99179a0aa",    /*パーリ语辞典*/
-            "6d6c6812-75e7-457d-874f-5b049ad4b6de",    /*パーリ语辞典-增补*/
+        'jp' => [
+            '91d3ec93-3811-4973-8d84-ced99179a0aa',    /* パーリ语辞典 */
+            '6d6c6812-75e7-457d-874f-5b049ad4b6de',    /* パーリ语辞典-增补 */
         ],
-        "en" => [
-            "c6e70507-4a14-4687-8b70-2d0c7eb0cf21",    /*	Concise P-E Dict*/
-            "eae9fd6f-7bac-4940-b80d-ad6cd6f433bf",    /*	Concise P-E Dict*/
-            "2f93d0fe-3d68-46ee-a80b-11fa445a29c6",    /*	unity*/
-            "b9163baf-2bca-41a5-a936-5a0834af3945",    /*	Pali-Dict Vri*/
-            "b089de57-f146-4095-b886-057863728c43",    /*	Buddhist Dictionary*/
-            "6afb8c05-5cbe-422e-b691-0d4507450cb7",    /*	PTS P-E dictionary*/
-            "0bfd87ec-f3ac-49a2-985e-28388779078d",    /*	Pali Proper Names Dict*/
-            "1cdc29e0-6783-4241-8784-5430b465b79c",    /*	Pāḷi Root In Saddanīti*/
-            "5718cbcf-684c-44d4-bbf2-4fa12f2588a4",    /*	Critical Pāli Dictionary*/
+        'en' => [
+            'c6e70507-4a14-4687-8b70-2d0c7eb0cf21',    /*	Concise P-E Dict */
+            'eae9fd6f-7bac-4940-b80d-ad6cd6f433bf',    /*	Concise P-E Dict */
+            '2f93d0fe-3d68-46ee-a80b-11fa445a29c6',    /*	unity */
+            'b9163baf-2bca-41a5-a936-5a0834af3945',    /*	Pali-Dict Vri */
+            'b089de57-f146-4095-b886-057863728c43',    /*	Buddhist Dictionary */
+            '6afb8c05-5cbe-422e-b691-0d4507450cb7',    /*	PTS P-E dictionary */
+            '0bfd87ec-f3ac-49a2-985e-28388779078d',    /*	Pali Proper Names Dict */
+            '1cdc29e0-6783-4241-8784-5430b465b79c',    /*	Pāḷi Root In Saddanīti */
+            '5718cbcf-684c-44d4-bbf2-4fa12f2588a4',    /*	Critical Pāli Dictionary */
         ],
-        "my" => [
-            "e740ef40-26d7-416e-96c2-925d6650ac6b",    /*	Tipiṭaka Pāḷi-Myanmar*/
-            "beb45062-7c20-4047-bcd4-1f636ba443d1",    /*	U Hau Sein’s Pāḷi-Myanmar Dictionary*/
-            "1e299ccb-4fc4-487d-8d72-08f63d84c809",    /*	Pali Roots Dictionary*/
-            "6f9caea1-17fa-41f1-92e5-bd8e6e70e1d7",    /*	U Hau Sein’s Pāḷi-Myanmar*/
+        'my' => [
+            'e740ef40-26d7-416e-96c2-925d6650ac6b',    /*	Tipiṭaka Pāḷi-Myanmar */
+            'beb45062-7c20-4047-bcd4-1f636ba443d1',    /*	U Hau Sein’s Pāḷi-Myanmar Dictionary */
+            '1e299ccb-4fc4-487d-8d72-08f63d84c809',    /*	Pali Roots Dictionary */
+            '6f9caea1-17fa-41f1-92e5-bd8e6e70e1d7',    /*	U Hau Sein’s Pāḷi-Myanmar */
         ],
-        "vi" => [
-            "23f67523-fa03-48d9-9dda-ede80d578dd2",    /*	Pali Viet Dictionary*/
-            "4ac8a0d5-9c6f-4b9f-983d-84288d47f993",    /*	Pali Viet Abhi-Terms*/
-            "7c7ee287-35ba-4cf3-b87b-30f1fa6e57c9",    /*	Pali Viet Vinaya Terms*/
+        'vi' => [
+            '23f67523-fa03-48d9-9dda-ede80d578dd2',    /*	Pali Viet Dictionary */
+            '4ac8a0d5-9c6f-4b9f-983d-84288d47f993',    /*	Pali Viet Abhi-Terms */
+            '7c7ee287-35ba-4cf3-b87b-30f1fa6e57c9',    /*	Pali Viet Vinaya Terms */
         ],
-        "cm" => [],
+        'cm' => [],
     ];
+
     /**
      * The console command description.
      *
@@ -89,19 +92,19 @@ class UpgradeDictDefaultMeaning extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
         $_word = $this->argument('word');
-        # 获取字典中所有的语言
+        // 获取字典中所有的语言
         $langInDict = UserDict::select('language')->groupBy('language')->get();
         $languages = [];
         foreach ($langInDict as $lang) {
-            if (!empty($lang["language"])) {
-                $languages[] = $lang["language"];
+            if (! empty($lang['language'])) {
+                $languages[] = $lang['language'];
             }
         }
-        //print_r($languages);
+        // print_r($languages);
         foreach ($this->dict as $thisLang => $dictId) {
             $this->info("running $thisLang");
 
@@ -113,15 +116,15 @@ class UpgradeDictDefaultMeaning extends Command
                     ->select('word', 'note')
                     ->cursor() as $word
             ) {
-                if (!empty($word['note'])) {
-                    Cache::put("dict_first_mean/{$thisLang}/{$word['word']}", mb_substr($word['note'], 0, 50, "UTF-8"));
+                if (! empty($word['note'])) {
+                    Cache::put("dict_first_mean/{$thisLang}/{$word['word']}", mb_substr($word['note'], 0, 50, 'UTF-8'));
                 }
                 $bar->advance();
             }
             $bar->finish();
 
             for ($i = count($dictId) - 1; $i >= 0; $i--) {
-                # code...
+                // code...
                 $this->info("running $thisLang - {$dictId[$i]}");
                 $count = 0;
                 foreach (
@@ -130,10 +133,10 @@ class UpgradeDictDefaultMeaning extends Command
                         ->cursor() as $word
                 ) {
                     $cacheKey = "dict_first_mean/{$thisLang}/{$word['word']}";
-                    if (!empty($word['note'])) {
-                        $cacheValue = mb_substr($word['note'], 0, 50, "UTF-8");
-                        if (!empty($_word) && $word['word'] === $_word) {
-                            Log::info($cacheKey . ':' . $cacheValue);
+                    if (! empty($word['note'])) {
+                        $cacheValue = mb_substr($word['note'], 0, 50, 'UTF-8');
+                        if (! empty($_word) && $word['word'] === $_word) {
+                            Log::info($cacheKey.':'.$cacheValue);
                         }
                         Cache::put($cacheKey, $cacheValue);
                     }

+ 10 - 8
api-v13/app/Console/Commands/UpgradeDictId.php

@@ -2,9 +2,10 @@
 
 namespace App\Console\Commands;
 
+use App\Http\Api\DictApi;
+use App\Tools\Tools;
 use Illuminate\Console\Command;
 use Illuminate\Support\Facades\DB;
-use App\Http\Api\DictApi;
 
 class UpgradeDictId extends Command
 {
@@ -39,24 +40,25 @@ class UpgradeDictId extends Command
      */
     public function handle()
     {
-        if(\App\Tools\Tools::isStop()){
+        if (Tools::isStop()) {
             return 0;
         }
         $this->info($this->description);
         $user_dict_id = DictApi::getSysDict('community');
-        if($user_dict_id){
-            $result = DB::select('UPDATE "user_dicts" set "dict_id"=? where "source"=? ',[$user_dict_id,'_USER_WBW_']);
-        }else{
+        if ($user_dict_id) {
+            $result = DB::select('UPDATE "user_dicts" set "dict_id"=? where "source"=? ', [$user_dict_id, '_USER_WBW_']);
+        } else {
             $this->error('没有找到 community 字典');
         }
 
         $user_dict_extract_id = DictApi::getSysDict('community_extract');
-        if($user_dict_extract_id){
-            $result = DB::select('UPDATE "user_dicts" set "dict_id"=? where "source"=? ',[$user_dict_extract_id,'_SYS_USER_WBW_']);
-        }else{
+        if ($user_dict_extract_id) {
+            $result = DB::select('UPDATE "user_dicts" set "dict_id"=? where "source"=? ', [$user_dict_extract_id, '_SYS_USER_WBW_']);
+        } else {
             $this->error('没有找到 community_extract 字典');
         }
         $this->info('all done');
+
         return 0;
     }
 }

+ 23 - 19
api-v13/app/Console/Commands/UpgradeDictSysPreference.php

@@ -2,11 +2,12 @@
 
 namespace App\Console\Commands;
 
-use Illuminate\Console\Command;
 use App\Http\Api\DictApi;
 use App\Models\UserDict;
 use App\Models\WordIndex;
+use App\Tools\Tools;
 use Carbon\Carbon;
+use Illuminate\Console\Command;
 
 class UpgradeDictSysPreference extends Command
 {
@@ -14,7 +15,7 @@ class UpgradeDictSysPreference extends Command
      * The name and signature of the console command.
      *
      * @var string
-     * php artisan upgrade:dict.sys.preference
+     *             php artisan upgrade:dict.sys.preference
      */
     protected $signature = 'upgrade:dict.sys.preference';
 
@@ -42,33 +43,34 @@ class UpgradeDictSysPreference extends Command
      */
     public function handle()
     {
-        if (\App\Tools\Tools::isStop()) {
+        if (Tools::isStop()) {
             return 0;
         }
-        $this->info("start");
+        $this->info('start');
         $dictList = [
             'community_extract',
             'robot_compound',
             'system_regular',
             'system_preference',
         ];
-        $dict_id = array();
+        $dict_id = [];
         foreach ($dictList as $key => $value) {
             $dict_id[$value] = DictApi::getSysDict($value);
-            if (!$dict_id[$value]) {
+            if (! $dict_id[$value]) {
                 $this->error("没有找到 {$value} 字典");
+
                 return 1;
             } else {
                 $this->info("{$value} :{$dict_id[$value]}");
             }
         }
-        if (!$this->confirm('继续吗?')) {
+        if (! $this->confirm('继续吗?')) {
             return 0;
         }
-        //搜索顺序
+        // 搜索顺序
         $order = [
-            '4d3a0d92-0adc-4052-80f5-512a2603d0e8',/* system irregular */
-            $dict_id['community_extract'],/* 社区字典*/
+            '4d3a0d92-0adc-4052-80f5-512a2603d0e8', /* system irregular */
+            $dict_id['community_extract'], /* 社区字典 */
             $dict_id['robot_compound'],
             $dict_id['system_regular'],
         ];
@@ -77,7 +79,7 @@ class UpgradeDictSysPreference extends Command
         $found = 0;
         foreach ($words as $key => $word) {
             if (preg_match('/\d/', $word->word)) {
-                //不处理带数字的
+                // 不处理带数字的
                 continue;
             }
             $rows++;
@@ -85,19 +87,19 @@ class UpgradeDictSysPreference extends Command
             $parent = null;
             $confidence = 0;
             foreach ($order as $key => $dict) {
-                //找到第一个有拆分的
+                // 找到第一个有拆分的
                 $preWords = UserDict::where('word', $word->word)
                     ->where('dict_id', $dict)
                     ->orderBy('confidence', 'desc')
                     ->get();
                 foreach ($preWords as $key => $value) {
-                    if (!$factors && !empty($value->factors)) {
+                    if (! $factors && ! empty($value->factors)) {
                         $factors = $value->factors;
                         if ($value->confidence > $confidence) {
                             $confidence = $value->confidence;
                         }
                     }
-                    if (!$parent && !empty($value->parent)) {
+                    if (! $parent && ! empty($value->parent)) {
                         $parent = $value->parent;
                         if ($value->confidence > $confidence) {
                             $confidence = $value->confidence;
@@ -112,19 +114,20 @@ class UpgradeDictSysPreference extends Command
                 $prefWord = UserDict::where('word', $word->word)
                     ->where('dict_id', $dict_id['system_preference'])
                     ->first();
-                if (!$prefWord) {
-                    $prefWord = new UserDict();
+                if (! $prefWord) {
+                    $prefWord = new UserDict;
                     $prefWord->word = $word->word;
                     $prefWord->dict_id = $dict_id['system_preference'];
                     $prefWord->id = app('snowflake')->id();
                     $prefWord->source = '_ROBOT_';
-                    $prefWord->create_time = (int)(microtime(true) * 1000);
+                    $prefWord->create_time = (int) (microtime(true) * 1000);
                     $prefWord->language = 'cm';
                     $prefWord->creator_id = 1;
                 } else {
                     if (Carbon::parse($prefWord->updated_at) > Carbon::parse($prefWord->created_at)) {
-                        //跳过已经被编辑过的。
-                        $this->info('跳过已经被编辑过的' . $word->word);
+                        // 跳过已经被编辑过的。
+                        $this->info('跳过已经被编辑过的'.$word->word);
+
                         continue;
                     }
                 }
@@ -140,6 +143,7 @@ class UpgradeDictSysPreference extends Command
                 $found = 0;
             }
         }
+
         return 0;
     }
 }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.