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

:sparkles: 段落动态更新图

visuddhinanda@gmail.com 3 лет назад
Родитель
Сommit
59c5955300

+ 139 - 45
app/Http/Controllers/SentenceInfoController.php

@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
 
 use App\Models\Sentence;
 use App\Models\PaliSentence;
+use App\Models\PaliText;
 
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Cache;
@@ -11,6 +12,8 @@ use Illuminate\Support\Facades\DB;
 
 class SentenceInfoController extends Controller
 {
+    protected $_endParagraph;
+    protected $_startParagraph;
     /**
      * Display a listing of the resource.
      *
@@ -45,42 +48,59 @@ class SentenceInfoController extends Controller
     private function getSentProgress(Request $request,$date=''){
         $channel = $request->get('channel');
         $from = $request->get('from');
-        $to = $request->get('to');
+        if ($request->has('to')){
+            $to = $request->get('to');
+        }else{
+            $to = $this->_endParagraph;
+        }
+
 
         #默认完成度显示字符数
         # strlen 
+        # palistrlen 巴利语等效字符数
         # page
         # percent 
         $view = 'strlen';
-        if(!empty($request->get('view'))){
+        if($request->has('view')){
             $view =$request->get('view');
-        }
-        if(!empty($request->get('type'))){
+        }else if($request->has('type')){
             $view =$request->get('type');
         }
+
+
         #一页书中的字符数
         $pageStrLen = 2000;
-        if(!empty($request->get('strlen'))){
+        if($request->has('strlen')){
             $pageStrLen =$request->get('strlen');
         }
-        if(!empty($request->get('pagelen'))){
-            $pageStrLen =$request->get('pagelen');
+        if($request->has('pagelen')){
+            $pageStrLen = $request->get('pagelen');
         }
 
         # 页数
         $pageNumber = 300;
-        if(!empty($request->get('pages'))){
+        if($request->has('pages')){
             $pageNumber =$request->get('pages');
         }
 
-        $db = Sentence::where('channel_uid',$request->get('channel'))
-                ->where('book_id','>=',$request->get('book'))
-                ->where('paragraph','>=',$request->get('from'))
-                ->where('paragraph','<=',$request->get('to'));
+        $db = Sentence::where('sentences.channel_uid',$request->get('channel'))
+                    ->where('sentences.book_id','>=',$request->get('book'))
+                    ->where('sentences.paragraph','>=',$request->get('from'))
+                    ->where('sentences.paragraph','<=',$to);
+        if($view==="palistrlen"){
+            $db = $db->leftJoin('pali_texts', function($join)
+                    {
+                        $join->on('sentences.book_id', '=', 'pali_texts.book');
+                        $join->on('sentences.paragraph','=','pali_texts.paragraph');
+                    });
+        }
         if(!empty($date)){
-            $db = $db->whereDate('created_at','=',$date);
+            $db = $db->whereDate('sentences.created_at','=',$date);
         }
-        $strlen =$db->sum('strlen');
+        if($view==="palistrlen"){
+            return $db->sum('pali_texts.lenght');
+        }
+        $strlen = $db->sum('sentences.strlen');
 
         if(is_null($strlen) || $strlen===0){
             return 0;
@@ -93,7 +113,7 @@ class SentenceInfoController extends Controller
                 ->where('channel_uid',$request->get('channel'))
                 ->where('book_id','>=',$request->get('book'))
                 ->where('paragraph','>=',$request->get('from'))
-                ->where('paragraph','<=',$request->get('to'));
+                ->where('paragraph','<=',$to);
             if(!empty($date)){
                 $db = $db->whereDate('created_at','=',$date);
             }
@@ -101,7 +121,7 @@ class SentenceInfoController extends Controller
             #查询这些句子的总共等效巴利语字符数
             $allStrLen = PaliSentence::where('book',$request->get('book'))
                             ->where('paragraph','>=',$request->get('from'))
-                            ->where('paragraph','<=',$request->get('to'))
+                            ->where('paragraph','<=',$to)
                             ->sum('length');            
             $para_strlen = 0;
             foreach ($sentFinished as $sent) {
@@ -120,7 +140,7 @@ class SentenceInfoController extends Controller
                                 ->where('paragraph',$sent->paragraph)
                                 ->where('word_begin',$sent->word_start)
                                 ->where('word_end',$sent->word_end)
-                                ->value('length');                    
+                                ->value('length');
                 }
             }
 
@@ -182,24 +202,26 @@ class SentenceInfoController extends Controller
         $imgWidth = 300;
         $imgHeight = 100;
         $xAxisOffset = 16;
-        $yAxisOffset = 16;
-        $maxDay = 10;
+        $yAxisOffset = 25;
+        $maxDay = 20;
         $maxPage = 20;
         $yLineSpace = 5;
 
+        $yMin = 20; //y轴满刻度数值 最小
+
         #默认完成度显示字符数
         # strlen 
         # page
         # percent 
         $view = 'strlen';
-        if(!empty($request->get('view'))){
+        if($request->has('view')){
             $view =$request->get('view');
         }
-        if(!empty($request->get('type'))){
+        if($request->has('type')){
             $view =$request->get('type');
         }
 
-
+        
 
         $pagePix = ($imgHeight-$xAxisOffset)/$maxPage;
         $dayPix = ($imgWidth-$yAxisOffset)/$maxDay;
@@ -208,7 +230,13 @@ class SentenceInfoController extends Controller
         ob_start();
         $channel = $request->get('channel');
         $from = $request->get('from');
-        $to = $request->get('to');
+        if ($request->has('to')){
+            $to = $request->get('to');
+        }else{
+            $chapterLen = PaliText::where('book',$request->get('book'))->where('paragraph',$from)->value('chapter_len');
+            $to =  $from + $chapterLen - 1;
+            $this->_endParagraph = $to;
+        }
 
         $img = imagecreate($imgWidth,$imgHeight) or die('create image fail ');
 
@@ -219,45 +247,111 @@ class SentenceInfoController extends Controller
         $gray = imagecolorallocate($img,180,180,180);
         $dataLineColor = imagecolorallocate($img,50,50,255);
 
+
+
+        $max=0;
+        $values = [];
+        #按天获取数据
+        for($i = 1; $i <= $maxDay; $i++){
+            $day = strtotime("today -{$i} day");
+            $date = date("Y-m-d",$day);
+            $current = $this->getSentProgress($request,$date);
+            $values[] = $current;
+            if($max < $current){
+                $max = $current;
+            }
+        }
+        /* 
+        * 计算Y 轴满刻度值
+        * 算法 不足 20 按 20 算 小于100 满刻度是是50的整倍数
+        * 小于1000 满刻度是是500的整倍数
+        */
+        
+        if($max < $yMin){
+            $yMax = $yMin;
+        }else{
+            $len = strlen($max);
+            $yMax = pow(10,$len);
+            if($max < $yMax/2){
+                $yMax = $yMax / 2;
+            }
+        }
+        //根据满刻度像素数 计算缩放比例
+        $yPix = $imgHeight - $xAxisOffset;//y轴实际像素数
+        $rate = $yPix / $yMax;
+
+        $svg = "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"currentColor\" class=\"bi bi-alarm-fill\" viewBox=\"0 0 $imgWidth $imgHeight\">";
+        
         //绘制坐标轴
         imageline($img,0,$imgHeight-$xAxisOffset,$imgWidth,$imgHeight-$xAxisOffset,$color);
         imageline($img,$yAxisOffset,$imgHeight,$yAxisOffset,0,$color);
-        //绘制y轴网格线
-        for($i=1;$i<$maxPage/$yLineSpace;$i++){
-            $space= ($imgHeight-$xAxisOffset)/$maxPage*$yLineSpace;
-            $y=$imgHeight-$yAxisOffset-$i*$space;
-            imageline($img,$yAxisOffset,$y,$imgWidth,$y,$gray);
-            imagestring($img,5,0,$y-5,$i*$yLineSpace,$color);
-        }
-        //绘制x轴网格线
+        // x 轴 
+        $y=$imgHeight-$xAxisOffset+1;
+        $svg .= "<line x1='$yAxisOffset'  y1='$y' x2='$imgWidth'   y2='$y' style='stroke:#666666;'></line>";
+        // y 轴 
+        $x = $yAxisOffset - 1;
+        $svg .= "<line x1='$x'  y1='0' x2='$x'   y2='".($imgHeight-$xAxisOffset)."' style='stroke:#666666;'></line>";
+        //绘制x轴刻度线
         for($i=0; $i<$maxDay; $i++){
             $space= ($imgWidth-$yAxisOffset)/$maxDay;
-            $x=$imgWidth-$yAxisOffset-$i*$space;
+            $x=$imgWidth-$i*$space - $space/2;
             $dayOffset = $maxDay-$i;
             $date = strtotime("today -{$i} day");
             $day = date("d",$date);
             imageline($img,$x,($imgHeight-$xAxisOffset),$x,($imgHeight-$xAxisOffset+5),$gray);
-            imagestring($img,5,$x,($imgHeight-$xAxisOffset),$day,$color);
-        }
-
-        $last=0;
-        for($i = 1; $i <= $maxDay; $i++){
-            $day = strtotime("today -{$i} day");
-            $date = date("Y-m-d",$day);
+            imagestring($img,5,$x,($imgHeight-$xAxisOffset-2),$day,$color);
 
-            $resulte = $this->getSentProgress($request,$date)*$pagePix;
-            if($i>0){
-                imageline($img,($imgWidth-$i*$dayPix),$imgHeight-$xAxisOffset-$resulte,($imgWidth-($i-1)*$dayPix),$imgHeight-$xAxisOffset-$last,$dataLineColor);
+            $y = $imgHeight-$xAxisOffset+1;
+            $height = 5;
+            $svg .= "<line x1='$x'  y1='$y' x2='$x'   y2='".($y+$height)."' style='stroke:#666666;'></line>";
+            $svg .= "<text x='".($x-5)."' y='".($y+12)."' style='font-size:8px;'>$day</text>";
+        }
+        
+        
+        //绘制y轴刻度线 将y轴五等分
+        $step = $yMax / 5 * $rate;
+        for ($i=1; $i < 5; $i++) { 
+            # code...
+            $yValue = $yMax / 5 * $i;
+            if($yValue>=1000000){
+                $yValue = ($yValue / 1000000 ).'m';
+            }else if($yValue>=1000){
+                $yValue = ($yValue / 1000 ).'k';
             }
-            $last = $resulte;
+            $x = $yAxisOffset;
+            $y = $imgHeight-$yAxisOffset-$i*$step;
+            $svg .= "<line x1='$x'  y1='$y' x2='".($x - 5)."'   y2='$y' style='stroke:#666666;'></line>";
+            $svg .= "<text x='".($x-18)."' y='".($y+4)."' style='font-size:8px;'>$yValue</text>";
+        }
+        for($i=1;$i < $maxPage/$yLineSpace;$i++){
+            $space= ($imgHeight-$xAxisOffset)/$maxPage*$yLineSpace;
+            $y=$imgHeight-$yAxisOffset-$i*$space;
+            imageline($img,$yAxisOffset,$y,$imgWidth,$y,$gray);
+            imagestring($img,5,0,$y-5,$i*$yLineSpace,$color);
         }
+// 绘制柱状图
+        $rectWidth = $dayPix*0.9;
+        $last = 0;
+        foreach ($values as $key => $value) {
+            # code...
+            $value = $value*$rate;
+            $x = $imgWidth - ($dayPix * $key + $yAxisOffset);
+            $y = $imgHeight - $xAxisOffset - $value;
+            $svg .= "<rect x='$x' y='$y' height='{$value}' width='{$rectWidth}' style='stroke:#006600; fill: #006600'/>";
+            if($key>0){
+                imageline($img,($imgWidth - $key * $dayPix),$imgHeight - $xAxisOffset - $value,($imgWidth-($key - 1)*$dayPix),$imgHeight-$xAxisOffset-$last,$dataLineColor);
+            }
+            $last = $value;
+        }
+
+    $svg .= "</svg>";
 
         imagegif($img);
         imagedestroy($img);
 
         $content = ob_get_clean();
-        return response($content,200,[
-            'Content-Type'=>'image/gif'
+        return response($svg,200,[
+            'Content-Type'=>'image/svg+xml'
         ]);
     }
 

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

@@ -449,6 +449,7 @@ function set_toc_visible(isVisible){
 	click_dropdown_init();
 	note_create();
 	historay_init();
+    chapter_dynamic_init();
 	switch (_view) {
 		case "article":
 			articel_load(_articel_id,_collection_id);

+ 1 - 0
public/app/pcdl/html_head.php

@@ -113,6 +113,7 @@ if (isset($_GET["language"])) {
 	<link type="text/css" rel="stylesheet" href="../term/term_edit_dlg.css" />
 	<script src="../uwbw/wbw_channal_list.js"></script>
 	<script src="../usent/historay.js"></script>
+	<script src="../usent/chapter_dynamic.js"></script>
 	<script src="../term/pali_sim_sent.js"></script>
 	<link type="text/css" rel="stylesheet" href="../term/pali_sim_dlg.css" />
 	<script src="../term/related_para.js"></script>

+ 3 - 0
public/app/studio/svg/icon.svg

@@ -949,5 +949,8 @@
 <path d="M519.314286 32.914286c157.013333 0 299.739429 75.093333 389.510095 194.901333l87.917714-52.370286s19.846095-9.898667 19.846095 13.312v346.940953s0 30.915048-23.259428 19.797333c-19.456-9.264762-230.64381-130.340571-297.106286-168.569905-36.473905-16.432762-4.437333-29.744762-4.437333-29.744762l105.179428-62.707809a357.180952 357.180952 0 1 0 14.628572 430.226286l105.618286 74.410666a485.814857 485.814857 0 0 1-397.897143 206.604191c-268.629333 0-486.4-217.770667-486.4-486.4C32.914286 250.684952 250.684952 32.914286 519.314286 32.914286z" p-id="6640"></path>
 </symbol>
 
+<symbol fill="currentColor" class="bi bi-graph-up" viewBox="0 0 16 16" id="graph-up" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" d="M0 0h1v15h15v1H0V0zm10 3.5a.5.5 0 01.5-.5h4a.5.5 0 01.5.5v4a.5.5 0 01-1 0V4.9l-3.613 4.417a.5.5 0 01-.74.037L7.06 6.767l-3.656 5.027a.5.5 0 01-.808-.588l4-5.5a.5.5 0 01.758-.06l2.609 2.61L13.445 4H10.5a.5.5 0 01-.5-.5z"/>
+</symbol>
 
 </svg>

+ 7 - 0
public/app/term/note.js

@@ -498,6 +498,9 @@ function render_channal_list(channalinfo) {
 	output += '<div class="pop_menu">';
 	output += render_icon_button("copy", "commit_init({src:'" + channalinfo.uid + "'})", gLocal.gui.copy_to);
 	output += render_icon_button("ic_mode_edit", "", gLocal.gui.modify);
+    if(_book && _par){
+        output += render_icon_button("graph-up", "chapter_dynamic_show("+_book+","+_par+",'"+channalinfo.uid+"')", "动态");
+    }
 	output += "</div>";
 	output += "</div>";
 	output += "</div>";
@@ -909,6 +912,10 @@ function sent_commit(src, id) {
 	});
 }
 
+function chapter_Dynamic_open(channel_id){
+
+}
+
 function render_icon_button(icon_id, event, tiptitle) {
 	let html = "";
 	html += "<button class='icon_btn tooltip' onclick=\"" + event + '">';

+ 30 - 0
public/app/usent/chapter_dynamic.js

@@ -0,0 +1,30 @@
+/**
+ * 显示句子历史记录窗口
+ */
+
+function chapter_dynamic_init() {
+	$("body").append('<div id="chapter_dynamic_dlg" title="Chapter Dynamic"><div id="chapter_dynamic_content"></div></div>');
+	$("#chapter_dynamic_dlg").dialog({
+		autoOpen: false,
+		width: 550,
+		buttons: [
+			{
+				text: "Close",
+				click: function () {
+					$(this).dialog("close");
+				},
+			},
+		],
+	});
+}
+
+function chapter_dynamic_show(book,para,channel_id) {
+    let imgUrl = location.host ;
+    imgUrl = "/api/sentence/progress/daily/image?";
+    imgUrl += "channel="+channel_id;
+    imgUrl += "&&book=" + book;
+    imgUrl += "&from=" + para;
+    imgUrl += "&view=palistrlen";
+    $("#chapter_dynamic_dlg").html("<img src='"+imgUrl+"'>");
+    $("#chapter_dynamic_dlg").dialog("open");
+}