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

Merge branch 'chanpter_progress' into laravel

visuddhinanda 3 лет назад
Родитель
Сommit
5190ec98b6
61 измененных файлов с 5195 добавлено и 1353 удалено
  1. 159 0
      app/Console/Commands/UpgradeChapterDynamic.php
  2. 33 1
      app/Console/Commands/UpgradeDaily.php
  3. 2 1
      app/Console/Commands/UpgradePaliText.php
  4. 6 1
      app/Console/Commands/UpgradePaliTextTag.php
  5. 16 9
      app/Console/Commands/UpgradeProgressChapter.php
  6. 67 0
      app/Console/Commands/WebHook.php
  7. 5 0
      app/Console/Kernel.php
  8. 126 0
      app/Http/Controllers/LikeController.php
  9. 176 0
      app/Http/Controllers/PaliTextController.php
  10. 165 21
      app/Http/Controllers/ProgressChapterController.php
  11. 95 0
      app/Http/Controllers/SentHistoryController.php
  12. 27 14
      app/Http/Controllers/SentenceInfoController.php
  13. 198 0
      app/Http/Controllers/ViewController.php
  14. 15 0
      app/Models/Like.php
  15. 8 0
      app/Models/ProgressChapter.php
  16. 5 0
      app/Models/TagMap.php
  17. 11 0
      app/Models/UserExperience.php
  18. 18 0
      app/Models/View.php
  19. 35 0
      database/migrations/2022_05_27_072344_create_views_table.php
  20. 36 0
      database/migrations/2022_05_28_120007_add_summary_in_progress_chapters.php
  21. 46 0
      database/migrations/2022_05_29_103822_create_likes_table.php
  22. 39 0
      database/migrations/2022_06_03_021251_create_user_experiences_table.php
  23. 41 0
      database/migrations/2022_06_18_134823_add_title_in_views.php
  24. 24 1
      public/app/article/article.js
  25. 11 1
      public/app/article/index.php
  26. 2 2
      public/app/config.table.php
  27. 7 2
      public/app/nissaya/get.php
  28. 57 0
      public/app/nissaya/get_book_list.php
  29. 7 1
      public/app/nissaya/index.php
  30. 49 2
      public/app/nissaya/nissaya.js
  31. 331 31
      public/app/palicanon/category/cscd.json
  32. 342 10
      public/app/palicanon/category/defualt.json
  33. 22 0
      public/app/palicanon/chapter_channel.css
  34. 164 0
      public/app/palicanon/chapter_channel.js
  35. 286 82
      public/app/palicanon/index.php
  36. 175 176
      public/app/palicanon/index1.php
  37. 55 0
      public/app/palicanon/loading.css
  38. 94 0
      public/app/palicanon/my_space.js
  39. 644 220
      public/app/palicanon/palicanon.js
  40. 45 0
      public/app/palicanon/router.js
  41. 345 17
      public/app/palicanon/style.css
  42. 67 0
      public/app/palicanon/style_mobile.css
  43. 35 0
      public/app/palicanon/test.js
  44. 2 2
      public/app/pcdl/css/style.css
  45. 221 221
      public/app/public/book_tag/en.json
  46. 3 0
      public/app/public/lang/default.json
  47. 3 0
      public/app/public/lang/en.json
  48. 3 4
      public/app/public/lang/my.json
  49. 3 0
      public/app/public/lang/si.json
  50. 3 0
      public/app/public/lang/zh-cn.json
  51. 5 2
      public/app/public/lang/zh-tw.json
  52. 4 3
      public/app/ucenter/function.php
  53. 8 0
      public/app/widget/like.css
  54. 73 34
      public/app/widget/like.js
  55. 0 0
      public/app/widget/submenu.css
  56. 31 0
      public/app/widget/submenu.js
  57. 88 0
      public/documents/模版设计.md
  58. 1 1
      public/pali_title/139_pali.csv
  59. 494 494
      public/pali_title/pali_text_tag.csv
  60. 10 0
      routes/api.php
  61. 152 0
      v1/scripts/migrations/20220529172100_like_copy.php

+ 159 - 0
app/Console/Commands/UpgradeChapterDynamic.php

@@ -0,0 +1,159 @@
+<?php
+
+namespace App\Console\Commands;
+use Illuminate\Support\Facades\Storage;
+use Illuminate\Console\Command;
+use Illuminate\Support\Carbon;
+use App\Models\SentHistory;
+use App\Models\Sentence;
+use App\Models\ProgressChapter;
+use App\Models\PaliText;
+
+class UpgradeChapterDynamic extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'upgrade:chapterdynamic {--test}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '更新章节活跃程度svg';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $start = time();
+        $img_width = 600;
+        $img_height = 120;
+        $days = 300; //统计多少天
+        $min = 30;
+        $linewidth = 2;
+
+        $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...
+            $max=0;
+            #章节长度
+            $paraEnd = PaliText::where('book',$chapter->book)
+                            ->where('paragraph',$chapter->para)
+                            ->value('chapter_len')+$chapter->para-1;            
+
+            $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...
+
+                #这一天有多少次更新
+                $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)
+                             ->whereBetween('paragraph',[$chapter->para,$paraEnd])
+                             ->count();
+                $x=($days-$i)*($img_width/$days);
+                $y=(300-$count)*($img_height/300)-$linewidth;
+                $svg .= "{$x},{$y} ";
+            }
+            $svg .= "'  style='fill:none;stroke:green;stroke-width:{$linewidth}' /></svg>";
+            $filename = "{$chapter->book}/{$chapter->para}/globle.svg";
+            Storage::disk('local')->put("public/images/chapter_dynamic/{$filename}", $svg);
+            $bar->advance();
+
+            if($this->option('test')){
+                break; //调试代码
+            }
+
+        }
+        $bar->finish();
+
+        $this->info('用时'.(time()-$start));
+        $start = time();
+
+        $this->info('更新缺的章节空白图');
+        // 更新缺的章节空白图
+        $chapters = PaliText::select('book','paragraph')
+                            ->where('level', '<', 8)
+                            ->get();
+        $bar = $this->output->createProgressBar(count($chapters));
+        $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}")){
+                Storage::disk('local')->put("public/images/chapter_dynamic/{$filename}", $svg);
+            }
+            $bar->advance();
+
+            if($this->option('test')){
+                break; //调试代码
+            }
+        }
+        $bar->finish();
+
+
+        //更新chennel动态
+        $this->info('更新chennel动态');
+        $bar = $this->output->createProgressBar(ProgressChapter::count());
+
+        foreach (ProgressChapter::select('book','para','channel_id')->cursor() as $chapter) {
+            # code...
+            $max=0;
+            #章节长度
+            $paraEnd = PaliText::where('book',$chapter->book)
+                            ->where('paragraph',$chapter->para)
+                            ->value('chapter_len')+$chapter->para-1;
+
+            $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...
+
+                #这一天有多少次更新
+                $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)
+                             ->whereBetween('paragraph',[$chapter->para,$paraEnd])
+                             ->where('sentences.channel_uid',$chapter->channel_id)
+                             ->count();
+                $x=($days-$i)*($img_width/$days);
+                $y=(300-$count)*($img_height/300)-$linewidth;
+                $svg .= "{$x},{$y} ";
+            }
+            $svg .= "'  style='fill:none;stroke:green;stroke-width:{$linewidth}' /></svg>";
+            $filename = "{$chapter->book}/{$chapter->para}/ch_{$chapter->channel_id}.svg";
+            Storage::disk('local')->put("public/images/chapter_dynamic/{$filename}", $svg);
+            $bar->advance();
+
+            if($this->option('test')){
+                break; //调试代码
+            }
+        }
+        $bar->finish();
+
+        return 0;
+    }
+}

+ 33 - 1
app/Console/Commands/UpgradeDaily.php

@@ -3,6 +3,8 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
+use Illuminate\Support\Carbon;
+
 
 class UpgradeDaily extends Command
 {
@@ -37,12 +39,42 @@ class UpgradeDaily extends Command
      */
     public function handle()
     {
-        $this->call('upgrade:palitext');
+        $start = time();
+		if(app()->isLocal()==false){
+			$this->call('message:webhook',[
+				'listener' => 'dingtalk',
+				'url' => 'dingtalk1',
+				'title' => "后台任务",
+				'message' => " wikipali: 每日统计后台任务开始执行。",
+			]);
+		}
+
+        # 刷巴利语句子uuid 仅调用一次
         $this->call('upgrade:palitextid');
+        //巴利原文段落库目录结构改变时运行
+        $this->call('upgrade:palitext'); 
+        #巴利段落标签
         $this->call('upgrade:palitexttag');
+        #译文进度
         $this->call('upgrade:progress');
         $this->call('upgrade:progresschapter');
+        # 段落更新图
+        $this->call('upgrade:chapterdynamic');
+        # 逐词译数据库分析
         $this->call('upgrade:wbwanalyses');
+
+        $time = time()-$start;
+
+		if(app()->isLocal()==false){
+			$this->call('message:webhook',[
+				'listener' => 'dingtalk',
+				'url' => 'dingtalk1',
+				'title' => "后台任务",
+				'message' => "wikipali: 每日统计后台任务执行完毕。用时{$time}",
+			]);			
+		}
+
+
         return 0;
     }
 }

+ 2 - 1
app/Console/Commands/UpgradePaliText.php

@@ -84,7 +84,8 @@ class UpgradePaliText extends Command
 				Log::error( "can not open csv file. filename=" . $csvFile) ;
 				continue;
 			}
-			$title_data = PaliText::where('book',$from)->orderby('paragraph','asc')->get();
+			$title_data = PaliText::select(['book','paragraph','level','parent','toc'])
+								->where('book',$from)->orderby('paragraph','asc')->get();
             {
 				$paragraph_count = count($title_data);
 				$paragraph_info = array();

+ 6 - 1
app/Console/Commands/UpgradePaliTextTag.php

@@ -15,7 +15,7 @@ class UpgradePaliTextTag extends Command
      *
      * @var string
      */
-    protected $signature = 'upgrade:palitexttag';
+    protected $signature = 'upgrade:palitexttag {book?}';
 
     /**
      * The console command description.
@@ -69,6 +69,11 @@ class UpgradePaliTextTag extends Command
             }
             */
             $book = $data[0];
+            if(!empty($this->argument('book'))){
+                if($book != (int)$this->argument('book')){
+                    continue;
+                }
+            }
             $para = $data[1];
             $tags = explode(':',$data[4]);
             $paliTextUuid = PaliText::where("book",$book)->where("paragraph",$para)->value('uid');

+ 16 - 9
app/Console/Commands/UpgradeProgressChapter.php

@@ -89,6 +89,21 @@ class UpgradeProgressChapter extends Command
                                 ->whereBetween('para',[$chapter->paragraph,$chapter->paragraph+$chapter->chapter_len-1])
                                 ->where('channel_id',$final->channel_id)
                                 ->max('updated_at');
+                    $transTexts = Sentence::where('book_id',$book->book_id)
+                                ->whereBetween('paragraph',[$chapter->paragraph+1,$chapter->paragraph+$chapter->chapter_len-1])
+                                ->where('channel_uid',$final->channel_id)
+                                ->select('content')
+                                ->orderBy('paragraph')
+                                ->orderBy('word_start')
+                                ->get();
+                    $summaryText = "";
+                    foreach ($transTexts as $text) {
+                        # code...
+                        $summaryText .= str_replace("\n","",$text->content);
+                        if(mb_strlen($summaryText,"UTF-8")>255){
+                            break;
+                        }
+                    }
                     #查询标题
                     $title = Sentence::where('book_id',$book->book_id)
                           ->where('paragraph',$chapter->paragraph)
@@ -102,15 +117,6 @@ class UpgradeProgressChapter extends Command
                             'book'=>$book->book_id,
                             'para'=>$chapter->paragraph,
                             'channel_id'=>$final->channel_id];
-                    $value = [
-                            'lang'=>$lang,
-                            'all_trans'=>$final->cp_len/$chapter_strlen,
-                            'public'=>$final->cp_len/$chapter_strlen,
-                            'progress'=>$final->cp_len/$chapter_strlen,
-                            'title'=>mb_substr($title,0,255,"UTF-8"),
-                            'created_at'=>$finalAt,
-                            'updated_at'=>$updateAt
-                        ];
                     
                     $rules = array(
                         'book' => 'integer',
@@ -137,6 +143,7 @@ class UpgradeProgressChapter extends Command
                     $chapterData->public = $final->cp_len/$chapter_strlen;
                     $chapterData->progress = $final->cp_len/$chapter_strlen;
                     $chapterData->title = mb_substr($title,0,255,"UTF-8");
+                    $chapterData->summary = mb_substr($summaryText,0,255,"UTF-8");
                     $chapterData->created_at = $finalAt;
                     $chapterData->updated_at = $updateAt;
                     $chapterData->save();

+ 67 - 0
app/Console/Commands/WebHook.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Http;
+
+class WebHook extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'message:webhook {listener} {url} {title} {message}';
+	protected $url = [
+		"dingtalk1"=>"https://oapi.dingtalk.com/robot/send?access_token=34143dbec80a8fc09c1cb5897a5639ee3a9a32ecfe31835ad29bf7013bdb9fdf",
+		"weixin1"=>"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=9693cceb-bd2e-40c9-8c0c-3260b2c50aa8",
+	];
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '发送消息到一个服务器机器人,';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+		switch ($this->argument('listener')) {
+			case 'weixin':
+				# code...
+				break;
+			case 'dingtalk':
+				# code...
+				$url = $this->url[$this->argument('url')];
+				$param = [
+				"markdown"=> [
+					"title"=> $this->argument('title'), 
+					"text"=> $this->argument('message'), 
+				], 
+				"msgtype"=>"markdown"
+				];
+				break;				
+			default:
+				# code...
+				break;
+		}
+		$response = Http::post($url, $param);
+        return 0;
+    }
+}

+ 5 - 0
app/Console/Kernel.php

@@ -16,6 +16,11 @@ class Kernel extends ConsoleKernel
     protected function schedule(Schedule $schedule)
     {
         // $schedule->command('inspire')->hourly();
+        $schedule->timezone('Asia/Shanghai')
+                 ->command('upgrade:daily')
+                 ->dailyAt('00:00')
+                 ->emailOutputTo('kosalla1987@126.com');
+				 //->emailOutputOnFailure()
     }
 
     /**

+ 126 - 0
app/Http/Controllers/LikeController.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\Like;
+use Illuminate\Http\Request;
+
+class LikeController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index(Request $request)
+    {
+        //
+        switch ($request->get("view")) {
+            case 'count':
+                # code...
+                $resulte = Like::where("target_id",$request->get("target_id"))
+                                ->groupBy("type")
+                                ->select("type")
+                                ->selectRaw("count(*)")
+                                ->get();
+                if(isset($_COOKIE["user_uid"])){
+                    foreach ($resulte as $key => $value) {
+                        # code...
+                        if(Like::where(["target_id"=>$request->get("target_id"),
+                                        'type'=>$value->type,
+                                        'user_id'=>$_COOKIE["user_uid"]])->exists()){
+                            $resulte[$key]->selected = true;
+                        }
+                    }
+                }
+                break;
+            default:
+                # code...
+                break;
+        }
+
+        return $this->ok($resulte);
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+        if(!isset($_COOKIE["user_uid"])){
+            return $this->error("no login");
+        }
+        $param = $request->all();
+        $param['user_id'] = $_COOKIE["user_uid"];
+        $like = Like::firstOrCreate($param);
+
+        return $this->ok($like);
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Models\Like  $like
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Like $like)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Models\Like  $like
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Like $like)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Models\Like  $like
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Like $like)
+    {
+        //
+        if(!isset($_COOKIE["user_uid"])){
+            return $this->error("no login");
+        }
+        if($like->user_id==$_COOKIE["user_uid"]){
+            return $this->ok($like->delete());
+        }
+        
+        $param = $request->all();
+        $param['user_id'] = $_COOKIE["user_uid"];
+        $like = Like::where($param)->delete();
+        return $this->ok($like);
+        
+    }
+    public function delete(Request $request){
+        if(!isset($_COOKIE["user_uid"])){
+            return $this->error("no login");
+        }
+        $param = [
+            "id"=>$request->get('id'),
+            'user_id'=>$_COOKIE["user_uid"]
+        ];
+        $del = Like::where($param)->delete();
+        $count = Like::where('target_id',$request->get('target_id'))
+                    ->where('type',$request->get('type'))
+                    ->count();
+        return $this->ok([
+            'deleted'=>$del,
+            'count'=>$count
+            ]);
+    }
+}

+ 176 - 0
app/Http/Controllers/PaliTextController.php

@@ -0,0 +1,176 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Support\Facades\DB;
+use App\Models\PaliText;
+use App\Models\Tag;
+use App\Models\TagMap;
+use Illuminate\Http\Request;
+
+class PaliTextController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index(Request $request)
+    {
+        //
+        switch ($request->get('view')) {
+            case 'chapter-tag':
+                $tm = (new TagMap)->getTable();
+                $tg = (new Tag)->getTable();     
+                $pt = (new PaliText)->getTable();  
+                if($request->get('tags') && $request->get('tags')!==''){
+                    $tags = explode(',',$request->get('tags'));
+                    foreach ($tags as $tag) {
+                        # code...
+                        if(!empty($tag)){
+                            $tagNames[] = $tag;
+                        }
+                    }
+                }
+                
+                if(isset($tagNames)){
+                    $where1 = " where co = ".count($tagNames);
+                    $a = implode(",",array_fill(0, count($tagNames), '?')) ;
+                    $in1 = "and t.name in ({$a})";
+                    $param  = $tagNames;
+                }else{
+                    $where1 = " ";
+                    $in1 = " ";
+                }
+                $query = "
+                    select tags.id,tags.name,co as count 
+                        from (
+                            select tm.tag_id,count(*) as co from (
+                                select anchor_id as id from (
+                                    select tm.anchor_id , count(*) as co
+                                        from $tm as  tm
+                                        left join $tg as t on tm.tag_id = t.id
+                                        left join $pt as pc on tm.anchor_id = pc.uid
+                                        where tm.table_name  = 'pali_texts' 
+                                        $in1
+                                        group by tm.anchor_id
+                                ) T 
+                                    $where1
+                            ) CID 
+                            left join $tm as tm on tm.anchor_id = CID.id 
+                            group by tm.tag_id
+                        ) tid
+                        left join $tg on $tg.id = tid.tag_id
+                        order by count desc
+                    ";
+                    if(isset($param)){
+                        $chapters = DB::select($query,$param);
+                    }else{
+                        $chapters = DB::select($query);
+                    }
+                    $all_count = count($chapters);
+                break;
+
+            case 'chapter':
+                $tm = (new TagMap)->getTable();
+                $tg = (new Tag)->getTable();     
+                $pt = (new PaliText)->getTable();  
+                if($request->get('tags') && $request->get('tags')!==''){
+                    $tags = explode(',',$request->get('tags'));
+                    foreach ($tags as $tag) {
+                        # code...
+                        if(!empty($tag)){
+                            $tagNames[] = $tag;
+                        }
+                    }
+                }
+                
+                
+                if(isset($tagNames)){
+                    $where1 = " where co = ".count($tagNames);
+                    $a = implode(",",array_fill(0, count($tagNames), '?')) ;
+                    $in1 = "and t.name in ({$a})";
+                    $param = $tagNames;
+                    $where2 = "where level < 3";
+                }else{
+                    $where1 = " ";
+                    $in1 = " ";
+                    $where2 = "where level = 1";
+                }
+                $query = "
+                        select uid as id,book,paragraph,level,toc as title,chapter_strlen,parent,path from (
+                            select anchor_id as cid from (
+                                select tm.anchor_id , count(*) as co 
+                                    from $tm as  tm
+                                    left join $tg as t on tm.tag_id = t.id
+                                    where tm.table_name  = 'pali_texts'
+                                    $in1
+                                    group by tm.anchor_id
+                            ) T 
+                                $where1 
+                        ) CID 
+                        left join $pt as pt on CID.cid = pt.uid 
+                        $where2
+                        order by book,paragraph";
+                        
+                    if(isset($param)){
+                        $chapters = DB::select($query,$param);
+                    }else{
+                        $chapters = DB::select($query);
+                    }
+
+                $all_count = count($chapters);
+                break;
+        }
+        if($chapters){
+            return $this->ok(["rows"=>$chapters,"count"=>$all_count]);
+        }else{
+            return $this->error("no data");
+        }
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Models\PaliText  $paliText
+     * @return \Illuminate\Http\Response
+     */
+    public function show(PaliText $paliText)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Models\PaliText  $paliText
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, PaliText $paliText)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Models\PaliText  $paliText
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(PaliText $paliText)
+    {
+        //
+    }
+}

+ 165 - 21
app/Http/Controllers/ProgressChapterController.php

@@ -2,12 +2,15 @@
 
 namespace App\Http\Controllers;
 
+use Illuminate\Support\Str;
 use Illuminate\Support\Facades\DB;
 use App\Models\ProgressChapter;
 use App\Models\Channel;
 use App\Models\Tag;
 use App\Models\TagMap;
 use App\Models\PaliText;
+use App\Models\View;
+use App\Models\Like;
 use Illuminate\Http\Request;
 
 class ProgressChapterController extends Controller
@@ -30,10 +33,24 @@ class ProgressChapterController extends Controller
         }else{
             $offset = 0;
         }
+
+        $channel_id = $request->get('channel');
+
         //
 
         $chapters=false;
         switch ($request->get('view')) {
+            case 'ids':
+                $aChannel = explode(',',$request->get('channel'));
+                $chapters = ProgressChapter::select("channel_id")->selectRaw("uid as id")
+                                         ->with(['channel' => function($query) {  //city对应上面province模型中定义的city方法名  闭包内是子查询
+                                                return $query->select('*');
+                                            }])
+                                        ->where("book",$request->get('book'))
+                                        ->where("para",$request->get('par'))
+                                        ->whereIn('channel_id', $aChannel)->get();
+                $all_count = count($chapters);
+                break;
 			case 'studio':
                 #查询该studio的channel
                 $channels = Channel::where('owner_uid',$request->get('id'))->select('uid')->get();
@@ -95,6 +112,12 @@ class ProgressChapterController extends Controller
                     $where1 = " ";
                     $in1 = " ";
                 }
+                if(Str::isUuid($channel_id)){
+                    $channel = "and channel_id = '{$channel_id}' "; 
+                }else{
+                    $channel = "";
+                }
+
                 $query = "
                     select tags.id,tags.name,co as count 
                         from (
@@ -107,6 +130,7 @@ class ProgressChapterController extends Controller
                                         where tm.table_name  = 'progress_chapters' and 
                                               pc.progress  > ? 
                                         $in1
+                                        $channel
                                         group by tm.anchor_id
                                 ) T 
                                     $where1
@@ -125,6 +149,7 @@ class ProgressChapterController extends Controller
                     $all_count = count($chapters);
                 break;
             case 'lang':
+                
                 $chapters = ProgressChapter::select('lang')
                                             ->selectRaw('count(*) as count')
                                             ->where("progress",">",$minProgress)
@@ -135,17 +160,66 @@ class ProgressChapterController extends Controller
             case 'channel-type':
                 break;
             case 'channel':
+            /*
+            总共有多少channel
+            */
                 $chapters = ProgressChapter::select('channel_id')
-                                            ->selectRaw('count(*) as count')
-                                            ->with(['channel' => function($query) {  //city对应上面province模型中定义的city方法名  闭包内是子查询
+                                           ->selectRaw('count(*) as count')
+                                           ->with(['channel' => function($query) {  
                                                 return $query->select('*');
                                             }])
-                                            ->where("progress",">",$minProgress)
-                                            ->groupBy('channel_id')
+                                           ->leftJoin('channels','progress_chapters.channel_id', '=', 'channels.uid')
+                                           ->where("progress",">",$minProgress)
+										   ->where('channels.status','>=',30);
+                if(!empty($request->get('channel_type'))){
+                    $chapters =  $chapters->where('channels.type',$request->get('channel_type'));
+                }
+                if(!empty($request->get('lang'))){
+                    $chapters =  $chapters->where('progress_chapters.lang',$request->get('lang'));
+                }
+                $chapters =  $chapters->groupBy('channel_id')
                                             ->orderBy('count','desc')
                                             ->get();
                 $all_count = count($chapters);
                 break;
+            case 'chapter_channels':
+            /*
+                某个章节 有多少channel
+            */
+                $chapters = ProgressChapter::select('book','para','progress_chapters.uid','progress_chapters.channel_id','progress','updated_at')
+                                            ->with(['channel' => function($query) {
+                                                return $query->select('*');
+                                            }])
+                                            ->where("book",$request->get('book'))
+                                            ->where("para",$request->get('par'))
+                                            ->orderBy('progress','desc')
+                                            ->get();
+                foreach ($chapters as $key => $value) {
+                    # code...
+                    $chapters[$key]->views = View::where("target_id",$value->uid)->count();
+                    
+                    $likes = Like::where("target_id",$value->uid)
+                                ->groupBy("type")
+                                ->select("type")
+                                ->selectRaw("count(*)")
+                                ->get();
+                    if(isset($_COOKIE["user_uid"])){
+                        foreach ($likes as $key1 => $like) {
+                            # 查看这些点赞里有没有我点的
+                            $myLikeId =Like::where(["target_id"=>$value->uid,
+                                            'type'=>$like->type,
+                                            'user_id'=>$_COOKIE["user_uid"]])->value('id');
+                            if($myLikeId){
+                                $likes[$key1]->selected = $myLikeId;
+                            }
+                        }
+                    }
+                    $chapters[$key]->likes = $likes;
+                    
+                }
+                
+                $all_count = count($chapters);
+                break;
             case 'chapter':
                 $tm = (new TagMap)->getTable();
                 $pc =(new ProgressChapter)->getTable();
@@ -171,35 +245,105 @@ class ProgressChapterController extends Controller
                     $where1 = " ";
                     $in1 = " ";
                 }
+                if(Str::isUuid($channel_id)){
+                    $channel = "and channel_id = '{$channel_id}' "; 
+                }else{
+                    $channel = "";
+                }
+
+				
+
+
                 $param[] = $minProgress;
+
+                if(!empty($request->get('lang'))){
+                    $whereLang = " and pc.lang = ? ";
+                    $param[] = $request->get('lang');
+                }else{
+                    $whereLang = "   ";
+                }                
+
+				if($request->has('channel_type') && !empty($request->get('channel_type'))){
+					$channel_type = "and ch.type = ? "; 
+					$param[] = $request->get('channel_type');
+				}else{
+					$channel_type = "";
+				}	
+
+                $param_count = $param;
                 $param[] = $offset;
+
+
                 $query = "
-                select tpc.book ,tpc.para,tpc.channel_id,tpc.title,pt.toc,pt.path,tpc.progress,tpc.created_at,tpc.updated_at 
+                select tpc.pc_uid as uid, tpc.book ,tpc.para,tpc.channel_id,tpc.title,pt.toc,pt.path,tpc.progress,tpc.summary,tpc.created_at,tpc.updated_at 
                     from (
-                        select * from (
-                            select anchor_id as cid from (
-                                select tm.anchor_id , count(*) as co 
-                                    from $tm as  tm
-                                    left join $tg as t on tm.tag_id = t.id
-                                    where tm.table_name  = 'progress_chapters'  
-                                    $in1
-                                    group by tm.anchor_id
-                            ) T 
-                                $where1 
-                        ) CID 
-                        left join $pc as pc on CID.cid = pc.uid 
-                        where pc.progress > ?
-                        order by created_at desc
+						select pcd.uid as pc_uid, ch.uid as ch_uid, book , para, channel_id,progress, title ,pcd.summary , pcd.created_at,pcd.updated_at
+							from (
+								select uid, book,para,lang,progress,channel_id,title,summary ,created_at ,updated_at
+									from (
+										select anchor_id as cid 
+											from (
+												select tm.anchor_id , count(*) as co 
+													from $tm as  tm
+													left join $tg as t on tm.tag_id = t.id
+													where tm.table_name  = 'progress_chapters'  
+													$in1
+													group by tm.anchor_id
+											) T 
+											$where1 
+									) CID 
+								left join $pc as pc on CID.cid = pc.uid 
+								where pc.progress > ? 
+								$channel  $whereLang
+							) pcd
+						left join channels as ch on pcd.channel_id = ch.uid
+						where ch.status >= 30 $channel_type
+                        order by pcd.created_at desc
                         limit 20 offset ?
                     ) tpc 
                     left join $pt as pt on tpc.book = pt.book and tpc.para = pt.paragraph;";
                 $chapters = DB::select($query,$param);
                 foreach ($chapters as $key => $value) {
                     # code...
-                    $chapters[$key]->channel_info = Channel::where('uid',$value->channel_id)->select(['name','owner_uid'])->first();
+                    $chapters[$key]->channel = Channel::where('uid',$value->channel_id)->select(['name','owner_uid'])->first();
+                    $chapters[$key]->views = View::where("target_id",$value->uid)->count();
+                    $chapters[$key]->likes = Like::where(["type"=>"like","target_id"=>$value->uid])->count();
+                    $chapters[$key]->tags = TagMap::where("anchor_id",$value->uid)
+                                                ->leftJoin('tags','tag_maps.tag_id', '=', 'tags.id')
+                                                ->select(['tags.id','tags.name','tags.description'])
+                                                ->get();
                 }
-                $all_count = 10;
+
+                //计算按照这个条件搜索到的总数
+                $query  = "
+                         select count(*) as count 
+							from (
+								select *
+								from (
+									select anchor_id as cid 
+										from (
+											select tm.anchor_id , count(*) as co 
+												from $tm as  tm
+												left join $tg as t on tm.tag_id = t.id
+												where tm.table_name  = 'progress_chapters'  
+												$in1
+												group by tm.anchor_id
+										) T 
+										$where1 
+								) CID 
+								left join $pc as pc on CID.cid = pc.uid 
+								where pc.progress > ? 
+								$channel   $whereLang
+							) pcd
+							left join channels as ch on pcd.channel_id = ch.uid
+							where ch.status >= 30 $channel_type
+
+                ";
+                $count = DB::select($query,$param_count);
+                $all_count = $count[0]->count;
                 break;
+            case 'top':
+            break;
         }
         if($chapters){
             return $this->ok(["rows"=>$chapters,"count"=>$all_count]);

+ 95 - 0
app/Http/Controllers/SentHistoryController.php

@@ -0,0 +1,95 @@
+<?php
+
+namespace App\Http\Controllers;
+
+require_once __DIR__.'/../../../public/app/ucenter/function.php';
+
+use App\Models\SentHistory;
+use Illuminate\Http\Request;
+
+class SentHistoryController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index(Request $request)
+    {
+        //
+        switch ($request->view) {
+            case 'contribution':
+                /**
+                 *  计算用户贡献度
+                 *  算法:统计句子历史记录里的用户贡献句子的数量
+                 *  TODO:
+                 *  应该祛除重复的句子,一个句子的多次修改只计算一次
+                 *  只统计一个月内的数值
+                 */
+                $result = SentHistory::select('user_uid')
+                                    ->selectRaw('count(*)')
+                                    ->groupBy('user_uid')
+                                    ->orderBy('count','desc')
+                                    ->take(10)
+                                    ->get();
+                
+                $userinfo = new \UserInfo();
+                foreach ($result as $key => $user) {
+                    # code...
+                    $user->username = $userinfo->getName($user->user_uid);
+                }
+                return $this->ok($result);
+                break;
+            
+            default:
+                # code...
+                break;
+        }
+        
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Models\SentHistory  $sentHistory
+     * @return \Illuminate\Http\Response
+     */
+    public function show(SentHistory $sentHistory)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Models\SentHistory  $sentHistory
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, SentHistory $sentHistory)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Models\SentHistory  $sentHistory
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(SentHistory $sentHistory)
+    {
+        //
+    }
+}

+ 27 - 14
app/Http/Controllers/SentenceInfoController.php

@@ -124,6 +124,7 @@ class SentenceInfoController extends Controller
                             ->where('paragraph','<=',$to)
                             ->sum('length');            
             $para_strlen = 0;
+            
             foreach ($sentFinished as $sent) {
                 # code...
                 if($request->get('cache')=="1"){
@@ -157,8 +158,8 @@ class SentenceInfoController extends Controller
                     $resulte = $strlen / $pageStrLen;
                 }
                 break;
-            case 'percent':
-                $resulte = $percent;
+            case 'percent': //百分比
+                $resulte = sprintf('%.2f',$percent);
                 break;
             case 'strlen':
             default:
@@ -176,23 +177,35 @@ class SentenceInfoController extends Controller
      *
      * @param  \App\Models\Sentence  $sentence
      * @return \Illuminate\Http\Response
-     * http://127.0.0.1:8000/api/sentence/progress/image?channel=00ae2c48-c204-4082-ae79-79ba2740d506&&book=168&from=916&to=926&view=page
+     * http://127.0.0.1:8000/api/sentence/progress/image?channel=00ae2c48-c204-4082-ae79-79ba2740d506&&book=168&from=916&to=926&view=percent
      */
     public function showprogress(Request $request)
     {
-        ob_clean();
-        ob_start();
         $resulte = $this->getSentProgress($request);
-        $img = imagecreate(strlen($resulte)*10,22) or die('create image fail ');
-        imagecolorallocate($img,255,255,255);
-        $color = imagecolorallocate($img,0,0,0);
-        imagestring($img,5,0,0,$resulte,$color);
-        imagegif($img);
-        imagedestroy($img);
+        $svg = "<svg  xmlns='http://www.w3.org/2000/svg'  xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 100 25'>";
 
-        $content = ob_get_clean();
-        return response($content,200,[
-            'Content-Type'=>'image/gif'
+        switch ($request->get('view')) {
+            case 'percent':
+                # code...
+                $resulte = $resulte*100;
+                $svg .= "<rect id='frontground' x='0' y='0' width='100' height='25' fill='#cccccc' ></rect>";
+                $svg .= "<text id='bg_text'  x='5' y='21' fill='#006600' style='font-size:25px;'>$resulte%</text>";
+                $svg .= "<rect id='background' x='0' y='0' width='100' height='25' fill='#006600' clip-path='url(#textClipPath)'></rect>";
+                $svg .= "<text id='bg_text'  x='5' y='21' fill='#ffffff' style='font-size:25px;' clip-path='url(#textClipPath)'>$resulte%</text>";
+                $svg .= "<clipPath id='textClipPath'>";
+                $svg .= "    <rect x='0' y='0' width='$resulte' height='25'></rect>";
+                $svg .= "</clipPath>";
+                break;
+            case 'strlen':
+            case 'page':
+            default:
+                $svg .= "<text id='bg_text'  x='5' y='21' fill='#006600' style='font-size:25px;'>$resulte</text>";
+                break;
+        }
+        $svg .= "</svg>";
+
+        return response($svg,200,[
+            'Content-Type'=>'image/svg+xml'
         ]);
     }
 

+ 198 - 0
app/Http/Controllers/ViewController.php

@@ -0,0 +1,198 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\View;
+use App\Models\ProgressChapter;
+use App\Models\PaliText;
+use Illuminate\Http\Request;
+use Illuminate\Support\Str;
+use Illuminate\Support\Facades\Log;
+
+class ViewController extends Controller
+{
+    private function getTargetId($request){
+        /*
+        *根据target type 和不同类型的不同参数
+        */
+        $target_id = FALSE;
+        switch ($request->get("target_type")) {
+            case 'chapter-instance':
+                # code...
+                $target_id = $request->get("target_id");
+                break;
+            case 'chapter':
+                # code...
+                $channel = $request->get("channel");
+                $book = $request->get("book");
+                $para = $request->get("para");
+                $target_id = ProgressChapter::where("channel_id",$request->get("channel"))
+                                            ->where("book",$request->get("book"))
+                                            ->where("para",$request->get("para"))
+                                            ->value("uid");
+                break;
+            case 'article-instance':
+                # code...
+                break;
+            case 'article':
+                # code...
+                break;
+            default:
+                $target_id = $request->get("target_id");
+                # code...
+                break;
+        }
+        if(Str::isUuid($target_id)){
+            return $target_id;
+        }else{
+            return false;
+        }
+        
+    }
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index(Request $request)
+    {
+        //
+        switch ($request->get("view")) {
+            case 'count':
+                #获取 target id
+                $target_id = $this->getTargetId($request);
+                if($target_id){
+                    $count = View::where("target_id",$target_id)->count();
+                }else{
+                    $count = 0;
+                }
+                return $this->ok($count);
+                break;
+            case 'user-recent':
+                if(!isset($_COOKIE["user_uid"])){
+                    return $this->error("no login");
+                }
+                $user_id = $_COOKIE["user_uid"];
+				$views =  View::where("user_id",$user_id)->orderBy('created_at','desc');
+				if($request->has("take")){
+					$views = $views->take($request->get("take"));
+				}else{
+					$views = $views->take(10);
+				}
+                $items = $views->get();
+                
+                return $this->ok($items);
+                break;
+            default:
+                # code...
+                break;
+        }
+        
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        /*
+        $rules = array(
+            'target_type' => 'required'
+        );
+        $validator = Validator::make($request->all(), $rules);
+
+        // process the login
+        if ($validator->fails()) {
+            return $this->error($validator);
+        }
+*/
+        //根据target type 获取 target id
+        $target_id = $this->getTargetId($request);
+        $clientIp = request()->ip();
+        $param = [
+            'target_id' => $target_id,
+            'target_type' => $request->get("target_type"),
+        ];
+        if(isset($_COOKIE['user_uid'])){
+            //已经登陆
+			Log::info('已经登陆');
+            $user_id = $_COOKIE['user_uid'];
+            $param['user_id'] = $user_id;
+        }else{
+			Log::info('没有登陆');
+            $param['user_ip'] = $clientIp;
+        }
+		
+        $new = View::firstOrNew($param);
+		Log::info('获取记录或新建');
+		Log::info(print_r($new, true));
+        $new->user_ip = $clientIp;
+		//获取标题 和 meta数据
+		Log::info('获取标题 和 meta数据');
+
+		switch($request->get("target_type")){
+			case "chapter":
+				$new->title = ProgressChapter::where("channel_id",$request->get("channel"))
+                                            ->where("book",$request->get("book"))
+                                            ->where("para",$request->get("para"))
+                                            ->value("title");
+				$new->org_title = PaliText::where("book",$request->get("book"))
+										->where("paragraph",$request->get("para"))
+										->value("toc");
+				Log::info('获取标题 成功');
+
+				$new->meta = \json_encode([
+					"book"=>$request->get("book"),
+					"para"=>$request->get("para"),
+					"channel"=>$request->get("channel"),
+				]);
+				Log::info('获取meta数据成功');
+
+				break;
+		}
+		$new->count = $new->count+1;
+        $new->save();
+		Log::info('保存成功');
+
+        $count = View::where("target_id",$new->target_id)->count();
+        return $this->ok($count);
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Models\View  $view
+     * @return \Illuminate\Http\Response
+     */
+    public function show(View $view)
+    {
+        //
+
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Models\View  $view
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, View $view)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Models\View  $view
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(View $view)
+    {
+        //
+    }
+}

+ 15 - 0
app/Models/Like.php

@@ -0,0 +1,15 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class Like extends Model
+{
+    use HasFactory;
+    protected $fillable = ['type' , 'target_id', 'target_type','user_id','context'];
+    protected $casts = [
+            'id' => 'string'
+        ];
+}

+ 8 - 0
app/Models/ProgressChapter.php

@@ -15,6 +15,9 @@ class ProgressChapter extends Model
             'uid' => 'string'
         ];
     protected $primaryKey = 'uid';
+    
+    //protected $dateFormat = 'U';
+
     public function tagid()
     {
         return $this->hasOne('App\Models\TagMap', 'anchor_id', 'uid'); //参数一:需要关联的子表类名,前面必须加上命名空间  参数二:子表关联父表的字段  参数三:父表关联子表的字段
@@ -29,4 +32,9 @@ class ProgressChapter extends Model
     {
         return $this->hasOne('App\Models\Channel', 'uid', 'channel_id'); //参数一:需要关联的子表类名,前面必须加上命名空间  参数二:子表关联父表的字段  参数三:父表关联子表的字段
     }
+
+    public function views()
+    {
+        return $this->hasMany('App\Models\View', 'target_id', 'uid');
+    }
 }

+ 5 - 0
app/Models/TagMap.php

@@ -15,4 +15,9 @@ class TagMap extends Model
     {
         return $this->belongsTo('App\Models\ProgressChapter', 'anchor_id', 'uid'); //参数一:需要关联的父表类名,前面必须加上命名空间  注意:参数二:子表关联父表的字段 参数三:父表关联子表的字段
     }
+
+    public function tags()
+    {
+        return $this->hasOne('App\Models\Tag', 'tag_id', 'id');
+    }
 }

+ 11 - 0
app/Models/UserExperience.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class UserExperience extends Model
+{
+    use HasFactory;
+}

+ 18 - 0
app/Models/View.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class View extends Model
+{
+    use HasFactory;
+
+    protected $casts = [
+    'id' => 'string',
+    'target_id' => 'string'
+    ];
+
+    protected $fillable = ['target_type' , 'target_id' , 'user_id', 'user_ip'];
+}

+ 35 - 0
database/migrations/2022_05_27_072344_create_views_table.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateViewsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     * 点击量统计
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('views', function (Blueprint $table) {
+            $table->uuid('id')->primary()->default(DB::raw('uuid_generate_v1mc()'));
+            $table->uuid('target_id')->index();
+            $table->string('target_type',32)->index();
+            $table->uuid('user_id')->index()->nullable();
+            $table->ipAddress('user_ip')->index();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('views');
+    }
+}

+ 36 - 0
database/migrations/2022_05_28_120007_add_summary_in_progress_chapters.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddSummaryInProgressChapters extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('progress_chapters', function (Blueprint $table) {
+            //
+            $table->string('summary',256)->nullable();
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('progress_chapters', function (Blueprint $table) {
+            //
+            $table->dropColumn('summary');
+
+        });
+    }
+}

+ 46 - 0
database/migrations/2022_05_29_103822_create_likes_table.php

@@ -0,0 +1,46 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateLikesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+     /*
+
+    点赞 like
+    关注 watch
+    收藏 favorite
+    书签 bookmark
+     */
+    public function up()
+    {
+        Schema::create('likes', function (Blueprint $table) {
+            $table->uuid('id')->primary()->default(DB::raw('uuid_generate_v1mc()'));
+            $table->string('type',32)->index();
+            $table->uuid('target_id')->index();
+            $table->string('target_type',32)->index();
+            $table->string('context',128)->nullable();
+            $table->uuid('user_id')->index();
+            $table->timestamps();
+
+            $table->unique(['type','target_id','user_id']);
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('likes');
+    }
+}

+ 39 - 0
database/migrations/2022_06_03_021251_create_user_experiences_table.php

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateUserExperiencesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('user_experiences', function (Blueprint $table) {
+            $table->uuid('id')->primary()->default(DB::raw('uuid_generate_v1mc()'));
+            $table->uuid('user_id');
+            $table->date('date');//统计日期
+            $table->integer('user_exp')->default(0);//总分
+            $table->integer('user_level')->default(1);//等级 1-60
+            $table->integer('edit_exp')->default(0);//编辑总时长 小时
+            $table->integer('wbw_count')->default(0);//逐词译个数
+            $table->integer('wbw_edit')->default(0);//逐词译编辑次数
+            $table->integer('trans_character')->default(0);//译文字符数
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('user_experiences');
+    }
+}

+ 41 - 0
database/migrations/2022_06_18_134823_add_title_in_views.php

@@ -0,0 +1,41 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddTitleInViews extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('views', function (Blueprint $table) {
+            //
+			$table->string('title',256)->nullable()->index();
+			$table->string('org_title',256)->nullable()->index();
+			$table->integer('count')->default(0);
+			$table->json('meta')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('views', function (Blueprint $table) {
+            //
+            $table->dropColumn('title');
+            $table->dropColumn('org_title');
+            $table->dropColumn('count');
+            $table->dropColumn('meta');
+
+        });
+    }
+}

+ 24 - 1
public/app/article/article.js

@@ -362,6 +362,23 @@ function gotoArticle(articleId) {
 	location.assign(url);
 }
 
+function OneHitChapter(book,para,channel){
+    fetch('/api/v2/view',{
+        method: 'POST',
+        credentials: 'same-origin',
+        headers: {
+            'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({
+            target_type:'chapter',
+            book:book,
+            para:para,
+            channel:channel
+        })
+    })
+  .then(response => response.json())
+  .then(data => console.log(data));
+}
 
 function palicanon_load() {
 	let param;
@@ -376,6 +393,11 @@ function palicanon_load() {
 				start: _start,
 				end: _end,
 			}
+            if(_channal !==""){
+                for (const iterator of _channal.split(",")) {
+                    OneHitChapter(_book,_par,iterator);
+                }
+            }
 			break;
 		case "simsent":
 		case "sim":
@@ -401,7 +423,8 @@ function palicanon_load() {
 						$("#article_path_title").html(result.title);
 						$("#page_title").text(result.title);
 						$("#article_subtitle").html(result.subtitle);
-						$("#article_author").html(result.username.nickname + "@" + result.username.username);
+						//$("#article_author").html(result.username.nickname + "@" + result.username.username);
+                        
 						$("#contents").html(note_init(result.content));
 						note_refresh_new(function () {
                             if(document.querySelector("#para_focus")){

+ 11 - 1
public/app/article/index.php

@@ -13,6 +13,8 @@ require_once "../pcdl/html_head.php";
 
 	<script src="../widget/like.js"></script>
 	<link type="text/css" rel="stylesheet" href="../widget/like.css"/>
+	<script src="../palicanon/chapter_channel.js"></script>
+	<link type="text/css" rel="stylesheet" href="../palicanon/chapter_channel.css"/>
 
 	<script src="../widget/click_dropdown.js"></script>
 	<link type="text/css" rel="stylesheet" href="../widget/click_dropdown.css"/>
@@ -480,7 +482,15 @@ function set_toc_visible(isVisible){
 		default:
 			break;
 	}
-
+    if(_view=='chapter'){
+        //获取章节的channel列表
+        loadChapterChannel({
+            book:_book,
+            para:_par,
+            target:$("#article_author"),
+            showchannel:_channal.split(',')
+        });
+    }
 	});
 
 	 window.addEventListener('scroll',winScroll);

+ 2 - 2
public/app/config.table.php

@@ -670,8 +670,8 @@ define("_TABLE_CUSTOM_BOOK_", _PG_TABLE_CUSTOM_BOOK_);
 define("_TABLE_CUSTOM_BOOK_SENT_", _PG_TABLE_CUSTOM_BOOK_SENT_);
 
 #点赞
-define("_FILE_DB_LIKE_", _SQLITE_DB_LIKE_);
-define("_TABLE_LIKE_", _SQLITE_TABLE_LIKE_);
+define("_FILE_DB_LIKE_", _PG_DB_LIKE_);
+define("_TABLE_LIKE_", _PG_TABLE_LIKE_);
 
 # 课程
 define("_FILE_DB_COURSE_", _SQLITE_DB_COURSE_);

+ 7 - 2
public/app/nissaya/get.php

@@ -31,6 +31,11 @@ if (isset($_GET["end"])) {
 } else {
     $end = 0;
 }
+if (isset($_GET["nsyid"])) {
+    $nsyid = substr($_GET["nsyid"],1) ;
+} else {
+    $nsyid = '';
+}
 add_edit_event(_NISSAYA_FIND_, "{$book}-{$para}-{$begin}-{$end}");
 
 PDO_Connect("" . _FILE_DB_PAGE_INDEX_);
@@ -42,8 +47,8 @@ foreach ($Fetch as $key => $value) {
     $Fetch_nsy_book = PDO_FetchRow($query, array($value["book"], $value["page1"]));
     if ($Fetch_nsy_book) {
         $prefix = $Fetch_nsy_book["table"];
-        $query = "SELECT * from {$prefix}_pagematch where bookid=? and bookpagenumber=?";
-        $Fetch_nsy_index = PDO_FetchRow($query, array($Fetch_nsy_book["bookid"], $value["page2"]));
+        $query = "SELECT * from {$prefix}_pagematch where bookid=? and bookpagenumber=? and nsyid = ?";
+        $Fetch_nsy_index = PDO_FetchRow($query, array($Fetch_nsy_book["bookid"], $value["page2"],$nsyid ));
         $Fetch_nsy_index["dir"] = $prefix;
         $result["data"][] = $Fetch_nsy_index;
     } else {

+ 57 - 0
public/app/nissaya/get_book_list.php

@@ -0,0 +1,57 @@
+<?php
+require_once "../public/_pdo.php";
+require_once "../config.php";
+require_once "../ucenter/active.php";
+
+$result["error"] = "";
+$result["data"] = array();
+
+if (isset($_GET["book"])) {
+    $book = $_GET["book"];
+} else {
+    $result["error"] = "no param";
+    echo json_encode($result, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+if (isset($_GET["para"])) {
+    $para = $_GET["para"];
+} else {
+    $result["error"] = "no param";
+    echo json_encode($result, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+
+if (isset($_GET["begin"])) {
+    $begin = $_GET["begin"];
+} else {
+    $begin = 0;
+}
+if (isset($_GET["end"])) {
+    $end = $_GET["end"];
+} else {
+    $end = 0;
+}
+add_edit_event(_NISSAYA_FIND_, "{$book}-{$para}-{$begin}-{$end}");
+
+PDO_Connect("" . _FILE_DB_PAGE_INDEX_);
+$query = "SELECT * from m where book=? and para=?";
+$Fetch = PDO_FetchRow($query, array($book, $para));
+    $query = "SELECT * from book_match where book_vri=? and vol=?";
+    $Fetch_nsy_book = PDO_FetchRow($query, array($Fetch["book"], $Fetch["page1"]));
+    if ($Fetch_nsy_book) {
+        $prefix = $Fetch_nsy_book["table"];
+		
+        $query = "select nsyid from {$prefix}_pagematch where bookid = ? and bookpagenumber = ? group by nsyid";
+        $Fetch_nsy_book = PDO_FetchAll($query, array($Fetch_nsy_book["bookid"],$Fetch["page2"]));
+		foreach ($Fetch_nsy_book as $key => $book) {
+			# code...
+			$query = "select nsyname from {$prefix}_pagematch where nsyid = ? ";
+			$Fetch_nsy_book[$key]['name'] = PDO_FetchRow($query, array($book["nsyid"]))['nsyname'];
+			$Fetch_nsy_book[$key]['type'] = $prefix;
+		}
+		$result["data"] =  json_encode($Fetch_nsy_book, JSON_UNESCAPED_UNICODE);
+        
+    } else {
+        $result["error"] = "error: in table book_match";
+    }
+echo json_encode($result, JSON_UNESCAPED_UNICODE);

+ 7 - 1
public/app/nissaya/index.php

@@ -23,6 +23,12 @@ if(isset($_GET["book"])){
 else{
 	$book = 0;
 }
+if(isset($_GET["nsyid"])){
+	$nsyid = $_GET["nsyid"];
+}
+else{
+	$nsyid = 0;
+}
 if(isset($_GET["par"])){
 	$para = $_GET["par"];
 }
@@ -44,7 +50,7 @@ else{
 ?>
 <script>
 $(document).ready(function () {
-	nissaya_get(<?php echo "{$book},{$para},{$begin},{$end}";?>);
+	nissaya_load(<?php echo "'{$nsyid}',{$book},{$para},{$begin},{$end}";?>);
 });
 </script>
 

+ 49 - 2
public/app/nissaya/nissaya.js

@@ -1,7 +1,46 @@
 var _nsy_book_dir = "";
 var _nsy_book_id = "";
 
-function nissaya_get(book, para, begin = 0, end = 0) {
+function nissaya_load(nsyid,book, para, begin = 0, end = 0){
+	if(nsyid==0){
+		nissaya_get_books(book, para);
+	}else{
+		nissaya_get(nsyid,book, para, begin, end );
+	}
+}
+function render_nissaya_books(list,book,para,begin=0,end=0){
+	let books = JSON.parse(list);
+	let html ="<ol>";
+	for (const iterator of books) {
+		html += "<li>";
+		html += "<a href='index.php?book="+book+"&par="+para+"&begin="+begin+"&end="+end+"&nsyid=a"+iterator.nsyid+"'>";
+		html +=  iterator.nsyid + "-" + iterator.name;
+		html += "</a>";
+		html += "</li>";
+	}
+	html += "</ol>";
+	return html;
+}
+function nissaya_get_books(book, para) {
+	$.get(
+		"../nissaya/get_book_list.php",
+		{
+			book: book,
+			para: para,
+		},
+		function (data) {
+			let result = JSON.parse(data);
+			if (result.error == "") {
+				if (result.data.length > 0) {
+					//找到的书的列表
+					$("#contence").html(render_nissaya_books(result.data,book,para));
+				}
+			}
+		}
+	);
+
+}
+function nissaya_get(nissayabook,book, para, begin = 0, end = 0) {
 	if (book == 0 || para == 0) {
 		return;
 	}
@@ -12,6 +51,7 @@ function nissaya_get(book, para, begin = 0, end = 0) {
 			para: para,
 			begin: begin,
 			end: end,
+			nsyid:nissayabook,
 		},
 		function (data) {
 			let result = JSON.parse(data);
@@ -29,7 +69,14 @@ function nissaya_get(book, para, begin = 0, end = 0) {
 }
 
 function render_on_page(params) {
-	let filename = params.dir + "/" + params.book + "_" + params.page + ".gif";
+	//加入前导零补足3位
+	let prefix='';
+	if(params.page < 10){
+		prefix='00';
+	}else if(params.page < 100){
+		prefix='0';
+	}
+	let filename = params.dir + "/" + params.book + "/" + prefix + params.page + ".png";
 	let html = "";
 
 	html += "<div class='img_box' dir='" + params.dir + "' book='" + params.book + "' page='" + params.page + "'>";

+ 331 - 31
public/app/palicanon/category/cscd.json

@@ -4,11 +4,11 @@
         "tag":["mūla"],
         "children":[
             {
-                "name":"sutta piṭaka",
+                "name":"Sutta Piṭaka",
                 "tag":["mūla","sutta"],
                 "children":[
                     {
-                        "name":"dīghanikāya",
+                        "name":"Dīghanikāya",
                         "tag":["mūla","sutta","dīghanikāya"],
                         "children":[
                             {
@@ -44,7 +44,7 @@
                         ]
                     },
                     {
-                        "name":"saṃyuttanikāya",
+                        "name":"Saṃyuttanikāya",
                         "tag":["mūla","sutta","saṃyuttanikāya"],
                         "children":[
                             {
@@ -70,7 +70,7 @@
                         ]
                     },
                     {
-                        "name":"aṅguttaranikāya",
+                        "name":"Aṅguttaranikāya",
                         "tag":["mūla","sutta","aṅguttaranikāya"],
                         "children":[
                             {
@@ -120,7 +120,7 @@
                         ]
                     },
                     {
-                        "name":"khuddakanikāya",
+                        "name":"Khuddakanikāya",
                         "tag":["mūla","sutta","khuddakanikāya"],
                         "children":[
                             {
@@ -200,33 +200,33 @@
                 ]
             },
             {
-                "name":"vinaya piṭaka",
+                "name":"Vinaya Piṭaka",
                 "tag":["mūla","vinaya"],
                 "children":[
                     {
                         "name":"pārājikapāḷi",
-                        "tag":["mūla","vinaya","pārājika"]
+                        "tag":["mūla","vinaya","pārājikapāḷi"]
                     },
                     {
                         "name":"pācittiyapāḷi",
-                        "tag":["mūla","vinaya","pācittiya"]
+                        "tag":["mūla","vinaya","pācittiyapāḷi"]
                     },
                     {
                         "name":"mahāvaggapāḷi",
-                        "tag":["mūla","vinaya","mahāvagga"]
+                        "tag":["mūla","vinaya","mahāvaggapāḷi"]
                     },
                     {
                         "name":"cūḷavaggapāḷi",
-                        "tag":["mūla","vinaya","cūḷavagga"]
+                        "tag":["mūla","vinaya","cūḷavaggapāḷi"]
                     },
                     {
                         "name":"parivārapāḷi",
-                        "tag":["mūla","vinaya","parivāra"]
+                        "tag":["mūla","vinaya","parivārapāḷi"]
                     }
                 ]
             },
             {
-                "name":"abhidhamma piṭaka",
+                "name":"Abhidhamma Piṭaka",
                 "tag":["mūla","abhidhamma"],
                 "children":[
                     {
@@ -472,7 +472,7 @@
                     },
                     {
                         "name":"Pācittiya-Aṭṭhakathā",
-                        "tag":["aṭṭhakathā","vinaya","pācittiya"]
+                        "tag":["aṭṭhakathā","vinaya","pācittiya-aṭṭhakathā"]
                     },
                     {
                         "name":"Mahāvagga-Aṭṭhakathā",
@@ -522,7 +522,7 @@
                         "children":[
                             {
                                 "name":"Sīlakkhandhavagga-Ṭīkā",
-                                "tag":["ṭīkā","sutta","dīghanikāya","sīlakkhandhavagga"]
+                                "tag":["ṭīkā","sutta","dīghanikāya","sīlakkhandhavaggaṭīkā"]
                             },
                             {
                                 "name":"Mahāvagga-Ṭīkā",
@@ -653,16 +653,8 @@
                 "tag":["ṭīkā","vinaya"],
                 "children":[
                     {
-                        "name":"Sāratthadīpanī-Tīkā-1",
-                        "tag":["ṭīkā","vinaya","sāratthadīpanī","paṭhamo bhāgo"]
-                    },
-                    {
-                        "name":"Sāratthadīpanī-Tīkā-2",
-                        "tag":["ṭīkā","vinaya","sāratthadīpanī","dutiyo bhāgo"]
-                    },
-                    {
-                        "name":"Sāratthadīpanī-Tīkā-3",
-                        "tag":["ṭīkā","vinaya","sāratthadīpanī","tatiyo bhāgo"]
+                        "name":"Sāratthadīpanī-Tīkā",
+                        "tag":["ṭīkā","vinaya","sāratthadīpanī"]
                     },
                     {
                         "name":"Dvemātikāpāḷi",
@@ -688,6 +680,10 @@
                         "name":"Kaṅkhāvitaraṇīpurāṇa-Ṭīkā",
                         "tag":["ṭīkā","vinaya","kaṅkhāvitaraṇī","purāṇaṭīkā"]
                     },
+                    {
+                        "name":"Kaṅkhāvitaraṇīabhinava-Ṭīkā",
+                        "tag":["ṭīkā","vinaya","kaṅkhāvitaraṇī","abhinavaṭīkā"]
+                    },
                     {
                         "name":"Vinayavinicchaya",
                         "tag":["ṭīkā","vinaya","vinayavinicchaya"]
@@ -696,10 +692,6 @@
                         "name":"Uttaravinicchayo",
                         "tag":["ṭīkā","vinaya","uttaravinicchaya"]
                     },
-                    {
-                        "name":"Vinayavinicchaya-Ṭīkā",
-                        "tag":["ṭīkā","vinaya","vinayavinicchayaṭīkā"]
-                    },
                     {
                         "name":"Pācityādiyojanāpali",
                         "tag":["ṭīkā","vinaya","pācityādiyojanā"]
@@ -723,7 +715,7 @@
                         "tag":["ṭīkā","abhidhamma","dhammasaṅgaṇī","mūlaṭīkā"]
                     },
                     {
-                        "name":"Sammohavinodanī-Mūlaṭīkā",
+                        "name":"Vibhaṅga-Mūlaṭīkā",
                         "tag":["ṭīkā","abhidhamma","vibhaṅga","mūlaṭīkā"]
                     },
                     {
@@ -740,11 +732,19 @@
                     },
                     {
                         "name":"Abhidhammāvatāro",
-                        "tag":["ṭīkā","abhidhamma","abhidhammāvatāro"]
+                        "tag":["ṭīkā","abhidhamma","abhidhammāvatāra"]
                     },
                     {
                         "name":"Nāmarūpaparicchedo",
-                        "tag":["ṭīkā","abhidhamma","nāmarūpaparicchedo"]
+                        "tag":["ṭīkā","abhidhamma","nāmarūpapariccheda"]
+                    },
+                    {
+                        "name":"Paramatthavinicchayo",
+                        "tag":["ṭīkā","abhidhamma","paramatthavinicchaya"]
+                    },
+                    {
+                        "name":"Saccasaṅkhepo",
+                        "tag":["ṭīkā","abhidhamma","saccasaṅkhepa"]
                     },
                     {
                         "name":"Abhidhammatthasaṅgaho",
@@ -799,6 +799,306 @@
                         "tag":["añña","visuddhimagga","nidānakathā"]
                     }
                 ]
+            },
+            {
+                "name":"Saṃgāyanassa-Pucchā Vissajjanā",
+                "tag":["añña","saṃgāyanassa pucchā vissajjanā"],
+                "children":[
+                    {
+                        "name":"Dīghanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","dīghanikāya"]
+                    },
+                    {
+                        "name":"Majjhimanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","majjhimanikāya"]
+                    },
+                    {
+                        "name":"Saṃyuttanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","saṃyuttanikāya"]
+                    },
+                    {
+                        "name":"Aṅguttaranikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","aṅguttaranikāya"]
+                    },
+                    {
+                        "name":"Vinayapiṭaka(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","vinayapiṭaka"]
+                    },
+                    {
+                        "name":"Abhidhammapiṭaka(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","abhidhammapiṭaka"]
+                    },
+                    {
+                        "name":"Aṭṭhakathā(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","aṭṭhakathā"]
+                    }
+                ]
+            },
+            {
+                "name":"Leḍī Sayādo Gantha-Saṅgaho",
+                "tag":["añña","leḍī sayādo"],
+                "children":[
+                    {
+                        "name":"Niruttidīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","niruttidīpanīpāṭha"]
+                    },
+                    {
+                        "name":"Paramatthadīpanī",
+                        "tag":["añña","leḍī sayādo","paramatthadīpanī"]
+                    },
+                    {
+                        "name":"Anudīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","anudīpanīpāṭha"]
+                    },
+                    {
+                        "name":"Paṭṭhānuddesa dīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","paṭṭhānuddesa dīpanīpāṭha"]
+                    }
+                ]
+            },
+            {
+                "name":"Buddha-Vandana Gantha-Saṅgaho",
+                "tag":["añña","buddha-vandana"],
+                "children":[
+                    {
+                        "name":"Namakkāratīkā",
+                        "tag":["añña","buddha-vandana","namakkāra"]
+                    },
+                    {
+                        "name":"Mahāpaṇāmapāṭha",
+                        "tag":["añña","buddha-vandana","mahāpaṇāmapāṭha"]
+                    },
+                    {
+                        "name":"Lakkhaṇāto Buddhathomanāgāthā",
+                        "tag":["añña","buddha-vandana","lakkhaṇāto"]
+                    },
+                    {
+                        "name":"Suttavandanā",
+                        "tag":["añña","buddha-vandana","suttavandanā"]
+                    },
+                    {
+                        "name":"Jinālaṅkāra",
+                        "tag":["añña","buddha-vandana","jinālaṅkāra"]
+                    },
+                    {
+                        "name":"Kamalāñjali",
+                        "tag":["añña","buddha-vandana","kamalāñjali"]
+                    },
+                    {
+                        "name":"Pajjamadhu",
+                        "tag":["añña","buddha-vandana","pajjamadhu"]
+                    },
+                    {
+                        "name":"Buddhaguṇagāthāvalī",
+                        "tag":["añña","buddha-vandana","buddhaguṇagāthāvalī"]
+                    }
+                ]
+            },
+            {
+                "name":"Vaṃsa Gantha-Saṅgaho",
+                "tag":["añña","vaṃsa"],
+                "children":[
+                    {
+                        "name":"Cūḷaganthavaṃsa",
+                        "tag":["añña","vaṃsa","Cūḷaganthavaṃsapāḷi"]
+                    },
+                    {
+                        "name":"sāsanavaṃsa",
+                        "tag":["añña","vaṃsa","sāsanavaṃsappadīpikā"]
+                    },
+                    {
+                        "name":"Mahāvaṃsa",
+                        "tag":["añña","vaṃsa","mahāvaṃsapāḷi"]
+                    }
+                ]
+            },
+            {
+                "name":"Byākaraṇa Gantha-Saṅgaho",
+                "tag":["añña","byākaraṇa ganthasaṅgaha"],
+                "children":[
+                    {
+                        "name":"Moggallānabyākaraṇa",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","moggallānasuttapāṭha"]
+                    },
+                    {
+                        "name":"Kaccāyanabyākaraṇaṃ",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","kaccāyanabyākaraṇa"]
+                    },
+                    {
+                        "name":"Saddanītippakaraṇaṃ (padamālā)",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","padamālā"]
+                    },
+                    {
+                        "name":"Saddanītippakaraṇaṃ (Dhātumālā)",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","dhātumālā"]
+                    },
+                    {
+                        "name":"Padarūpasiddhi",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","padarūpasiddhi"]
+                    },
+                    {
+                        "name":"Moggallānapañcikā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","moggallānapañcikā"]
+                    },
+                    {
+                        "name":"Payogasiddhipāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","payogasiddhipāḷi"]
+                    },
+                    {
+                        "name":"Vuttodayapāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","vuttodaya"]
+                    },
+                    {
+                        "name":"Abhidhānappadīpikāpāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","abhidhānappadīpikā"]
+                    },
+                    {
+                        "name":"Abhidhānappadīpikāṭīkā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","abhidhānappadīpikāṭīkā"]
+                    },
+                    {
+                        "name":"Subodhālaṅkārapāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","subodhālaṅkāra"]
+                    },
+                    {
+                        "name":"Subodhālaṅkāraṭīkā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","subodhālaṅkāraṭīkā"]
+                    },
+                    {
+                        "name":"Bālāvatāra",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","bālāvatāra"]
+                    }
+                ]
+            },
+            {
+                "name":"Nīti-Gantha-Saṅgaho",
+                "tag":["añña","nīti"],
+                "children":[
+                    {
+                        "name":"Kavidappaṇanīti",
+                        "tag":["añña","nīti","kavidappaṇanīti"]
+                    },
+                    {
+                        "name":"Nītimañjarī",
+                        "tag":["añña","nīti","nītimañjarī"]
+                    },
+                    {
+                        "name":"Dhammanīti",
+                        "tag":["añña","nīti","dhammanīti"]
+                    },
+                    {
+                        "name":"Mahārahanīti",
+                        "tag":["añña","nīti","mahārahanīti"]
+                    },
+                    {
+                        "name":"Lokanīti",
+                        "tag":["añña","nīti","lokanīti"]
+                    },
+                    {
+                        "name":"Suttantanīti",
+                        "tag":["añña","nīti","suttantanīti"]
+                    },
+                    {
+                        "name":"Sūrassatīnīti",
+                        "tag":["añña","nīti","sūrassatīnīti"]
+                    },
+                    {
+                        "name":"Cāṇakyanītipāḷi",
+                        "tag":["añña","nīti","cāṇakyanītipāḷi"]
+                    },
+                    {
+                        "name":"Naradakkhadīpanī",
+                        "tag":["añña","nīti","naradakkhadīpanī"]
+                    },
+                    {
+                        "name":"Caturārakkhadīpanī",
+                        "tag":["añña","nīti","caturārakkhadīpanī"]
+                    }
+                ]
+            },
+            {
+                "name":"Pakiṇṇaka-Gantha-Saṅgaho",
+                "tag":["añña","pakiṇṇaka"],
+                "children":[
+                    {
+                        "name":"Rasavāhinī",
+                        "tag":["añña","pakiṇṇaka","rasavāhinī"]
+                    },
+                    {
+                        "name":"Sīmavisodhanī",
+                        "tag":["añña","pakiṇṇaka","sīmavisodhanī"]
+                    },
+                    {
+                        "name":"Vessantarāgīti",
+                        "tag":["añña","pakiṇṇaka","vessantarāgīti"]
+                    }
+                ]
+            },
+            {
+                "name":"Sihaḷa-Gantha-Saṅgaho",
+                "tag":["añña","sihaḷa"],
+                "children":[
+                    {
+                        "name":"Moggallāna vuttivivaraṇapañcikā",
+                        "tag":["añña","sihaḷa","moggallāna vuttivivaraṇapañcikā"]
+                    },
+                    {
+                        "name":"Thupavaṃsa",
+                        "tag":["añña","sihaḷa","thupavaṃsa"]
+                    },
+                    {
+                        "name":"Dāṭhāvaṃsa",
+                        "tag":["añña","sihaḷa","Dāṭhāvaṃsa"]
+                    },
+                    {
+                        "name":"Dhātupāṭha vilāsiniyā",
+                        "tag":["añña","sihaḷa","dhātupāṭha vilāsiniyā"]
+                    },
+                    {
+                        "name":"Dhātuvaṃsa",
+                        "tag":["añña","sihaḷa","dhātuvaṃsa"]
+                    },
+                    {
+                        "name":"Hatthavanagallavihāravaṃsa",
+                        "tag":["añña","sihaḷa","hatthavanagallavihāravaṃsa"]
+                    },
+                    {
+                        "name":"Jinacaritaya",
+                        "tag":["añña","sihaḷa","jinacaritaya"]
+                    },
+                    {
+                        "name":"Jinavaṃsadīpaṃ",
+                        "tag":["añña","sihaḷa","jinavaṃsadīpa"]
+                    },
+                    {
+                        "name":"Telakaṭāhagāthā",
+                        "tag":["añña","nīti","telakaṭāhagāthā"]
+                    },
+                    {
+                        "name":"Milidaṭīkā",
+                        "tag":["añña","nīti","milidaṭīkā"]
+                    },
+                    {
+                        "name":"Padamañjarī",
+                        "tag":["añña","nīti","padamañjarī"]
+                    },
+                    {
+                        "name":"Padasādhana",
+                        "tag":["añña","nīti","padasādhana"]
+                    },
+                    {
+                        "name":"saddabindupakaraṇa",
+                        "tag":["añña","nīti","saddabindupakaraṇa"]
+                    },
+                    {
+                        "name":"Kaccāyanadhātumañjūsā",
+                        "tag":["añña","nīti","kaccāyanadhātumañjūsā"]
+                    },
+                    {
+                        "name":"Samantakūṭavaṇṇanā",
+                        "tag":["añña","nīti","samantakūṭavaṇṇanā"]
+                    }
+                ]
             }
         ]
     }

+ 342 - 10
public/app/palicanon/category/defualt.json

@@ -1,6 +1,6 @@
 [
            {
-                "name":"sutta",
+                "name":"Sutta Piṭaka",
                 "tag":["sutta"],
                 "children":[
                     {
@@ -196,7 +196,7 @@
                 ]
             },
             {
-                "name":"vinaya piṭaka",
+                "name":"Vinaya Piṭaka",
                 "tag":["vinaya"],
                 "children":[
                     {
@@ -222,37 +222,369 @@
                 ]
             },
             {
-                "name":"abhidhamma piṭaka",
+                "name":"Abhidhamma Piṭaka",
                 "tag":["abhidhamma"],
                 "children":[
                     {
-                        "name":"dhammasaṅgaṇī",
+                        "name":"Dhammasaṅgaṇī",
                         "tag":["abhidhamma","dhammasaṅgaṇī"]
                     },
                     {
-                        "name":"vibhaṅga",
+                        "name":"Vibhaṅga",
                         "tag":["abhidhamma","vibhaṅga"]
                     },
                     {
-                        "name":"dhātukathā",
+                        "name":"Dhātukathā",
                         "tag":["abhidhamma","dhātukathā"]
                     },
                                 {
-                        "name":"puggalapaññatti",
+                        "name":"Puggalapaññatti",
                         "tag":["abhidhamma","puggalapaññatti"]
                     },
                                 {
-                        "name":"kathāvatthu",
+                        "name":"Kathāvatthu",
                         "tag":["abhidhamma","kathāvatthu"]
                     },
                     {
-                        "name":"yamaka",
+                        "name":"Yamaka",
                         "tag":["abhidhamma","yamaka"]
                     },
                     {
-                        "name":"paṭṭhāna",
+                        "name":"Paṭṭhāna",
                         "tag":["abhidhamma","paṭṭhāna"]
                     }
                 ]
+            },
+    {
+        "name":"Añña",
+        "tag":["añña"],
+        "children":[
+            {
+                "name":"Visuddhimagga",
+                "tag":["añña","visuddhimagga"],
+                "children":[
+                    {
+                        "name":"Visuddhimagga-1",
+                        "tag":["añña","visuddhimagga","aṭṭhakathā","paṭhamo bhāgo"]
+                    },
+                    {
+                        "name":"Visuddhimagga-2",
+                        "tag":["añña","visuddhimagga","aṭṭhakathā","dutiyo bhāgo"]
+                    },
+                    {
+                        "name":"Visuddhimagga-mahāṭīkā-1",
+                        "tag":["añña","visuddhimagga","ṭīkā","paṭhamo bhāgo"]
+                    },
+                    {
+                        "name":"Visuddhimagga-mahāṭīkā-2",
+                        "tag":["añña","visuddhimagga","ṭīkā","dutiyo bhāgo"]
+                    },
+                    {
+                        "name":"Visuddhimagga-nidānakathā",
+                        "tag":["añña","visuddhimagga","nidānakathā"]
+                    }
+                ]
+            },
+            {
+                "name":"Saṃgāyanassa-Pucchā Vissajjanā",
+                "tag":["añña","saṃgāyanassa pucchā vissajjanā"],
+                "children":[
+                    {
+                        "name":"Dīghanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","dīghanikāya"]
+                    },
+                    {
+                        "name":"Majjhimanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","majjhimanikāya"]
+                    },
+                    {
+                        "name":"Saṃyuttanikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","saṃyuttanikāya"]
+                    },
+                    {
+                        "name":"Aṅguttaranikāya(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","aṅguttaranikāya"]
+                    },
+                    {
+                        "name":"Vinayapiṭaka(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","vinayapiṭaka"]
+                    },
+                    {
+                        "name":"Abhidhammapiṭaka(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","abhidhammapiṭaka"]
+                    },
+                    {
+                        "name":"Aṭṭhakathā(Pu-Vi)",
+                        "tag":["añña","saṃgāyanassa pucchā vissajjanā","aṭṭhakathā"]
+                    }
+                ]
+            },
+            {
+                "name":"Leḍī Sayādo Gantha-Saṅgaho",
+                "tag":["añña","leḍī sayādo"],
+                "children":[
+                    {
+                        "name":"Niruttidīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","niruttidīpanīpāṭha"]
+                    },
+                    {
+                        "name":"Paramatthadīpanī",
+                        "tag":["añña","leḍī sayādo","paramatthadīpanī"]
+                    },
+                    {
+                        "name":"Anudīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","anudīpanīpāṭha"]
+                    },
+                    {
+                        "name":"Paṭṭhānuddesa dīpanīpāṭha",
+                        "tag":["añña","leḍī sayādo","paṭṭhānuddesa dīpanīpāṭha"]
+                    }
+                ]
+            },
+            {
+                "name":"Buddha-Vandana Gantha-Saṅgaho",
+                "tag":["añña","buddha-vandana"],
+                "children":[
+                    {
+                        "name":"Namakkāratīkā",
+                        "tag":["añña","buddha-vandana","namakkāra"]
+                    },
+                    {
+                        "name":"Mahāpaṇāmapāṭha",
+                        "tag":["añña","buddha-vandana","mahāpaṇāmapāṭha"]
+                    },
+                    {
+                        "name":"Lakkhaṇāto Buddhathomanāgāthā",
+                        "tag":["añña","buddha-vandana","lakkhaṇāto"]
+                    },
+                    {
+                        "name":"Suttavandanā",
+                        "tag":["añña","buddha-vandana","suttavandanā"]
+                    },
+                    {
+                        "name":"Jinālaṅkāra",
+                        "tag":["añña","buddha-vandana","jinālaṅkāra"]
+                    },
+                    {
+                        "name":"Kamalāñjali",
+                        "tag":["añña","buddha-vandana","kamalāñjali"]
+                    },
+                    {
+                        "name":"Pajjamadhu",
+                        "tag":["añña","buddha-vandana","pajjamadhu"]
+                    },
+                    {
+                        "name":"Buddhaguṇagāthāvalī",
+                        "tag":["añña","buddha-vandana","buddhaguṇagāthāvalī"]
+                    }
+                ]
+            },
+            {
+                "name":"Vaṃsa Gantha-Saṅgaho",
+                "tag":["añña","vaṃsa"],
+                "children":[
+                    {
+                        "name":"Cūḷaganthavaṃsa",
+                        "tag":["añña","vaṃsa","Cūḷaganthavaṃsapāḷi"]
+                    },
+                    {
+                        "name":"sāsanavaṃsa",
+                        "tag":["añña","vaṃsa","sāsanavaṃsappadīpikā"]
+                    },
+                    {
+                        "name":"Mahāvaṃsa",
+                        "tag":["añña","vaṃsa","mahāvaṃsapāḷi"]
+                    }
+                ]
+            },
+            {
+                "name":"Byākaraṇa Gantha-Saṅgaho",
+                "tag":["añña","byākaraṇa ganthasaṅgaha"],
+                "children":[
+                    {
+                        "name":"Moggallānabyākaraṇa",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","moggallānasuttapāṭha"]
+                    },
+                    {
+                        "name":"Kaccāyanabyākaraṇaṃ",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","kaccāyanabyākaraṇa"]
+                    },
+                    {
+                        "name":"Saddanītippakaraṇaṃ (padamālā)",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","padamālā"]
+                    },
+                    {
+                        "name":"Saddanītippakaraṇaṃ (Dhātumālā)",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","dhātumālā"]
+                    },
+                    {
+                        "name":"Padarūpasiddhi",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","padarūpasiddhi"]
+                    },
+                    {
+                        "name":"Moggallānapañcikā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","moggallānapañcikā"]
+                    },
+                    {
+                        "name":"Payogasiddhipāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","payogasiddhipāḷi"]
+                    },
+                    {
+                        "name":"Vuttodayapāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","vuttodaya"]
+                    },
+                    {
+                        "name":"Abhidhānappadīpikāpāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","abhidhānappadīpikā"]
+                    },
+                    {
+                        "name":"Abhidhānappadīpikāṭīkā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","abhidhānappadīpikāṭīkā"]
+                    },
+                    {
+                        "name":"Subodhālaṅkārapāṭha",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","subodhālaṅkāra"]
+                    },
+                    {
+                        "name":"Subodhālaṅkāraṭīkā",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","subodhālaṅkāraṭīkā"]
+                    },
+                    {
+                        "name":"Bālāvatāra",
+                        "tag":["añña","byākaraṇa ganthasaṅgaha","bālāvatāra"]
+                    }
+                ]
+            },
+            {
+                "name":"Nīti-Gantha-Saṅgaho",
+                "tag":["añña","nīti"],
+                "children":[
+                    {
+                        "name":"Kavidappaṇanīti",
+                        "tag":["añña","nīti","kavidappaṇanīti"]
+                    },
+                    {
+                        "name":"Nītimañjarī",
+                        "tag":["añña","nīti","nītimañjarī"]
+                    },
+                    {
+                        "name":"Dhammanīti",
+                        "tag":["añña","nīti","dhammanīti"]
+                    },
+                    {
+                        "name":"Mahārahanīti",
+                        "tag":["añña","nīti","mahārahanīti"]
+                    },
+                    {
+                        "name":"Lokanīti",
+                        "tag":["añña","nīti","lokanīti"]
+                    },
+                    {
+                        "name":"Suttantanīti",
+                        "tag":["añña","nīti","suttantanīti"]
+                    },
+                    {
+                        "name":"Sūrassatīnīti",
+                        "tag":["añña","nīti","sūrassatīnīti"]
+                    },
+                    {
+                        "name":"Cāṇakyanītipāḷi",
+                        "tag":["añña","nīti","cāṇakyanītipāḷi"]
+                    },
+                    {
+                        "name":"Naradakkhadīpanī",
+                        "tag":["añña","nīti","naradakkhadīpanī"]
+                    },
+                    {
+                        "name":"Caturārakkhadīpanī",
+                        "tag":["añña","nīti","caturārakkhadīpanī"]
+                    }
+                ]
+            },
+            {
+                "name":"Pakiṇṇaka-Gantha-Saṅgaho",
+                "tag":["añña","pakiṇṇaka"],
+                "children":[
+                    {
+                        "name":"Rasavāhinī",
+                        "tag":["añña","pakiṇṇaka","rasavāhinī"]
+                    },
+                    {
+                        "name":"Sīmavisodhanī",
+                        "tag":["añña","pakiṇṇaka","sīmavisodhanī"]
+                    },
+                    {
+                        "name":"Vessantarāgīti",
+                        "tag":["añña","pakiṇṇaka","vessantarāgīti"]
+                    }
+                ]
+            },
+            {
+                "name":"Sihaḷa-Gantha-Saṅgaho",
+                "tag":["añña","sihaḷa"],
+                "children":[
+                    {
+                        "name":"Moggallāna vuttivivaraṇapañcikā",
+                        "tag":["añña","sihaḷa","moggallāna vuttivivaraṇapañcikā"]
+                    },
+                    {
+                        "name":"Thupavaṃsa",
+                        "tag":["añña","sihaḷa","thupavaṃsa"]
+                    },
+                    {
+                        "name":"Dāṭhāvaṃsa",
+                        "tag":["añña","sihaḷa","Dāṭhāvaṃsa"]
+                    },
+                    {
+                        "name":"Dhātupāṭha vilāsiniyā",
+                        "tag":["añña","sihaḷa","dhātupāṭha vilāsiniyā"]
+                    },
+                    {
+                        "name":"Dhātuvaṃsa",
+                        "tag":["añña","sihaḷa","dhātuvaṃsa"]
+                    },
+                    {
+                        "name":"Hatthavanagallavihāravaṃsa",
+                        "tag":["añña","sihaḷa","hatthavanagallavihāravaṃsa"]
+                    },
+                    {
+                        "name":"Jinacaritaya",
+                        "tag":["añña","sihaḷa","jinacaritaya"]
+                    },
+                    {
+                        "name":"Jinavaṃsadīpaṃ",
+                        "tag":["añña","sihaḷa","jinavaṃsadīpa"]
+                    },
+                    {
+                        "name":"Telakaṭāhagāthā",
+                        "tag":["añña","nīti","telakaṭāhagāthā"]
+                    },
+                    {
+                        "name":"Milidaṭīkā",
+                        "tag":["añña","nīti","milidaṭīkā"]
+                    },
+                    {
+                        "name":"Padamañjarī",
+                        "tag":["añña","nīti","padamañjarī"]
+                    },
+                    {
+                        "name":"Padasādhana",
+                        "tag":["añña","nīti","padasādhana"]
+                    },
+                    {
+                        "name":"saddabindupakaraṇa",
+                        "tag":["añña","nīti","saddabindupakaraṇa"]
+                    },
+                    {
+                        "name":"Kaccāyanadhātumañjūsā",
+                        "tag":["añña","nīti","kaccāyanadhātumañjūsā"]
+                    },
+                    {
+                        "name":"Samantakūṭavaṇṇanā",
+                        "tag":["añña","nīti","samantakūṭavaṇṇanā"]
+                    }
+                ]
             }
+        ]
+    }
 ]

+ 22 - 0
public/app/palicanon/chapter_channel.css

@@ -0,0 +1,22 @@
+ul.chapter_info_list>li{
+	display:flex;
+}
+ul.chapter_info_list>li .channel_name{
+	flex:3;
+}
+ul.chapter_info_list>li .progress_bar{
+	flex:3;
+}
+ul.chapter_info_list>li .views{
+	flex:1;
+}
+ul.chapter_info_list>li .likes{
+	flex:1;
+}
+ul.chapter_info_list>li>.updated_at{
+	flex:3;
+}
+
+.progress_bar>svg{
+	width:80px;
+}

+ 164 - 0
public/app/palicanon/chapter_channel.js

@@ -0,0 +1,164 @@
+//获取章节的channel列表
+/*
+param
+{
+    book:book,
+    para:para,
+    target:target,
+    topchannel:[1,2,3],
+    showchannel:[1,2,3]
+
+}
+*/
+function loadChapterChannel(param){
+    $.getJSON(
+    "/api/v2/progress?view=chapter_channels",
+    {
+        book: param.book,
+        par: param.para,
+    },
+    function (data, status) {
+        let arrChannelList = data.data.rows;
+		if(typeof param.readonly != "undefined" && param.readonly == true){
+			$(param.target).html(render_chapter_progress_list_readonly(arrChannelList,param));
+		}else{
+			$(param.target).html(render_chapter_progress_list(arrChannelList,param));
+			Like();
+		}
+    }
+    );
+}
+
+//章节已经有译文的channel 列表
+function render_chapter_progress_list(chapterList,param) {
+	let html = "";
+    html += "<ul class='chapter_info_list'>";
+
+	for (const iterator of chapterList) {
+        if(iterator.channel){
+            if(param.showchannel){
+                if(!param.showchannel.includes(iterator.channel.uid)){
+                    continue;
+                }
+            }
+            html += "<li>";
+            html += "<span clsss='channel_name' style='flex:2;'>";
+            html += "<a href='../article/?view=chapter&book="+iterator.book+"&par="+iterator.para+"&channel="+iterator.channel.uid+"' target='_blanck'>";
+            html += iterator.channel.name;
+            html += "</a>";
+            html += "</span>";
+            html += "<span class='progress_bar'>";
+            html += renderProgressBar(iterator.progress);
+            html += "</span>";
+            html += "<span class='views' >";
+            html += iterator.views;
+            html += "</span>";
+            html += "<span class='likes' style='flex:5;'>";
+            html += renderChannelLikes(iterator.likes,'progress_chapter',iterator.uid);
+            html += "</span>";
+            html += "<span class='updated_at' title='"+iterator.updated_at+"' >";
+            html += getPassDataTime(new Date(iterator.updated_at));
+            html += "</span>";
+            html += "</li>";
+        }
+	}
+    html += "</ul>";
+
+	return html;
+}
+
+function render_chapter_progress_list_readonly(chapterList,param) {
+	let html = "";
+    html += "<ul class='chapter_info_list'>";
+	html += "<li>";
+	html += "<span clsss='channel_name' >版本</span>";
+	html += "<span clsss='progress_bar' >进度</span>";
+	html += "<span clsss='views' >阅读</span>";
+	html += "<span clsss='likes' >点赞</span>";
+	html += "<span clsss='updated_at' >更新于</span>";
+	html += "</li>";
+
+	for (const iterator of chapterList) {
+        if(iterator.channel){
+            if(param.showchannel){
+                if(!param.showchannel.includes(iterator.channel.uid)){
+                    continue;
+                }
+            }
+            html += "<li>";
+            html += "<span clsss='channel_name' style='flex:3;'>";
+            html += "<a href='../article/?view=chapter&book="+iterator.book+"&par="+iterator.para+"&channel="+iterator.channel.uid+"' target='_blanck'>";
+            html += iterator.channel.name;
+            html += "</a>";
+            html += "</span>";
+            html += "<span class='progress_bar'>";
+            html += renderProgressBar(iterator.progress);
+            html += "</span>";
+            html += "<span class='views' >";
+            html += iterator.views;
+            html += "</span>";
+            html += "<span class='likes' >";
+            html += getChapterLikeCount(iterator.likes,'like');
+            html += "</span>";
+            html += "<span class='updated_at' title='"+iterator.updated_at+"' >";
+            html += getPassDataTime(new Date(iterator.updated_at));
+            html += "</span>";
+            html += "</li>";            
+        }
+	}
+    html += "</ul>";
+
+	return html;
+}
+
+function getChapterLikeCount(info,likeType){
+	for (const item of info) {
+		if(item.type==likeType){
+			return item.count;
+		}
+	}
+	return 0;
+}
+function renderChannelLikes(info,restype,resid){
+    /*
+    点赞 like
+    收藏 favorite
+    关注 watch
+    书签 bookmark
+     */
+    let like_types = ["like",'favorite',"watch"];
+    let html = "";
+    for (const typs of like_types) {
+        html += "<like ";
+        html +="liketype='"+typs+"' ";
+        let count = 0;
+        for (const item of info) {
+            if(item.type==typs){
+                count = item.count;
+                if(item.selected){
+                    html +=" mine='"+item.selected+"' ";
+                }
+            }
+        }
+        html +="count='"+count+"' ";
+        html +="restype='"+restype+"' ";
+        html += "resid='"+resid+"' ";
+        html += ">"+count+"</like>";
+    }
+    return html;
+}
+
+function renderProgressBar(progress){
+	let html = "<svg  xmlns='http://www.w3.org/2000/svg'  xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 100 25'>";
+	let resulte = Math.round(progress*100);
+	let clipPathId = "ClipPath_"+com_uuid();
+	html += "<rect id='frontground' x='0' y='0' width='100' height='25' fill='#cccccc' ></rect>";
+	html += "<text id='bg_text'  x='5' y='19' fill='#006600' style='font-size:20px;'>"+resulte+"%</text>";
+	html += "<rect id='background' x='0' y='0' width='100' height='25' fill='#006600' clip-path='url(#"+clipPathId+")'></rect>";
+	html += "<text id='bg_text'  x='5' y='19' fill='#ffffff' style='font-size:20px;' clip-path='url(#"+clipPathId+")'>"+resulte+"%</text>";
+	html += "<clipPath id='"+clipPathId+"'>";
+	html += "    <rect x='0' y='0' width='"+resulte+"' height='25'></rect>";
+	html += "</clipPath>";
+	html += "</svg>";
+	return html;
+}

+ 286 - 82
public/app/palicanon/index.php

@@ -6,8 +6,8 @@ require_once "../pcdl/html_head.php";
     <script src="../palicanon/palicanon.js"></script>
     <script src="../term/term.js"></script>
 
-    <?php
-require_once "../pcdl/head_bar.php";
+<?php
+    require_once "../pcdl/head_bar.php";
 ?>
 
 	<link type="text/css" rel="stylesheet" href="../palicanon/style.css" />
@@ -17,7 +17,7 @@ require_once "../pcdl/head_bar.php";
     <script>
         var tag_level = <?php echo file_get_contents("../public/book_tag/tag_list.json"); ?>;
     </script>
-    <?php
+<?php
 //
 
 require_once "../config.php";
@@ -25,93 +25,297 @@ require_once "../public/_pdo.php";
 require_once '../media/function.php';
 require_once '../public/function.php';
 ?>
-    <div id='course_head_bar' style='background-color:var(--tool-bg-color1);padding:1em 10px 10px 10px;'>
-    <div class='index_inner '>
-    <div style='font-size:140%'>
-    </div>
-    <div id="main_tag"  style="">
-    <span tag="sutta" title="sutta"></span>
-    <span tag="vinaya"  title="vinaya"></span>
-    <span tag="abhidhamma" title="abhidhamma"></span>
-    <span tag="mūla" title="mūla"></span>
-    <span tag="aṭṭhakathā" title="aṭṭhakathā"></span>
-    <span tag="ṭīkā" title="ṭīkā"></span>
-    <span tag="añña" title="añña"></span>
-	</div>
-
-	<div id="select_bar" >
-		<div id="tag_selected"></div>
-		<div>
-			<button onclick="tag_list_slide_toggle(this)">
-				⮝
-			</button>
-		</div>
-	</div>
-	<div>
-
-		<div id="tag_list">
-			<div level="0" class="tag_others"></div>
-			<div level="1" class="tag_others"></div>
-			<div level="2" class="tag_others"></div>
-			<div level="3" class="tag_others"></div>
-			<div level="4" class="tag_others"></div>
-			<div level="5" class="tag_others"></div>
-			<div level="100" class="tag_others"></div>
-			<div level="8" class="tag_others"></div>
-		</div>
-	</div>
-    </div>
+
+<link href="../../node_modules/jquery.fancytree/dist/skin-win7/ui.fancytree.css" rel="stylesheet" type="text/css" class="skinswitcher">
+<script src="../tree/jquery.fancytree.js" type="text/javascript"></script>
+
+	<script src="../widget/like.js"></script>
+	<link type="text/css" rel="stylesheet" href="../widget/like.css"/>
+	<script src="../palicanon/chapter_channel.js"></script>
+	<link type="text/css" rel="stylesheet" href="../palicanon/chapter_channel.css"/>
+	<link type="text/css" rel="stylesheet" href="../palicanon/loading.css"/>
+
+    <script src="router.js"></script>
+    <script src="test.js"></script>
+    <script src="my_space.js"></script>
+
+<style>
+
+
+</style>
+
+<?php
+    if(isset($_GET["view"])){
+        $_view = $_GET["view"];
+    }else{
+        $_view = "community";
+    }
+?>
+
+<div id='main_view' >
+    <div id='left-bar' >
+        <div id='left-bar-inner'>
+            <div class="filter submenu">
+                <div class="title submenu_title" style="flex;">
+                    <span>分类</span>
+                    <span>
+                        <select id="tag_category_index" onchange="TagCategoryIndexchange(this)"></select>
+                    </span>
+                </div>
+                <div class='inner' style='max-height: unset;'>
+                    <div id='tag-category' ></div>
+                </div>
+            </div>
+            <div class="filter submenu">
+                <div class="title submenu_title"><span>作者</span></div>
+                <div class='inner' id='filter-author' >
+                    <div  class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
+                </div>
+            </div>
+        </div>
     </div>
+    <div id='course_head_bar' >
+        <div class='index_inner '>
+            <div style='display:flex;justify-content: space-between;display:none;'>
+                <div> </div>
+                <div style=''>
+                    <select onchange='viewChanged(this)'>
+                        <option value='list'>列表</option>                    
+                        <option value='card'>卡片</option>
+                    </select>
+                </div>
+            </div>
+            <div>
+                <div class='main_menu' id = 'main_menu'>
+
+                </div>
+            </div>
+            <div id="main_tag"  style="display:none;">
+                <span tag="sutta" title="sutta"></span>
+                <span tag="vinaya"  title="vinaya"></span>
+                <span tag="abhidhamma" title="abhidhamma"></span>
+                <span tag="mūla" title="mūla"></span>
+                <span tag="aṭṭhakathā" title="aṭṭhakathā"></span>
+                <span tag="ṭīkā" title="ṭīkā"></span>
+                <span tag="añña" title="añña"></span>
+            </div>
+
+            <div id="select_bar" >
+                <div id="select_bar_home" onclick='categoryGoHome()'>
+                <span>
+                    <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#house'>
+                    </svg>
+                </span>
+                <span>
+                    <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#chevron-compact-right'>
+                    </svg>
+                </span>
+                </div>
+                <div id="channel_selected"></div>
+                <div id="tag_selected"></div>
+            </div>
 
-	<div class='index_inner'>
-
-	<div id="chapter_shell" class="chapter_list" >
-	<div id="list_shell_1" class="show" level="1">
-		<ul id="list-1" class="grid" level="1" >
-		</ul>
-	</div>
-
-	<div id="list_shell_2" level="2">
-		<ul id="list-2" class="hidden" level="2"  >
-		</ul>
-	</div>
-
-	<div id="list_shell_3" level="3">
-		<ul id="list-3" class="hidden" level="3" >
-		</ul>
-	</div>
-
-	<div id="list_shell_4" level="4">
-		<ul id="list-4" class="hidden" level="4" >
-		</ul>
-	</div>
-
-	<div id="list_shell_5" level="5">
-		<ul id="list-5" class="hidden" level="5" >
-		</ul>
-	</div>
-
-	<div id="list_shell_6" level="6">
-		<ul id="list-6" class="hidden" level="6" >
-		</ul>
-	</div>
-
-	<div id="list_shell_7" level="7">
-		<ul id="list-7" class="hidden" level="7" >
-		</ul>
-	</div>
-
-	<div id="list_shell_8" level="8">
-		<ul id="list-8" class="hidden" level="8" >
-		</ul>
-	</div>
+            <div id='palicanon-category'></div>
 
+            
+            <div id='filter_bar'>
+                <div id='filter_bar_left'></div>
+                <div id='filter_bar_right'>
+                    <button id='btn-filter' onclick="tag_list_slide_toggle(this)">
+                        <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#filter'>
+                        </svg>
+                    </button>
+                </div>
+            </div>
+            <div>
+                <div id="tag_list" style='display:none;'>
+                    <div id="tag_list_head" style="display:flex;justify-content: space-between;border-bottom: 1px solid var(--border-line-color);">
+                        <div style='width:20em;'>
+                            
+                        </div>
+                        <div>
+                            <button id="btn-tag_list_close" onclick='close_tag_list()'>X</button>
+                        </div>
+                    </div>
+
+                    <div id='tag_list_inner'>
+                        <div id='tag_list_tag_div'>
+                            <h2>标签</h2>
+                            <div><input id="tag_input" type="input" placeholder="tag search" size="20"></div>
+                            <div level="0" class="tag_others"></div>
+                            <div level="1" class="tag_others"></div>
+                            <div level="2" class="tag_others"></div>
+                            <div level="3" class="tag_others"></div>
+                            <div level="4" class="tag_others"></div>
+                            <div level="5" class="tag_others"></div>
+                            <div level="100" class="tag_others"></div>
+                            <div level="8" class="tag_others"></div>
+                        </div>
+                        <div id='tag_list_setting_div'>
+                            <h2>设定</h2>
+                            <div class='inner' id='filter-setting' >
+                                <div class='settting-item'>
+                                    <span>语言</span>
+                                    <span>
+                                        <select id='setting_lang'>
+                                            <option value='auto'>自动</option>
+                                            <option value=''>全部</option>
+                                            <option value='zh'>中文</option>
+                                            <option value='en'>英文</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div class='settting-item'>
+                                    <span>内容类型</span>
+                                    <span>
+                                        <select id='setting_channel_type'>
+                                            <option value=''>全部</option>
+                                            <option value='translation' selected >译文</option>
+                                            <option value='nissaya'>Nissaya</option>
+                                            <option value='commentray'>注疏</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div class='settting-item'>
+                                    <span>完成度</span>
+                                    <span>
+                                        <select id='setting_progress'>
+                                            <option value='0.9'>90</option>
+                                            <option value='0.8'>80</option>
+                                            <option value='0.5'>50</option>
+                                            <option value='0.2'>20</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div style='display:flex;justify-content: space-between;'><button>还原默认</button><button onclick="updateSetting()">应用</button></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+			<div id="index_div">
+				<div id='file_background'></div>
+				<div id = "file_list_div">
+					<div id='bread-crumbs'></div>
+					<div class='index_inner'>
+						<div id="chapter_shell" class="chapter_list" >
+							<div id="list_shell_1" class="show" level="1">
+								<ul id="list-1" class="grid" level="1" >
+								</ul>
+							</div>
+
+							<div id="list_shell_2" level="2">
+								<ul id="list-2" class="hidden" level="2"  >
+								</ul>
+							</div>
+
+							<div id="list_shell_3" level="3">
+								<ul id="list-3" class="hidden" level="3" >
+								</ul>
+							</div>
+
+							<div id="list_shell_4" level="4">
+								<ul id="list-4" class="hidden" level="4" >
+								</ul>
+							</div>
+
+							<div id="list_shell_5" level="5">
+								<ul id="list-5" class="hidden" level="5" >
+								</ul>
+							</div>
+
+							<div id="list_shell_6" level="6">
+								<ul id="list-6" class="hidden" level="6" >
+								</ul>
+							</div>
+
+							<div id="list_shell_7" level="7">
+								<ul id="list-7" class="hidden" level="7" >
+								</ul>
+							</div>
+
+							<div id="list_shell_8" level="8">
+								<ul id="list-8" class="hidden" level="8" >
+								</ul>
+							</div>
+
+						</div>
+					</div>
+				</div>
+			</div>
+        </div>
+    </div>
+    <div style="flex:2;">
+    <div class='bangdan' id = "user_recent">
+        <div class='title'>最近阅读</div>
+        <div class='list'>
+            <div class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
+        </div>
+    </div>
+    <div class='bangdan' id='contribution'>
+        <div class='title'>月度贡献</div>
+        <div class='list'>
+            <div class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
+        </div>
     </div>
     </div>
+</div>
+
+
 
     <script>
         $(document).ready(function() {
-            palicanon_onload();
+            
+            let indexFilename = localStorage.getItem('palicanon_tag_category');
+            if(!indexFilename){
+                indexFilename = "defualt";
+            }
+            loadTagCategory(indexFilename);
+            loadTagCategoryIndex();
+            loadFilterSetting();//载入上次的过滤器配置
+            LoadAllLanguage();
+            <?php
+            if(isset($_GET["view"])){
+                echo "_view = '{$_GET["view"]}';";
+            }else{
+                echo "_view = 'community';";
+                echo "updataHistory();";
+            }
+
+            if(isset($_GET["tag"])){
+                echo "_tags = '{$_GET["tag"]}';";
+            }
+            if(isset($_GET["channel"])){
+                echo "_channel = '{$_GET["channel"]}';";
+            }
+            
+            switch ($_view) {
+                case 'community':
+                    //echo "community_onload();";
+                    break;
+                case 'category':
+                    //echo "palicanon_onload();";
+                    break;
+                case 'my';
+                default:
+                    # code...
+                    break;
+            }
+            ?>
+            list_tag = _tags.split(',');
+            refresh_selected_tag();
+            ReanderMainMenu();
+            updateFirstListView();
+            //载入用户最近的阅读列表
+            loadUserRecent();
+            loadContribution();
+			//TODO 处理标签搜索
+			$("#tag_input").keypress(function () {
+				tag_render_others();
+			});
         });
     </script>
     <?php

+ 175 - 176
public/app/palicanon/index1.php

@@ -29,97 +29,17 @@ require_once '../public/function.php';
 <link href="../../node_modules/jquery.fancytree/dist/skin-win7/ui.fancytree.css" rel="stylesheet" type="text/css" class="skinswitcher">
 <script src="../tree/jquery.fancytree.js" type="text/javascript"></script>
 
-<style>
-.chapter_list ul {
-    margin-left: 0;
-}
-.head_bar{
-    display:flex;
-    max-width: 30vh;
-}
-#left-bar{
-    flex: 2;
-    background-color: var(--box-bg-color2);
-}
-.more_info{
-    font-size:80%;
-    color: var(--main-color1);
-}
-.more_info>.item{
-    margin-right:1em;
-}
-.chapter_list ul li{
-    display:flex;
-}
-.book_view  ul li{
-    display:block;
-}
-.book_view .level_1{
-    background:unset;
-}
+	<script src="../widget/like.js"></script>
+	<link type="text/css" rel="stylesheet" href="../widget/like.css"/>
+	<script src="../palicanon/chapter_channel.js"></script>
+	<link type="text/css" rel="stylesheet" href="../palicanon/loading.css"/>
+
+    <script src="router.js"></script>
+    <script src="test.js"></script>
 
-.book_view ul li{
-    border:unset;
-    width: 30%;
-    height:90px;
-}
-.chapter_list .list {
-    display: none;
-}
-.chapter_list .show {
-    display: block;
-    width: 100%;
-}
-.chapter_list .grid {
-    width: 100%;
-}
-.chapter_list > div {
-    max-height: unset;
-    overflow-y: unset; 
-}
-.chapter_list .more_info {
-    display: block;
-}
+<style>
 
-.filter>.inner {
-    max-height: 200px;
-    overflow-y: auto;
-    background-color: var(--input-bg-color);
-}
 
-.main_menu {
-    font-size: 100%;
-    text-align: center;
-    margin: 0 1em;
-    transition: all 600ms ease;
-    text-transform: capitalize;
-}
-.main_menu>span {
-    margin: 2px;
-    padding: 2px 12px;
-    font-weight: 500;
-    transition-duration: 0.2s;
-    cursor: pointer;
-    font-size: 120%;
-    border: unset;
-    border-radius: 0;
-    border-bottom: 2px solid var(--nocolor);
-    display: inline-block;
-}
-.main_menu>.select {
-    border-bottom: 2px solid var(--link-color);
-}
-.main_menu>span>a {
-    color:unset;
-}
-.main_menu span:hover {
-    background-color: unset;
-    color: unset;
-    border-color: var(--link-hover-color);
-}
-select#tag_category_index option {
-    background-color: gray;
-}
 </style>
 
 <?php
@@ -130,46 +50,31 @@ select#tag_category_index option {
     }
 ?>
 
-<div style="display:flex;">
+<div id='main_view' >
     <div id='left-bar' >
         <div id='left-bar-inner'>
             <div class="filter submenu">
                 <div class="title submenu_title" style="flex;">
-                    <span>分类标签</span>
+                    <span>分类</span>
                     <span>
-                            <select id="tag_category_index" onchange="TagCategoryIndexchange(this)">
-                            </select>
+                        <select id="tag_category_index" onchange="TagCategoryIndexchange(this)"></select>
                     </span>
                 </div>
-                <div class='inner' >
-                    <div id='tag-category' >
-                    
-                    </div>
+                <div class='inner' style='max-height: unset;'>
+                    <div id='tag-category' ></div>
                 </div>
             </div>
             <div class="filter submenu">
-                <div class="title submenu_title">作者</div>
+                <div class="title submenu_title"><span>作者</span></div>
                 <div class='inner' id='filter-author' >
-                
-                </div>
-            </div>
-            <div class="filter submenu">
-                <div class="title submenu_title">语言</div>
-                <div class='inner' id='filter-lang' >
-                
-                </div>
-            </div>
-            <div class="filter submenu">
-                <div class="title submenu_title">类型</div>
-                <div class='inner' id='filter-type' >
-                
+                    <div  class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
                 </div>
             </div>
         </div>
     </div>
-    <div id='course_head_bar' style='flex:6;background-color:var(--tool-bg-color1);padding:0 10px 10px 10px;'>
+    <div id='course_head_bar' >
         <div class='index_inner '>
-            <div style='display:flex;justify-content: space-between;'>
+            <div style='display:flex;justify-content: space-between;display:none;'>
                 <div> </div>
                 <div style=''>
                     <select onchange='viewChanged(this)'>
@@ -194,84 +99,162 @@ select#tag_category_index option {
             </div>
 
             <div id="select_bar" >
+                <div id="select_bar_home" onclick='categoryGoHome()'>
+                <span>
+                    <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#house'>
+                    </svg>
+                </span>
+                <span>
+                    <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#chevron-compact-right'>
+                    </svg>
+                </span>
+                </div>
+                <div id="channel_selected"></div>
                 <div id="tag_selected"></div>
-                <div>
-                    <button onclick="tag_list_slide_toggle(this)">
-                        ⮝
+            </div>
+
+            <div id='palicanon-category'></div>
+
+            
+            <div id='filter_bar'>
+                <div id='filter_bar_left'></div>
+                <div id='filter_bar_right'>
+                    <button id='btn-filter' onclick="tag_list_slide_toggle(this)">
+                        <svg class='icon' style='fill: var(--box-bg-color1)'>
+                        <use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#filter'>
+                        </svg>
                     </button>
                 </div>
             </div>
             <div>
-                <div id="tag_list">
-                    <div level="0" class="tag_others"></div>
-                    <div level="1" class="tag_others"></div>
-                    <div level="2" class="tag_others"></div>
-                    <div level="3" class="tag_others"></div>
-                    <div level="4" class="tag_others"></div>
-                    <div level="5" class="tag_others"></div>
-                    <div level="100" class="tag_others"></div>
-                    <div level="8" class="tag_others"></div>
-                </div>
-            </div>
-            <div id='bread-crumbs'></div>
-            <div class='index_inner'>
-                <div id="chapter_shell" class="chapter_list" >
-                    <div id="list_shell_1" class="show" level="1">
-                        <ul id="list-1" class="grid" level="1" >
-                        </ul>
-                        <button>More</button>
+                <div id="tag_list" style='display:none;'>
+                    <div id="tag_list_head" style="display:flex;justify-content: space-between;border-bottom: 1px solid var(--border-line-color);">
+                        <div style='width:20em;'>
+                            
+                        </div>
+                        <div>
+                            <button id="btn-tag_list_close" onclick='close_tag_list()'>X</button>
+                        </div>
                     </div>
 
-                    <div id="list_shell_2" level="2">
-                        <ul id="list-2" class="hidden" level="2"  >
-                        </ul>
+                    <div id='tag_list_inner'>
+                        <div id='tag_list_tag_div'>
+                            <h2>标签</h2>
+                            <div><input id="tag_input" type="input" placeholder="tag search" size="20"></div>
+                            <div level="0" class="tag_others"></div>
+                            <div level="1" class="tag_others"></div>
+                            <div level="2" class="tag_others"></div>
+                            <div level="3" class="tag_others"></div>
+                            <div level="4" class="tag_others"></div>
+                            <div level="5" class="tag_others"></div>
+                            <div level="100" class="tag_others"></div>
+                            <div level="8" class="tag_others"></div>
+                        </div>
+                        <div id='tag_list_setting_div'>
+                            <h2>设定</h2>
+                            <div class='inner' id='filter-setting' >
+                                <div class='settting-item'>
+                                    <span>语言</span>
+                                    <span>
+                                        <select id='setting_lang'>
+                                            <option value='auto'>自动</option>
+                                            <option value=''>全部</option>
+                                            <option value='zh'>中文</option>
+                                            <option value='en'>英文</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div class='settting-item'>
+                                    <span>内容类型</span>
+                                    <span>
+                                        <select id='setting_channel_type'>
+                                            <option value=''>全部</option>
+                                            <option value='translation' selected >译文</option>
+                                            <option value='nissaya'>Nissaya</option>
+                                            <option value='commentray'>注疏</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div class='settting-item'>
+                                    <span>完成度</span>
+                                    <span>
+                                        <select id='setting_progress'>
+                                            <option value='0.9'>90</option>
+                                            <option value='0.8'>80</option>
+                                            <option value='0.5'>50</option>
+                                            <option value='0.2'>20</option>
+                                        </select>
+                                    </span>
+                                </div>
+                                <div style='display:flex;justify-content: space-between;'><button>还原默认</button><button onclick="updateSetting()">应用</button></div>
+                            </div>
+                        </div>
                     </div>
+                </div>
+            </div>
+			<div id="index_div">
+				<div id='file_background'></div>
+				<div id = "file_list_div">
+					<div id='bread-crumbs'></div>
+					<div class='index_inner'>
+						<div id="chapter_shell" class="chapter_list" >
+							<div id="list_shell_1" class="show" level="1">
+								<ul id="list-1" class="grid" level="1" >
+								</ul>
+							</div>
 
-                    <div id="list_shell_3" level="3">
-                        <ul id="list-3" class="hidden" level="3" >
-                        </ul>
-                    </div>
+							<div id="list_shell_2" level="2">
+								<ul id="list-2" class="hidden" level="2"  >
+								</ul>
+							</div>
 
-                    <div id="list_shell_4" level="4">
-                        <ul id="list-4" class="hidden" level="4" >
-                        </ul>
-                    </div>
+							<div id="list_shell_3" level="3">
+								<ul id="list-3" class="hidden" level="3" >
+								</ul>
+							</div>
 
-                    <div id="list_shell_5" level="5">
-                        <ul id="list-5" class="hidden" level="5" >
-                        </ul>
-                    </div>
+							<div id="list_shell_4" level="4">
+								<ul id="list-4" class="hidden" level="4" >
+								</ul>
+							</div>
 
-                    <div id="list_shell_6" level="6">
-                        <ul id="list-6" class="hidden" level="6" >
-                        </ul>
-                    </div>
+							<div id="list_shell_5" level="5">
+								<ul id="list-5" class="hidden" level="5" >
+								</ul>
+							</div>
 
-                    <div id="list_shell_7" level="7">
-                        <ul id="list-7" class="hidden" level="7" >
-                        </ul>
-                    </div>
+							<div id="list_shell_6" level="6">
+								<ul id="list-6" class="hidden" level="6" >
+								</ul>
+							</div>
 
-                    <div id="list_shell_8" level="8">
-                        <ul id="list-8" class="hidden" level="8" >
-                        </ul>
-                    </div>
+							<div id="list_shell_7" level="7">
+								<ul id="list-7" class="hidden" level="7" >
+								</ul>
+							</div>
 
-                </div>
-            </div>
+							<div id="list_shell_8" level="8">
+								<ul id="list-8" class="hidden" level="8" >
+								</ul>
+							</div>
+
+						</div>
+					</div>
+				</div>
+			</div>
         </div>
     </div>
     <div style="flex:2;">
-    <div class='bangdan'>
-        <div class='title'>最新</div>
+    <div class='bangdan' id = "user_recent">
+        <div class='title'>最近阅读</div>
         <div class='list'>
-            <ul>
-                <li>zuixin-1</li>
-            </ul>
+            <div class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
         </div>
     </div>
     <div class='bangdan'>
-        <div class='title'>新手区</div>
+        <div class='title'>求助</div>
         <div class='list'>
             <ul>
                 <li>zuixin-1</li>
@@ -279,19 +262,17 @@ select#tag_category_index option {
         </div>
     </div>
     <div class='bangdan'>
-        <div class='title'>推荐</div>
+        <div class='title'>社区推荐</div>
         <div class='list'>
             <ul>
                 <li>zuixin-1</li>
             </ul>
         </div>
     </div>
-    <div class='bangdan'>
-        <div class='title'>白金作者</div>
+    <div class='bangdan' id='contribution'>
+        <div class='title'>月度贡献</div>
         <div class='list'>
-            <ul>
-                <li>zuixin-1</li>
-            </ul>
+            <div class="lds-ellipsis" ><div></div><div></div><div></div><div></div></div>
         </div>
     </div>
     </div>
@@ -308,17 +289,29 @@ select#tag_category_index option {
             }
             loadTagCategory(indexFilename);
             loadTagCategoryIndex();
+            loadFilterSetting();//载入上次的过滤器配置
+            LoadAllLanguage();
             <?php
             if(isset($_GET["view"])){
                 echo "_view = '{$_GET["view"]}';";
+            }else{
+                echo "_view = 'community';";
+                echo "updataHistory();";
+            }
+
+            if(isset($_GET["tag"])){
+                echo "_tags = '{$_GET["tag"]}';";
+            }
+            if(isset($_GET["channel"])){
+                echo "_channel = '{$_GET["channel"]}';";
             }
             
             switch ($_view) {
                 case 'community':
-                    echo "community_onload();";
+                    //echo "community_onload();";
                     break;
                 case 'category':
-                    echo "palicanon_onload();";
+                    //echo "palicanon_onload();";
                     break;
                 case 'my';
                 default:
@@ -326,8 +319,14 @@ select#tag_category_index option {
                     break;
             }
             ?>
+            list_tag = _tags.split(',');
+            refresh_selected_tag();
             ReanderMainMenu();
             updateFirstListView();
+            //载入用户最近的阅读列表
+            loadUserRecent();
+            loadContribution();
+            
         });
     </script>
     <?php

+ 55 - 0
public/app/palicanon/loading.css

@@ -0,0 +1,55 @@
+.lds-ellipsis {
+  display: inline-block;
+  position: relative;
+  width: 80px;
+  height: 80px;
+}
+.lds-ellipsis div {
+  position: absolute;
+  top: 33px;
+  width: 13px;
+  height: 13px;
+  border-radius: 50%;
+  background: var(--border-line-color);
+  animation-timing-function: cubic-bezier(0, 1, 1, 0);
+}
+.lds-ellipsis div:nth-child(1) {
+  left: 8px;
+  animation: lds-ellipsis1 0.6s infinite;
+}
+.lds-ellipsis div:nth-child(2) {
+  left: 8px;
+  animation: lds-ellipsis2 0.6s infinite;
+}
+.lds-ellipsis div:nth-child(3) {
+  left: 32px;
+  animation: lds-ellipsis2 0.6s infinite;
+}
+.lds-ellipsis div:nth-child(4) {
+  left: 56px;
+  animation: lds-ellipsis3 0.6s infinite;
+}
+@keyframes lds-ellipsis1 {
+  0% {
+    transform: scale(0);
+  }
+  100% {
+    transform: scale(1);
+  }
+}
+@keyframes lds-ellipsis3 {
+  0% {
+    transform: scale(1);
+  }
+  100% {
+    transform: scale(0);
+  }
+}
+@keyframes lds-ellipsis2 {
+  0% {
+    transform: translate(0, 0);
+  }
+  100% {
+    transform: translate(24px, 0);
+  }
+}

+ 94 - 0
public/app/palicanon/my_space.js

@@ -0,0 +1,94 @@
+function my_space_onload() {
+	$("#main_view").addClass("myspace");
+    render_selected_filter_list();
+    userRecentGet();
+    //LoadAllChannel();
+    LoadAllLanguage();
+	$("#filter-author").parent().hide();
+	$("#palicanon-category").hide();
+}
+function userRecentGet(offset=0){
+    $.getJSON(
+        "/api/v2/view?view=user-recent"
+    )
+    .done(function(data) {
+        let html = "";
+        for (const item of data.data) {
+			item.meta = JSON.parse(item.meta);
+            html += "<li class='recent'>";
+            html += "<span class='title'>";
+			html += "<a href='";
+			switch (item.target_type) {
+				case "chapter":
+					html += "/app/article/?view=chapter&book="+item.meta.book;
+					html += "&par="+item.meta.para;
+					html += "&channel="+item.meta.channel;
+					break;
+			
+				default:
+					break;
+			}
+			html += "' target='_blank'>";
+			if(item.title){
+				html += item.title;
+			}else{
+				html += item.org_title;
+			}
+            html += "</a>";
+			html +="</span>";
+            html += "<span class='count'>";
+			html += item.count;
+            html += "</span>";  
+            html += "<span class='update'>";
+			html += item.updated_at;
+            html += "</span>";            
+            html += "</li>";
+        }
+		$("#list-1").html(html);
+    })
+    .fail(function() {
+        console.log( "error" );
+    });
+}
+
+
+
+function loadUserRecent(){
+    $.getJSON(
+        "/api/v2/view?view=user-recent",
+		{
+			take:10,
+		}
+    )
+    .done(function(data) {
+        let html = "";
+        html += "<ol>";
+        for (const item of data.data) {
+			item.meta = JSON.parse(item.meta);
+            html += "<li>";
+			html += "<a href='";
+			switch (item.target_type) {
+				case "chapter":
+					html += "/app/article/?view=chapter&book="+item.meta.book;
+					html += "&par="+item.meta.para;
+					html += "&channel="+item.meta.channel;
+					break;
+				default:
+					break;
+			}
+			html += "' target='_blank'>";
+			if(item.title){
+				html += item.title;
+			}else{
+				html += item.org_title;
+			}
+            html += "</a>";
+            html += "</li>";
+        }
+        html += "</ol>";
+        $("#user_recent").find('.list').first().html(html);
+    })
+    .fail(function() {
+        console.log( "error" );
+    });
+}

Разница между файлами не показана из-за своего большого размера
+ 644 - 220
public/app/palicanon/palicanon.js


+ 45 - 0
public/app/palicanon/router.js

@@ -0,0 +1,45 @@
+//构造函数
+function Router() {
+    this.routes = {};
+    this.currentUrl = '';
+}
+Router.prototype.route = function(path, callback) {
+    this.routes[path] = callback || function(){};//给不同的hash设置不同的回调函数
+};
+Router.prototype.refresh = function() {
+    console.log(location.search.slice(1));//获取到相应的hash值
+    this.currentUrl = location.search.slice(1) || '/';//如果存在hash值则获取到,否则设置hash值为/
+    // console.log(this.currentUrl);
+    let params = new URLSearchParams(document.location.search);
+    let view = params.get("view");
+    if(this.currentUrl&&this.currentUrl!='/'){
+        this.routes[view]();//根据当前的hash值来调用相对应的回调函数
+    }
+ 
+};
+Router.prototype.init = function() {
+    window.addEventListener('load', this.refresh.bind(this), false);
+    //window.addEventListener('hashchange', this.refresh.bind(this), false);
+    window.onpopstate = function(event) {
+        console.log("location: " + document.location + ", state: " + JSON.stringify(event.state));
+        _view = event.state.view;
+        _tags = event.state.tag;
+        _channel = event.state.channel;
+        list_tag = _tags.split(',');
+        switch (_view) {
+            case "community":
+                community_onload();
+                break;
+            case "category":
+                palicanon_onload();
+                palicanonGetChapter();
+                break;
+            default:
+                break;
+        }
+        
+    };
+}
+//给window对象挂载属性
+window.Router = new Router();
+window.Router.init();

+ 345 - 17
public/app/palicanon/style.css

@@ -38,9 +38,12 @@ tag {
 	margin: 2px;
 	padding: 2px 12px;
 	border-radius: 5px;
-	border: 1px solid #fe897c;
+    cursor: pointer;
+    display: inline-block;
+}
+tag:hover{
+    background-color: var(--border-line-color);
 }
-
 .tag-delete {
 	margin-left: 6px;
 	color: #f93e3e;
@@ -116,9 +119,8 @@ tag {
 	display: none;
 }
 
-#select_bar {
-	display: flex;
-	justify-content: space-between;
+#select_bar>div {
+    display:inline;
 }
 
 .chapter_list {
@@ -154,50 +156,68 @@ tag {
 	display: none;
 }
 .chapter_list ul {
-	background-color: antiquewhite;
-	border-left: 1px solid brown;
-	border-right: 1px solid brown;
 	padding: 0;
 }
-.chapter_list ul li {
+.chapter_list ul li .main {
 	display: flex;
 	justify-content: space-between;
 	padding: 8px;
 	white-space: nowrap;
 	overflow-x: hidden;
+    border-bottom: 1px solid var(--border-line-color);
 }
 .chapter_list ul li:hover {
-	background-color: darkorange;
-	cursor: pointer;
+	/*background-color: darkorange;*/
+	/*cursor: pointer;*/
 }
 .chapter_list .resource {
-	display: flex;
-	margin-top: auto;
-	margin-bottom: auto;
+
+    margin-top: auto;
+    margin-bottom: auto;
+    white-space: normal;
+    display: -webkit-box;
+    -webkit-box-orient: vertical;
+    -webkit-line-clamp: 3;
+    overflow: hidden;
+    word-break: break-word;
+    word-wrap: break-word;
 }
 .chapter_list .title .title_1 {
-	color: var(--main-color);
+	color: var(--link-color);
 	font-weight: 700;
 	font-size: 110%;
+    width: 637px;
+    white-space: normal;
+}
+.chapter_list .title .title_1:hover {
+	color: var(--link-hover-color);
+	cursor: pointer;
 }
 .chapter_list .title .title_2 {
 	font-size: 80%;
 	color: var(--main-color1);
 }
+.subchapter {
+    margin-left: 1.5em;
+    padding-left: 0.5em;
+    display: none;
+    border-left: 2px solid gray;
+}
 .selected .title_2 {
 	font-size: 80%;
 	color: unset;
 }
 .chapter_list .title {
 	text-transform: capitalize;
+    display: flex;
+    justify-content: space-between;
 }
 .chapter_list .title div:lang(pali) {
 	font-size: 80%;
 }
 
 .chapter_list .selected {
-	background-color: chocolate;
-	color: whitesmoke;
+	background-color: var(--btn-color);
 }
 /*書標題特殊樣式*/
 .chapter_list .level_1 {
@@ -295,4 +315,312 @@ li.level_1.selected {
     height: unset;
     margin: unset;
     border: unset;
+}
+
+.chapter_dynamic_svg{
+    width:150px;
+}
+
+.bangdan li{
+    list-style-type:unset;
+    white-space: nowrap;
+    overflow: auto;
+}
+.bangdan ol{
+    padding-left: 1.5em;
+    width: 200px;
+}
+
+.chapter_list ul {
+    margin-left: 0;
+}
+.head_bar{
+    display: flex;
+    flex-direction: column;
+}
+#left-bar{
+    flex: 2;
+	width: 300px;
+    background-color: var(--box-bg-color2);
+	position: fixed;
+}
+
+.chapter_list ul li .main{
+    display:flex;
+}
+.book_view  ul li{
+    display:block;
+}
+.book_view .level_1{
+    background:unset;
+}
+
+.book_view ul li{
+    border:unset;
+    width: 30%;
+    height:90px;
+}
+.chapter_list .list {
+    display: none;
+}
+.chapter_list .show {
+    display: block;
+    width: 100%;
+}
+.chapter_list .grid {
+    width: 100%;
+}
+.chapter_list > div {
+    max-height: unset;
+    overflow-y: unset; 
+}
+
+.chapter_list .more_info{
+    display:flex;
+    font-size:80%;
+    color: var(--main-color1);
+    justify-content: space-between;
+}
+
+.more_info>.palicanon_chapter_info>.item{
+    margin-right:1em;
+}
+.left_item>.item{
+    margin-right:1em;
+}
+.filter>.inner {
+    /*max-height: 200px;*/
+    /*overflow-y: auto;*/
+    background-color: var(--input-bg-color);
+}
+
+.main_menu {
+    font-size: 100%;
+    text-align: center;
+    margin: 0 1em;
+    transition: all 600ms ease;
+    text-transform: capitalize;
+}
+.main_menu>span {
+    margin: 2px;
+    padding: 2px 12px;
+    font-weight: 500;
+    transition-duration: 0.2s;
+    cursor: pointer;
+    font-size: 120%;
+    border: unset;
+    border-radius: 0;
+    border-bottom: 2px solid var(--nocolor);
+    display: inline-block;
+}
+.main_menu>.select {
+    border-bottom: 2px solid var(--link-color);
+}
+.main_menu>span>a {
+    color:unset;
+}
+.main_menu span:hover {
+    background-color: unset;
+    color: unset;
+    border-color: var(--link-hover-color);
+}
+.submenu select>option {
+    background-color: gray;
+}
+button.active {
+    background-color: gray;
+}
+
+.chapter_list ul li>.main>.left{
+    width: 100px;
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+}
+.chapter_list ul li>.main>.right{
+    width:100%;
+}
+.chapter_tag {
+    width: 475px;
+    padding: 5px 0;
+    overflow-y: visible;
+    overflow-x: auto;
+    display: flex;
+    flex-wrap: wrap;
+}
+.left_item {
+    margin: 4px 0;
+}
+.left_item>.item>.small_icon{
+    width:16px;
+    height:16px;
+}
+.left_item>.item>.text{
+    padding:5px;
+}
+
+div#tag_list {
+    background-color: var(--btn-color);
+    padding: 5px;
+    display: none;
+}
+
+#more_chapter {
+    text-align: center;
+}
+#more_chapter_line {
+    border-bottom: 1px solid var(--border-line-color);
+    height: 1em;
+}
+#btn_more_chapter{
+        position: absolute;
+    margin-top: -1.1em;
+    background-color: var(--link-color);
+    color: var(--bg-color);
+    border: none;
+    padding: 2px 40px;
+    margin-left: -5em;
+}
+#filter-author li.active{
+    background-color:gray;
+}
+
+#filter_bar {
+    display: flex;
+    justify-content: space-between;
+}
+div#filter_bar {
+    font-size: 120%;
+}
+
+span.channel:hover {
+    background-color: wheat;
+}
+span.channel {
+    cursor: pointer;
+}
+
+.settting-item {
+    display: flex;
+    justify-content: space-between;
+    padding: 2px;
+}
+
+#main_view{
+    display:flex;
+}
+
+#tag_list_inner {
+    display: flex;
+    flex-direction: row;
+}
+
+#tag_list_tag_div {
+    flex: 7;
+    padding: 10px;
+}
+
+#tag_list_setting_div {
+    flex: 3;
+    padding: 10px;
+}
+
+#palicanon-category{
+    display:none;
+}
+#select_bar_home{
+    display:none;
+}
+
+#left-bar-inner {
+    height: calc(100vh - 50px);
+    overflow-y: scroll;
+}
+#palicanon-category{
+    display:block;
+}
+
+.community #palicanon-category{
+    display:none;
+}
+
+#palicanon-category>.chapter_list {
+    flex-direction: column;
+}
+
+#palicanon-category li{
+    display: flex;
+    padding: 5px 0;
+    border-bottom: 1px solid var(--border-line-color);
+}
+
+#palicanon-category .chapter_list .title .title_1 {
+    width: unset;
+}
+#palicanon-category .chapter_list .title{
+    width: -webkit-fill-available;
+    padding-left: 12px;
+}
+
+#course_head_bar{
+	flex:6;
+	padding:0 10px 10px 315px;
+}
+
+#bread-crumbs{
+	display: none;
+}
+.popup {
+    color: var(--tool-bt-color);
+}
+.popup #bread-crumbs{
+	display: block;
+}
+.popup #file_background {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100vw;
+    height: 100vh;
+    background-color: rgba(0,0,0,0.85);
+	z-index: 200;
+}
+.popup #file_list_div {
+    position: fixed;
+    top: 4em;
+	z-index: 210;
+}
+.popup #index_inner {
+    height: calc(100vh - 4em);
+    overflow-y: auto;
+}
+.popup  .index_inner {
+    height: calc(100vh - 5em);
+    overflow-y: auto;
+}
+header {
+	z-index: 100;
+}
+
+#bread-crumbs>span{
+	padding: 0 4px;
+}
+
+
+.category #btn_more_chapter{
+	display:none;
+}
+
+.recent{
+	display:flex;
+}
+
+.recent>.title{
+	flex:5;
+}
+.recent>.count{
+	flex:1;
+}
+.recent>.update{
+	flex:3;
 }

+ 67 - 0
public/app/palicanon/style_mobile.css

@@ -14,3 +14,70 @@
 .chapter_head_tool_bar .chapter_close_button {
 	display: none;
 }
+#main_view{
+    display:flex;
+    flex-direction: column;
+}
+
+#left-bar {
+    flex: 2;
+    background-color: var(--box-bg-color2);
+    display: none;
+}
+
+.chapter_list .more_info {
+    display: flex;
+    font-size: 80%;
+    color: var(--main-color1);
+    flex-direction: column;
+}
+
+.chapter_list ul li .main {
+    display: flex;
+    flex-direction: column;
+}
+
+.left_items {
+    display: flex;
+    flex-direction: row;
+}
+
+#tag_list_inner {
+    display: flex;
+    flex-direction: column-reverse;
+}
+
+#tag_list_tag_div {
+    padding: 6px;
+}
+
+#tag_list_setting_div {
+    padding: 6px;
+}
+#palicanon-category{
+    display:block;
+}
+
+#palicanon-category>.chapter_list {
+    flex-direction: column;
+}
+
+#palicanon-category li{
+    display: flex;
+    padding: 5px 0;
+    border-bottom: 1px solid var(--border-line-color);
+}
+
+#palicanon-category .chapter_list .title .title_1 {
+    width: unset;
+}
+#palicanon-category .chapter_list .title{
+    width: -webkit-fill-available;
+    padding-left: 12px;
+}
+#course_head_bar{
+	padding:0 10px 10px 15px;
+}
+.chapter_list .title .title_1 {
+    width: 100%;
+}

+ 35 - 0
public/app/palicanon/test.js

@@ -0,0 +1,35 @@
+Router.route('community', function () {
+    let params = new URLSearchParams(document.location.search);
+    // 
+    if(params.get("tag")){
+        _tags = params.get("tag"); 
+    }
+    if(params.get("channel")){
+        _channel = params.get("channel"); 
+    }
+    list_tag = _tags.split(',');
+    community_onload();
+});
+Router.route('category', function () {
+    let params = new URLSearchParams(document.location.search);
+    if(params.get("tag")){
+        _tags = params.get("tag"); 
+    }
+    if(params.get("channel")){
+        _channel = params.get("channel"); 
+    }
+    list_tag = _tags.split(',');
+    palicanon_onload();
+    palicanonGetChapter();
+});
+Router.route('my', function () {
+	let params = new URLSearchParams(document.location.search);
+    if(params.get("tag")){
+        _tags = params.get("tag"); 
+    }
+    if(params.get("channel")){
+        _channel = params.get("channel"); 
+    }
+    list_tag = _tags.split(',');
+    my_space_onload();
+});

+ 2 - 2
public/app/pcdl/css/style.css

@@ -101,8 +101,8 @@ h3 {
 }
 
 ::-webkit-scrollbar {
-	width: 8px;
-	height: 8px;
+	/*width: 8px;*/
+	/*height: 8px;*/
 	/*display: none;*/
 }
 

+ 221 - 221
public/app/public/book_tag/en.json

@@ -4281,7 +4281,7 @@
 		"para": "3",
 		"level": "1",
 		"title": "mahāvaggapāḷi",
-		"tag": ":mahāvagga::mūla::vinaya::khandhaka::pāḷi:"
+		"tag": ":mahāvagga::mūla::vinaya::khandhaka::mahāvaggapāḷi::pāḷi:"
 	},
 	{
 		"book": "215",
@@ -4358,7 +4358,7 @@
 		"para": "3",
 		"level": "1",
 		"title": "cūḷavaggapāḷi",
-		"tag": ":cūḷavagga::mūla::vinaya::khandhaka::pāḷi:"
+		"tag": ":cūḷavagga::mūla::vinaya::khandhaka::cūḷavaggapāḷi::pāḷi:"
 	},
 	{
 		"book": "216",
@@ -4444,7 +4444,7 @@
 		"title": "12. sattasatikakkhandhakaṃ",
 		"tag": ":cūḷavagga::mūla::vinaya::khandhaka::pāḷi:"
 	},
-	{ "book": "217", "para": "3", "level": "1", "title": "parivārapāḷi", "tag": ":parivāra::mūla::vinaya::pāḷi:" },
+	{ "book": "217", "para": "3", "level": "1", "title": "parivārapāḷi", "tag": ":parivāra::mūla::vinaya::parivārapāḷi::pāḷi:" },
 	{ "book": "217", "para": "5", "level": "2", "title": "soḷasamahāvāro", "tag": ":parivāra::mūla::vinaya::pāḷi:" },
 	{
 		"book": "217",
@@ -5123,8 +5123,8 @@
 		"book": "81",
 		"para": "3",
 		"level": "1",
-		"title": "paṭṭhānapāḷi",
-		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi:"
+		"title": "paṭṭhānapāḷi(Paṭhamo Bhāgo)",
+		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi::paṭhama bhāga:"
 	},
 	{
 		"book": "81",
@@ -5172,8 +5172,8 @@
 		"book": "69",
 		"para": "3",
 		"level": "1",
-		"title": "paṭṭhānapāḷi",
-		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi:"
+		"title": "paṭṭhānapāḷi(Dutiyo Bhāgo)",
+		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi::dutiya bhāga:"
 	},
 	{
 		"book": "69",
@@ -5298,8 +5298,8 @@
 		"book": "70",
 		"para": "3",
 		"level": "1",
-		"title": "paṭṭhānapāḷi",
-		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi:"
+		"title": "paṭṭhānapāḷi(Tatiyo Bhāgo)",
+		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi::tatiya bhāga:"
 	},
 	{
 		"book": "70",
@@ -5375,8 +5375,8 @@
 		"book": "71",
 		"para": "3",
 		"level": "1",
-		"title": "paṭṭhānapāḷi",
-		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi:"
+		"title": "paṭṭhānapāḷi(Catuttho Bhāgo)",
+		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi::catuttha bhāga:"
 	},
 	{
 		"book": "71",
@@ -5529,8 +5529,8 @@
 		"book": "72",
 		"para": "3",
 		"level": "1",
-		"title": "paṭṭhānapāḷi",
-		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi:"
+		"title": "paṭṭhānapāḷi(Pañcamo Bhāgo)",
+		"tag": ":paṭṭhāna::mūla::abhidhamma::paṭṭhāna::paṭṭhānapāḷi::pāḷi::pañcama bhāga:"
 	},
 	{
 		"book": "72",
@@ -12257,385 +12257,385 @@
 		"para": "3",
 		"level": "1",
 		"title": "sāratthadīpanī-ṭīkā (paṭhamo bhāgo)",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::paṭhamo bhāgo:"
 	},
 	{
 		"book": "204",
 		"para": "4",
 		"level": "2",
 		"title": "ganthārambhakathā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::paṭhamo bhāgo:"
 	},
 	{
 		"book": "204",
 		"para": "37",
 		"level": "2",
 		"title": "ganthārambhakathāvaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::paṭhamo bhāgo:"
 	},
 	{
 		"book": "204",
 		"para": "133",
 		"level": "2",
 		"title": "bāhiranidānakathā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::paṭhamo bhāgo:"
 	},
 	{
 		"book": "204",
 		"para": "817",
 		"level": "2",
 		"title": "verañjakaṇḍavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::paṭhamo bhāgo:"
 	},
 	{
 		"book": "205",
 		"para": "3",
 		"level": "1",
 		"title": "sāratthadīpanī-ṭīkā (dutiyo bhāgo)",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::dīpanī::dutiyo bhāgo:"
 	},
 	{
 		"book": "205",
 		"para": "4",
 		"level": "2",
 		"title": "1. pārājikakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::pārājika::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::pārājika::dīpanī::dutiyo bhāgo:"
 	},
 	{
 		"book": "205",
 		"para": "1115",
 		"level": "2",
 		"title": "2. saṅghādisesakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::saṅghādisesa::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::saṅghādisesa::dīpanī::dutiyo bhāgo:"
 	},
 	{
 		"book": "205",
 		"para": "1380",
 		"level": "2",
 		"title": "3. aniyatakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::aniyata::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::aniyata::dīpanī::dutiyo bhāgo:"
 	},
 	{
 		"book": "205",
 		"para": "1398",
 		"level": "2",
 		"title": "4. nissaggiyakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::nissaggiya::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pārājikapāḷi::nissaggiya::dīpanī::dutiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "3",
 		"level": "1",
 		"title": "sāratthadīpanī-ṭīkā (tatiyo bhāgo)",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::pācittiyapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::pācittiyapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "4",
 		"level": "2",
 		"title": "5. pācittiyakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::pācittiya::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::pācittiya::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "515",
 		"level": "2",
 		"title": "6. pāṭidesanīyakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::pāṭidesanīya::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::pāṭidesanīya::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "523",
 		"level": "2",
 		"title": "7. sekhiyakaṇḍaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::sekhiya::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::mahāvibhaṅga::pācittiyapāḷi::sekhiya::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "578",
 		"level": "2",
 		"title": "bhikkhunīvibhaṅgavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::bhikkhunīvibhaṅga::pācittiyapāḷi::bhikkhunī::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::suttavibhaṅga::bhikkhunīvibhaṅga::pācittiyapāḷi::bhikkhunī::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "717",
 		"level": "1",
 		"title": "mahāvagga-ṭīkā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "718",
 		"level": "2",
 		"title": "1. mahākhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1317",
 		"level": "2",
 		"title": "2. uposathakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::uposatha::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::uposatha::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1381",
 		"level": "2",
 		"title": "3. vassūpanāyikakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1407",
 		"level": "2",
 		"title": "4. pavāraṇakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1425",
 		"level": "2",
 		"title": "5. cammakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1478",
 		"level": "2",
 		"title": "6. bhesajjakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1622",
 		"level": "2",
 		"title": "7. kathinakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1637",
 		"level": "2",
 		"title": "8. cīvarakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1683",
 		"level": "2",
 		"title": "9. campeyyakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1695",
 		"level": "2",
 		"title": "10. kosambakakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::mahāvagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1753",
 		"level": "1",
 		"title": "cūḷavagga-ṭīkā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1754",
 		"level": "2",
 		"title": "1. kammakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1780",
 		"level": "2",
 		"title": "2. pārivāsikakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1789",
 		"level": "2",
 		"title": "3. samuccayakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1814",
 		"level": "2",
 		"title": "4. samathakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1840",
 		"level": "2",
 		"title": "5. khuddakavatthukkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1880",
 		"level": "2",
 		"title": "6. senāsanakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "1950",
 		"level": "2",
 		"title": "7. saṅghabhedakakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2005",
 		"level": "2",
 		"title": "8. vattakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2024",
 		"level": "2",
 		"title": "9. pātimokkhaṭṭhapanakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2074",
 		"level": "2",
 		"title": "10. bhikkhunikkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::bhikkhunī::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::bhikkhunī::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2114",
 		"level": "2",
 		"title": "11. pañcasatikakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2133",
 		"level": "2",
 		"title": "12. sattasatikakkhandhakaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::khandhaka::cūḷavagga::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2154",
 		"level": "1",
 		"title": "parivāra-ṭīkā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2155",
 		"level": "2",
 		"title": "soḷasamahāvāro",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2164",
 		"level": "2",
 		"title": "samuṭṭhānasīsavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2171",
 		"level": "2",
 		"title": "antarapeyyālaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2221",
 		"level": "2",
 		"title": "ekuttarikanayo",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2287",
 		"level": "2",
 		"title": "uposathādipucchāvissajjanāvaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2292",
 		"level": "2",
 		"title": "paṭhamagāthāsaṅgaṇikaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2304",
 		"level": "2",
 		"title": "adhikaraṇabhedavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2311",
 		"level": "2",
 		"title": "dutiyagāthāsaṅgaṇikavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2313",
 		"level": "2",
 		"title": "saṅgāmadvayavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2316",
 		"level": "2",
 		"title": "kathinabhedavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2320",
 		"level": "2",
 		"title": "upālipañcakavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2335",
 		"level": "2",
 		"title": "samuṭṭhānavaṇṇanā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2337",
 		"level": "2",
 		"title": "aparadutiyagāthāsaṅgaṇikaṃ",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2345",
 		"level": "2",
 		"title": "sedamocanagāthā",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "206",
 		"para": "2355",
 		"level": "2",
 		"title": "pañcavaggo",
-		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī:"
+		"tag": ":sāratthadīpanī::ṭīkā::vinaya::parivāra::parivārapāḷi::dīpanī::tatiyo bhāgo:"
 	},
 	{
 		"book": "207",
@@ -16457,56 +16457,56 @@
 		"para": "2",
 		"level": "1",
 		"title": "niruttidīpanīpāṭha",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "16",
 		"level": "2",
 		"title": "1. sandhikaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "631",
 		"level": "2",
 		"title": "2. nāmakaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "1858",
 		"level": "2",
 		"title": "3. kārakakaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "2255",
 		"level": "2",
 		"title": "4. samāsakaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "2889",
 		"level": "2",
 		"title": "5. taddhita",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "3494",
 		"level": "2",
 		"title": "6. ākhyātakaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "22",
 		"para": "5030",
 		"level": "2",
 		"title": "7. kitakaṇḍa",
-		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo gantha-saṅgaho:"
+		"tag": ":añña::niruttidīpanīpāṭha::nirutti::leḍī sayādo:"
 	},
 	{
 		"book": "23",
@@ -16863,308 +16863,308 @@
 		"para": "2",
 		"level": "1",
 		"title": "namakkārapāḷi",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::namakkārapāḷi:"
+		"tag": ":añña::buddha-vandanā::namakkāra::namakkārapāḷi:"
 	},
 	{
 		"book": "1",
 		"para": "159",
 		"level": "1",
 		"title": "namakkāraṭīkā",
-		"tag": ":añña::ṭīkā::buddha-vandanā gantha-saṅgaho::namakkārapāḷi:"
+		"tag": ":añña::ṭīkā::buddha-vandanā::namakkāra::namakkāraṭīkā:"
 	},
 	{
 		"book": "2",
 		"para": "2",
 		"level": "1",
 		"title": "mahāpaṇāmapāṭha",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::mahāpaṇāmapāṭha(buddhavandanā):"
+		"tag": ":añña::buddha-vandanā::mahāpaṇāmapāṭha(buddhavandanā):"
 	},
 	{
 		"book": "2",
 		"para": "428",
 		"level": "1",
 		"title": "tigumbacetiya thomanā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::mahāpaṇāmapāṭha(buddhavandanā):"
+		"tag": ":añña::buddha-vandanā::mahāpaṇāmapāṭha(buddhavandanā):"
 	},
 	{
 		"book": "2",
 		"para": "479",
 		"level": "1",
 		"title": "vāsamālinīkya",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::mahāpaṇāmapāṭha(buddhavandanā):"
+		"tag": ":añña::buddha-vandanā::mahāpaṇāmapāṭha(buddhavandanā):"
 	},
 	{
 		"book": "3",
 		"para": "2",
 		"level": "1",
 		"title": "lakkhaṇāto",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::lakkhaṇāto:"
+		"tag": ":añña::buddha-vandanā::lakkhaṇāto:"
 	},
 	{
 		"book": "3",
 		"para": "3",
 		"level": "2",
 		"title": "buddhathomanāgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::lakkhaṇāto:"
+		"tag": ":añña::buddha-vandanā::lakkhaṇāto:"
 	},
 	{
 		"book": "3",
 		"para": "268",
 		"level": "2",
 		"title": "buddhavandanā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::lakkhaṇāto:"
+		"tag": ":añña::buddha-vandanā::lakkhaṇāto:"
 	},
 	{
 		"book": "3",
 		"para": "304",
 		"level": "2",
 		"title": "uṇṇālomikanātha vandanā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::lakkhaṇāto:"
+		"tag": ":añña::buddha-vandanā::lakkhaṇāto:"
 	},
 	{
 		"book": "4",
 		"para": "2",
 		"level": "1",
 		"title": "suttavandanā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::suttavandanā:"
+		"tag": ":añña::buddha-vandanā::suttavandanā:"
 	},
 	{
 		"book": "5",
 		"para": "2",
 		"level": "1",
 		"title": "jinālaṅkāra",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "3",
 		"level": "2",
 		"title": "paṇāmadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "12",
 		"level": "2",
 		"title": "yogāvacarasampattidīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "16",
 		"level": "2",
 		"title": "vatthuvisodhanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "30",
 		"level": "2",
 		"title": "anaññasādhāraṇadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "65",
 		"level": "2",
 		"title": "abhinīhāradīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "114",
 		"level": "2",
 		"title": "bodhisambhāradīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "160",
 		"level": "2",
 		"title": "gabbhokkantidīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "173",
 		"level": "2",
 		"title": "vijāyanamaṅgaladīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "220",
 		"level": "2",
 		"title": "agāriyasampattidīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "232",
 		"level": "2",
 		"title": "nekkhammajjhāsayadīpanīyamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "314",
 		"level": "2",
 		"title": "pāduddhāravimhayadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "380",
 		"level": "2",
 		"title": "apunarāvattigamanadīpanīyamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "426",
 		"level": "2",
 		"title": "dvipādabyāsayamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "472",
 		"level": "2",
 		"title": "tipādabyāsayamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "478",
 		"level": "2",
 		"title": "pādabyāsamahāyamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "484",
 		"level": "2",
 		"title": "abyāpetādyantayamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "490",
 		"level": "2",
 		"title": "paṭilomayamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "497",
 		"level": "2",
 		"title": "ekaṭhānikādiyamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "510",
 		"level": "2",
 		"title": "akkharuttarikayamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "523",
 		"level": "2",
 		"title": "paheḷigāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "527",
 		"level": "2",
 		"title": "byāpetādiyamakagāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "533",
 		"level": "2",
 		"title": "mahāpadhānadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "554",
 		"level": "2",
 		"title": "māraparājayadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "635",
 		"level": "2",
 		"title": "abhisambodhidīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "740",
 		"level": "2",
 		"title": "dhammacakkapavattanadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "746",
 		"level": "2",
 		"title": "pāṭihāriyadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "757",
 		"level": "2",
 		"title": "navaguṇadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "793",
 		"level": "2",
 		"title": "guṇadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "818",
 		"level": "2",
 		"title": "pūjānidhānadīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "5",
 		"para": "980",
 		"level": "2",
 		"title": "patthanādīpanīgāthā",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::jinālaṅkāra:"
+		"tag": ":añña::buddha-vandanā::jinālaṅkāra:"
 	},
 	{
 		"book": "6",
 		"para": "2",
 		"level": "1",
 		"title": "kamalāñjali",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::kamalāñjali:"
+		"tag": ":añña::buddha-vandanā::kamalāñjali:"
 	},
 	{
 		"book": "7",
 		"para": "2",
 		"level": "1",
 		"title": "pajjamadhu",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::pajjamadhu:"
+		"tag": ":añña::buddha-vandanā::pajjamadhu:"
 	},
 	{
 		"book": "8",
 		"para": "2",
 		"level": "1",
 		"title": "buddhaguṇagāthāvalī",
-		"tag": ":añña::buddha-vandanā gantha-saṅgaho::buddhaguṇagāthāvalī:"
+		"tag": ":añña::buddha-vandanā::buddhaguṇagāthāvalī:"
 	},
 	{
 		"book": "61",
@@ -17745,707 +17745,707 @@
 		"para": "2",
 		"level": "1",
 		"title": "moggallānasuttapāṭho",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "1105",
 		"level": "1",
 		"title": "moggallānabyākaraṇaṃ",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "1106",
 		"level": "2",
 		"title": "1. paṭhamo saññādikaṇḍo",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "1236",
 		"level": "2",
 		"title": "2. dutiyo kaṇḍo (syādi)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "1738",
 		"level": "2",
 		"title": "(3) tatiyo kaṇḍo (samāso)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "1973",
 		"level": "2",
 		"title": "4. catuttho kaṇḍo (ṇādi)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "2250",
 		"level": "2",
 		"title": "5. pañcamo kaṇḍo (khādi)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "2609",
 		"level": "2",
 		"title": "6. chaṭṭho kaṇḍo (tyādi)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "13",
 		"para": "2771",
 		"level": "2",
 		"title": "7. sattamo kaṇḍo (ṇvādi)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallānasuttapāṭho::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallānasuttapāṭho::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "2",
 		"level": "1",
 		"title": "kaccāyanabyākaraṇaṃ",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "715",
 		"level": "1",
 		"title": "mahākaccāyanasaddāpāṭha",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "716",
 		"level": "2",
 		"title": "1. sandhikappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "948",
 		"level": "2",
 		"title": "2. nāmakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "1883",
 		"level": "2",
 		"title": "3. kārakakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "2109",
 		"level": "2",
 		"title": "4. samāsakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "2249",
 		"level": "2",
 		"title": "5. taddhitakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "2520",
 		"level": "2",
 		"title": "6. ākhyātakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "2955",
 		"level": "2",
 		"title": "7. kibbidhānakappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "14",
 		"para": "3321",
 		"level": "2",
 		"title": "8. uṇādikappa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::kaccāyanabyākaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::kaccāyanabyākaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2",
 		"level": "1",
 		"title": "saddanītippakaraṇaṃ (padamālā)",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "3",
 		"level": "2",
 		"title": "ganthārambhakathā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "34",
 		"level": "2",
 		"title": "1. savikaraṇākhyātavibhāga",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "212",
 		"level": "2",
 		"title": "2. bhavatikriyāpadamālāvibhāga",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "427",
 		"level": "2",
 		"title": "3. pakiṇṇakavinicchaya",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "840",
 		"level": "2",
 		"title": "4. bhūdhātumayanāmikarūpavibhāga",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "1158",
 		"level": "2",
 		"title": "5. okārantapulliṅganāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "1525",
 		"level": "2",
 		"title": "6. ākārantapulliṅganāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "1736",
 		"level": "2",
 		"title": "7. niggahītantapulliṅganāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "1992",
 		"level": "2",
 		"title": "8. itthiliṅganāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2194",
 		"level": "2",
 		"title": "9. napuṃsakaliṅganāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2262",
 		"level": "2",
 		"title": "10. liṅgattayamissakanāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2365",
 		"level": "2",
 		"title": "11. vāccābhidheyyaliṅgādiparidīpananāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2538",
 		"level": "2",
 		"title": "12. sabbanāmataṃsadisanāmanāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2823",
 		"level": "2",
 		"title": "13. savinicchayasaṅkhyānāmanāmikapadamālā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "15",
 		"para": "2915",
 		"level": "2",
 		"title": "14. atthattikavibhāga",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ (padamālā)::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ (padamālā)::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "2",
 		"level": "1",
 		"title": "saddanītippakaraṇaṃ",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "4",
 		"level": "2",
 		"title": "15. saravaggapañcakantika suddhassaradhātu",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "1176",
 		"level": "2",
 		"title": "16. bhūvādigaṇikapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "1898",
 		"level": "2",
 		"title": "17. rudhādichakka",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "2395",
 		"level": "2",
 		"title": "18. curādigaṇaparidīpana",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "16",
 		"para": "3067",
 		"level": "2",
 		"title": "19. sabbagaṇavinicchaya",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::saddanītippakaraṇaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::saddanītippakaraṇaṃ::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "2",
 		"level": "1",
 		"title": "padarūpasiddhi",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "14",
 		"level": "2",
 		"title": "1. sandhikaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "697",
 		"level": "2",
 		"title": "2. nāmakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "1598",
 		"level": "2",
 		"title": "3. kārakakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "1981",
 		"level": "2",
 		"title": "4. samāsakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "2285",
 		"level": "2",
 		"title": "5. taddhitakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "2604",
 		"level": "2",
 		"title": "6. ākhyātakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "17",
 		"para": "3384",
 		"level": "2",
 		"title": "7. kibbidhānakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::padarūpasiddhi::nirutti:"
+		"tag": ":añña::byākaraṇa::padarūpasiddhi::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "2",
 		"level": "1",
 		"title": "moggallāna pañcikā ṭīkā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "84",
 		"level": "2",
 		"title": "1. paṭhamakaṇḍavaṇṇanā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "249",
 		"level": "2",
 		"title": "2. dutiyakaṇḍa vaṇṇanā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "593",
 		"level": "2",
 		"title": "3. tatiyakaṇḍavaṇṇanā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "868",
 		"level": "2",
 		"title": "catutthakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "1109",
 		"level": "2",
 		"title": "pañcamakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "18",
 		"para": "1419",
 		"level": "2",
 		"title": "chaṭṭhakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::moggallāna pañcikā ṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::moggallāna pañcikā ṭīkā::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "2",
 		"level": "1",
 		"title": "payogasiddhipāḷi",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "3",
 		"level": "2",
 		"title": "1. saññādikaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "5",
 		"level": "2",
 		"title": "ganthārambhakathā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "184",
 		"level": "2",
 		"title": "2. nāmakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "977",
 		"level": "2",
 		"title": "3. kārakakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "1166",
 		"level": "2",
 		"title": "4. samāsakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "1465",
 		"level": "2",
 		"title": "5. ṇādikaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "1774",
 		"level": "2",
 		"title": "6. tyādikaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "19",
 		"para": "2171",
 		"level": "2",
 		"title": "7. khādikaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::payogasiddhipāḷi::nirutti:"
+		"tag": ":añña::byākaraṇa::payogasiddhipāḷi::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "2",
 		"level": "1",
 		"title": "vuttodayaṃ",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "3",
 		"level": "2",
 		"title": "1. saññāparibhāsāniddesa-paṭhamapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "61",
 		"level": "2",
 		"title": "2. mattāvuttiniddesa-dutiyapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "139",
 		"level": "2",
 		"title": "3. samavuttiniddesa-tatiyapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "224",
 		"level": "2",
 		"title": "4. aḍḍhasamavuttiniddesa-catutthapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "261",
 		"level": "2",
 		"title": "5. visamavuttiniddesa-pañcamapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "20",
 		"para": "278",
 		"level": "2",
 		"title": "6. chappaccayavibhāga-chaṭṭhapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::vuttodayaṃ::nirutti:"
+		"tag": ":añña::byākaraṇa::vuttodayaṃ::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "2",
 		"level": "1",
 		"title": "abhidhānappadīpikā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "41",
 		"level": "2",
 		"title": "1. saggakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "619",
 		"level": "2",
 		"title": "2. bhūkaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "677",
 		"level": "2",
 		"title": "2. bhūkaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "2272",
 		"level": "2",
 		"title": "3. sāmaññakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "21",
 		"para": "3703",
 		"level": "2",
 		"title": "3. sāmaññakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti:"
 	},
 	{
 		"book": "9",
 		"para": "2",
 		"level": "1",
 		"title": "abhidhānappadīpikāṭīkā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti::ṭīkā:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti::ṭīkā:"
 	},
 	{
 		"book": "9",
 		"para": "37",
 		"level": "2",
 		"title": "1. saggakaṇḍavaṇṇanā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti::ṭīkā:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti::ṭīkā:"
 	},
 	{
 		"book": "9",
 		"para": "546",
 		"level": "2",
 		"title": "2. bhūkaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti::ṭīkā:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti::ṭīkā:"
 	},
 	{
 		"book": "9",
 		"para": "1869",
 		"level": "2",
 		"title": "3. sāmaññakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::abhidhānappadīpikā::nirutti::ṭīkā:"
+		"tag": ":añña::byākaraṇa::abhidhānappadīpikā::nirutti::ṭīkā:"
 	},
 	{
 		"book": "10",
 		"para": "2",
 		"level": "1",
 		"title": "subodhālaṅkāro",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "10",
 		"para": "3",
 		"level": "2",
 		"title": "1. dosāvabodha-paṭhamapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "10",
 		"para": "233",
 		"level": "2",
 		"title": "2. dosaparihārāvabodha-dutiyapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "10",
 		"para": "414",
 		"level": "2",
 		"title": "3. guṇāvabodha-tatiyapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "10",
 		"para": "585",
 		"level": "2",
 		"title": "4. atthālaṅkārāvabodha-catutthapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "10",
 		"para": "1191",
 		"level": "2",
 		"title": "5. bhāvāvabodha-pañcamapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāro::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāro::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "2",
 		"level": "1",
 		"title": "subodhālaṅkāraṭīkā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "3",
 		"level": "2",
 		"title": "ganthārambhakathā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "20",
 		"level": "2",
 		"title": "1. dosāvabodha paṭhamapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "807",
 		"level": "2",
 		"title": "2. dosaparihārāvabodhaparicchedavaṇṇanā",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "1108",
 		"level": "2",
 		"title": "3. guṇāvabodhapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "1475",
 		"level": "2",
 		"title": "4. atthālaṅkārāvabodhapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "2536",
 		"level": "2",
 		"title": "5. bhāvāvabodhapariccheda",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "11",
 		"para": "2723",
 		"level": "2",
 		"title": "ṭhāyībhāvaniddesa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::subodhālaṅkāraṭīkā::nirutti:"
+		"tag": ":añña::byākaraṇa::subodhālaṅkāraṭīkā::nirutti:"
 	},
 	{
 		"book": "12",
 		"para": "2",
 		"level": "1",
 		"title": "bālāvatāra",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::bālāvatāra::nirutti::avatāra:"
+		"tag": ":añña::byākaraṇa::bālāvatāra::nirutti::avatāra:"
 	},
 	{
 		"book": "12",
 		"para": "42",
 		"level": "2",
 		"title": "1. sandhi kaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::bālāvatāra::nirutti::avatāra:"
+		"tag": ":añña::byākaraṇa::bālāvatāra::nirutti::avatāra:"
 	},
 	{
 		"book": "12",
 		"para": "182",
 		"level": "2",
 		"title": "2. nāmakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::bālāvatāra::nirutti::avatāra:"
+		"tag": ":añña::byākaraṇa::bālāvatāra::nirutti::avatāra:"
 	},
 	{
 		"book": "12",
 		"para": "619",
 		"level": "2",
 		"title": "3. samāsakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::bālāvatāra::nirutti::avatāra:"
+		"tag": ":añña::byākaraṇa::bālāvatāra::nirutti::avatāra:"
 	},
 	{
 		"book": "12",
 		"para": "735",
 		"level": "2",
 		"title": "4. taddhitakaṇḍa",
-		"tag": ":añña::byākaraṇa gantha-saṅgaho::bālāvatāra::nirutti::avatāra:"
+		"tag": ":añña::byākaraṇa::bālāvatāra::nirutti::avatāra:"
 	},
 	{
 		"book": "27",

+ 3 - 0
public/app/public/lang/default.json

@@ -656,6 +656,9 @@
 		"pass": "pass.",
 		"space": "&nbsp;",
 		"channel_type": "channel type",
+		"community_new": "community new",
+		"pali_text": "pali text",
+		"my_read": "recent",
 		"": ""
 	},
 	"grammastr": [

+ 3 - 0
public/app/public/lang/en.json

@@ -655,6 +655,9 @@
 		"pass": "pass.",
 		"space": "&nbsp;",
 		"channel_type": "channel type",
+		"community_new": "community new",
+		"pali_text": "pali text",
+		"my_read": "recent",
 		"": ""
 	},
 	"grammastr": [

+ 3 - 4
public/app/public/lang/my.json

@@ -636,10 +636,9 @@
 		"pass": "အောင်သည်။ ကျော်ဖျက်သည်။",
 		"space": "&nbsp;",
 		"channel_type": "ချန်နယ်အမျိုးအစား",
-		
-		
-		
-
+		"community_new": "community new",
+		"pali_text": "pali text",
+		"my_read": "recent",
 		"": ""
 	},
 	"grammastr": [

+ 3 - 0
public/app/public/lang/si.json

@@ -660,6 +660,9 @@
 		"pass": "pass.",
 		"space": "&nbsp;",
 		"channel_type": "channel type",
+		"community_new": "community new",
+		"pali_text": "pali text",
+		"my_read": "recent",
 		"": ""
 	},
 	"grammastr": [

+ 3 - 0
public/app/public/lang/zh-cn.json

@@ -658,6 +658,9 @@
 		"pass": "被动",
 		"space": "",
 		"channel_type": "资源类型",
+		"community_new": "社区动态",
+		"pali_text": "圣典原文",
+		"my_read": "我的阅读",
 		"": ""
 	},
 	"grammastr": [

+ 5 - 2
public/app/public/lang/zh-tw.json

@@ -612,9 +612,9 @@
 		"empty_null_mark": "這裡很安靜",
 		"lesson_intro": "看看世界各地的巴利專家都是如何解析聖典的",
 		"teaching_course": "主講的課程",
-		"watching_course": "關的課程",
+		"watching_course": "關的課程",
 		"searching_instruction": "查詞指南",
-		"dict_searching_placehold": "单词里面添加“+”可分别查看查询结果",
+		"dict_searching_placehold": "單詞裏麵添加“+”可分別查看查詢結果",
 		"copy_to": "複製到",
 		"add_tran": "新增譯文",
 		"no_updated": "無更新",
@@ -657,6 +657,9 @@
 		"pass": "被動",
 		"channel_type": "資源類型",
 		"space": "",
+		"community_new": "社區動態",
+		"pali_text": "聖典原文",
+		"my_read": "我的閱讀",
 		"": ""
 	},
 	"grammastr": [

+ 4 - 3
public/app/ucenter/function.php

@@ -1,5 +1,6 @@
 <?php
-require_once '../config.php';
+
+require_once __DIR__.'/../config.php';
 function ucenter_get($userid, $fields = "username")
 {
     //打开数据库
@@ -22,10 +23,10 @@ function ucenter_get($userid, $fields = "username")
 function ucenter_getA($userid, $fields = "nickname")
 {
     //打开数据库
-    $dns = "" . _FILE_DB_USERINFO_;
+    $dns = _FILE_DB_USERINFO_;
     $dbh = new PDO($dns, "", "", array(PDO::ATTR_PERSISTENT => true));
     $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
-    $query = "select username,nickname from user where userid= ? ";
+    $query = "SELECT username,nickname FROM user WHERE userid= ? ";
     $stmt = $dbh->prepare($query);
     $stmt->execute(array($userid));
     $fUser = $stmt->fetchAll(PDO::FETCH_ASSOC);

+ 8 - 0
public/app/widget/like.css

@@ -12,4 +12,12 @@
 
 like{
     display: inline-block;
+}
+
+span.number {
+    border: 1px solid gray;
+    padding: 0px 5px;
+    border-radius: 99px;
+    margin-left: 5px;
+    font-size: 90%;
 }

+ 73 - 34
public/app/widget/like.js

@@ -1,21 +1,26 @@
 var arrElement = new Array();
-function Like (){
+function Like(){
 	$("like").each(function(){
 		if($(this).attr("init")!="true"){
-			arrElement.push({
+            let likeItem = {
 							like_type:$(this).attr("liketype"),
 							resource_type:$(this).attr("restype"),
 							resource_id:$(this).attr("resid"),
-							like:0,
-							me:0,
+							like:$(this).attr("count"),
+							me:$(this).attr("mine"),
 							init:false
-						});
+						};
+			arrElement.push(likeItem);
 		}
 	});
 	$("like").on("click",function(){
 			let liketype = $(this).attr("liketype");
 			let rettype = $(this).attr("restype");
 			let resid = $(this).attr("resid");		
+			let readonly = $(this).attr("readonly");
+            if(readonly=='true'){
+                return;
+            }
 		let e = arrElement.find(function(item){
 
 			if(liketype===item.like_type && rettype===item.resource_type && resid===item.resource_id){
@@ -25,42 +30,73 @@ function Like (){
 				return false;
 			}
 		});
-		if(e.me==0 ){
-			add(e.like_type,e.resource_type,e.resource_id);				
+		if(e.me){
+            remove(e.me,e.like_type,e.resource_id);
 		}else{
-			remove(e.like_type,e.resource_type,e.resource_id);	
+			add(e.like_type,e.resource_type,e.resource_id);	
 		}
 	})
-	LikeRefreshAll();
+	Render();
 }
 function add(liketype,restype,resid) {
-	$.ajaxSetup({contentType: "application/json; charset=utf-8"});
-	$.post(
-		"../api/like.php?_method=create",
-		JSON.stringify({
-			like_type:liketype,
-			resource_type:restype,
-			resource_id:resid
-		})
-		
-	).done(function (data) {
-		console.log(data);
-		let result = JSON.parse(data);
-		if(result.ok==true){
+    fetch('/api/v2/like',{
+        method: 'POST',
+        credentials: 'include',
+        headers: {
+            'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({
+            type:liketype,
+            target_type:restype,
+			target_id:resid
+        })
+    })
+  .then(response => response.json())
+  .then(function(data){
+      console.log(data);
+		let result = data.data;
+		if(data.ok==true){
 			for (let it of arrElement) {
-				if(result["data"].resource_type===it.resource_type &&
-				result["data"].resource_id===it.resource_id &&
-				result["data"].like_type===it.like_type){
+				if(result.type===it.like_type &&
+				result.target_id===it.resource_id){
 					it.like++;
-					it.me=1;
+					it.me=result.id;
 				}
 			}
 			Render();
 		}
-		
-	});
+  });
+
 }
-function remove(liketype,restype,resid) {
+function remove(id,liketype,resid) {
+        fetch('/api/v2/like',{
+        method: 'DELETE',
+        credentials: 'include',
+        headers: {
+            'Content-Type': 'application/json'
+        },
+        body: JSON.stringify({
+            id:id,
+            type:liketype,
+			target_id:resid
+        })
+    })
+  .then(response => response.json())
+  .then(function(data){
+      console.log(data);
+		let result = data.data;
+		if(data.ok==true){
+			for (let it of arrElement) {
+				if(liketype===it.like_type &&
+				   resid===it.resource_id){
+					it.like = result.count;
+					it.me=false;
+				}
+			}
+			Render();
+		}
+  });
+/*
 	$.getJSON(
 		"../api/like.php",
 		{
@@ -98,6 +134,7 @@ function remove(liketype,restype,resid) {
 		}
 		
 	});
+    */
 }
 function LikeRefresh(data){
 	$.ajaxSetup({contentType: "application/json; charset=utf-8"});
@@ -138,21 +175,23 @@ function Render(){
 		let likeIcon="";
 		switch (it.like_type) {
 			case "like":
-				likeIcon = "👍";
+				likeIcon = "👍Like";
 				break;
 			case "favorite":
-				likeIcon = "⭐";
+				likeIcon = "⭐Favorite";
 				break;
 			case "watch":
-				likeIcon = "👁️";
+				likeIcon = "👁️Watch";
 				break;
 			default:
 				break;
 		}
-		if(it.me>0){
+		if(it.me){
 			meClass = " like_mine";
 		}
-		html +="<div class='like_inner "+meClass+"'>"+likeIcon+it.like+"</div>";
+		html +="<div class='like_inner "+meClass+"'>"+likeIcon;
+        html +="<span class='number'>"+it.like+"<span>";
+        html +="</div>";
 
 		$("like[liketype='"+it.like_type+"'][restype='"+it.resource_type+"'][resid='"+it.resource_id+"']").html(html);
 	}

+ 0 - 0
public/app/widget/submenu.css


+ 31 - 0
public/app/widget/submenu.js

@@ -0,0 +1,31 @@
+function submenu_init(obj,param){
+    let html = "";
+    <div class="submenu" >
+		<p class="submenu_title" onclick="submenu_show_detail(this)">
+			样式
+            <svg class="icon" style="transform: rotate(0deg);">
+				<use xlink:href="../studio/svg/icon.svg#ic_add"></use>
+			</svg>
+		</p>
+		<div class="submenu_details hidden" style="max-height: 0px; padding: 0px; opacity: 0;">
+
+		</div>
+	</div>
+}
+
+function submenu_show_detail(obj) {
+	eParent = obj.parentNode;
+	var x = eParent.getElementsByTagName("div");
+	var o = obj.getElementsByTagName("svg");
+	if (x[0].style.maxHeight == "200em") {
+		x[0].style.maxHeight = "0px";
+		x[0].style.padding = "0px";
+		x[0].style.opacity = "0";
+		o[0].style.transform = "rotate(0deg)";
+	} else {
+		x[0].style.maxHeight = "200em";
+		x[0].style.padding = "10px";
+		x[0].style.opacity = "1";
+		o[0].style.transform = "rotate(45deg)";
+	}
+}

+ 88 - 0
public/documents/模版设计.md

@@ -0,0 +1,88 @@
+# 文章内模版设计方案
+
+## 需求
+
+在用户编辑的markdown文档内嵌入自定义模版。支持术语显示,注释,文章引用,声明等可重用内容。
+
+markdown 文档内容:
+```
+# 标题
+
+{{term|citta}}
+{{term|word=citta}}
+
+```
+
+## 解决方案
+
+使用 https://mustache.github.io/ 。由于mustache不支持自定义函数。所以绕道,用mustache 的 helper 拿到用户输入的参数后再次用mustache进行渲染。
+
+https://github.com/bobthecow/mustache.php/wiki#helpers
+
+# 第一步
+
+用户输入的markdown 文本。
+用正则替换
+```
+搜索
+\{\{(.+?)\}\}
+替换为
+\n{{#function}}\n$1\n{{/function}}\n
+```
+```
+{{term|citta}}
+就变成
+{{#function}}
+term|citta
+{{/function}}
+```
+
+# 第二步 准备模版文件
+这个其实是放数据库里的
+
+term.tpl
+```
+<term word='{{word}}'>
+<span class='word'>{{word}}</span>
+(<span class='meaning'>{{meaning}}</span>)
+</term>
+```
+
+# 第三步 解析{{#function}} 
+
+用helper 解析{{#function}} 里面的内容。拿到模版名称和参数。并再次用Mustache 和对应的**模版文件**以及**参数**渲染html字符串
+需要预处理,得到这个文章里面用的模版名称(函数名)列表。
+
+```
+$tpl-list=["term"=>"term.tpl的内容"];
+$m = new Mustache_Engine(array('entity_flags' => ENT_QUOTES));
+$m->render($tpl, array(
+  'function' => function($text) use($m,$tpl-list) {
+    1: 使用url函数解析path
+    $param = explode("|",$text);
+    3: 处理业务逻辑
+    switch([param[0]){
+        case 'term':
+            //获取实际的参数
+            $tplParam = Term::where("word",param[1])->first();
+        case 'article':
+            $tplParam = Article::where("uid",param[1])->first();
+        default:
+            $tplParam['p1'] = param[1];
+        break;
+    }
+    4: 返回拼好的字符串
+    $html = $m->render($tpl-list[param[0]], $tplParam)
+    return $html;
+  }
+)); 
+```
+
+## 模版
+
+{{inlinenote|note content}}
+
+{{q|sn.a. 2|3|2}}
+{{q|137|45}}
+
+{{article|122342234324}}

+ 1 - 1
public/pali_title/139_pali.csv

@@ -923,7 +923,7 @@ NULL,p139,921,100,gatha1,,"Ciraṃ tiṭṭhatu saddhammo, kāle vassaṃ cira
 NULL,p139,922,100,gathalast,,"Tappetu devo dhammena, rājā rakkhatu medaninti."
 NULL,p139,923,100,centered,,"Mahāvibhaṅgo niṭṭhito."
 NULL,p139,924,100,centered,," Namo tassa bhagavato arahato sammāsambuddhassa"
-NULL,p139,925,2,book,Bhikkhunīvibhaṅgavaṇṇanā,Bhikkhunīvibhaṅgavaṇṇanā
+NULL,p139,925,1,book,Bhikkhunīvibhaṅgavaṇṇanā,Bhikkhunīvibhaṅgavaṇṇanā
 NULL,p139,926,2,chapter,"1. Pārājikakaṇḍaṃ (bhikkhunīvibhaṅgavaṇṇanā)","1. Pārājikakaṇḍaṃ (bhikkhunīvibhaṅgavaṇṇanā)"
 NULL,p139,927,100,gatha1,,"Yo  bhikkhūnaṃ vibhaṅgassa, saṅgahito anantaraṃ;"
 NULL,p139,928,100,gathalast,,"Bhikkhunīnaṃ vibhaṅgassa, tassa saṃvaṇṇanākkamo."

Разница между файлами не показана из-за своего большого размера
+ 494 - 494
public/pali_title/pali_text_tag.csv


+ 10 - 0
routes/api.php

@@ -9,6 +9,10 @@ use App\Http\Controllers\ProgressChapterController;
 use App\Http\Controllers\SentenceInfoController;
 use App\Http\Controllers\SentPrController;
 use App\Http\Controllers\TagController;
+use App\Http\Controllers\ViewController;
+use App\Http\Controllers\LikeController;
+use App\Http\Controllers\SentHistoryController;
+use App\Http\Controllers\PaliTextController;
 
 
 /*
@@ -33,5 +37,11 @@ Route::group(['prefix' => 'v2'],function(){
 	Route::apiResource('sentpr',SentPrController::class);
 	Route::apiResource('progress',ProgressChapterController::class);
 	Route::apiResource('tag',TagController::class);
+	Route::apiResource('view',ViewController::class);
+
+    Route::delete('like', [LikeController::class, 'delete']);
+    Route::apiResource('like',LikeController::class);
+    Route::apiResource('sent_history',SentHistoryController::class);
+    Route::apiResource('palitext',PaliTextController::class);
 
 });

+ 152 - 0
v1/scripts/migrations/20220529172100_like_copy.php

@@ -0,0 +1,152 @@
+<?php
+/*
+迁移  article 库
+从旧数据表中提取数据插入到新的表
+插入时用uuid判断是否曾经插入
+曾经插入就不插入了
+*/
+require_once __DIR__."/../../../public/app/config.php";
+
+set_exception_handler(function($e){
+	fwrite(STDERR,"error-msg:".$e->getMessage().PHP_EOL);
+	fwrite(STDERR,"error-file:".$e->getFile().PHP_EOL);
+	fwrite(STDERR,"error-line:".$e->getLine().PHP_EOL);
+	exit;
+});
+$start = time();
+
+$fpError = fopen(__DIR__.'/log/'.basename($_SERVER['PHP_SELF'],'.php').".err.data.csv",'w');
+
+#user info
+$user_db=_FILE_DB_USERINFO_;#user数据库
+$user_table=_TABLE_USER_INFO_;#user表名
+
+# 
+$src_db = _SQLITE_DB_LIKE_;#源数据库
+$src_table = _SQLITE_TABLE_LIKE_;#源表名
+
+$dest_db = _PG_DB_LIKE_;#目标数据库
+$dest_table = _PG_TABLE_LIKE_;#目标表名
+
+fwrite(STDOUT,"migarate like".PHP_EOL);
+#打开user数据库
+$PDO_USER = new PDO($user_db,_DB_USERNAME_,_DB_PASSWORD_,array(PDO::ATTR_PERSISTENT=>true));
+$PDO_USER->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+fwrite(STDOUT,"open user table".PHP_EOL);
+
+#打开源数据库
+$PDO_SRC = new PDO($src_db,_DB_USERNAME_,_DB_PASSWORD_,array(PDO::ATTR_PERSISTENT=>true));
+$PDO_SRC->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+fwrite(STDOUT,"open src table".PHP_EOL);
+
+#打开目标数据库
+$PDO_DEST = new PDO($dest_db,_DB_USERNAME_,_DB_PASSWORD_,array(PDO::ATTR_PERSISTENT=>true));
+$PDO_DEST->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+fwrite(STDOUT,"open dest table".PHP_EOL);
+
+$queryInsert = "INSERT INTO ".$dest_table." 
+								(
+                                    type,
+                                    target_id,
+                                    target_type,
+                                    user_id,
+									updated_at,
+									created_at)
+									VALUES (? , ? , ? , ? , ?, ? )";
+$stmtDEST = $PDO_DEST->prepare($queryInsert);
+
+$commitData = [];
+$allInsertCount = 0;
+$allSrcCount = 0;
+$count = 0;
+
+#从user数据表中读取
+$query = "SELECT id,userid  FROM ".$user_table." WHERE userid = ? ";
+$stmtUser = $PDO_USER->prepare($query);
+
+#从源数据表中读取
+$query = "SELECT *  FROM ".$src_table;
+$stmtSrc = $PDO_SRC->prepare($query);
+$stmtSrc->execute();
+while($srcData = $stmtSrc->fetch(PDO::FETCH_ASSOC)){
+	$allSrcCount++;
+
+    if($srcData["user_id"]=='visuddhinanda'){
+		$srcData["user_id"] = 'ba5463f3-72d1-4410-858e-eadd10884713';
+	}
+    if($srcData["user_id"]=='test7'){
+		$srcData["user_id"] = '6bd2f4d7-d970-419c-8ee5-f4bac42f4bc1';
+	}
+    if($srcData["user_id"]=='Dhammadassi'){
+		$srcData["user_id"] = 'd8538ebd-d369-4777-b99a-3ccb1aff8bfc';
+	}
+    if($srcData["user_id"]=='pannava'){
+		$srcData["user_id"] = '4db550c4-bc1b-43f2-a518-2740cb478f37';
+	}
+    if($srcData["user_id"]=='NST'){
+		$srcData["user_id"] = '5c23e629-56a3-48e9-97c7-2af73b59c3b9';
+	}
+    if($srcData["user_id"]=='viranyani'){
+		$srcData["user_id"] = 'C1AB2ABF-EAA8-4EEF-B4D9-3854321852B4';
+	}
+    if($srcData["user_id"]=='test6'){
+		$srcData["user_id"] = 'f81c7140-64b4-4025-b58c-45a3b386324a';
+	}
+	if($srcData["user_id"]=='test28'){
+		$srcData["user_id"] = 'df0ad9bc-c0cd-4cd9-af05-e43d23ed57f0';
+	}
+	if($srcData["user_id"]=='290fd808-2f46-4b8c-b300-0367badd67ed'){
+		$srcData["user_id"] = 'f81c7140-64b4-4025-b58c-45a3b386324a';
+	}
+	if($srcData["user_id"]=='BA837178-9ABD-4DD4-96A0-D2C21B756DC4'){
+		$srcData["user_id"] = 'ba5463f3-72d1-4410-858e-eadd10884713';
+	}
+	$stmtUser->execute(array($srcData["user_id"]));
+	$userId = $stmtUser->fetch(PDO::FETCH_ASSOC);
+	if(!$userId){
+		fwrite(STDERR,time()."error,no user id {$srcData["owner"]}".PHP_EOL);
+		continue;
+	}
+	if(strlen($srcData["user_id"])>36){
+		fwrite(STDERR,time().",error,user id too long {$srcData["user_id"]}".PHP_EOL);
+		continue;	
+	}
+
+	//查询是否已经插入
+	$queryExsit = "SELECT id  FROM ".$dest_table." WHERE type = ? and target_id = ? and user_id = ? ";
+	$getExist = $PDO_DEST->prepare($queryExsit);
+	$getExist->execute(array($srcData["like_type"],$srcData["resource_id"],$srcData["user_id"]));
+	$exist = $getExist->fetch(PDO::FETCH_ASSOC);
+	if($exist){
+		continue;
+	}
+	#插入目标表
+	$commitData = array(
+			$srcData["like_type"],
+			$srcData["resource_id"],
+			$srcData["resource_type"],
+			$srcData["user_id"],
+			$srcData["created_at"],
+			$srcData["created_at"]
+		);
+	$stmtDEST->execute($commitData);
+
+	$count++;	
+	$allInsertCount++;
+
+
+	if($count ==10000){
+		#10000行输出log 一次
+		echo "finished $count".PHP_EOL;
+		$count=0;
+	}	
+}
+
+fwrite(STDOUT,"insert done $allInsertCount in $allSrcCount ".PHP_EOL) ;
+fwrite(STDOUT, "all done in ".(time()-$start)."s".PHP_EOL);
+
+fclose($fpError);
+
+
+
+

Некоторые файлы не были показаны из-за большого количества измененных файлов