ソースを参照

Merge pull request #869 from visuddhinanda/chanpter_progress

Chanpter progress 基本完成
visuddhinanda 3 年 前
コミット
85843696fc
37 ファイル変更3413 行追加1030 行削除
  1. 159 0
      app/Console/Commands/UpgradeChapterDynamic.php
  2. 6 1
      app/Console/Commands/UpgradePaliTextTag.php
  3. 16 0
      app/Console/Commands/UpgradeProgressChapter.php
  4. 126 0
      app/Http/Controllers/LikeController.php
  5. 176 0
      app/Http/Controllers/PaliTextController.php
  6. 104 4
      app/Http/Controllers/ProgressChapterController.php
  7. 95 0
      app/Http/Controllers/SentHistoryController.php
  8. 175 0
      app/Http/Controllers/ViewController.php
  9. 15 0
      app/Models/Like.php
  10. 8 0
      app/Models/ProgressChapter.php
  11. 5 0
      app/Models/TagMap.php
  12. 11 0
      app/Models/UserExperience.php
  13. 18 0
      app/Models/View.php
  14. 35 0
      database/migrations/2022_05_27_072344_create_views_table.php
  15. 36 0
      database/migrations/2022_05_28_120007_add_summary_in_progress_chapters.php
  16. 46 0
      database/migrations/2022_05_29_103822_create_likes_table.php
  17. 39 0
      database/migrations/2022_06_03_021251_create_user_experiences_table.php
  18. 24 1
      public/app/article/article.js
  19. 10 1
      public/app/article/index.php
  20. 2 2
      public/app/config.table.php
  21. 324 24
      public/app/palicanon/category/cscd.json
  22. 92 0
      public/app/palicanon/chapter_channel.js
  23. 195 46
      public/app/palicanon/index1.php
  24. 55 0
      public/app/palicanon/loading.css
  25. 538 181
      public/app/palicanon/palicanon.js
  26. 45 0
      public/app/palicanon/router.js
  27. 49 17
      public/app/palicanon/style.css
  28. 31 0
      public/app/palicanon/test.js
  29. 221 221
      public/app/public/book_tag/en.json
  30. 4 3
      public/app/ucenter/function.php
  31. 8 0
      public/app/widget/like.css
  32. 73 34
      public/app/widget/like.js
  33. 15 0
      public/documents/模版设计.md
  34. 1 1
      public/pali_title/139_pali.csv
  35. 494 494
      public/pali_title/pali_text_tag.csv
  36. 10 0
      routes/api.php
  37. 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 {--one}';
+
+    /**
+     * 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('one')){
+                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('one')){
+                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('one')){
+                break; //调试代码
+            }
+        }
+        $bar->finish();
+
+        return 0;
+    }
+}

+ 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 - 0
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)
@@ -137,6 +152,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();

+ 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)
+    {
+        //
+    }
+}

+ 104 - 4
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
@@ -135,6 +159,9 @@ 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方法名  闭包内是子查询
@@ -146,6 +173,44 @@ class ProgressChapterController extends Controller
                                             ->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,10 +236,17 @@ class ProgressChapterController extends Controller
                     $where1 = " ";
                     $in1 = " ";
                 }
+                if(Str::isUuid($channel_id)){
+                    $channel = "and channel_id = '{$channel_id}' "; 
+                }else{
+                    $channel = "";
+                }
+
                 $param[] = $minProgress;
+                $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.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 (
@@ -188,7 +260,8 @@ class ProgressChapterController extends Controller
                                 $where1 
                         ) CID 
                         left join $pc as pc on CID.cid = pc.uid 
-                        where pc.progress > ?
+                        where pc.progress > ? 
+                        $channel
                         order by created_at desc
                         limit 20 offset ?
                     ) tpc 
@@ -196,10 +269,37 @@ class ProgressChapterController extends Controller
                 $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 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
+                ";
+                $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)
+    {
+        //
+    }
+}

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

@@ -0,0 +1,175 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\View;
+use App\Models\ProgressChapter;
+use Illuminate\Http\Request;
+use Illuminate\Support\Str;
+
+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"];
+                $items =  View::where("user_id",$user_id)
+                ->orderBy('created_at','desc')
+                ->take(10)->get();
+                foreach ($items as $key => $item) {
+                    # 根据不同的资源类型查找标题
+                    switch ($item->target_type) {
+                        case 'chapter':
+                            # code...
+                            $items[$key]['title'] = ProgressChapter::where('uid',$item->target_id)
+                                                    ->value('title');
+                            break;
+                        default:
+                            # code...
+                            $items[$key]['title'] = "unknow";
+                            break;
+                    }
+                    
+                }
+                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'])){
+            //已经登陆
+            $user_id = $_COOKIE['user_uid'];
+            $param['user_id'] = $user_id;
+        }else{
+            $param['user_ip'] = $clientIp;
+        }
+        $new = View::firstOrNew($param);
+        $new->user_ip = $clientIp;
+        $new->save();
+        $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');
+    }
+}

+ 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: 'include',
+        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")){

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

@@ -12,6 +12,7 @@ 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>
 
 	<script src="../widget/click_dropdown.js"></script>
 	<link type="text/css" rel="stylesheet" href="../widget/click_dropdown.css"/>
@@ -476,7 +477,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_);

+ 324 - 24
public/app/palicanon/category/cscd.json

@@ -205,23 +205,23 @@
                 "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"]
                     }
                 ]
             },
@@ -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ā"]
+                    }
+                ]
             }
         ]
     }

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

@@ -0,0 +1,92 @@
+//获取章节的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;
+        $(param.target).html(render_chapter_progress_list(arrChannelList,param));
+        Like();
+    }
+    );
+}
+
+//章节已经有译文的channel 列表
+function render_chapter_progress_list(chapterList,param) {
+	let html = "";
+    html += "<ul>";
+	for (const iterator of chapterList) {
+        if(iterator.channel){
+            if(param.showchannel){
+                if(!param.showchannel.includes(iterator.channel.uid)){
+                    continue;
+                }
+            }
+            html += "<li>";
+            html += "<span>";
+            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>";
+            html += iterator.progress;
+            html += "</span>";
+            html += "<span>";
+            html += iterator.views;
+            html += "</span>";
+            html += "<span class='likes'>";
+            html += renderChannelLikes(iterator.likes,'progress_chapter',iterator.uid);
+            html += "</span>";
+            html += "<span title='"+iterator.updated_at+"'>";
+            html += getPassDataTime(new Date(iterator.updated_at));
+            html += "</span>";
+            html += "</li>";            
+        }
+	}
+    html += "</ul>";
+
+	return html;
+}
+
+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;
+}

+ 195 - 46
public/app/palicanon/index1.php

@@ -29,26 +29,28 @@ 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>
 
+	<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>
+
 <style>
 .chapter_list ul {
     margin-left: 0;
 }
 .head_bar{
-    display:flex;
-    max-width: 30vh;
+    display: flex;
+    flex-direction: column;
 }
 #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{
+
+.chapter_list ul li .main{
     display:flex;
 }
 .book_view  ul li{
@@ -77,10 +79,22 @@ require_once '../public/function.php';
     max-height: unset;
     overflow-y: unset; 
 }
-.chapter_list .more_info {
-    display: block;
+
+.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;
@@ -117,9 +131,88 @@ require_once '../public/function.php';
     color: unset;
     border-color: var(--link-hover-color);
 }
-select#tag_category_index option {
+.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;
+}
+
 </style>
 
 <?php
@@ -133,43 +226,71 @@ select#tag_category_index option {
 <div style="display:flex;">
     <div id='left-bar' >
         <div id='left-bar-inner'>
+            <div class="filter submenu">
+                <div class="title submenu_title">设定</div>
+                <div class='inner' id='filter-setting' >
+                    <div class='settting-item'>
+                        <span>内容类型</span>
+                        <span>
+                            <select>
+                                <option value=''>全部</option>
+                                <option value='translation'>译文</option>
+                                <option value='nissaya'>Nissaya</option>
+                                <option value='commentray'>注疏</option>
+                            </select>
+                        </span>
+                    </div>
+                    <div class='settting-item'>
+                        <span>完成度阈值</span>
+                        <span>
+                            <select>
+                                <option value='0.9'>90</option>
+                                <option value='0.8'>80</option>
+                                <option value='0.7'>70</option>
+                            </select>
+                        </span>
+                    </div>
+                    <div class='settting-item'>
+                        <span>语言</span>
+                        <span>
+                            <select>
+                                <option value=''>全部</option>
+                                <option value='zh'>中文</option>
+                                <option value='en'>英文</option>
+                            </select>
+                        </span>
+                    </div>
+                    <div><button>还原默认</button><button>应用</button></div>
+                </div>
+            </div>
             <div class="filter submenu">
                 <div class="title submenu_title" style="flex;">
                     <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='inner' id='filter-author' >
-                
-                </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 class='inner' id='filter-lang' ></div>
             </div>
             <div class="filter submenu">
                 <div class="title submenu_title">类型</div>
-                <div class='inner' id='filter-type' >
-                
-                </div>
+                <div class='inner' id='filter-type' ></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' style='flex:6;padding:0 10px 10px 10px;'>
         <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,15 +315,31 @@ select#tag_category_index option {
             </div>
 
             <div id="select_bar" >
+                <div id="channel_selected"></div>
                 <div id="tag_selected"></div>
-                <div>
-                    <button onclick="tag_list_slide_toggle(this)">
-                        ⮝
+            </div>
+
+            <div id='bread-crumbs'></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 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;'>
+                            <input id="tag_input" type="input" placeholder="tag search" size="20">
+                        </div>
+                        <div>
+                            <button id="btn-tag_list_close" onclick='close_tag_list()'>X</button>
+                        </div>
+                    </div>
                     <div level="0" class="tag_others"></div>
                     <div level="1" class="tag_others"></div>
                     <div level="2" class="tag_others"></div>
@@ -213,7 +350,6 @@ select#tag_category_index option {
                     <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">
@@ -262,16 +398,14 @@ select#tag_category_index option {
         </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 id="page_loader" class="lds-ellipsis" style="visibility: hidden;"><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,15 +413,15 @@ 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>
@@ -311,14 +445,24 @@ select#tag_category_index option {
             <?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 +470,13 @@ 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);
+  }
+}

+ 538 - 181
public/app/palicanon/palicanon.js

@@ -6,6 +6,12 @@ var allTags = new Array();
 var arrMyTerm = new Array();
 var _listView="list";
 var gBreadCrumbs=['','','','','','','','',''];
+var _nextPageStart = 0;
+var _pageSize = 20;
+var _channel = "";
+var _lang = "";
+var _tags = "";
+var _channelList;
 
 palicanon_load_term();
 
@@ -16,14 +22,14 @@ function community_onload() {
 		main_tag = $(this).attr("tag");
 		list_tag = new Array();
 		tag_changed();
-		render_tag_list();
+		render_selected_filter_list();
 	});
 
 	$("#tag_input").keypress(function () {
 		tag_render_others();
 	});
     render_main_tag();
-    render_tag_list();
+    render_selected_filter_list();
     communityGetChapter();
     LoadAllChannel();
     LoadAllLanguage();
@@ -36,7 +42,7 @@ function palicanon_onload() {
 		main_tag = $(this).attr("tag");
 		list_tag = new Array();
 		tag_changed();
-		render_tag_list();
+		render_selected_filter_list();
 	});
 
 	$("#tag_input").keypress(function () {
@@ -83,13 +89,15 @@ function render_main_tag() {
 		});
 }
 function tag_changed() {
+    _nextPageStart= 0;
 	let strTags = "";
 	if (list_tag.length > 0) {
-		strTags = main_tag + "," + list_tag.join();
+		_tags =  list_tag.join();
 	} else {
-		strTags = main_tag;
+		_tags = "";
 	}
-	console.log(strTags);
+
+	console.log(_tags);
 	let lang = getCookie("language");
     switch (lang) {
         case 'zh-cn':
@@ -104,27 +112,64 @@ function tag_changed() {
     }
     switch (_view) {
         case "community":
-            communityGetChapter(strTags,lang)
+            communityGetChapter()
             break;
         case "category":
-            palicanonGetChapter(strTags,lang)
+            palicanonGetChapter(_tags,lang)
             break;
         case "my":
             break;
         default:
             break;
     }
-    
+    gBreadCrumbs =['','','','','','','','',''];
+    RenderBreadCrumbs();
+    updataHistory();
 }
-function communityGetChapter(strTags="",lang="",offset=0){
+
+function updataHistory(){
+    let url = "?view="+_view;
+    if(_tags !== ""){
+        url += "&tag=" + _tags;
+    }
+    if(_channel !== ""){
+        url += "&channel=" + _channel;
+    }
+    history.pushState({view:_view,tag:_tags,channel:_channel}, 'title', url);
+}
+
+function communityGetChapter(offset=0){
+    let strTags = "";
+	if (list_tag.length > 0) {
+		strTags = main_tag + "," + list_tag.join();
+	} else {
+		strTags = main_tag;
+	}
+	console.log(strTags);
+	let lang = getCookie("language");
+    switch (lang) {
+        case 'zh-cn':
+            lang = 'zh-hans';
+            break;
+        case 'zh-tw':
+            lang = 'zh-hant';
+            break;    
+        case '':
+            lang = 'en';
+            break;
+    }
+    next_page_loader_show();
     $.getJSON(
 		"/api/v2/progress?view=chapter",
 		{
-			tags: strTags,
-			lang: lang,
+			tags: _tags,
+			lang: _lang,
+            channel: _channel,
             offset: offset
-		},
-		function (data, status) {
+		}
+	)
+    .done(function (data, status) {
+            $("#filter_bar_left").html(data.data.count+"个章节");
 			let arrChapterData = data.data.rows;
 			let arrChapterList = new Array();
 			let html = "";
@@ -141,19 +186,41 @@ function communityGetChapter(strTags="",lang="",offset=0){
                     trans_title:iterator.title,
                     channel_id:iterator.channel_id,
                     type:'article',
-                    channel_info:iterator.channel_info,
-                    path:JSON.parse(iterator.path)
+                    channel_info:iterator.channel,
+                    path:JSON.parse(iterator.path),
+                    views:iterator.views,
+                    likes:iterator.likes,
+                    tags:iterator.tags,
+                    summary:iterator.summary,
+                    created_at:iterator.created_at
                 });
             }
 			for (const iterator of arrChapterList) {
                 arrChapter.push(iterator);
 			}
 
-			palicanon_chapter_list_apply(0);
-			$("#list-1").html(render_chapter_list(arrChapter));
-            
-		}
-	);
+			
+            if(_nextPageStart==0){
+                palicanon_chapter_list_apply(0);
+                $("#list-1").html(render_chapter_list(arrChapter));
+            }else{
+                $("#list-1").append(render_chapter_list(arrChapter));
+            }
+            next_page_loader_hide();
+		})
+        .fail(function(jqXHR, textStatus, errorThrown){
+            switch (jqXHR.status) {
+                case 404:
+                    $("#list-1").html("未找到");
+                    next_page_loader_hide();
+                    break;
+                case 500:
+                    console.error('/api/v2/progress?view=chapter',textStatus);
+                    break;
+                default:
+                    break;
+            }
+        });
 
     communityLoadChapterTag(strTags,lang);
 }
@@ -164,6 +231,7 @@ function communityLoadChapterTag(strTags="",lang=""){
 		{
 			tags: strTags,
 			lang: lang,
+            channel:_channel
 		},
 		function (data, status) {
             let tagData = data.data.rows;
@@ -178,65 +246,89 @@ function communityLoadChapterTag(strTags="",lang=""){
 
         });
 }
-function palicanonGetChapter(strTags,lang){
-	$.get(
-		"./book_tag.php",
+
+function palitextGetChapter(strTags=""){
+    $.getJSON(
+		"/api/v2/palitext?view=chapter",
 		{
-			tag: strTags,
-			lang: lang,
-		},
-		function (data, status) {
-			let arrBookList = JSON.parse(data);
-			let html = "";
-			allTags = new Array();
+			tags: _tags
+		}
+	)
+    .done(function (data, status) {
+			let arrChapterData = data.data.rows;
+			let arrChapterList = new Array();
 			let arrChapter = new Array();
+            let lastParent = -1;
+            for (let index = 0; index < arrChapterData.length; index++) {
+                arrChapterData[index].children = new Array();
+            }
+			for (const it of arrChapterData) {
+                if(arrChapterList.length==0){
+                    arrChapterList.push(it);
+                    continue;
+                }
+                if(lastParent>=0){
+                    //判断是否为这个章节的子章节
+                    if(arrChapterList[lastParent].book==it.book && arrChapterList[lastParent].paragraph == it.parent){
+                        arrChapterList[lastParent].children.push(it)
+                    }else{
+                        arrChapterList.push(it);
+                        lastParent = -1;
+                    }
+                }else{
+                    //判断是否为最末尾章节的子章节
+                    if(arrChapterList[arrChapterList.length-1].book==it.book && arrChapterList[arrChapterList.length-1].paragraph == it.parent){
+                        lastParent = arrChapterList.length-1;
+                        arrChapterList[arrChapterList.length-1].children.push(it);
+                    }else{
+                        arrChapterList.push(it);
+                    }
+                }
+            }
 
-			for (const iterator of arrBookList) {
-				let tag0 = "";
-				let tags = iterator.tag.split("::");
-				let currTag = new Array();
-				currTag[main_tag] = 1;
-				for (const scondTag of list_tag) {
-					currTag[scondTag] = 1;
-				}
-				for (let tag of tags) {
-					if (tag.slice(0, 1) == ":") {
-						tag = tag.slice(1);
-					}
-					if (tag.slice(-1) == ":") {
-						tag = tag.slice(0, -1);
-					}
-					if (currTagLevel0.hasOwnProperty(tag)) {
-						tag0 = tag;
-					}
-					if (!currTag.hasOwnProperty(tag)) {
-						if (allTags.hasOwnProperty(tag)) {
-							allTags[tag] += 1;
-						} else {
-							allTags[tag] = 1;
-						}
-					}
-				}
+			palicanon_chapter_list_apply(0);
+			$("#list-1").html(render_chapter_list(arrChapterList));
+            
+		})
+    .fail(function(jqXHR, textStatus, errorThrown){
+            switch (jqXHR.status) {
+                case 404:
+                    $("#list-1").html("未找到");
+                    next_page_loader_hide();
+                    break;
+                case 500:
+                    console.error('/api/v2/progress?view=chapter',textStatus);
+                    break;
+                default:
+                    break;
+            }
+        });
 
-				if (arrBookList.length < 20 || (arrBookList.length > 20 && iterator.level == 1)) {
-					arrChapter.push(iterator);
-				}
-			}
+    palitextLoadChapterTag(strTags);
+}
 
-			let newTags = new Array();
-			for (const oneTag in allTags) {
-				if (allTags[oneTag] < arrBookList.length) {
-					newTags[oneTag] = allTags[oneTag];
-				}
-			}
-			allTags = newTags;
-			allTags.sort(sortNumber);
+function palitextLoadChapterTag(strTags=""){
+
+    $.getJSON(
+		"/api/v2/palitext?view=chapter-tag",
+		{
+			tags: strTags,
+		},
+		function (data, status) {
+            let tagData = data.data.rows;
+            allTags = new Array();
+            let maxCount = tagData[0].count;
+            for (const tag of tagData) {
+                if(tag.count < maxCount){
+                    allTags[tag.name] = tag.count;
+                }
+            }
 			tag_render_others();
-			palicanon_chapter_list_apply(0);
-			$("#list-1").html(render_chapter_list(arrChapter));
 
-		}
-	);
+        });
+}
+function palicanonGetChapter(strTags,lang){
+    palitextGetChapter(strTags);
 }
 function viewChanged(obj){
 
@@ -294,11 +386,17 @@ function palicanon_load_chapter(book, para, div_index = 1) {
 				},
 				function (data, status) {
 					let arrChapterList = JSON.parse(data);
-					$("#list-" + (parseInt(div_index) + 1)).html(render_chapter_list(arrChapterList));
-
-					//palicanon_chapter_list_apply(arrChapterList, div_index);
+                    $("#list-" + (parseInt(div_index) + 1)).html(render_chapter_list(arrChapterList));
+					
 				}
 			);
+
+            //获取章节的channel列表
+            loadChapterChannel({
+                book:book,
+                para:para,
+                target:$("#chapter_head_" + (parseInt(div_index) + 1)).find('.progress').first()
+            });
 		}
 	);
 }
@@ -350,7 +448,7 @@ function render_chapter_head(chapter_info, parent) {
 	html += "</div>";
 	html += "<div class='res res_more'>";
 	html += "<h2>译文</h2>";
-	html += "<div class='progress'>";
+	html += "<div class='progress' id='chapter_progress'>";
 	if (chapter_info.progress && chapter_info.progress.length > 0) {
 		let r = 12;
 		let perimeter = 2 * Math.PI * r;
@@ -389,20 +487,22 @@ function render_chapter_list(chapterList) {
 	return html;
 }
 
+function isChapterWithParent(list,item){
+
+}
+
 function palicanon_chapter_list_apply(div_index) {
 	let iDiv = parseInt(div_index);
 	let html = "";
 	html += "<div id='chapter_head_" + (iDiv + 1) + "' class='chapter_head'></div>";
 
 	html += "<ul id='list-" + (iDiv + 1) + "' class='grid' level='" + (iDiv + 1) + "'>";
-	/*	
-	for (const iterator of chapterList) {
-		html += palicanon_render_chapter_row(iterator);
-	}
-*/
 	html += "</ul>";
-	html += "<button>More</button>";
-
+    html += "<div id='more_chapter'>";
+    html += '<div id="page_loader" class="lds-ellipsis" style="visibility: hidden;"><div></div><div></div><div></div><div></div></div>';
+    html += "<div id='more_chapter_line'></div>";
+	html += "<button id='btn_more_chapter' onclick='next_page()'>More</button>";
+    html += "</div>";
 	$("#list_shell_" + (iDiv + 1)).html(html);
 	$("#list_shell_" + (iDiv + 1)).removeClass();
 	$("#list_shell_" + (iDiv + 1)).addClass("show");
@@ -423,57 +523,157 @@ function palicanon_chapter_list_apply(div_index) {
     updateFirstListView();
 }
 
+function next_page_loader_show(){
+    $("#page_loader").css("visibility","visible");
+}
+function next_page_loader_hide(){
+    $("#page_loader").css("visibility","hidden");
+}
+function next_page(){
+    _nextPageStart += _pageSize;
+    communityGetChapter(_nextPageStart);
+}
 function chapter_onclick(obj) {
-	let book = $(obj).attr("book");
-	let para = $(obj).attr("para");
-	let channel = $(obj).attr("channel");
-	let type = $(obj).attr("type");
-	let level =  parseInt($(obj).parent().attr("level"));
-    let title1 = $(obj).find(".title_1").first().text();
+    let objList = $(obj).parent().parent().parent().parent().parent();
+	let book = $(objList).attr("book");
+	let para = $(objList).attr("para");
+	let channel = $(objList).attr("channel");
+	let type = $(objList).attr("type");
+	let level =  parseInt($(objList).parent().attr("level"));
+    let title1 = $(objList).find(".title_1").first().text();
     if(type=='article'){
         window.open("../article/index.php?view=chapter&book="+book+"&par="+para+"&channel="+channel,);
     }else{
         gBreadCrumbs[level] = {title1:title1,book:book,para:para,level:level};
         RenderBreadCrumbs();
-        $(obj).siblings().removeClass("selected");
-        $(obj).addClass("selected");
+        $(objList).siblings().removeClass("selected");
+        $(objList).addClass("selected");
         $("#tag_list").slideUp();
         palicanon_load_chapter(book, para, level);
     }
 
 }
+function close_tag_list(){
+    $("#tag_list").slideUp();
+    $("#btn-filter").removeClass("active");
+
+}
+function renderProgress(progress=0,width=16,height=16){
+        //绘制进度圈
+    
 
+		let r = 12;
+		let perimeter = 2 * Math.PI * r;
+		let stroke1 = parseInt(perimeter * progress);
+		let stroke2 = perimeter - stroke1;
+        let html="";
+		html += '<svg class="progress_circle" width="16" height="16" viewbox="0,0,30,30">';
+		html += '<circle class="progress_bg" cx="15" cy="15" r="12" stroke-width="5"  fill="none"></circle>';
+		html +=
+			'<circle class="progress_color" cx="15" cy="15" r="12" stroke-width="5" fill="none"  stroke-dasharray="' +
+			stroke1 +
+			" " +
+			stroke2 +
+			'"></circle>';
+		html += "</svg>";
+    return html;
+    
+}
 function palicanon_render_chapter_row(chapter) {
 	let html = "";
 	let levelClass = "";
 	if (chapter.level == 1) {
 		//levelClass = " level_1";
 	}
-	html +='<li class="' + 	levelClass +'" book="' + chapter.book + '" para="' + chapter.para + '"';
+    let para=0;
+    if(chapter.para){
+        para=chapter.para;
+    }else if(chapter.paragraph){
+        para=chapter.paragraph;
+    }
+	html +='<li class="' + 	levelClass +'" book="' + chapter.book + '" para="' + para + '"';
     if(typeof chapter.type !== "undefined" && chapter.type==='article'){
         html += ' channel="' + chapter.channel_id + '" type="' + chapter.type + '"';
     }
-    html += ' onclick="chapter_onclick(this)">';
+    html += ' >';
     
-	html += '<div class="head_bar">';
+	html += '<div class="main">';
 
-    html += '<span class="" style="margin-right: 1em;padding: 4px 0;">';
-    html += "<svg class='icon' style='fill: var(--box-bg-color1)'>";
-    if(typeof chapter.type !== "undefined" && chapter.type==='article'){
-        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journal-text'>";
-    }else{
-        if (chapter.level == 1) {
-            html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journal'>";
+	html += '<div class="left">';
+
+    html += "<div class='left_items'>";
+
+
+
+    if(typeof chapter.views != "undefined"){
+        html += "<div class='left_item'>";        
+        html += "<span class='item'>";
+        html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
+        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#eye'>";
+        html += "</svg>" ;
+        html += "<span class='text'>";
+        html += chapter.views;
+        html += "</span>";
+        html += "</span>";
+        html += "</div>"
+    }
+
+    if(typeof chapter.likes != "undefined"){
+        html += "<div class='left_item'>";
+        html += "<span class='item'>";
+        html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
+        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#heart'>";
+        html += "</svg>" ;
+        html += "<span class='text'>";
+        html += chapter.likes;
+        html += "</span>";
+        html += "</span>";
+        html += "</div>"
+    }
+
+    //完成度
+    if(chapter.progress && chapter.progress.all_trans){
+        html += "<div class='left_item'>";
+        html += "<span class='item'>";
+        html += renderProgress(chapter.progress.all_trans);
+        html += "<span class='text'>";
+        if(chapter.progress){
+            html += parseInt(chapter.progress.all_trans*100+1)+"%";
         }else{
-            html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#folder2-open'>";
+            html += "";
         }
+        html += "</span>";
+        html += "</span>";
+        html += "</div>"
     }
 
-	html += "</svg>" ;
-	html += "</span>";   
 
-	html += '<div class="title">';
+    html += "<div class='left_item'></div>"
+    html += "</div>";//end of left_items
+
+    html += "<div class='chapter_icon'>";
+        html += '<span class="" style="margin-right: 1em;padding: 4px 0;">';
+        html += "<svg class='icon' style='fill: var(--box-bg-color1)'>";
+        if(typeof chapter.type !== "undefined" && chapter.type==='article'){
+            html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journal-text'>";
+        }else{
+            if (chapter.level == 1) {
+                html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journal'>";
+            }else{
+                html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#folder2-open'>";
+            }
+        }
+        html += "</svg>" ;
+        html += "</span>";
+    html += "</div>";
+	html += '</div>';//end of left
+
+	html += '<div class="right">';
+
+	html += '<div class="head_bar">';
 
+	html += '<div class="title" >';
+	html += '<div class="title_left" onclick="chapter_onclick(this)">';
     
     let sPaliTitle = chapter.title;
     if(chapter.title==""){
@@ -498,72 +698,127 @@ function palicanon_render_chapter_row(chapter) {
 		html += "	<div class='title_1'>" + chapter.trans_title + "</div>";
 	}
 
-	html += '	<div class="title_2" lang="pali">' + sPaliTitle + "</div>";
+	html += '<div class="title_2" lang="pali">' + sPaliTitle + "</div>";
+	html += '<div class="title_2" lang="pali">';
+//书名
+    if(chapter.path){
+        let arrPath=false;
+        if(Array.isArray(chapter.path)){
+            arrPath = chapter.path;
+        }else{
+            try{
+                arrPath = JSON.parse(chapter.path);
+            }catch(e){
+                console.error('json parse',chapter.path);
+            }
+        }
+        if(arrPath && arrPath.length>0){
+            html += "<span class='item'>";        
+            html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
+            html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journals'>";        
+            html += "</svg>" ;
+            html += arrPath[0].title;
+            html += "</span>";
+        }
+        
+    }
+    let chapterPara;
+    if(chapter.paragraph){
+
+    }
+    html +=  "</div>";
+	html += "</div>";
+	html += '<div class="title_right" >';
+    html += "<img class='chapter_dynamic_svg' src='/storage/images/chapter_dynamic/";
+    html += chapter.book + "/";
+    if(chapter.paragraph){
+        html += chapter.paragraph;
+    }else{
+        html += chapter.para;
+    }
+    if(chapter.channel_id){
+        html += "/ch_" + chapter.channel_id;
+    }else{
+        html += "/globle";
+    }
+    html += ".svg' />";
 	html += "</div>";
-	html += '<div class="resource">';
-    //绘制进度圈
-    /*
-	if (chapter.progress) {
-		let r = 12;
-		let perimeter = 2 * Math.PI * r;
-		let stroke1 = parseInt(perimeter * chapter.progress.all_trans);
-		let stroke2 = perimeter - stroke1;
-		html += '<svg class="progress_circle" width="30" height="30" viewbox="0,0,30,30">';
-		html += '<circle class="progress_bg" cx="15" cy="15" r="12" stroke-width="5"  fill="none"></circle>';
-		html +=
-			'<circle class="progress_color" cx="15" cy="15" r="12" stroke-width="5" fill="none"  stroke-dasharray="' +
-			stroke1 +
-			" " +
-			stroke2 +
-			'"></circle>';
-		html += "</svg>";
-	}
-    */
 	html += "</div>";
-	html += "</div>";//end of head bar
 
+	html += '<div class="resource">';
+    if(chapter.summary){
+        html += chapter.summary;
+    }
+
+	html += "</div>";
 
     html += '<div class="more_info">';
+    //最下面一栏,左侧的标签列表
+    html += "<div class='chapter_tag'>";
 
-    html += "<span class='item'>";
-    if(chapter.path){
-        html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
-        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#journals'>";        
-        html += "</svg>" ;
-        html += chapter.path[0].title;
-    }
-    html += "</span>"
-    
-	html += "<span class='item'>";
-    html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
-	html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#translate'>";
-	html += "</svg>" ;
-    if(chapter.progress){
-        html += parseInt(chapter.progress.all_trans*100+1)+"%";
-    }else{
-         html += "无";
+
+    if(chapter.tags){
+        html += renderChapterTags(chapter.tags);
     }
     
-    html += "</span>";
+    html += "</div>";
+    html += "<div class='palicanon_chapter_info'>"
 
-	html += "<span class='item'>";
-    html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
-	html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#person'>";
-	html += "</svg>" ;
     if(typeof chapter.type !== "undefined" && chapter.type==='article'){
+        html += "<span class='item channel'>";
+        html += "<svg class='small_icon' style='width:16px;height:16px;fill: var(--box-bg-color1)'>";
+        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#person-circle'>";
+        html += "</svg>" ;
+        html += "<span class='text' onclick=\"select_channel('"+chapter.channel_id+"')\">";
         html += chapter.channel_info.name;
-    }else{
-        html += "简体中文(3)";
+        html += "</span>";
+        html += "</span>";
     }
-    
-    html += "</span>";
 
 
+    if(chapter.created_at){
+        html += "<span class='item'>";
+        html += "<svg class='small_icon' style='width:16px;height:16px;fill: var(--box-bg-color1)'>";
+        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#clock'>";
+        html += "</svg>" ;
+        html += "<span class='text'>";
+        html += getPassDataTime(new Date(chapter.created_at));
+        html += "</span>";
+        html += "</span>";
+
+    }
+    if(chapter.children && chapter.children.length>0){
+        html += "<span class='item' onclick=\"subchapter_slideToggle(this)\">";
+        html += "<span class='text'>";
+        html += "展开折叠子章节 " + chapter.children.length;
+        html += "</span>";
+        html += "</span>";
+    }    
+    html += "</div>";
+    html += "</div>";        
+
+	html += "</div>";//end of head bar
 
+	html += "</div>";
+
+	html += "</div>";//end of main
+
+	html += "<div class='subchapter'>";
+    if(chapter.children){
+        html += "<ul class='subchapter_inner'>";
+        for (const subchapter of chapter.children) {
+            html +=palicanon_render_chapter_row(subchapter);
+        }
+        html += "</ul>";
+    }
 	html += "</div>";
 	html += "</li>";
 	return html;
 }
+
+function subchapter_slideToggle(obj){
+    $(obj).parent().parent().parent().parent().parent().siblings(".subchapter").slideToggle();
+}
 function tag_get_local_word(word) {
 	let termKey = term_lookup_my(word, "", getCookie("userid"), getCookie("language"));
 	if (typeof termKey == 'undefined' || termKey === false || termKey === '') {
@@ -623,45 +878,93 @@ function tag_render_others() {
 
 function tag_click(tag) {
 	list_tag.push(tag);
-	render_tag_list();
+	render_selected_filter_list();
 	tag_changed();
 }
 
 function tag_set(tag) {
-	list_tag = tag;
-	render_tag_list();
+    list_tag = new Array();
+    if(Array.isArray(tag)){
+        for (const iterator of tag) {
+            list_tag.push(iterator);
+        }
+    }else{
+        list_tag.push(tag);
+    }
+	_tags = list_tag.join();
+	render_selected_filter_list();
 	tag_changed();
 }
 
-function render_tag_list() {
-	$("#tag_list").slideDown();
+function renderChapterTags(tags){
+    let html = "";
+    for (const iterator of tags) {
+		html += '<tag onclick="tag_set(\''+iterator.name+'\')">';
+        html += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
+        html += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#tag'>";
+        html += "</svg>" 
+        html += '<span class="textt" title="' + iterator.name + '">' + tag_get_local_word(iterator.name) + "</span>";
+		//html += '<span class="tag-delete" onclick ="tag_remove(\'' + iterator + "')\">✕</span>";
+        html += "</tag>";
+	}
+    return html;
+}
+
+function render_selected_filter_list() {
+    refresh_selected_tag();
+    refresh_selected_channel();
+}
 
-	let strListTag="";// = gLocal.gui.selected + ":";
-    strListTag += "<svg class='icon' style='fill: var(--box-bg-color1)'>";
-    strListTag += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#filter'>";
-    strListTag += "</svg>" ;
+function refresh_selected_tag(){
+	let strListTag="";
 	for (const iterator of list_tag) {
-		strListTag += '<tag>';
-        strListTag += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
-        strListTag += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#tag'>";
-        strListTag += "</svg>" 
-        strListTag += '<span class="textt" title="' + iterator + '">' + tag_get_local_word(iterator) + "</span>";
-		strListTag += '<span class="tag-delete" onclick ="tag_remove(\'' + iterator + "')\">✕</span></tag>";
+        if(iterator!=''){
+            strListTag += '<tag>';
+            strListTag += "<svg class='small_icon' style='fill: var(--box-bg-color1)'>";
+            strListTag += "<use xlink:href='../../node_modules/bootstrap-icons/bootstrap-icons.svg#tag'>";
+            strListTag += "</svg>" 
+            strListTag += '<span class="textt" title="' + iterator + '">' + tag_get_local_word(iterator) + "</span>";
+            strListTag += '<span class="tag-delete" onclick ="tag_remove(\'' + iterator + "')\">✕</span></tag>";            
+        }
 	}
-	strListTag +=
-		"<div style='display:inline-block;width:20em;'>" +
-		"<input id='tag_input' type='input' placeholder='tag' size='20'  />" +
-		"</div>";
+	strListTag +="</div>";
 	$("#tag_selected").html(strListTag);
 }
+function refresh_selected_channel(){
+    let channels = _channel.split(",");
+	let html="";
+	for (const iterator of channels) {
+        if(_channelList){
+            let item = _channelList.find(element => element.channel_id == iterator);
+            if(item){
+                html += '<tag>';
+                html += '<span class="textt" title="">版本:' + item.channel.name + "</span>";
+                html += '<span class="tag-delete" onclick ="channel_tag_remove(\'' + item.channel_id + "')\">✕</span>";
+                html += "</tag>";
+            }            
+        }
+	}
+	html +="</div>";
+	$("#channel_selected").html(html);
+}
+function channel_tag_remove(channelId){
+    let channels = _channel.split(',');
+    if(channels.indexOf(channelId)>=0){
+        channels.splice(channels.indexOf(channelId),1);
+        _channel = channels.join();
+        refresh_selected_channel();
+        tag_changed();
+    }
+    
 
+}
 function tag_remove(tag) {
 	for (let i = 0; i < list_tag.length; i++) {
 		if (list_tag[i] == tag) {
 			list_tag.splice(i, 1);
 		}
 	}
-	render_tag_list();
+	render_selected_filter_list();
 	tag_changed();
 }
 
@@ -670,10 +973,10 @@ function sortNumber(a, b) {
 }
 
 function tag_list_slide_toggle(element) {
-	if ($(element).html().indexOf("⮟") != -1) {
-		$(element).html("⮝");
+	if ($("#tag_list").css("display") == 'none') {
+		$(element).addClass("active");
 	} else {
-		$(element).html("⮟");
+		$(element).removeClass("active");
 	}
 	$("#tag_list").slideToggle();
 }
@@ -707,12 +1010,10 @@ function loadTagCategory(name="defualt"){
             selectMode: 1, // 1:single, 2:multi, 3:multi-hier
             checkbox: false, // Show checkboxes.
             source: tocGetTagCategory(result),
-            click: function(e, data) {
-                    //tag_set([data.node.title]);
-                },
             activate: function(e, data) {
 //				alert("activate " + );
                 //currSelectNode = data.node;
+                console.log('tree',data);
                 tag_set(arrTagCategory[data.node.key]);
             },
             select: function(e, data) {
@@ -777,7 +1078,15 @@ function RenderBreadCrumbs(){
 
     $("#bread-crumbs").html(html);
 }
-
+function select_channel(id,obj=null){
+    _channel = id;
+    updataHistory();
+    communityGetChapter(0);
+    refresh_selected_channel();
+    console.log("change channel",_channel);
+    //$(obj).siblings.removeClass('active');
+    //$(obj).addClass('active');
+}
 function LoadAllChannel(){
     $.getJSON(
 		"/api/v2/progress?view=channel",
@@ -785,9 +1094,10 @@ function LoadAllChannel(){
 		function (data, status) {
             let html = "";
             html += "<ul>"
+            _channelList = data.data.rows;
             for (const iterator of data.data.rows) {
                 if(iterator.channel){
-                    html += "<li>"
+                    html += "<li onclick=\"select_channel('"+iterator.channel.uid+"',this)\">"
                     html += iterator.channel.name+"("+iterator.count+")";
                     html += "</li>"                    
                 }
@@ -795,6 +1105,7 @@ function LoadAllChannel(){
             }
             html += "</ul>";
             $("#filter-author").html(html);
+            refresh_selected_channel();
         }
     );
 }
@@ -835,4 +1146,50 @@ function ReanderMainMenu(){
     }
     html +="><a href='index1.php?view=my' >我的</a></span>";
     $("#main_menu").html(html);
+}
+
+function loadUserRecent(){
+    $.getJSON(
+        "/api/v2/view?view=user-recent", function() {
+            console.log( "success" );
+            }
+    )
+    .done(function(data) {
+        let html = "";
+        html += "<ol>";
+        for (const item of data.data) {
+            html += "<li>";
+            html += item.title;
+            html += "</li>";
+        }
+        html += "</ol>";
+        $("#user_recent").find('.list').first().html(html);
+    })
+    .fail(function() {
+        console.log( "error" );
+    });
+}
+
+function loadContribution(){
+    $.getJSON(
+        "/api/v2/sent_history?view=contribution", function() {
+            console.log( "success" );
+            }
+    )
+    .done(function(data) {
+        let html = "";
+        html += "<ol>";
+        for (const item of data.data) {
+            html += "<li>";
+            html += item.username.nickname;
+            html += "—";
+            html += item.count;
+            html += "</li>";
+        }
+        html += "</ol>";
+        $("#contribution").find('.list').first().html(html);
+    })
+    .fail(function() {
+        console.log( "error" );
+    });
 }

+ 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();

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

@@ -38,9 +38,11 @@ tag {
 	margin: 2px;
 	padding: 2px 12px;
 	border-radius: 5px;
-	border: 1px solid #fe897c;
+    cursor: pointer;
+}
+tag:hover{
+    background-color: var(--border-line-color);
 }
-
 .tag-delete {
 	margin-left: 6px;
 	color: #f93e3e;
@@ -116,9 +118,8 @@ tag {
 	display: none;
 }
 
-#select_bar {
-	display: flex;
-	justify-content: space-between;
+#select_bar>div {
+    display:inline-block;
 }
 
 .chapter_list {
@@ -154,50 +155,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 +314,17 @@ li.level_1.selected {
     height: unset;
     margin: unset;
     border: unset;
+}
+
+.chapter_dynamic_svg{
+    width:150px;
+}
+
+.bangdan li{
+    list-style-type:unset;
+    white-space: nowrap;
+}
+.bangdan ol{
+    padding-left: 1.5em;
+    width: 200px;
 }

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

@@ -0,0 +1,31 @@
+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 () {
+    
+});
+
+function go(){
+    location.assign('index.html?view=one');
+}

+ 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",

+ 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);
 	}

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

@@ -0,0 +1,15 @@
+{{sent|10|2|56|89}}
+
+function:sent
+param:book=1,para=2,start=3,end=4
+{
+    <note book="{{book}}" para='{{meaning}}' start='{{meaning2}}' end='{{end}}'></note>
+}
+
+{{term|dhamma}}
+
+function:term
+param:word
+{
+    <term word="{{word}}" ></term>
+}

+ 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);
+
+
+
+

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません