Просмотр исходного кода

Merge pull request #1713 from visuddhinanda/laravel

添加自定义书支持
visuddhinanda 2 лет назад
Родитель
Сommit
1eec6403d4

+ 71 - 51
app/Console/Commands/CopyUserBook.php

@@ -15,10 +15,10 @@ 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=}';
+    protected $signature = 'copy:user.book {--lang} {--book=} {--test}';
 
     /**
      * The console command description.
@@ -52,68 +52,87 @@ class CopyUserBook extends Command
         if($this->option('lang')){
             return 0;
         }
-        $userBooks = CustomBookSentence::select('book')->groupBy('book')->get();
+
+        if($this->option('test')){
+            $this->info('run in test mode');
+        }
+
+        $this->info('给CustomBook 添加channel');
+        foreach (CustomBook::get() as $key => $customBook) {
+            $this->info('doing book='.$customBook->book_id);
+            if(empty($customBook->channel_id)){
+                $bookLang = $customBook->lang;
+                if(empty($bookLang) || $bookLang === 'false' || $bookLang === 'null'){
+                    $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){
+                    $this->info('create new channel');
+                    $channelUuid = Str::uuid();
+                    $channel = new Channel;
+                    $channel->id = app('snowflake')->id();
+                    $channel->uid = $channelUuid;
+                    $channel->owner_uid = $customBook->owner;
+                    $channel->name = $channelName;
+                    $channel->type = 'original';
+                    $channel->lang = $bookLang;
+                    $channel->editor_id = 0;
+                    $channel->create_time = time()*1000;
+                    $channel->modify_time = time()*1000;
+                    $channel->status = $customBook->status;
+                    if(!$this->option('test')){
+                        $saveOk = $channel->save();
+                        if($saveOk){
+                            Log::debug('copy user book : create channel success name='.$channelName);
+                        }else{
+                            Log::error('copy user book : create channel fail.',['channel'=>$channelName,'book'=>$book->book]);
+                            $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'=>$book->book]);
+                    $this->error('copy user book : channel id error.  name='.$channelName);
+                    continue;
+                }
+                $customBook->channel_id = $channel->uid;
+                if(!$this->option('test')){
+                    $customBook->save();
+                }
+            }
+        }
+        $this->info('给CustomBook 添加channel 结束');
+
+        $userBooks = CustomBook::get();
         $this->info('book '. count($userBooks));
         foreach ($userBooks as $key => $book) {
             $queryBook = $this->option('book');
             if(!empty($queryBook)){
-                if($book->book != $queryBook){
+                if($book->book_id != $queryBook){
                     continue;
                 }
             }
-            $this->info('doing book '. $book->book);
-            $bookInfo = CustomBookSentence::where('book',$book->book)->first();
-            $bookLang = $bookInfo->lang;
-            //|| $bookLang === 'false' || $bookLang === 'null'
-            if(empty($bookLang) || $bookLang === 'false' || $bookLang === 'null'){
-                $this->info('language can not be empty change to pa, book='.$book->book);
-                Log::warning('copy:user.book language can not be empty ,change to pa, book='.$book->book);
-                $bookLang = 'pa';
-            }
-            $channelName = '_user_book_'.$bookLang;
-            $channel = Channel::where('owner_uid',$bookInfo->owner)
-                            ->where('name',$channelName)->first();
-            if($channel === null){
-                $channelUuid = Str::uuid();
-                $channel = new Channel;
-                $channel->id = app('snowflake')->id();
-                $channel->uid = $channelUuid;
-                $channel->owner_uid = $bookInfo->owner;
-                $channel->name = $channelName;
-                $channel->type = 'original';
-                $channel->lang = $bookLang;
-                $channel->editor_id = 0;
-                $channel->create_time = time()*1000;
-                $channel->modify_time = time()*1000;
-                $channel->status = $bookInfo->status;
-                $saveOk = $channel->save();
-                if($saveOk){
-                    Log::debug('copy user book : create channel success name='.$channelName);
-                }else{
-                    Log::error('copy user book : create channel fail.',['channel'=>$channelName,'book'=>$book->book]);
-                    $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'=>$book->book]);
-                $this->error('copy user book : channel id error.  name='.$channelName);
+            if(empty($book->channel_id)){
+                $this->error('book channel is empty');
                 continue;
             }
-            CustomBook::where('book_id',$book->book)->update(['channel_id'=>$channel->uid]);
+            $this->info('doing book '. $book->book_id);
 
-            $bar = $this->output->createProgressBar(CustomBookSentence::where('book',$book->book)
-                                                    ->count());
-            $bookSentence = CustomBookSentence::where('book',$book->book)->cursor();
+            $bookSentence = CustomBookSentence::where('book',$book->book_id)->cursor();
             foreach ($bookSentence as $key => $sentence) {
-                $bar->advance();
                 $newRow = Sentence::firstOrNew(
                     [
                         "book_id" => $sentence->book,
                         "paragraph" => $sentence->paragraph,
                         "word_start" => $sentence->word_start,
                         "word_end" => $sentence->word_end,
-                        "channel_uid" => $channel->uid,
+                        "channel_uid" => $book->channel_id,
                     ],
                     [
                         'id' => app('snowflake')->id(),
@@ -127,18 +146,19 @@ class CopyUserBook extends Command
                 $newRow->strlen = mb_strlen($sentence->content,"UTF-8");
                 $newRow->status = $sentence->status;
                 $newRow->content_type = $sentence->content_type;
-                $newRow->language = $channel->lang;
+                $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{
-                    $newRow->save();
+                    if(!$this->option('test')){
+                        $newRow->save();
+                    }
                 }
-
             }
-            $bar->finish();
             $this->info("book {$book->book} finished");
         }
+        $this->info('all done');
         return 0;
     }
 }

+ 83 - 0
app/Console/Commands/TestMarkdownToTpl.php

@@ -0,0 +1,83 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use App\Http\Controllers\ArticleController;
+use Illuminate\Support\Facades\Log;
+
+class TestMarkdownToTpl extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'test:markdown.tpl {item?}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        if(\App\Tools\Tools::isStop()){
+            return 0;
+        }
+        Log::info('md render start item='.$this->argument('item'));
+        $data = array();
+        $data['basic'] = <<<md
+        # 去除烦恼的五种方法(一种分类)
+
+        1 为了自己的利益而从别人处听法;
+        2 为了自己的利益而开示自己听闻过的法;
+        3 念诵听闻过、学习过的法;
+        4 一次又一次地用心思维听闻过、学习过的法;
+        5 在心中忆念自己适合的禅修业处,如十遍、十不净等。
+
+        (无碍解道,义注,1,63)
+        md;
+
+        $data['tpl'] = <<<md
+        为了自己的利益而从别人处听法;
+
+        {{168-916-2-9}}
+        md;
+
+        $article = new ArticleController;
+
+        foreach ($data as $key => $value) {
+            $_item = $this->argument('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,
+                        ]
+                    );
+            var_dump($tpl);
+        }
+        return 0;
+    }
+}

+ 33 - 0
app/Http/Api/ChannelApi.php

@@ -2,6 +2,7 @@
 namespace App\Http\Api;
 use App\Models\Channel;
 use Illuminate\Support\Str;
+use Illuminate\Support\Facades\Log;
 
 class ChannelApi{
     public static function getById($id){
@@ -71,4 +72,36 @@ class ChannelApi{
         }
     }
 
+    /**
+     * 获取某个studio 的某个语言的自定义书的channel
+     * 如果没有,建立
+     */
+    public static function userBookGetOrCreate($studioId,$lang){
+        $channelName = '_user_book_'.$lang;
+        $channel = Channel::where('owner_uid',$studioId)
+                        ->where('name',$channelName)->first();
+        if($channel){
+            return $channel->uid;
+        }
+        $channelUuid = Str::uuid();
+        $channel = new Channel;
+        $channel->id = app('snowflake')->id();
+        $channel->uid = $channelUuid;
+        $channel->owner_uid = $customBook->owner;
+        $channel->name = $channelName;
+        $channel->type = 'original';
+        $channel->lang = $bookLang;
+        $channel->editor_id = 0;
+        $channel->create_time = time()*1000;
+        $channel->modify_time = time()*1000;
+        $channel->status = $customBook->status;
+        $saveOk = $channel->save();
+        if($saveOk){
+            Log::debug('copy user book : create channel success name='.$channelName);
+            return $channel->uid;
+        }else{
+            Log::error('copy user book : create channel fail.',['channel'=>$channelName,'book'=>$book->book]);
+            return false;
+        }
+    }
 }

+ 9 - 4
app/Http/Api/MdRender.php

@@ -302,6 +302,7 @@ class MdRender{
                 }
                 break;
             case 'text':
+            case 'simple':
                 if(isset($tplProps)){
                     if(is_array($tplProps)){
                         return '';
@@ -554,6 +555,7 @@ class MdRender{
                 $output = preg_replace($pattern,$replacement,$html);
                 break;
             case 'text':
+            case 'simple':
                 $html = strip_tags($html);
                 $output = htmlspecialchars_decode($html,ENT_QUOTES);
                 //$output = html_entity_decode($html);
@@ -588,10 +590,13 @@ class MdRender{
             $GLOBALS["MdRenderStack"] = 1;
         }
         if($GLOBALS["MdRenderStack"]<3){
-            $mdRender = new MdRender(['mode'=>$mode,
-                                    'channelType'=>$channelType,
-                                    'contentType'=>$contentType,
-                                    'format'=>$format]);
+            $mdRender = new MdRender(
+                            [
+                                'mode'=>$mode,
+                                'channelType'=>$channelType,
+                                'contentType'=>$contentType,
+                                'format'=>$format
+                            ]);
 
             $output  = $mdRender->convert($markdown,$channelId,$queryId);
         }else{

+ 90 - 0
app/Http/Api/SentenceApi.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace App\Http\Api;
+
+use Illuminate\Support\Str;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Redis;
+
+use App\Models\Sentence;
+use App\Models\SentHistory;
+use App\Models\Channel;
+
+use App\Http\Api\ShareApi;
+
+class SentenceApi{
+    protected $auth = false;
+    protected $channel = null;
+
+    public function auth($channelId,$userId){
+        $channel = Channel::where('uid',$channelId)->first();
+        if(!$channel){
+            return false;
+        }
+        if($channel->owner_uid !== $userId){
+            //判断是否为协作
+            $power = ShareApi::getResPower($userId,$channel->uid,2);
+            if($power < 20){
+                return false;
+            }
+        }
+        $this->channel = $channel;
+        $this->auth = true;
+        return true;
+    }
+    public function store($sent,$user,$copy=false){
+        $row = Sentence::firstOrNew([
+            "book_id"=>$sent['book_id'],
+            "paragraph"=>$sent['paragraph'],
+            "word_start"=>$sent['word_start'],
+            "word_end"=>$sent['word_end'],
+            "channel_uid"=>$this->channel->uid,
+        ],[
+            "id"=>app('snowflake')->id(),
+            "uid"=>Str::uuid(),
+        ]);
+        $row->content = $sent['content'];
+        $row->strlen = mb_strlen($sent['content'],"UTF-8");
+        $row->language = $this->channel->lang;
+        $row->status = $this->channel->status;
+        if($copy){
+            //复制句子,保留原作者信息
+            $row->editor_uid = $sent["editor_uid"];
+            $row->acceptor_uid = $user["user_uid"];
+            $row->pr_edit_at = $sent["updated_at"];
+        }else{
+            $row->editor_uid = $user["user_uid"];
+            $row->acceptor_uid = null;
+            $row->pr_edit_at = null;
+        }
+        $row->create_time = time()*1000;
+        $row->modify_time = time()*1000;
+        $row->save();
+
+        //保存历史记录
+        if($copy){
+            $this->saveHistory($row->uid,$sent["editor_uid"],$sent['content']);
+        }else{
+            $this->saveHistory($row->uid,$user["user_uid"],$sent['content']);
+        }
+        //清除缓存
+        $sentId = "{$sent['book_id']}-{$sent['paragraph']}-{$sent['word_start']}-{$sent['word_end']}";
+        $hKey = "/sentence/res-count/{$sentId}/";
+        Redis::del($hKey);
+    }
+
+    private function saveHistory($uid,$editor,$content){
+        $newHis = new SentHistory;
+        $newHis->id = app('snowflake')->id();
+        $newHis->sent_uid = $uid;
+        $newHis->user_uid = $editor;
+        if(empty($content)){
+            $newHis->content = "";
+        }else{
+            $newHis->content = $content;
+        }
+
+        $newHis->create_time = time()*1000;
+        $newHis->save();
+    }
+}

+ 64 - 18
app/Http/Api/TemplateRender.php

@@ -250,6 +250,20 @@ class TemplateRender{
                     $output = $props["word"];
                 }
                 break;
+            case 'simple':
+                if(isset($props["meaning"])){
+                    $output = $props["meaning"];
+                }else{
+                    $output = $props["word"];
+                }
+                break;
+            default:
+                if(isset($props["meaning"])){
+                    $output = $props["meaning"];
+                }else{
+                    $output = $props["word"];
+                }
+                break;
         }
         return $output;
     }
@@ -322,6 +336,12 @@ class TemplateRender{
             case 'tex':
                 $output = $trigger;
                 break;
+            case 'simple':
+                $output = '';
+                break;
+            default:
+                $output = '';
+                break;
         }
         return $output;
     }
@@ -354,6 +374,9 @@ class TemplateRender{
             case 'tex':
                 $output = $pali.'၊'.$meaning;
                 break;
+            case 'simple':
+                $output = $pali.'၊'.$meaning;
+                break;
             default:
                 $output = $pali.'၊'.$meaning;
                 break;
@@ -390,6 +413,9 @@ class TemplateRender{
             case 'tex':
                 $output = $title;
                 break;
+            case 'simple':
+                $output = $title;
+                break;
             default:
                 $output = '';
                 break;
@@ -434,6 +460,9 @@ class TemplateRender{
             case 'tex':
                 $output = $title;
                 break;
+            case 'simple':
+                $output = $title;
+                break;
             default:
                 $output = '';
                 break;
@@ -489,8 +518,11 @@ class TemplateRender{
                 case 'tex':
                     $output = $props["innerString"];
                     break;
+                case 'simple':
+                    $output = $props["innerString"];
+                    break;
                 default:
-                    $output = '';
+                    $output = $props["innerString"];
                     break;
             }
             return $output;
@@ -510,7 +542,9 @@ class TemplateRender{
             $channels = [$sentInfo[1]];
         }
         $Sent = new CorpusController();
-        $props = $Sent->getSentTpl($sentId,$channels,$this->mode,true);
+        $props = $Sent->getSentTpl($sentId,$channels,
+                                   $this->mode,true,
+                                   $this->format);
         if($props === false){
             $props['error']="句子模版渲染错误。句子参数个数不符。应该是四个。";
         }
@@ -539,14 +573,7 @@ class TemplateRender{
                 $output = '';
                 if(isset($props['translation']) && is_array($props['translation'])){
                     foreach ($props['translation'] as $key => $value) {
-                        $output .= MdRender::render($value['content'],
-                                    [$value['channel']['id']],
-                                    null,
-                                    'read',
-                                    $value['channel']['type'],
-                                    'translation',
-                                    'text'
-                                    );
+                        $output .= $value['html'];
                     }
                 }
                 break;
@@ -554,14 +581,30 @@ class TemplateRender{
                 $output = '';
                 if(isset($props['translation']) && is_array($props['translation'])){
                     foreach ($props['translation'] as $key => $value) {
-                        $output .= MdRender::render($value['content'],
-                                    [$value['channel']['id']],
-                                    null,
-                                    'read',
-                                    $value['channel']['type'],
-                                    'translation',
-                                    'tex'
-                                    );
+                        $output .= $value['html'];
+                    }
+                }
+                break;
+            case 'simple':
+                $output = '';
+                if(isset($props['translation']) &&
+                   is_array($props['translation']) &&
+                   count($props['translation']) > 0
+                   ){
+                    $sentences = $props['translation'];
+                    foreach ($sentences as $key => $value) {
+                        $output .= $value['html'];
+                    }
+                }
+                if(empty($output)){
+                    if(isset($props['origin']) &&
+                            is_array($props['origin']) &&
+                            count($props['origin']) > 0
+                            ){
+                        $sentences = $props['origin'];
+                        foreach ($sentences as $key => $value) {
+                            $output .= $value['html'];
+                        }
                     }
                 }
                 break;
@@ -598,6 +641,9 @@ class TemplateRender{
             case 'tex':
                 $output = 'mermaid';
                 break;
+            case 'simple':
+                $output = 'mermaid';
+                break;
             default:
                 $output = 'mermaid';
                 break;

+ 205 - 7
app/Http/Controllers/ArticleController.php

@@ -2,18 +2,24 @@
 
 namespace App\Http\Controllers;
 
+use Illuminate\Http\Request;
+use Illuminate\Support\Str;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Log;
+
 use App\Models\Article;
 use App\Models\ArticleCollection;
 use App\Models\Collection;
+use App\Models\CustomBook;
+use App\Models\CustomBookId;
+use App\Models\Sentence;
 
-use Illuminate\Http\Request;
-use Illuminate\Support\Str;
 use App\Http\Resources\ArticleResource;
 use App\Http\Api\AuthApi;
 use App\Http\Api\ShareApi;
 use App\Http\Api\StudioApi;
-use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Log;
+use App\Http\Api\ChannelApi;
+use App\Http\Api\SentenceApi;
 use App\Tools\OpsLog;
 
 class ArticleController extends Controller
@@ -388,14 +394,14 @@ class ArticleController extends Controller
         //鉴权
         $user = AuthApi::current($request);
         if(!$user){
-            return $this->error(__('auth.failed'),[],401);
+            return $this->error(__('auth.failed'),401,401);
         }else{
             $user_uid=$user['user_uid'];
         }
 
         $canEdit = ArticleController::userCanEdit($user_uid,$article);
         if(!$canEdit){
-            return $this->error(__('auth.failed'),[],401);
+            return $this->error(__('auth.failed'),401,401);
         }
 
         /*
@@ -407,10 +413,21 @@ class ArticleController extends Controller
             return $this->error(__('validation.exists'));
         }*/
 
+        $content = $request->get('content');
+        if($request->get('to_tpl')===true){
+            /**
+             * 转化为模版
+             */
+            $tplContent = $this->toTpl($content,
+                                       $request->get('anthology_id'),
+                                       $user);
+            $content = $tplContent;
+        }
+
         $article->title = $request->get('title');
         $article->subtitle = $request->get('subtitle');
         $article->summary = $request->get('summary');
-        $article->content = $request->get('content');
+        $article->content = $content;
         $article->lang = $request->get('lang');
         $article->status = $request->get('status',10);
         $article->editor_id = $user['user_id'];
@@ -447,4 +464,185 @@ class ArticleController extends Controller
 
         return $this->ok($delete);
     }
+
+    public function toTpl($content,$anthologyId,$user){
+        //查询书号
+        if(!Str::isUuid($anthologyId)){
+            throw new \Exception('anthology Id not uuid');
+        }
+
+        $bookId = $this->getBookId($anthologyId,$user);
+
+        $tpl = $this->convertToTpl($content,$bookId['book'],$bookId['paragraph']);
+
+        //保存原文到句子表
+        $customBook = $this->getCustomBookByBookId($bookId['book']);
+        $sentenceSave = new SentenceApi;
+        $auth = $sentenceSave->auth($customBook->channel_id,$user['user_uid']);
+        if(!$auth){
+            throw new \Exception('auth fail');
+        }
+        foreach ($tpl['sentences'] as $key => $sentence) {
+            $sentenceSave->store($sentence,$user);
+        }
+        return $tpl['content'];
+    }
+
+    private function getCustomBookByBookId($bookId){
+        return CustomBook::where('book_id',$bookId)->first();
+    }
+
+    private function getBookId($anthologyId,$user){
+        $anthology = Collection::where('uid',$anthologyId)->first();
+        if(!$anthology){
+            throw new \Exception('anthology not exists id='.$anthologyId);
+        }
+        $bookId = $anthology->book_id;
+        if(empty($bookId)){
+            //生成 book id
+            $newBookId = CustomBook::max('book_id') + 1;
+
+            $newBook = new CustomBook;
+            $newBook->id = app('snowflake')->id();
+            $newBook->book_id = $newBookId;
+            $newBook->title = $anthology->title;
+            $newBook->owner = $anthology->owner;
+            $newBook->editor_id = $user['user_id'];
+            $newBook->lang = $anthology->lang;
+            $newBook->status = $anthology->status;
+            //查询anthology所在的studio有没有符合要求的channel 没有的话,建立
+            $channelId = ChannelApi::userBookGetOrCreate($anthology->owner,$anthology->lang);
+            if($channelId === false){
+                throw new \Exception('user book get fail studio='.$anthology->owner.' language='.$anthology->lang);
+            }
+            $newBook->channel_id = $channelId;
+            $ok = $newBook->save();
+            if(!$ok){
+                throw new \Exception('user book create fail studio='.$anthology->owner.' language='.$anthology->lang);
+            }
+            CustomBookId::where('key','max_book_number')->update(['value'=>$newBookId]);
+            $bookId = $newBookId;
+            $anthology->book_id = $newBookId;
+            $anthology->save();
+        }else{
+            $channelId = CustomBook::where('book_id',$bookId)->value('channel_id');
+        }
+        $maxPara = Sentence::where('channel_uid',$channelId)
+                           ->where('book_id',$bookId)->max('paragraph');
+        if(!$maxPara){
+            $maxPara = 0;
+        }
+        return ['book'=>$bookId,'paragraph'=>$maxPara+1];
+    }
+
+    public function convertToTpl($content,$bookId,$paraStart){
+        $newSentence = array();
+        $para = $paraStart;
+		$sentNum = 1;
+		$newText =  "";
+		$isTable=false;
+		$isList=false;
+		$newSent="";
+        $sentences = explode("\n",$content);
+		foreach ($sentences as $row) {
+			//$data 为一行文本
+            $listHead= "";
+            $isList = false;
+
+            $heading = false;
+            $title = false;
+
+			$trimData = trim($row);
+
+            # 判断是否为list
+			$listLeft =strstr($row,"- ",true);
+			if($listLeft !== FALSE){
+                if(ctype_space($listLeft) || empty($listLeft)){
+                    # - 左侧是空,判定为list
+                    $isList=true;
+                    $iListPos = mb_strpos($row,'- ',0,"UTF-8");
+                    $listHead = mb_substr($row,0,$iListPos+2,"UTF-8");
+                    $listBody = mb_substr($row,$iListPos+2,mb_strlen($row,"UTF-8")-$iListPos+2,"UTF-8");
+                }
+			}
+
+            # TODO 判断是否为标题
+			$headingStart =mb_strpos($row,"# ",0,'UTF-8');
+			if($headingStart !== false){
+                $headingLeft = mb_substr($row,0,$headingStart+2,'UTF-8');
+                $title = mb_substr($row,$headingStart+2,null,'UTF-8');
+                if(str_replace('#','', trim($headingLeft)) === ''){
+                    # 除了#没有其他东西,那么是标题
+                    $heading = $headingLeft;
+                    $newText .= $headingLeft;
+                    $newText .='{{'."{$bookId}-{$para}-{$sentNum}-{$sentNum}"."}}\n";
+                    $newSentence[] = $this->newSent($bookId,$para,$sentNum,$sentNum,$title);
+                    $newSent="";
+                    $para++;
+                    $sentNum = 1;
+                    continue;
+                }
+			}
+
+			//判断是否为表格开始
+			if(mb_substr($trimData,0,1,"UTF-8") == "|"){
+				$isTable=true;
+			}
+			if($trimData!="" && $isTable == true){
+				//如果是表格 不新增句子
+				$newSent .= "{$row}\n";
+				continue;
+			}
+            if($isList == true){
+                $newSent .= $listBody;
+            }else{
+                $newSent .= $trimData;
+            }
+
+			#生成句子编号
+			if($trimData==""){
+				#空行
+				if(strlen($newSent)>0){
+					//之前有内容
+					$newText .='{{'."{$bookId}-{$para}-{$sentNum}-{$sentNum}"."}}\n";
+                    $newSentence[] = $this->newSent($bookId,$para,$sentNum,$sentNum,$newSent);
+					$newSent="";
+				}
+				#新的段落 不插入数据库
+				$para++;
+				$sentNum = 1;
+				$newText .="\n";
+				$isTable = false; //表格开始标记
+				$isList = false;
+				continue;
+			}else{
+				$sentNum=$sentNum+10;
+			}
+
+			if(mb_substr($trimData,0,2,"UTF-8")=="{{"){
+				#已经有的句子链接不处理
+				$newText .= $trimData."\n";
+			}else{
+                $newText .= $listHead;
+				$newText .='{{'."{$bookId}-{$para}-{$sentNum}-{$sentNum}"."}}\n";
+                $newSentence[] = $this->newSent($bookId,$para,$sentNum,$sentNum,$newSent);
+				$newSent="";
+			}
+		}
+
+        return [
+            'content' =>$newText,
+            'sentences' =>$newSentence,
+        ];
+    }
+
+    private function newSent($book,$para,$start,$end,$content){
+        return array(
+            'book_id'=>$book,
+            'paragraph'=>$para,
+            'word_start'=>$start,
+            'word_end'=>$end,
+            'content'=>$content,
+        );
+    }
 }

+ 37 - 7
app/Http/Controllers/ChannelController.php

@@ -2,20 +2,26 @@
 
 namespace App\Http\Controllers;
 
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\DB;
+
 use App\Models\Channel;
 use App\Models\Sentence;
 use App\Models\DhammaTerm;
 use App\Models\WbwBlock;
 use App\Models\PaliSentence;
+use App\Models\CustomBook;
+
 use App\Http\Controllers\AuthController;
-use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Log;
+
 use App\Http\Api\AuthApi;
 use App\Http\Api\StudioApi;
 use App\Http\Api\ShareApi;
 use App\Http\Api\PaliTextApi;
-use Illuminate\Support\Arr;
-use Illuminate\Support\Facades\DB;
+use App\Http\Api\ChannelApi;
+
 
 class ChannelController extends Controller
 {
@@ -281,24 +287,48 @@ class ChannelController extends Controller
 
         $sent = $request->get('sentence') ;
         $query = [];
+        $queryWithChannel = [];
         $sentContainer = [];
         $sentLenContainer = [];
 
+        $paliChannel = ChannelApi::getSysChannel('_System_Pali_VRI_');
+        $customBookChannel = array();
+
         foreach ($sent as $value) {
             $ids = explode('-',$value);
+            $idWithChannel = $ids;
             if(count($ids)===4){
+                if($ids[0] < 1000){
+                    $idWithChannel[] = $paliChannel;
+                }else{
+                    if(!isset($customBookChannel[$ids[0]])){
+                        $cbChannel = CustomBook::where('book_id',$ids[0])->value('channel_id');
+                        if($cbChannel){
+                            $customBookChannel[$ids[0]] = $cbChannel;
+                        }else{
+                            $customBookChannel[$ids[0]] = $paliChannel;
+                        }
+                    }
+                    $idWithChannel[] = $customBookChannel[$ids[0]];
+                }
                 $sentContainer[$value] = false;
                 $query[] = $ids;
+                $queryWithChannel[] = $idWithChannel;
             }
         }
         //获取单句长度
         if(count($query)>0){
-            $table = PaliSentence::whereIns(['book','paragraph','word_begin','word_end'],$query)
-                                    ->select(['book','paragraph','word_begin','word_end','length']);
+            $table = Sentence::whereIns(['book_id','paragraph','word_start','word_end','channel_uid'],$queryWithChannel)
+                                    ->select(['book_id','paragraph','word_start','word_end','strlen']);
             $sentLen = $table->get();
 
             foreach ($sentLen as $value) {
-                $sentLenContainer["{$value->book}-{$value->paragraph}-{$value->word_begin}-{$value->word_end}"] = $value->length;
+                $strlen = $value->strlen;
+                if(empty($strlen)){
+                    $strlen = 0;
+                }
+                $sentId = "{$value->book_id}-{$value->paragraph}-{$value->word_start}-{$value->word_end}";
+                $sentLenContainer[$sentId] = $strlen;
             }
         }
 

+ 60 - 58
app/Http/Controllers/CollectionController.php

@@ -28,11 +28,18 @@ class CollectionController extends Controller
                 //
         $userinfo = new \UserInfo();
 		$result=false;
-		$indexCol = ['uid','title','subtitle','summary','article_list','owner','status','lang','updated_at','created_at'];
+		$indexCol = ['uid','title','subtitle','summary',
+                      'article_list','owner','status',
+                      'default_channel','lang',
+                      'updated_at','created_at'];
 		switch ($request->get('view')) {
             case 'studio_list':
 		        $indexCol = ['owner'];
-                $table = Collection::select($indexCol)->selectRaw('count(*) as count')->where('status', 30)->groupBy('owner');
+                //TODO ?
+                $table = Collection::select($indexCol)
+                                    ->selectRaw('count(*) as count')
+                                    ->where('status', 30)
+                                    ->groupBy('owner');
                 break;
 			case 'studio':
                 $user = AuthApi::current($request);
@@ -67,7 +74,7 @@ class CollectionController extends Controller
 				break;
 			default:
 				# code...
-			    return $this->error("没有查询到数据");
+			    return $this->error("无法识别的view参数",200,200);
 				break;
 		}
         if($request->has("search") && !empty($request->has("search"))){
@@ -150,34 +157,31 @@ class CollectionController extends Controller
     public function store(Request $request)
     {
         $user = \App\Http\Api\AuthApi::current($request);
-        if($user){
-            //判断当前用户是否有指定的studio的权限
-            if($user['user_uid'] === \App\Http\Api\StudioApi::getIdByName($request->get('studio'))){
-                //查询是否重复
-                if(Collection::where('title',$request->get('title'))->where('owner',$user['user_uid'])->exists()){
-                    return $this->error(__('validation.exists'));
-                }else{
-                    $newOne = new Collection;
-                    $newOne->id = app('snowflake')->id();
-                    $newOne->uid = Str::uuid();
-                    $newOne->title = $request->get('title');
-                    $newOne->lang = $request->get('lang');
-                    $newOne->article_list = "[]";
-                    $newOne->owner = $user['user_uid'];
-                    $newOne->owner_id = $user['user_id'];
-                    $newOne->editor_id = $user['user_id'];
-                    $newOne->create_time = time()*1000;
-                    $newOne->modify_time = time()*1000;
-                    $newOne->save();
-                    return $this->ok(new CollectionResource($newOne));
-                }
-            }else{
-                return $this->error(__('auth.failed'));
-            }
+        if(!$user){
+            return $this->error(__('auth.failed'),401,401);
+        }
+        //判断当前用户是否有指定的studio的权限
+        if($user['user_uid'] !== \App\Http\Api\StudioApi::getIdByName($request->get('studio'))){
+            return $this->error(__('auth.failed'),403,403);
+        }
+        //查询是否重复
+        if(Collection::where('title',$request->get('title'))->where('owner',$user['user_uid'])->exists()){
+            return $this->error(__('validation.exists'),200,200);
         }else{
-            return $this->error(__('auth.failed'));
+            $newOne = new Collection;
+            $newOne->id = app('snowflake')->id();
+            $newOne->uid = Str::uuid();
+            $newOne->title = $request->get('title');
+            $newOne->lang = $request->get('lang');
+            $newOne->article_list = "[]";
+            $newOne->owner = $user['user_uid'];
+            $newOne->owner_id = $user['user_id'];
+            $newOne->editor_id = $user['user_id'];
+            $newOne->create_time = time()*1000;
+            $newOne->modify_time = time()*1000;
+            $newOne->save();
+            return $this->ok(new CollectionResource($newOne));
         }
-
     }
 
     /**
@@ -188,34 +192,31 @@ class CollectionController extends Controller
      */
     public function show(Request  $request,$id)
     {
-        //
-		$indexCol = ['uid','title','subtitle','summary','article_list','status','owner','lang','updated_at','created_at'];
-
-		$result  = Collection::select($indexCol)->where('uid', $id)->first();
-		if($result){
-            if($result->status<30){
-                //私有文章,判断权限
-                Log::error('私有文章,判断权限'.$id);
-                $user = \App\Http\Api\AuthApi::current($request);
-                if(!$user){
-                    Log::error('未登录');
-                    return $this->error(__('auth.failed'));
-                }
-                //判断当前用户是否有指定的studio的权限
-                if($user['user_uid'] !== $result->owner){
-                    Log::error($user["user_uid"].'私有文章,判断权限'.$id);
-                    //非所有者
-                    if(CollectionController::UserCanRead($user['user_uid'],$result)===false){
-                        Log::error($user["user_uid"].'没有读取权限');
-                        return $this->error(__('auth.failed'));
-                    }
+		$result  = Collection::where('uid', $id)->first();
+		if(!$result){
+            return $this->error("没有查询到数据");
+        }
+        if($result->status<30){
+            //私有文章,判断权限
+            Log::error('私有文章,判断权限'.$id);
+            $user = \App\Http\Api\AuthApi::current($request);
+            if(!$user){
+                Log::error('未登录');
+                return $this->error(__('auth.failed'),401,401);
+            }
+            //判断当前用户是否有指定的studio的权限
+            if($user['user_uid'] !== $result->owner){
+                Log::error($user["user_uid"].'私有文章,判断权限'.$id);
+                //非所有者
+                if(CollectionController::UserCanRead($user['user_uid'],$result)===false){
+                    Log::error($user["user_uid"].'没有读取权限');
+                    return $this->error(__('auth.failed'),403,403);
                 }
             }
-            $result->fullArticleList = true;
-			return $this->ok(new CollectionResource($result));
-		}else{
-			return $this->error("没有查询到数据");
-		}
+        }
+        $result->fullArticleList = true;
+        return $this->ok(new CollectionResource($result));
+
     }
 
     /**
@@ -235,19 +236,20 @@ class CollectionController extends Controller
         //鉴权
         $user = AuthApi::current($request);
         if(!$user){
-            return $this->error(__('auth.failed'));
+            return $this->error(__('auth.failed'),401,401);
         }
         if(!CollectionController::UserCanEdit($user["user_uid"],$collection)){
-            return $this->error(__('auth.failed'));
+            return $this->error(__('auth.failed'),403,403);
         }
         $collection->title = $request->get('title');
         $collection->subtitle = $request->get('subtitle');
         $collection->summary = $request->get('summary');
         if($request->has('aritcle_list')){
             $collection->article_list = \json_encode($request->get('aritcle_list'));
-        } ;
+        }
         $collection->lang = $request->get('lang');
         $collection->status = $request->get('status');
+        $collection->default_channel = $request->get('default_channel');
         $collection->modify_time = time()*1000;
         $collection->save();
         return $this->ok(new CollectionResource($collection));

+ 45 - 68
app/Http/Controllers/CorpusController.php

@@ -14,6 +14,7 @@ use App\Models\Discussion;
 use App\Models\PaliSentence;
 use App\Models\SentSimIndex;
 use App\Models\CustomBookSentence;
+use App\Models\CustomBook;
 
 use Illuminate\Support\Str;
 use Illuminate\Http\Request;
@@ -114,20 +115,21 @@ class CorpusController extends Controller
     {
         //
     }
-    public function getSentTpl($id,$channels,$mode='edit',$onlyProps=false){
+    public function getSentTpl($id,$channels,$mode='edit',$onlyProps=false,$format='react'){
         $sent = [];
         $sentId = \explode('-',$id);
         if(count($sentId) !== 4){
             return false;
         }
-        if((int)$sentId[0] < 1000){
+        $bookId = (int)$sentId[0];
+        if( $bookId < 1000){
             if($mode==='read'){
                 $channelId = ChannelApi::getSysChannel('_System_Pali_VRI_');
             }else{
                 $channelId = ChannelApi::getSysChannel('_System_Wbw_VRI_');
             }
         }else{
-
+            $channelId = CustomBook::where('book_id',$bookId)->value('channel_id');
         }
 
 
@@ -144,49 +146,6 @@ class CorpusController extends Controller
 
         $channelIndex = $this->getChannelIndex($channels);
 
-        if((int)$sentId[0] >= 1000){
-            $orgChannelId = (string)Str::uuid();
-            //载入自定义原文
-            $customOrigin = CustomBookSentence::
-                              where('book',(int)$sentId[0])
-                            ->where('paragraph',(int)$sentId[1])
-                            ->where('word_start',(int)$sentId[2])
-                            ->where('word_end',(int)$sentId[3])
-                            ->get();
-            $toSentFormat = array();
-            $owner_uid = null;
-            foreach ($customOrigin as $custom) {
-                if($owner_uid === null){
-                    $owner_uid = $custom->owner;
-                }
-                $toSentFormat[] = (object)[
-                    'uid'=>$custom->id,
-                    'book_id'=>$custom->book,
-                    'paragraph'=>$custom->paragraph,
-                    'word_start'=>$custom->word_start,
-                    "word_end"=>$custom->word_end,
-                    'channel_uid'=>$orgChannelId,
-                    'content'=>$custom->content,
-                    'content_type'=>$custom->content_type,
-                    'editor_uid'=>$custom->owner,
-                    'acceptor_uid'=>null,
-                    'pr_edit_at'=>null,
-                    'create_time'=>$custom->create_time,
-                    'modify_time'=>$custom->modify_time,
-                    'created_at'=>$custom->created_at,
-                    'updated_at'=>$custom->updated_at,
-                ];
-            }
-            $orgChannel = (object)array(
-                        'uid'=>$orgChannelId,
-                        'type'=>'original',
-                        'name'=>'custom',
-                        'owner_uid'=>$owner_uid,
-                        'studio'=>StudioApi::getById($owner_uid),
-                    );
-            $channelIndex[$orgChannelId] = $orgChannel;
-        }
-
         if(isset($toSentFormat)){
             foreach ($toSentFormat as $key => $org) {
                 $record[] = $org;
@@ -202,7 +161,7 @@ class CorpusController extends Controller
                 break;
             }
         }
-        return $this->makeContent($record,$mode,$channelIndex,[],$onlyProps);
+        return $this->makeContent($record,$mode,$channelIndex,[],$onlyProps,false,$format);
     }
     /**
      * Display the specified resource.
@@ -595,7 +554,7 @@ class CorpusController extends Controller
      * $indexChannel channel索引
      * $indexedHeading 标题索引 用于给段落加标题标签 <h1> ect.
      */
-    private function makeContent($record,$mode,$indexChannel,$indexedHeading=[],$onlyProps=false,$paraMark=false){
+    private function makeContent($record,$mode,$indexChannel,$indexedHeading=[],$onlyProps=false,$paraMark=false,$format='react'){
         $content = [];
 		$lastSent = "0-0";
 		$sentCount = 0;
@@ -677,7 +636,7 @@ class CorpusController extends Controller
                     $newSent['id'] = $row->uid;
                     $newSent['content'] = $row->content;
                     $newSent['contentType'] = $row->content_type;
-                    $newSent['html'] = "";
+                    $newSent['html'] = '';
                     $newSent["editor"]=UserApi::getByUuid($row->editor_uid);
                     /**
                      * TODO 刷库改数据
@@ -704,18 +663,20 @@ class CorpusController extends Controller
                             // 传过来的数据一定有一个原文channel
                             //
                             if($mode !== "read"){
-
-                                $newSent['channel']['type'] = "wbw";
-
-                                if(isset($this->wbwChannels[0])){
-                                    $newSent['channel']['name'] = $indexChannel[$this->wbwChannels[0]]->name;
-                                    $newSent['channel']['id'] = $this->wbwChannels[0];
-                                    //存在一个translation channel
-                                    //尝试查找逐词解析数据。找到,替换现有数据
-                                    $wbwData = $this->getWbw($arrSentId[0],$arrSentId[1],$arrSentId[2],$arrSentId[3],$this->wbwChannels[0]);
-                                    if($wbwData){
-                                        $newSent['content'] = $wbwData;
-                                        $newSent['html'] = "";
+                                if($info->content_type==='json'){
+                                    $newSent['channel']['type'] = "wbw";
+                                    if(isset($this->wbwChannels[0])){
+                                        $newSent['channel']['name'] = $indexChannel[$this->wbwChannels[0]]->name;
+                                        $newSent['channel']['id'] = $this->wbwChannels[0];
+                                        //存在一个translation channel
+                                        //尝试查找逐词解析数据。找到,替换现有数据
+                                        $wbwData = $this->getWbw($arrSentId[0],$arrSentId[1],$arrSentId[2],$arrSentId[3],
+                                                                $this->wbwChannels[0]);
+                                        if($wbwData){
+                                            $newSent['content'] = $wbwData;
+                                            $newSent['contentType'] = 'json';
+                                            $newSent['html'] = "";
+                                        }
                                     }
                                 }
                             }else{
@@ -725,10 +686,12 @@ class CorpusController extends Controller
 
                             break;
                         case 'nissaya':
-                            $newSent['html'] = RedisClusters::remember("/sent/{$channelId}/{$currSentId}",
+                            $newSent['html'] = RedisClusters::remember("/sent/{$channelId}/{$currSentId}/{$format}",
                                                 config('mint.cache.expire'),
-                                                function() use($row,$mode){
-                                                    return MdRender::render($row->content,[$row->channel_uid],null,$mode,"nissaya",$row->content_type);
+                                                function() use($row,$mode,$format){
+                                                    return MdRender::render($row->content,[$row->channel_uid],
+                                                                            null,$mode,"nissaya",
+                                                                            $row->content_type,$format);
                                                 });
                             break;
                         default:
@@ -737,13 +700,27 @@ class CorpusController extends Controller
                          * 包涵术语的不用cache
                          */
                             if(strpos($row->content,'[[')===false){
-                                $newSent['html'] = RedisClusters::remember("/sent/{$channelId}/{$currSentId}",
+                                $newSent['html'] = MdRender::render($row->content,[$row->channel_uid],
+                                                            null,$mode,'translation',
+                                                            $row->content_type,$format);
+                                /*
+                                RedisClusters::remember("/sent/{$channelId}/{$currSentId}/{$format}",
                                                     config('mint.cache.expire'),
-                                                function() use($row){
-                                                    return MdRender::render($row->content,[$row->channel_uid]);
+                                                function() use($row,$mode,$format){
+                                                    return MdRender::render($row->content,[$row->channel_uid],
+                                                                            null,$mode,'translation',
+                                                                            $row->content_type,$format);
                                                 });
+                                            */
                             }else{
-                                $mdRender = new MdRender(['debug'=>$this->debug]);
+                                $mdRender = new MdRender(
+                                    [
+                                        'debug'=>$this->debug,
+                                        'format'=>$format,
+                                        'mode'=>$mode,
+                                        'channelType'=>'translation',
+                                        'contentType'=>$row->content_type,
+                                    ]);
                                 $newSent['html'] = $mdRender->convert($row->content,[$row->channel_uid]);
                             }
                             break;

+ 1 - 0
app/Http/Controllers/SearchController.php

@@ -18,6 +18,7 @@ use App\Tools\Tools;
 use App\Models\WbwTemplate;
 use App\Models\PageNumber;
 use App\Tools\PaliSearch;
+use Illuminate\Support\Facades\App;
 
 
 class SearchController extends Controller

+ 3 - 3
app/Http/Controllers/SentenceController.php

@@ -229,17 +229,17 @@ class SentenceController extends Controller
         $user = AuthApi::current($request);
         if(!$user ){
             //未登录用户
-            return $this->error(__('auth.failed'),[],401);
+            return $this->error(__('auth.failed'),401,401);
         }
         $channel = Channel::where('uid',$request->get('channel'))->first();
         if(!$channel){
-            return $this->error(__('auth.failed'));
+            return $this->error(__('auth.failed'),403,403);
         }
         if($channel->owner_uid !== $user["user_uid"]){
             //判断是否为协作
             $power = ShareApi::getResPower($user["user_uid"],$channel->uid,2);
             if($power < 20){
-                return $this->error(__('auth.failed'),[],403);
+                return $this->error(__('auth.failed'),403,403);
             }
         }
         $sentFirst=null;

+ 14 - 1
app/Http/Resources/ArticleMapResource.php

@@ -4,6 +4,8 @@ namespace App\Http\Resources;
 
 use Illuminate\Http\Resources\Json\JsonResource;
 use App\Http\Api\UserApi;
+use App\Http\Api\MdRender;
+use App\Models\Collection;
 
 class ArticleMapResource extends JsonResource
 {
@@ -27,6 +29,17 @@ class ArticleMapResource extends JsonResource
             "created_at" => $this->created_at,
             "updated_at" => $this->updated_at,
         ];
-        return parent::toArray($request);
+        $channels = [];
+        if($request->has('channel')){
+            $channels = explode('_',$request->get('channel')) ;
+        }else{
+            $defaultChannel = Collection::where('uid',$this->collect_id)->value('default_channel');
+            if($defaultChannel){
+                $channels[] = $defaultChannel;
+            }
+        }
+        $mdRender = new MdRender(['format'=>'simple']);
+        $data['title_text'] = $mdRender->convert($this->title,$channels);
+        return $data;
     }
 }

+ 23 - 5
app/Http/Resources/ArticleResource.php

@@ -3,19 +3,23 @@
 namespace App\Http\Resources;
 
 use Illuminate\Http\Resources\Json\JsonResource;
-use App\Http\Api\MdRender;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Str;
+
 use App\Models\CourseMember;
 use App\Models\Course;
 use App\Models\Collection;
 use App\Models\ArticleCollection;
 use App\Models\Channel;
-use Illuminate\Support\Facades\Log;
+
+use App\Http\Controllers\ArticleController;
+
+use App\Http\Api\MdRender;
 use App\Http\Api\UserApi;
 use App\Http\Api\StudioApi;
 use App\Http\Api\AuthApi;
-use App\Http\Controllers\ArticleController;
 use App\Http\Api\ChannelApi;
-use Illuminate\Support\Str;
+
 
 class ArticleResource extends JsonResource
 {
@@ -40,6 +44,13 @@ class ArticleResource extends JsonResource
             "created_at" => $this->created_at,
             "updated_at" => $this->updated_at,
         ];
+        $channels = [];
+        if($request->has('channel')){
+            $channels = explode('_',$request->get('channel')) ;
+        }
+        $mdRender = new MdRender(['format'=>'simple']);
+        $data['title_text'] = $mdRender->convert($this->title,$channels);
+
         $user = AuthApi::current($request);
         if($user){
             $canEdit = ArticleController::userCanEdit($user['user_uid'],$this);
@@ -113,7 +124,14 @@ class ArticleResource extends JsonResource
         if(isset($this->content) && !empty($this->content)){
             if($request->has('channel')){
                 $channels = explode('_',$request->get('channel')) ;
-            }else{
+            }else if($request->has('anthology')){
+                $defaultChannel = Collection::where('uid',$request->get('anthology'))
+                                    ->value('default_channel');
+                if($defaultChannel){
+                    $channels[] = $defaultChannel;
+                }
+            }
+            if(count($channels) === 0){
                 //查找用户默认channel
                 $studioChannel = Channel::where('owner_uid',$this->owner)
                                         ->where('type','translation')

+ 5 - 0
app/Http/Resources/CollectionResource.php

@@ -4,6 +4,7 @@ namespace App\Http\Resources;
 
 use Illuminate\Http\Resources\Json\JsonResource;
 use App\Http\Api\StudioApi;
+use App\Http\Api\ChannelApi;
 use App\Models\ArticleCollection;
 
 
@@ -29,6 +30,10 @@ class CollectionResource extends JsonResource
             "created_at" => $this->created_at,
             "updated_at" => $this->updated_at,
         ];
+        $channel = ChannelApi::getById($this->default_channel);
+        if($channel){
+            $data['default_channel'] = $channel;
+        }
         if($this->fullArticleList===true){
             $data["article_list"] = \json_decode($this->article_list);
         }else{

+ 33 - 0
database/migrations/2023_11_11_145019_add_book_id_in_collections.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddBookIdInCollections extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('collections', function (Blueprint $table) {
+            $table->integer('book_id')->nullable()->index();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('collections', function (Blueprint $table) {
+            $table->dropColumn('book_id');
+
+        });
+    }
+}

+ 32 - 0
database/migrations/2023_11_14_120933_add_default_channel_in_collections.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddDefaultChannelInCollections extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('collections', function (Blueprint $table) {
+            $table->uuid('default_channel')->nullable()->index();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('collections', function (Blueprint $table) {
+            $table->dropColumn('default_channel');
+        });
+    }
+}

+ 5 - 5
public/app/article/my_article_post.php

@@ -15,7 +15,7 @@ $respond=array("status"=>0,"message"=>"");
 
 # 检查是否有修改权限
 $redis = redis_connect();
-$article = new Article($redis); 
+$article = new Article($redis);
 $power = $article->getPower($_POST["id"]);
 if($power<20){
 	$respond["status"]=1;
@@ -26,7 +26,7 @@ if($power<20){
 
 $_content = $_POST["content"];
 
-
+/*
 if(isset($_POST["import"]) && $_POST["import"]=='on'){
 	#导入自定义书
 	$custom_book = new CustomBook($redis);
@@ -53,7 +53,7 @@ if(isset($_POST["import"]) && $_POST["import"]=='on'){
 		exit;
 	}
 }
-
+*/
 
 PDO_Connect(_FILE_DB_USER_ARTICLE_,_DB_USERNAME_,_DB_PASSWORD_);
 
@@ -71,7 +71,7 @@ else{
 		$redis->del("article://".$_POST["id"]);
 		$redis->del("power://article/".$_POST["id"]);
 	}
-	
+
 }
 echo json_encode($respond, JSON_UNESCAPED_UNICODE);
-?>
+?>