ソースを参照

Merge branch 'master' of https://github.com/visuddhinanda/mint

Bhikkhu-Kosalla 5 年 前
コミット
cd5ed098b0
65 ファイル変更3573 行追加762 行削除
  1. 72 0
      app/article/add_article_to_collect.php
  2. 111 0
      app/article/add_to_collect_dlg.js
  3. 85 0
      app/article/article.js
  4. 49 0
      app/article/article_add_dlg.js
  5. 60 0
      app/article/collect_add_dlg.js
  6. 48 0
      app/article/collect_get.php
  7. 21 0
      app/article/collect_list.php
  8. 2 2
      app/article/get.php
  9. 81 72
      app/article/index.php
  10. 39 0
      app/article/list_article_in_collect.php
  11. 0 0
      app/article/my_article.del.php
  12. 174 1
      app/article/my_article.js
  13. 99 0
      app/article/my_article_edit.php
  14. 40 5
      app/article/my_article_index.php
  15. 109 0
      app/article/my_article_post.php
  16. 19 0
      app/article/my_article_put.php
  17. 229 0
      app/article/my_collect.js
  18. 100 0
      app/article/my_collect_edit.php
  19. 64 0
      app/article/my_collect_index.php
  20. 43 0
      app/article/my_collect_post.php
  21. 19 0
      app/article/my_collect_put.php
  22. 155 17
      app/channal/channal.js
  23. 64 0
      app/channal/channal_add_dlg.js
  24. 35 5
      app/channal/get.php
  25. 99 0
      app/channal/my_channal_edit.php
  26. 25 0
      app/channal/my_channal_get.php
  27. 9 9
      app/channal/my_channal_index.php
  28. 56 0
      app/channal/my_channal_post.php
  29. 20 0
      app/channal/my_channal_put.php
  30. 10 11
      app/guide/guide.css
  31. 0 6
      app/guide/guide.js
  32. 1 2
      app/guide/guide_icon.svg
  33. 48 0
      app/hostsetting/function.php
  34. 21 0
      app/lang/tran_lang_select.js
  35. 0 0
      app/like/get.php
  36. 18 0
      app/like/like.css
  37. 9 0
      app/like/like.js
  38. 1 0
      app/like/like.svg
  39. 1 0
      app/like/like1.svg
  40. 0 0
      app/like/put.php
  41. 1 0
      app/path.php
  42. 96 77
      app/pcdl/css/basic_style.css
  43. 7 0
      app/pcdl/css/edit.svg
  44. 11 1
      app/pcdl/js/reader.js
  45. 50 3
      app/pcdl/reader.php
  46. 6 0
      app/public/images/svg/more.svg
  47. 15 0
      app/public/js/comm.js
  48. 13 1
      app/studio/css/style.css
  49. 6 0
      app/studio/editor.php
  50. 1 1
      app/studio/index_tool_bar.php
  51. 475 471
      app/studio/js/common.js
  52. 62 11
      app/studio/js/render.js
  53. 117 0
      app/studio/project_load_article.php
  54. 1 1
      app/studio/project_load_db.php
  55. 9 4
      app/term/channal_list.php
  56. 287 50
      app/term/note.js
  57. 42 8
      app/term/note.php
  58. 58 0
      app/term/term.css
  59. 77 0
      app/term/term.js
  60. 37 0
      app/term/term_popup.js
  61. 1 0
      app/time.php
  62. 2 1
      app/ucenter/setting.php
  63. 156 0
      app/usent/sent_post.php
  64. 3 3
      app/usent/update.php
  65. 4 0
      app/wiki/wiki.js

+ 72 - 0
app/article/add_article_to_collect.php

@@ -0,0 +1,72 @@
+<?php
+//查询term字典
+
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../ucenter/function.php';
+
+$output  = array();
+$respond = array();
+$respond['status']=0;
+$respond['message']="";
+$respond['id']=$_POST["id"];
+
+if(isset($_POST["id"])){
+    $dirty_collect = array();
+    $data = json_decode($_POST["data"]);
+    $title = $_POST["title"];
+    PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+    $article_id=$_POST["id"];
+    //找出脏的collect
+    $query = "SELECT collect_id FROM article_list  WHERE article_id = ? ";
+    $collect = PDO_FetchAll($query,array($article_id));
+    foreach ($collect as $key => $value) {
+        # code...
+        $dirty_collect[$value["collect_id"]] = 1;
+    }
+    $query = "DELETE FROM article_list WHERE article_id = ? ";
+     PDO_Execute($query,array($article_id));
+     if(count($data)>0){
+        /* 开始一个事务,关闭自动提交 */
+        $PDO->beginTransaction();
+        $query = "INSERT INTO article_list (collect_id, article_id,level,title) VALUES (?, ?, ? , ?)";
+        $sth = $PDO->prepare($query);
+        foreach ($data as $row) {
+            $sth->execute(array($row,$article_id,1,$title));
+        }
+        $PDO->commit();
+        if (!$sth || ($sth && $sth->errorCode() != 0)) {
+            /*  识别错误且回滚更改  */
+            $PDO->rollBack();
+            $error = PDO_ErrorInfo();
+            $respond['status']=1;
+            $respond['message']=$error[2];
+        }
+     }
+
+     # 更新collect
+     $query = "SELECT collect_id FROM article_list WHERE article_id  = ?";
+     $collect = PDO_FetchAll($query,array($article_id));
+     foreach ($collect as $key => $value) {
+        # code...
+        $dirty_collect[$value["collect_id"]] = 1;
+    }
+     foreach ($dirty_collect as $key => $value) {
+         # code...
+         $query = "SELECT level,article_id as article , title FROM article_list WHERE collect_id  = ?";
+         $collect_info = PDO_FetchAll($query,array($key));
+         $query = "UPDATE collect SET article_list = ? WHERE id = ? ";
+         $strArticleList = json_encode($collect_info, JSON_UNESCAPED_UNICODE);
+         $stmt = PDO_Execute($query,array( $strArticleList ,$key));
+         if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
+             $error = PDO_ErrorInfo();
+             $respond['status']=1;
+             $respond['message']=$error[2];
+         }
+     }
+
+}
+
+	echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 111 - 0
app/article/add_to_collect_dlg.js

@@ -0,0 +1,111 @@
+function add_to_collect_dlg_init() {
+  $("[vui='collect-dlg']").each(function () {
+    $(this).css("position", "relative");
+    $(this).html(
+      "<span class='button_add_to_collect'>添加到文集</span><div class='float_dlg'></div>"
+    );
+  });
+
+  $(".button_add_to_collect").click(function () {
+    let html = "";
+    let article_id = $(this).parent().attr("a_id");
+    html += "<div id='add_to_collect_dlg_" + article_id + "'>";
+    html += "<div >";
+    html += "<input type='input'  placeholder='搜索文集' />";
+    html += "</div>";
+    html += "<div>";
+    html += "<div class='exist'>";
+    html += "</div>";
+    html += "<div class='others'>";
+    html += "</div>";
+    html += "</div>";
+    html += "<div style='display:flex;'>";
+    html += "<button onclick='collect_new()'>New Collect</button>";
+    html +=
+      "<button onclick=\"article_add_to_collect_ok('" +
+      article_id +
+      "')\">Finish</button>";
+    html +=
+      "<button onclick=\"article_add_to_collect_cancel('" +
+      article_id +
+      "')\">Cancel</button>";
+    html += "</div>";
+    html += "</div>";
+    $(this).siblings(".float_dlg").first().html(html);
+    $(this).siblings(".float_dlg").first().show();
+    $.get(
+      "../article/list_article_in_collect.php",
+      {
+        id: article_id,
+      },
+      function (data, status) {
+        let collect_list = JSON.parse(data);
+
+        let id = collect_list.article_id;
+        let html_exist = "";
+        for (const iterator of collect_list.exist) {
+          html_exist +=
+            "<div><input type='checkbox' class='collect' collect_id='" +
+            iterator.id +
+            "' checked />";
+          html_exist += iterator.title;
+          html_exist += "</div>";
+        }
+        $("#add_to_collect_dlg_" + id)
+          .find(".exist")
+          .first()
+          .html(html_exist);
+
+        let html_others = "";
+        for (const iterator of collect_list.others) {
+          html_others +=
+            "<div><input type='checkbox' class='collect' collect_id='" +
+            iterator.id +
+            "' />";
+          html_others += iterator.title;
+          html_others += "</div>";
+        }
+        $("#add_to_collect_dlg_" + id)
+          .find(".others")
+          .first()
+          .html(html_others);
+      }
+    );
+  });
+}
+
+function article_add_to_collect_ok(article_id) {
+  let obj = document.querySelectorAll(".collect");
+  let collect_id = new Array();
+  for (const iterator of obj) {
+    if (iterator.checked == true) {
+      collect_id.push(iterator.getAttributeNode("collect_id").value);
+    }
+  }
+  $.post(
+    "../article/add_article_to_collect.php",
+    {
+      id: article_id,
+      title: $("#input_article_title").val(),
+      data: JSON.stringify(collect_id),
+    },
+    function (data) {
+      let result = JSON.parse(data);
+      if (result.status > 0) {
+        alert(result.message);
+      } else {
+        add_to_collect_dlg_close(result.id);
+      }
+    }
+  );
+}
+
+function article_add_to_collect_cancel(article_id) {
+  add_to_collect_dlg_close(article_id);
+}
+
+function add_to_collect_dlg_close(article_id) {
+  $("#add_to_collect_dlg_" + article_id)
+    .parent()
+    .hide();
+}

+ 85 - 0
app/article/article.js

@@ -36,3 +36,88 @@ function articel_load(id) {
     }
   );
 }
+
+function articel_load_collect(article_id) {
+  $.get(
+    "../article/collect_get.php",
+    {
+      article: article_id,
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let result = JSON.parse(data);
+          if (result) {
+            $("#collect_title").html(result[0].title);
+            let html = "";
+            html += "<ul>";
+            let article_list = JSON.parse(result[0].article_list);
+            let display = "";
+            if (_display == "para") {
+              display = "&display=para";
+            }
+            let prevArticle = "无";
+            let nextArticle = "无";
+            for (let index = 0; index < article_list.length; index++) {
+              const element = article_list[index];
+              if (element.article == _articel_id) {
+                if (index > 0) {
+                  const prev = article_list[index - 1];
+                  prevArticle =
+                    "<a href='../article/index.php?id=" +
+                    prev.article +
+                    display +
+                    "'>" +
+                    prev.title +
+                    "</a>";
+                }
+                if (index < article_list.length - 1) {
+                  const next = article_list[index + 1];
+                  nextArticle =
+                    "<a href='../article/index.php?id=" +
+                    next.article +
+                    display +
+                    "'>" +
+                    next.title +
+                    "</a>";
+                }
+                $("#contents_nav_left").html(prevArticle);
+                $("#contents_nav_right").html(nextArticle);
+              }
+              html +=
+                "<li class='level_" +
+                element.level +
+                "'>" +
+                "<a href='../article/index.php?id=" +
+                element.article +
+                display +
+                "'>" +
+                element.title +
+                "</a></li>";
+            }
+
+            html += "</ul>";
+
+            $("#toc_content").html(html);
+          }
+        } catch (e) {
+          console.error(e);
+        }
+      } else {
+        console.error("ajex error");
+      }
+    }
+  );
+}
+
+function set_channal(channalid) {
+  let url = "../article/index.php?id=" + _articel_id;
+  if (channalid != "") {
+    url += "&channal=" + channalid;
+  }
+  if (_display != "") {
+    url += "&display=" + _display;
+  }
+  location.assign(url);
+}

+ 49 - 0
app/article/article_add_dlg.js

@@ -0,0 +1,49 @@
+var _article_add_dlg_div;
+function article_add_dlg_init(div) {
+  _article_add_dlg_div = div;
+  let html = "";
+  html += "<div id='article_add_dlg'>";
+  html += "<div >";
+  html += "<div >Title</div>";
+  html += "<input type='input' id='article_add_title' />";
+  html += "</div>";
+  html += "<div>";
+  html += "</div>";
+  html +=
+    "<div style='display:flex;justify-content: space-between;padding-top: 1em;'>";
+  html += "<button onclick='article_add_cancel()'>Cancel</button>";
+  html += "<button onclick='article_add_new()'>New</button>";
+  html += "</div>";
+  html += "</div>";
+
+  $("#" + div).append(html);
+}
+
+function article_add_dlg_show() {
+  $("#" + _article_add_dlg_div).show();
+}
+function article_add_dlg_hide() {
+  $("#" + _article_add_dlg_div).hide();
+}
+function article_add_cancel() {
+  article_add_dlg_hide();
+  $("#article_add_title").val("");
+}
+
+function article_add_new() {
+  $.post(
+    "../article/my_article_put.php",
+    {
+      title: $("#article_add_title").val(),
+    },
+    function (data) {
+      let error = JSON.parse(data);
+      if (error.status == 0) {
+        alert("ok");
+        article_add_cancel();
+      } else {
+        alert(error.message);
+      }
+    }
+  );
+}

+ 60 - 0
app/article/collect_add_dlg.js

@@ -0,0 +1,60 @@
+var _collect_add_dlg_div;
+function collect_add_dlg_init(div) {
+  _collect_add_dlg_div = div;
+  let html = "";
+  html += "<div id='collect_add_dlg'>";
+  html += "<div >";
+  html += "<div >Collect Title</div>";
+  html += "<input type='input' id='collect_add_title' />";
+  html += "</div>";
+  html += "<div>";
+  html += "</div>";
+  html +=
+    "<div style='display:flex;justify-content: space-between;padding-top: 1em;'>";
+  html += "<div>";
+  html += "<select id='collect_add_dlg_status'>";
+  html += "<option value='1'>私有</option>";
+  html += "<option value='2'>不公开列出</option>";
+  html += "<option value='3'>公开</option>";
+  html += "</select>";
+
+  html += "</div>";
+  html += "<div>";
+  html += "<button onclick='collect_add_cancel()'>Cancel</button>";
+  html += "<button onclick='collect_add_new()'>New</button>";
+  html += "</div>";
+  html += "</div>";
+  html += "</div>";
+
+  $("#" + div).append(html);
+}
+
+function collect_add_dlg_show() {
+  $("#" + _collect_add_dlg_div).show();
+}
+function collect_add_dlg_hide() {
+  $("#" + _collect_add_dlg_div).hide();
+}
+function collect_add_cancel() {
+  collect_add_dlg_hide();
+  $("#collect_add_title").val("");
+}
+
+function collect_add_new() {
+  $.post(
+    "../article/my_collect_put.php",
+    {
+      title: $("#collect_add_title").val(),
+      status: $("#collect_add_dlg_status").val(),
+    },
+    function (data) {
+      let error = JSON.parse(data);
+      if (error.status == 0) {
+        alert("ok");
+        collect_add_cancel();
+      } else {
+        alert(error.message);
+      }
+    }
+  );
+}

+ 48 - 0
app/article/collect_get.php

@@ -0,0 +1,48 @@
+<?php
+//查询term字典
+
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../ucenter/function.php';
+
+
+if(isset($_GET["id"])){
+    PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+    $id=$_GET["id"];
+    $query = "select * from collect  where id = ".$PDO->quote($id);
+    $Fetch = PDO_FetchRow($query);
+    if($Fetch){
+        $userinfo = new UserInfo();
+        $user = $userinfo->getName($Fetch["owner"]);
+        $Fetch["username"] = $user;
+        echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+        exit;
+    }
+}
+else if(isset($_GET["article"])){
+    # 给文章编号,查文集信息
+    PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+    $article=$_GET["article"];
+    $query = "SELECT collect_id FROM article_list  WHERE article_id = ? ";
+    $Fetch = PDO_FetchAll($query,array($article));
+    
+    /*  使用一个数组的值执行一条含有 IN 子句的预处理语句 */
+    $params = array();
+    foreach ($Fetch as $key => $value) {
+        # code...
+        $params[] = $value["collect_id"];
+    }
+    /*  创建一个填充了和params相同数量占位符的字符串 */
+    $place_holders = implode(',', array_fill(0, count($params), '?'));
+
+    $query = "SELECT * FROM collect WHERE id IN ($place_holders)";
+
+    $Fetch = PDO_FetchAll($query,$params);
+        echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+        exit;
+}
+
+echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
+
+?>

+ 21 - 0
app/article/collect_list.php

@@ -0,0 +1,21 @@
+<?php
+//查询term字典
+
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../ucenter/function.php';
+
+
+if(isset($_GET["userid"])){
+    PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+    $userid=$_GET["userid"];
+    $query = "SELECT * from collect  where owner = ".$PDO->quote($userid)." and status <> 0 order by modify_time DESC";
+    $Fetch = PDO_FetchAll($query);
+    echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+
+echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
+
+?>

+ 2 - 2
app/article/get.php

@@ -10,8 +10,8 @@ require_once '../ucenter/function.php';
 if(isset($_GET["id"])){
     PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
     $id=$_GET["id"];
-    $query = "select * from article  where id = ".$PDO->quote($id);
-    $Fetch = PDO_FetchRow($query);
+    $query = "SELECT * FROM article  WHERE id = ? ";
+    $Fetch = PDO_FetchRow($query,array($id));
     if($Fetch){
         $userinfo = new UserInfo();
         $user = $userinfo->getName($Fetch["owner"]);

+ 81 - 72
app/article/index.php

@@ -1,16 +1,16 @@
 <?php
 require_once "../public/load_lang.php";
 require_once "../path.php";
-
-?>
-
-<?PHP
-include "../pcdl/html_head.php";
+require_once "../pcdl/html_head.php";
 ?>
 <body style="margin: 0;padding: 0;" class="reader_body" >
 	<script src="../term/term.js"></script>
 	<script src="../term/note.js"></script>
+	<script src="../channal/channal.js"></script>
 	<script src="./article.js"></script>
+	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>
+	<link type="text/css" rel="stylesheet" href="../term/term.css"/>
+	<link type="text/css" rel="stylesheet" href="../public/js/jquery-ui-1.12.1/jquery-ui.css"/>
 	<script>
 	<?php
 	$_id = "";
@@ -35,50 +35,15 @@ include "../pcdl/html_head.php";
 	?>
 	</script>
 	<style>
-	body{
-		font-size:12pt;
-	}
-	.term_link,.term_link_new{
-		color: blue;
-		padding-left: 2px;
-		padding-right: 2px;
-	}
-	.term_link_new{
-		color:red;
-	}
+
+
 	#search_result{
 		position: absolute;
 		background: wheat;
 		max-width: 95%;
 		width: 24em;
 	}
-	note:hover chapter{
-		display:inline;
-	} 
-	.ref>chapter:first-child{
-		display:inline;
-	}
-	chapter{
-		display:none;
-		color: var(--box-bg-color1);
-		text-decoration: none;
-		cursor: pointer;
-	}
-	chapter:hover{
-		color: var(--link-color);
-		text-decoration: underline;
-	}
-	para{
-		background-color: var(--drop-bg-color);
-		padding: 2px 8px;
-		text-decoration: none;
-		cursor: pointer;
-		color: var(--btn-border-color);
-		border-radius: 5px;
-	}
-	para:hover{
-		text-decoration: underline;
-	}
+
 	.icon{
 		width: 15px;
 		height: 15px;
@@ -116,7 +81,6 @@ include "../pcdl/html_head.php";
 		margin-top: 8px;
 	}
 	note{
-		background-color: #80808014;
 		padding: 0.5em 0.8em;
 		margin-bottom: 0.4em;
 		border-radius: 5px;
@@ -127,6 +91,7 @@ include "../pcdl/html_head.php";
 		}
 		else{
 			echo "display:block;";
+			echo "background-color: #80808014;";
 		}
 		?>
 	}
@@ -158,8 +123,9 @@ include "../pcdl/html_head.php";
 		display: flex;
     justify-content: space-between;
     height: 5em;
-    background-color: var(--bookx);
+    background-color: var(--tool-bg-color1);
     border-bottom: 1px solid var(--tool-line-color);
+	padding:10px;
 	}
 	.term_block_bar_left{
 		display: flex;
@@ -177,21 +143,7 @@ include "../pcdl/html_head.php";
 	.term_block_bar_left_info{
 		    padding-left: 8px;
 	}
-	.term_meaning{
-		font-weight: 700;
-	}
-	.term_author{
-		font-size: 80%;
-		color: gray;
-	}
-	.term_tag{
-		font-size: 80%;
-		font-weight: 500;
-		margin: 0 8px;
-	}
-	.term_link {
-    cursor: pointer;
-	}
+
 	.main_view{
 		padding: 0 1em;
 		max-width: 1280px;
@@ -232,6 +184,12 @@ include "../pcdl/html_head.php";
 	.when_right_fixed{
 		padding-right:20em;
 	}
+	<?php
+		if(isset($_GET["display"]) && $_GET["display"]=="para"){
+
+		}
+		else{
+?>
 	.bg_color_1{
 		background-color:#ebebeb66;
 	}
@@ -247,6 +205,10 @@ include "../pcdl/html_head.php";
 	.bg_color_5{
 		background:linear-gradient(to right, #fe99b91c, #ebebeb66);
 	}
+<?php
+		}
+		?>
+
 
 	pre {
 		white-space: pre-line;
@@ -258,9 +220,15 @@ include "../pcdl/html_head.php";
 	#contents_view{
 		display:flex;
 	}
-	#contents{
+	#contents_div{
 		flex:7;
 	}
+	#contents{
+		min-height: 400px;
+	}
+	#contents li{
+		white-space: normal;
+	}
 	#right_pannal{
 		flex:3;
 		max-width:20em;
@@ -283,6 +251,30 @@ include "../pcdl/html_head.php";
 		}
 ?>
 
+#toc_content .level_2{
+	padding-left:0.5em;
+}
+#toc_content .level_3{
+	padding-left:1em;
+}
+#toc_content .level_4{
+	padding-left:1.5em;
+}
+#toc_content .level_5{
+	padding-left:2em;
+}
+.ui-dialog-titlebar{
+		display: flex;
+    justify-content: space-between;
+	background-color: var(--btn-bg-color);
+    padding: 5px;
+	}
+	.ui-widget-content{
+		background-color: var(--bg-color);
+	}
+	.ui-dialog{
+		box-shadow:  8px 8px 20px var(--border-shadow);
+	}
 	</style>
 
 <style media="screen and (max-width:767px)">
@@ -301,6 +293,8 @@ include "../pcdl/html_head.php";
     margin-bottom: auto;
     padding-left: 0.5em;
 	}
+
+
 </style>
 
 <script>
@@ -336,30 +330,44 @@ term_word_link_fun("wiki_goto_word");
 	<div id="article_author">author</div>
 </div>
 <div id="contents_view">
-	<div id="contents" style="padding: 0 1em;">
-	loading...
-	</div>
-	<div id="right_pannal">
-		<div class="fun_frame">
-			<div class="title">About Author</div>
-			<div class="content" style="max-height:10em;">
+	<div id="contents_div" style="padding: 0 1em;">
+		<div id="contents">
+		loading...
+		</div>
+		<div id="contents_foot">
+			<div id="contents_nav" style="display:flex;justify-content: space-between;">
+				<div id="contents_nav_left"></div>
+				<div id="contents_nav_right"></div>
+			</div>
+			<div id="contents_dicuse">
+			
 			</div>
 		</div>
+	</div>
+	<div id="right_pannal">
 		<div class="fun_frame">
-			<div class="title">Table of Content</div>
-			<div class="content" style="max-height:10em;">
+			<div id = "collect_title" class="title">Table of Content</div>
+			<div id = "toc_content" class="content" style="max-height:20em;">
 			</div>
 		</div>
 		<div class="fun_frame">
-			<div class="title">Other Authors</div>
-			<div class="content" style="max-height:10em;">
+			<div class="title">Translations</div>
+			<div id="channal_list" class="content" style="max-height:20em;">
 			</div>
 		</div>
 	</div>
 </div>
 </div>
+
+<!-- ui-dialog -->
+<div id="dialog" title="Dialog Title">
+	<div id="edit_dialog_content"></div>
+</div>
+
 <script>
+	note_create();
 	articel_load(_articel_id);
+	articel_load_collect(_articel_id);
 
 	 window.addEventListener('scroll',winScroll);
 	function winScroll(e){ 
@@ -394,5 +402,6 @@ function GetPageScroll()
 }
 	</script>
 
+
 </body>
 </html>

+ 39 - 0
app/article/list_article_in_collect.php

@@ -0,0 +1,39 @@
+<?php
+//查询term字典
+
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../ucenter/function.php';
+
+$output  = array();
+if(isset($_GET["id"])){
+    PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+    $article_id=$_GET["id"];
+    $query = "SELECT collect_id as id from article_list  where article_id = ?  ";
+    $exist = PDO_FetchAll($query,array($article_id));
+    $exist_id = array();
+    for ($i=0; $i < count($exist) ; $i++) { 
+        # query collect title
+        $query = "SELECT title from collect  where id = ?  ";
+        $exist[$i]["title"] = PDO_FetchOne($query,array($exist[$i]["id"]));        
+        $exist_id[$exist[$i]["id"]] = 1;
+    }
+    $output["exist"] = $exist;
+
+    $query = "SELECT id,title from collect  where owner = ? AND status <> 0 order by modify_time DESC limit 0,10";
+    $others = PDO_FetchAll($query,array($_COOKIE["userid"])); 
+    foreach ($others as $key => $value) {
+        # remove exist record
+        if(!isset($exist_id[$value["id"]])){
+            $output["others"][] = $value;
+        }
+    }
+    $output["article_id"]=$article_id;
+    echo json_encode($output, JSON_UNESCAPED_UNICODE);
+}
+else{
+    echo json_encode(array(), JSON_UNESCAPED_UNICODE);	
+}
+
+?>

+ 0 - 0
app/article/my_article.del.php


+ 174 - 1
app/article/my_article.js

@@ -1,3 +1,8 @@
+var _display = "para";
+function my_article_init() {
+  my_article_list();
+  article_add_dlg_init("article_add_div");
+}
 function my_article_list() {
   $.get(
     "../article/list.php",
@@ -17,7 +22,19 @@ function my_article_list() {
               '<div style="max-width:2em;flex:1;"><input type="checkbox" /></div>';
             html += "<div style='flex:1;'>" + key++ + "</div>";
             html += "<div style='flex:2;'>" + iterator.title + "</div>";
-            html += "<div style='flex:2;'>" + "</div>";
+            html +=
+              "<div style='flex:2;'>" +
+              render_status(iterator.status) +
+              "</div>";
+            html += "<div style='flex:1;'>Copy Link</div>";
+            html +=
+              "<div style='flex:1;'><a href='../article/my_article_edit.php?id=" +
+              iterator.id +
+              "'>Edit</a></div>";
+            html +=
+              "<div style='flex:1;'><a href='../article/?id=" +
+              iterator.id +
+              "' target='_blank'>Preview</a></div>";
             html += "<div style='flex:1;'>15</div>";
             html += "</div>";
           }
@@ -31,3 +48,159 @@ function my_article_list() {
     }
   );
 }
+
+function render_status(status) {
+  status = parseInt(status);
+  let html = "";
+  let objStatus = [
+    { id: 1, name: "私有", tip: "仅自己可见" },
+    { id: 2, name: "不公开列出", tip: "不能被搜索到,只能通过链接访问" },
+    { id: 3, name: "公开", tip: "所有人均可看到" },
+  ];
+  html += '<div class="case_dropdown">';
+  html += '<input type="hidden" name="status"  value ="' + status + '" />';
+
+  for (const iterator of objStatus) {
+    if (iterator.id == status) {
+      html += "<div >" + iterator.name + "</div>";
+    }
+  }
+  html += '<div class="case_dropdown-content">';
+
+  for (const iterator of objStatus) {
+    let active = "";
+    if (iterator.id == status) {
+      active = "active";
+    }
+    html += "<a class='" + active + "'  onclick='setStatus(this)'>";
+    html += "<div style='font-size:110%'>" + iterator.name + "</div>";
+    html += "<div style='font-size:80%'>" + iterator.tip + "</div>";
+    html += "</a>";
+  }
+  html += "</div></div>";
+  return html;
+}
+
+function my_article_edit(id) {
+  $.get(
+    "../article/get.php",
+    {
+      id: id,
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          $("#article_collect").attr("a_id", result.id);
+          html += '<div class="" style="padding:5px;">';
+          html += '<div style="max-width:2em;flex:1;"></div>';
+          html += "<input type='hidden' name='id' value='" + result.id + "'/>";
+          html +=
+            "<input type='hidden' name='tag' value='" + result.tag + "'/>";
+          html +=
+            "<input type='hidden' name='summary' value='" +
+            result.summary +
+            "'/>";
+          html +=
+            "<input type='hidden' name='status' value='" +
+            result.status +
+            "'/>";
+
+          html += "<button onclick='article_preview()'>Preview</button>";
+          html += "<input type='checkbox' name='import' />Import Data";
+          html += "</div>";
+          html += "<div style='display:flex;'>";
+          html += "<div style='flex:4;'>";
+
+          html +=
+            "<textarea id='article_content' name='content' style='height:500px;'>" +
+            result.content +
+            "</textarea>";
+          html += "</div>";
+
+          html += "<div id='preview_div'>";
+          html += "<div id='preview_inner' ></div>";
+          html += "</div>";
+
+          html += "</div>";
+
+          $("#article_list").html(html);
+          $("#aritcle_status").html(render_status(result.status));
+          let html_title =
+            "<input id='input_article_title' type='input' name='title' value='" +
+            result.title +
+            "' />";
+          $("#article_title").html(html_title);
+          $("#preview_inner").html(note_init(result.content));
+          note_refresh_new();
+
+          add_to_collect_dlg_init();
+        } catch (e) {
+          console.error(e);
+        }
+      } else {
+        console.error("ajex error");
+      }
+    }
+  );
+}
+
+function article_preview() {
+  $("#preview_inner").html(note_init($("#article_content").val()));
+  note_refresh_new();
+}
+
+function my_article_save() {
+  $.ajax({
+    type: "POST", //方法类型
+    dataType: "json", //预期服务器返回的数据类型
+    url: "../article/my_article_post.php", //url
+    data: $("#article_edit").serialize(),
+    success: function (result) {
+      console.log(result); //打印服务端返回的数据(调试用)
+
+      if (result.status == 0) {
+        alert("保存成功");
+      } else {
+        alert("error:" + result.message);
+      }
+    },
+    error: function (data, status) {
+      alert("异常!" + data.responseText);
+      switch (status) {
+        case "timeout":
+          break;
+        case "error":
+          break;
+        case "notmodified":
+          break;
+        case "parsererror":
+          break;
+        default:
+          break;
+      }
+    },
+  });
+}
+
+function course_validate_required(field, alerttxt) {
+  with (field) {
+    if (value == null || value == "") {
+      alert(alerttxt);
+      return false;
+    } else {
+      return true;
+    }
+  }
+}
+
+function course_validate_form(thisform) {
+  with (thisform) {
+    if (course_validate_required(title, "Title must be filled out!") == false) {
+      title.focus();
+      return false;
+    }
+  }
+}

+ 99 - 0
app/article/my_article_edit.php

@@ -0,0 +1,99 @@
+<?php
+require_once '../studio/index_head.php';
+?>
+<body id="file_list_body" >
+
+	<script language="javascript" src="../article/my_article.js"></script>
+	<script language="javascript" src="../term/note.js"></script>
+	<script language="javascript" src="../term/term.js"></script>
+	<script language="javascript" src="../public/js/marked.js"></script>
+	<script language="javascript" src="../article/add_to_collect_dlg.js"></script>
+	<script >
+	var gCurrPage="article";
+	</script>
+
+	<style>
+	#article {
+		background-color: var(--btn-border-color);
+		
+	}
+	#article:hover{
+		background-color: var(--btn-border-color);
+		color: var(--btn-color);
+		cursor:auto;
+	}
+	.file_list_block{
+		width:unset;
+	}
+	.case_dropdown-content>a {
+		display:block;
+	}
+	.case_dropdown-content>.active{
+		background-color:gray;
+	}
+	.file_list_block {
+    max-width: 100%;
+    margin-right: 1em;
+	}
+	.index_inner {
+    margin-left: 16em;
+    margin-top: 5em;
+}
+#preview_div {
+    flex: 6;
+    overflow-y: scroll;
+    height: 550px;
+}
+
+	</style>
+
+	<?php
+	require_once '../studio/index_tool_bar.php';
+	?>
+		
+	<div class="index_inner " >
+	<form id="article_edit" action="##" onsubmit="return false"  method="POST" >
+	<div class="file_list_block">
+		<div class="tool_bar">
+			<div style="display:flex;">
+				<a href="../article/my_article_index.php">返回</a>
+				<span id="article_title"></span>
+				<div id="article_collect" vui='collect-dlg' ></div>
+			</div>
+			<div style="display:flex;">
+				<div id="aritcle_status"></div>
+				<span class="icon_btn_div">
+					<span class="icon_btn_tip"></span>
+					<button id="edit_save" type="button" class="icon_btn" title=" " onclick="my_article_save()">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_save"></use>
+						</svg>
+					</button>
+				</span>
+				
+				<span class="icon_btn_div">				
+					<span class="icon_btn_tip">回收站</span>
+					<button id="to_recycle" type="button" class="icon_btn" onclick="article_del()" title=" ">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_delete"></use>
+						</svg>
+					</button>
+				</span>	
+			</div>
+		</div>
+
+		<div id="article_list"  class="file_list_block" style="">
+
+		</div>
+
+	</div>
+</form>
+	</div>
+	
+<script>
+my_article_edit("<?php echo $_GET["id"] ?>");
+</script>
+<?php
+require_once '../studio/index_foot.php';
+?>
+

+ 40 - 5
app/article/my_article_index.php

@@ -1,9 +1,10 @@
 <?php
 require_once '../studio/index_head.php';
 ?>
-<body id="file_list_body" onLoad="my_article_list()">
+<body id="file_list_body" onLoad="my_article_init()">
 
 	<script language="javascript" src="../article/my_article.js"></script>
+	<script language="javascript" src="../article/article_add_dlg.js"></script>
 	<script >
 	var gCurrPage="article";
 	</script>
@@ -18,18 +19,52 @@ require_once '../studio/index_head.php';
 		color: var(--btn-color);
 		cursor:auto;
 	}
+	.file_list_block{
+		width:unset;
+	}
+	.case_dropdown-content>a {
+		display:block;
+	}
+	.case_dropdown-content>.active{
+		background-color:gray;
+	}
+
 	</style>
 
 	<?php
 	require_once '../studio/index_tool_bar.php';
 	?>
 		
-	<div class="index_inner" style="margin-left: 18em;margin-top: 5em;display:flex;">
-		<div id="article_list"  class="file_list_block" style="flex:3;">
+	<div class="index_inner " style="margin-left: 18em;margin-top: 5em;">
+		<div class="file_list_block">
+			<div class="tool_bar">
+				<div>作品列表</div>
+				<div>
+					<span class="icon_btn_div">
+						<span class="icon_btn_tip"></span>
+						<button id="file_add" type="button" class="icon_btn" title=" " onclick="article_add_dlg_show()">
+							<svg class="icon">
+								<use xlink:href="../studio/svg/icon.svg#ic_add_circle"></use>
+							</svg>
+						</button>
+						<div id='article_add_div' class="float_dlg"></div>
+					</span>
+					
+					<span class="icon_btn_div">				
+						<span class="icon_btn_tip">回收站</span>
+						<button id="to_recycle" type="button" class="icon_btn" onclick="file_del()" title=" ">
+							<svg class="icon">
+								<use xlink:href="../studio/svg/icon.svg#ic_delete"></use>
+							</svg>
+						</button>
+					</span>	
+				</div>
+			</div>
+
+			<div id="article_list"  class="file_list_block" style="">
 
+			</div>
 		</div>
-        <div style="flex:3;"></div>
-        <div style="flex:4;"></div>
 	</div>
 	
 <?php

+ 109 - 0
app/article/my_article_post.php

@@ -0,0 +1,109 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+$_content = $_POST["content"];
+
+if($_POST["import"]=='on'){
+    $sent = explode("\n",$_POST["content"]);
+    if($sent && count($sent)>0){
+        $setting =  new Hostsetting();
+        $max_book = $setting->get("max_book_number");
+        if($max_book){
+            $currBook = $max_book+1;
+            $setbooknum = $setting->set("max_book_number",$currBook);
+            if($setbooknum==false){
+                $respond["status"]=1;
+                $respond["message"]="设置书号错误";
+                echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+                exit;
+            }
+        }
+        else{
+            $respond["status"]=1;
+            $respond["message"]="获取书号错误";
+            echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+            exit;
+        }
+        PDO_Connect("sqlite:"._FILE_DB_SENTENCE_);
+
+        /* 开始一个事务,关闭自动提交 */
+        $PDO->beginTransaction();
+        $query="INSERT INTO sentence ('id','block_id','book','paragraph','begin','end','tag','author','editor','text','language','ver','status','strlen','modify_time','receive_time') VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
+        
+        $sth = $PDO->prepare($query);
+        
+        $para = 1;
+        $sentNum = 0;
+        $newText =  "";
+        foreach ($sent as $data) {
+            $data = trim($data);
+            if($data==""){
+                $para++;
+                $sentNum = 0;
+                $newText .="\n";
+                continue;
+            }
+            else{
+                $sentNum=$sentNum+10;
+            }
+            if(mb_substr($data,0,2,"UTF-8")=="{{"){
+                $newText .=$data."\n";
+            }
+            else{
+                $newText .='{{'."{$currBook}-{$para}-{$sentNum}-{$sentNum}"."}}\n";
+                $sth->execute(
+                        array(UUID::v4(),
+                                    "",
+                                    $currBook,
+                                    $para,
+                                    $sentNum,
+                                    $sentNum,
+                                    "",
+                                    "[]",
+                                    $_COOKIE["userid"],
+                                    $data,
+                                    "my",
+                                    1,
+                                    1,
+                                    mb_strlen($data,"UTF-8"),
+                                    mTime(),
+                                    mTime()
+                                ));                
+            }
+
+        }
+        $PDO->commit();
+        
+        if (!$sth || ($sth && $sth->errorCode() != 0)) {
+            /*  识别错误且回滚更改  */
+            $PDO->rollBack();
+            $error = PDO_ErrorInfo();
+            $respond['status']=1;
+            $respond['message']=$error[2];
+            echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+            exit;
+        }
+        else{
+            $respond['status']=0;
+            $respond['message']="成功";
+            $_content = $newText;
+        }		        
+    }
+}
+
+PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+
+$query="UPDATE article SET title = ? , subtitle = ? , summary = ?, content = ?  , tag = ? , setting = ? , status = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$sth = $PDO->prepare($query);
+$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"], $_content , $_POST["tag"] , $_POST["setting"] , $_POST["status"] ,   mTime() , mTime() , $_POST["id"]));
+$respond=array("status"=>0,"message"=>"");
+if (!$sth || ($sth && $sth->errorCode() != 0)) {
+	$error = PDO_ErrorInfo();
+	$respond['status']=1;
+	$respond['message']=$error[2];
+}
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 19 - 0
app/article/my_article_put.php

@@ -0,0 +1,19 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+
+$query="INSERT INTO article ( id,  title  , subtitle  , summary , content   , tag  , owner, setting  , status  , create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) ";
+$sth = $PDO->prepare($query);
+$sth->execute(array(UUID::v4() , $_POST["title"] , "" ,"", "" , "" , $_COOKIE["userid"] , "{}" , 1 , mTime() ,  mTime() , mTime() ));
+$respond=array("status"=>0,"message"=>"");
+if (!$sth || ($sth && $sth->errorCode() != 0)) {
+	$error = PDO_ErrorInfo();
+	$respond['status']=1;
+	$respond['message']=$error[2];
+}
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 229 - 0
app/article/my_collect.js

@@ -0,0 +1,229 @@
+function my_collect_init() {
+  my_collect_list();
+  collect_add_dlg_init("collect_add_div");
+}
+function my_collect_list() {
+  $.get(
+    "../article/collect_list.php",
+    {
+      userid: getCookie("userid"),
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          let key = 1;
+          for (const iterator of result) {
+            html += '<div class="file_list_row" style="padding:5px;">';
+            html +=
+              '<div style="max-width:2em;flex:1;"><input type="checkbox" /></div>';
+            html += "<div style='flex:1;'>" + key++ + "</div>";
+            html += "<div style='flex:2;'>" + iterator.title + "</div>";
+            html +=
+              "<div style='flex:2;'>" +
+              render_status(iterator.status) +
+              "</div>";
+            html += "<div style='flex:1;'>Copy Link</div>";
+            html +=
+              "<div style='flex:1;'><a href='../article/my_collect_edit.php?id=" +
+              iterator.id +
+              "'>Edit</a></div>";
+            html +=
+              "<div style='flex:1;'><a href='../article/?id=" +
+              iterator.id +
+              "' target='_blank'>Preview</a></div>";
+            html += "<div style='flex:1;'>15</div>";
+            html += "</div>";
+          }
+          $("#article_list").html(html);
+        } catch (e) {
+          console.error(e);
+        }
+      } else {
+        console.error("ajex error");
+      }
+    }
+  );
+}
+var _arrArticleList;
+var _arrArticleOrder = new Array();
+function my_collect_edit(id) {
+  $.get(
+    "../article/collect_get.php",
+    {
+      id: id,
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          $("#article_collect").attr("a_id", result.id);
+          html += '<div class="" style="padding:5px;">';
+          html += '<div style="max-width:2em;flex:1;"></div>';
+          html += "<input type='hidden' name='id' value='" + result.id + "'/>";
+          html +=
+            "<input type='hidden' name='subtitle' value='" +
+            result.subtitle +
+            "'/>";
+          html +=
+            "<input type='hidden' name='summary' value='" +
+            result.summary +
+            "'/>";
+          html +=
+            "<input type='hidden' name='status' value='" +
+            result.status +
+            "'/>";
+          html +=
+            "<input type='hidden' name='lang' value='" + result.lang + "'/>";
+          html +=
+            "<input id='form_article_list' type='hidden' name='article_list' value='" +
+            result.article_list +
+            "'/>";
+          html += "</div>";
+          html += "<div style='display:flex;'>";
+          html += "<div style='flex:4;'>";
+
+          _arrArticleList = JSON.parse(result.article_list);
+          html += "<ul id='ul_article_list'>";
+          for (let index = 0; index < _arrArticleList.length; index++) {
+            const element = _arrArticleList[index];
+            html += my_collect_render_article(index, element);
+            _arrArticleOrder.push(index);
+          }
+
+          html += "</ul>";
+
+          html += "</div>";
+
+          html += "<div id='preview_div'>";
+          html += "<div id='preview_inner' ></div>";
+          html += "</div>";
+
+          html += "</div>";
+
+          $("#article_list").html(html);
+          $("#collect_title").val(result.title);
+
+          $("#ul_article_list").sortable({
+            update: function (event, ui) {
+              let sortedIDs = $("#ul_article_list").sortable("toArray");
+              _arrArticleOrder = new Array();
+              for (const iSorted of sortedIDs) {
+                let newindex = parseInt($("#" + iSorted).attr("article_index"));
+                _arrArticleOrder.push(_arrArticleList[newindex]);
+              }
+              $("#form_article_list").val(JSON.stringify(_arrArticleOrder));
+            },
+          });
+
+          $("#aritcle_status").html(render_status(result.status));
+          let html_title =
+            "<input id='input_article_title' type='input' name='title' value='" +
+            result.title +
+            "' />";
+          $("#article_title").html(html_title);
+        } catch (e) {
+          console.error(e);
+        }
+      } else {
+        console.error("ajex error");
+      }
+    }
+  );
+}
+
+function my_collect_render_article(index, article) {
+  let html = "";
+  html +=
+    "<li id='article_item_" +
+    index +
+    "' article_index='" +
+    index +
+    "' class='file_list_row'>";
+  html += "<span style='flex:1;'>";
+  html += "<select>";
+  let selected = "";
+  for (let i = 1; i < 9; i++) {
+    if (parseInt(article.level) == i) {
+      selected = "selected";
+    } else {
+      selected = "";
+    }
+    html += "<option " + selected + " value='" + i + "' >H " + i + "</option>";
+  }
+  html += "</select>";
+  html += "</span>";
+  html += "<span style='flex:3;'>";
+  html +=
+    "<a href='../article/my_article_edit.php?id=" + article.article + "'>";
+  html += article.title;
+  html += "</a>";
+  html += "</span>";
+  html +=
+    "<span style='flex:1;' onclick=\"article_preview('" +
+    article.article +
+    "')\">";
+  html += "Preview";
+  html += "</span>";
+  html += "</li>";
+  return html;
+}
+
+function article_preview(id) {
+  $.get(
+    "../article/get.php",
+    {
+      id: id,
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          $("#preview_inner").html(note_init(result.content));
+          note_refresh_new();
+        } catch (e) {
+          console.error(e.message);
+        }
+      }
+    }
+  );
+}
+
+function my_collect_save() {
+  $.ajax({
+    type: "POST", //方法类型
+    dataType: "json", //预期服务器返回的数据类型
+    url: "../article/my_collect_post.php", //url
+    data: $("#collect_edit").serialize(),
+    success: function (result) {
+      console.log(result); //打印服务端返回的数据(调试用)
+
+      if (result.status == 0) {
+        alert("保存成功");
+      } else {
+        alert("error:" + result.message);
+      }
+    },
+    error: function (data, status) {
+      alert("异常!" + data.responseText);
+      switch (status) {
+        case "timeout":
+          break;
+        case "error":
+          break;
+        case "notmodified":
+          break;
+        case "parsererror":
+          break;
+        default:
+          break;
+      }
+    },
+  });
+}

+ 100 - 0
app/article/my_collect_edit.php

@@ -0,0 +1,100 @@
+<?php
+require_once '../studio/index_head.php';
+?>
+<body id="file_list_body" >
+
+	<script language="javascript" src="../article/my_collect.js"></script>
+	<script language="javascript" src="../term/note.js"></script>
+	<script language="javascript" src="../term/term.js"></script>
+	<script language="javascript" src="../public/js/marked.js"></script>
+	<script language="javascript" src="../article/add_to_collect_dlg.js"></script>
+	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>
+
+	<script >
+	var gCurrPage="collect";
+	</script>
+
+	<style>
+	#collect {
+		background-color: var(--btn-border-color);
+		
+	}
+	#collect:hover{
+		background-color: var(--btn-border-color);
+		color: var(--btn-color);
+		cursor:auto;
+	}
+	.file_list_block{
+		width:unset;
+	}
+	.case_dropdown-content>a {
+		display:block;
+	}
+	.case_dropdown-content>.active{
+		background-color:gray;
+	}
+	.file_list_block {
+    max-width: 100%;
+    margin-right: 1em;
+	}
+	.index_inner {
+    margin-left: 16em;
+    margin-top: 5em;
+}
+#preview_div {
+    flex: 6;
+    overflow-y: scroll;
+    height: 550px;
+}
+
+	</style>
+
+	<?php
+	require_once '../studio/index_tool_bar.php';
+	?>
+		
+	<div class="index_inner " >
+	<form id="collect_edit" action="##" onsubmit="return false"  method="POST" >
+	<div class="file_list_block">
+		<div class="tool_bar">
+			<div style="display:flex;">
+				<a href="../article/my_collect_index.php">返回</a>
+				<span><input  id="collect_title" type='input' name='title' value="" /></span>
+			</div>
+			<div style="display:flex;">
+				<div id="aritcle_status"></div>
+				<span class="icon_btn_div">
+					<span class="icon_btn_tip">保存</span>
+					<button id="edit_save" type="button" class="icon_btn" title=" " onclick="my_collect_save()">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_save"></use>
+						</svg>
+					</button>
+				</span>
+				
+				<span class="icon_btn_div">				
+					<span class="icon_btn_tip">回收站</span>
+					<button id="to_recycle" type="button" class="icon_btn" onclick="article_del()" title=" ">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_delete"></use>
+						</svg>
+					</button>
+				</span>	
+			</div>
+		</div>
+
+		<div id="article_list"  class="file_list_block" style="">
+
+		</div>
+
+	</div>
+</form>
+	</div>
+	
+<script>
+my_collect_edit("<?php echo $_GET["id"] ?>");
+</script>
+<?php
+require_once '../studio/index_foot.php';
+?>
+

+ 64 - 0
app/article/my_collect_index.php

@@ -0,0 +1,64 @@
+<?php
+require_once '../studio/index_head.php';
+?>
+<body id="file_list_body" onLoad="my_collect_init()">
+
+	<script language="javascript" src="../article/my_article.js"></script>
+	<script language="javascript" src="../article/my_collect.js"></script>
+	<script language="javascript" src="../article/collect_add_dlg.js"></script>
+	<script >
+	var gCurrPage="collect";
+	</script>
+
+	<style>
+	#collect {
+		background-color: var(--btn-border-color);
+		
+	}
+	#collect:hover{
+		background-color: var(--btn-border-color);
+		color: var(--btn-color);
+		cursor:auto;
+	}
+	</style>
+
+<?php
+require_once '../studio/index_tool_bar.php';
+?>
+		
+		<div class="index_inner " style="margin-left: 18em;margin-top: 5em;">
+		<div class="file_list_block">
+			<div class="tool_bar">
+				<div>文集列表</div>
+				<div>
+					<span class="icon_btn_div">
+						<span class="icon_btn_tip"></span>
+						<button id="file_add" type="button" class="icon_btn" title=" " onclick="collect_add_dlg_show()">
+							<svg class="icon">
+								<use xlink:href="../studio/svg/icon.svg#ic_add_circle"></use>
+							</svg>
+						</button>
+						<div id='collect_add_div' class="float_dlg"></div>
+					</span>
+					
+					<span class="icon_btn_div">				
+						<span class="icon_btn_tip">回收站</span>
+						<button id="to_recycle" type="button" class="icon_btn" onclick="file_del()" title=" ">
+							<svg class="icon">
+								<use xlink:href="../studio/svg/icon.svg#ic_delete"></use>
+							</svg>
+						</button>
+					</span>	
+				</div>
+			</div>
+
+			<div id="article_list"  class="file_list_block" style="">
+
+			</div>
+		</div>
+	</div>
+	
+<?php
+require_once '../studio/index_foot.php';
+?>
+

+ 43 - 0
app/article/my_collect_post.php

@@ -0,0 +1,43 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+
+PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+
+$query="UPDATE collect SET title = ? , subtitle = ? , summary = ?, article_list = ?  ,  status = ? , lang = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$sth = $PDO->prepare($query);
+$sth->execute(array($_POST["title"] , $_POST["subtitle"] ,$_POST["summary"], $_POST["article_list"] , $_POST["status"] , $_POST["lang"] ,  mTime() , mTime() , $_POST["id"]));
+$respond=array("status"=>0,"message"=>"");
+if (!$sth || ($sth && $sth->errorCode() != 0)) {
+	$error = PDO_ErrorInfo();
+	$respond['status']=1;
+	$respond['message']=$error[2];
+}
+else{
+    # 更新 article_list 表
+    $query = "DELETE FROM article_list WHERE collect_id = ? ";
+     PDO_Execute($query,array($_POST["id"]));
+     $arrList = json_decode($_POST["article_list"]);
+     if(count($arrList)>0){
+        /* 开始一个事务,关闭自动提交 */
+        $PDO->beginTransaction();
+        $query = "INSERT INTO article_list (collect_id, article_id,level,title) VALUES ( ?, ?, ? , ? )";
+        $sth = $PDO->prepare($query);
+        foreach ($arrList as $row) {
+            $sth->execute(array($_POST["id"],$row->article,$row->level,$row->title));
+        }
+        $PDO->commit();
+        if (!$sth || ($sth && $sth->errorCode() != 0)) {
+            /*  识别错误且回滚更改  */
+            $PDO->rollBack();
+            $error = PDO_ErrorInfo();
+            $respond['status']=1;
+            $respond['message']=$error[2];
+        }
+     }
+}
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 19 - 0
app/article/my_collect_put.php

@@ -0,0 +1,19 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+
+$query="INSERT INTO collect ( id,  title  , subtitle  , summary , article_list   , owner, lang  , status  , create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ?  , ? , ? , ? , ? , ? , ? , ? ) ";
+$sth = $PDO->prepare($query);
+$sth->execute(array(UUID::v4() , $_POST["title"] , "" ,"", "[]" ,  $_COOKIE["userid"] , "" , 1 , mTime() ,  mTime() , mTime() ));
+$respond=array("status"=>0,"message"=>"");
+if (!$sth || ($sth && $sth->errorCode() != 0)) {
+	$error = PDO_ErrorInfo();
+	$respond['status']=1;
+	$respond['message']=$error[2];
+}
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 155 - 17
app/channal/channal.js

@@ -1,25 +1,163 @@
 var _my_channal = null;
+channal_list();
 
-$.post(
-      "../channal/get.php",
-      {
+function channal_list_init() {
+  my_channal_list();
+  channal_add_dlg_init("channal_add_div");
+}
+function channal_list() {
+  $.post("../channal/get.php", {}, function (data) {
+    try {
+      _my_channal = JSON.parse(data);
+    } catch (e) {
+      console.error(e);
+    }
+  });
+}
 
-      },
-      function(data){
-          try{
-              _my_channal = JSON.parse(data);
-          }
-          catch(e){
-              console.error(e);
+function channal_getById(id) {
+  for (const iterator of _my_channal) {
+    if (iterator.id == id) {
+      return iterator;
+    }
+  }
+  return false;
+}
+
+function my_channal_list() {
+  $.get(
+    "../channal/get.php",
+    {
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          let key = 1;
+          for (const iterator of result) {
+            html += '<div class="file_list_row" style="padding:5px;">';
+            html +=
+              '<div style="max-width:2em;flex:1;"><input type="checkbox" /></div>';
+            html += "<div style='flex:1;'>" + key++ + "</div>";
+            html += "<div style='flex:2;'>" + iterator.name + "</div>";
+            html += "<div style='flex:2;'>" + iterator.owner + "</div>";
+            html +=
+              "<div style='flex:2;'>" +
+              //render_status(iterator.status) +
+              "</div>";
+            html +=
+              "<div style='flex:1;'><a href='../channal/my_channal_edit.php?id=" +
+              iterator.id +
+              "'>Edit</a></div>";
+            html += "<div style='flex:1;'>15</div>";
+            html += "</div>";
           }
+          $("#my_channal_list").html(html);
+        } catch (e) {
+          console.error(e);
+        }
+      } else {
+        console.error("ajex error");
       }
-    );
+    }
+  );
+}
 
-function channal_getById(id) {
-    for (const iterator of _my_channal) {
-        if(iterator.id==id){
-            return iterator;
+function my_channal_edit(id) {
+  $.get(
+    "../channal/my_channal_get.php",
+    {
+      id: id,
+      setting: "",
+    },
+    function (data, status) {
+      if (status == "success") {
+        try {
+          let html = "";
+          let result = JSON.parse(data);
+          $("#article_collect").attr("a_id", result.id);
+          html += '<div class="" style="padding:5px;">';
+          html += '<div style="max-width:2em;flex:1;"></div>';
+          html += "</div>";
+          html += "<div style='display:flex;'>";
+          html += "<div style='flex:4;'>";
+          html += "<input type='hidden' name='id' value='" + result.id + "'/>";
+          html +=
+            "<input type='input' name='name' value='" + result.name + "'/>";
+          html += "<textarea name='summary'>" + result.summary + "</textarea>";
+          html +=
+            '<div>	<input id="channal_lang_select" type="input" onchange="channal_lang_change()"  title="type language name/code" code="' +
+            result.lang +
+            '" value="' +
+            result.lang +
+            '" > <input id="channal_lang" type="hidden" name="lang" value=""></div>';
+          html +=
+            "<input type='hidden' name='status' value='" +
+            result.status +
+            "'/>";
+          html += "</div>";
+
+          html += "<div id='preview_div'>";
+          html += "<div id='preview_inner' ></div>";
+          html += "</div>";
+
+          html += "</div>";
+
+          $("#channal_info").html(html);
+          tran_lang_select_init("channal_lang_select");
+          //$("#aritcle_status").html(render_status(result.status));
+          $("#channal_title").html(result.name);
+          $("#preview_inner").html();
+        } catch (e) {
+          console.error(e);
         }
+      } else {
+        console.error("ajex error");
+      }
     }
-    return false;
-}
+  );
+}
+
+function channal_lang_change() {
+  let lang = $("#channal_lang_select").val();
+  if (lang.split("-").length == 3) {
+    $("#channal_lang").val(lang.split("-")[2]);
+  } else {
+    $("#channal_lang").val(lang);
+  }
+}
+
+function my_channal_save() {
+  $.ajax({
+    type: "POST", //方法类型
+    dataType: "json", //预期服务器返回的数据类型
+    url: "../channal/my_channal_post.php", //url
+    data: $("#channal_edit").serialize(),
+    success: function (result) {
+      console.log(result); //打印服务端返回的数据(调试用)
+
+      if (result.status == 0) {
+        alert("保存成功");
+      } else {
+        alert("error:" + result.message);
+      }
+    },
+    error: function (data, status) {
+      alert("异常!" + status + data.responseText);
+      switch (status) {
+        case "timeout":
+          break;
+        case "error":
+          break;
+        case "notmodified":
+          break;
+        case "parsererror":
+          break;
+        default:
+          break;
+      }
+    },
+  });
+}

+ 64 - 0
app/channal/channal_add_dlg.js

@@ -0,0 +1,64 @@
+var _channal_add_dlg_div;
+function channal_add_dlg_init(div) {
+  _channal_add_dlg_div = div;
+  let html = "";
+  html += "<div id='channal_add_dlg'>";
+  html += "<div >";
+  html += "<div >Channal Title</div>";
+  html += "<input type='input' id='channal_add_title' />";
+  html += "</div>";
+  html += "<div>";
+  html += "</div>";
+  html +=
+    "<div style='display:flex;justify-content: space-between;padding-top: 1em;'>";
+  html += "<div>";
+  html += "<select id='channal_add_dlg_lang' name='lang'>";
+  html += "<option value='zh'>Chinese-中文</option>";
+  html += "<option value='en'>English-English</option>";
+  html += "<option value='my'>Mymarnese-</option>";
+  html += "</select>";
+
+  html += "</div>";
+  html += "<div>";
+  html += "<button onclick='channal_add_cancel()'>Cancel</button>";
+  html += "<button onclick='channal_add_new()'>New</button>";
+  html += "</div>";
+  html += "</div>";
+  html += "</div>";
+
+  $("#" + div).append(html);
+}
+
+function channal_add_dlg_show() {
+  $("#" + _channal_add_dlg_div).show();
+}
+function channal_add_dlg_hide() {
+  $("#" + _channal_add_dlg_div).hide();
+}
+function channal_add_cancel() {
+  channal_add_dlg_hide();
+  $("#channal_add_title").val("");
+}
+
+function channal_add_new() {
+  if ($("#channal_add_title").val() == "") {
+    alert("channal name is empty!");
+    return;
+  }
+  $.post(
+    "../channal/my_channal_put.php",
+    {
+      name: $("#channal_add_title").val(),
+      lang: $("#channal_add_dlg_lang").val(),
+    },
+    function (data) {
+      let error = JSON.parse(data);
+      if (error.status == 0) {
+        alert("ok");
+        channal_add_cancel();
+      } else {
+        alert(error.message);
+      }
+    }
+  );
+}

+ 35 - 5
app/channal/get.php

@@ -3,11 +3,41 @@
 
 require_once "../path.php";
 require_once "../public/_pdo.php";
+require_once '../ucenter/function.php';
+
+$_userinfo = new UserInfo();
 
-global $PDO;
 PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
-$query = "select * from channal where owner = '{$_COOKIE["userid"]}'   limit 0,100";
-$Fetch = PDO_FetchAll($query);
-echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+$query = "SELECT * from channal where owner = ?   limit 0,100";
+$Fetch_my = PDO_FetchAll($query,array($_COOKIE["userid"]));
+
+# 找协作的
+$Fetch_coop = array();
+$query = "SELECT channal_id FROM cooperation WHERE  user_id = ? ";
+$coop_channal = PDO_FetchAll($query,array($_COOKIE["userid"]));
+if(count($coop_channal)>0){
+    foreach ($coop_channal as $key => $value) {
+        # code...
+        $channal[]=$value["channal_id"];
+    }
+    /*  创建一个填充了和params相同数量占位符的字符串 */
+    $place_holders = implode(',', array_fill(0, count($channal), '?'));
+    $query = "SELECT * FROM channal WHERE id IN ($place_holders) order by owner";
+    $Fetch_coop = PDO_FetchAll($query,$channal);
+}
+$all = array_merge_recursive($Fetch_my,$Fetch_coop);
+$output = array();
+foreach ($all as $key => $value) {
+    # code...
+    $new = $value;
+    $name = $_userinfo->getName($value["owner"]);
+    $new["username"] = $name["username"];
+	$new["nickname"] = $name["nickname"];
+	$new["count"] = 0;
+    $new["all"] = 1;
+    $output[]=$new;
+}
+
+echo json_encode($output, JSON_UNESCAPED_UNICODE);
 
-?>				
+?>

+ 99 - 0
app/channal/my_channal_edit.php

@@ -0,0 +1,99 @@
+<?php
+require_once '../studio/index_head.php';
+?>
+<body id="file_list_body" >
+
+	<script language="javascript" src="../channal/channal.js"></script>
+	<script language="javascript" src="../public/js/marked.js"></script>
+	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>
+	<link type="text/css" rel="stylesheet" href="../public/js/jquery-ui-1.12.1/jquery-ui.css"/>
+	<script language="javascript" src="../lang/tran_lang_select.js"></script>
+
+	<script >
+	var gCurrPage="channal";
+	</script>
+
+	<style>
+	#channal {
+		background-color: var(--btn-border-color);
+		
+	}
+	#channal:hover{
+		background-color: var(--btn-border-color);
+		color: var(--btn-color);
+		cursor:auto;
+	}
+	.file_list_block{
+		width:unset;
+	}
+	.case_dropdown-content>a {
+		display:block;
+	}
+	.case_dropdown-content>.active{
+		background-color:gray;
+	}
+	.file_list_block {
+    max-width: 100%;
+    margin-right: 1em;
+	}
+	.index_inner {
+    margin-left: 16em;
+    margin-top: 5em;
+}
+#preview_div {
+    flex: 6;
+    overflow-y: scroll;
+    height: 550px;
+}
+
+	</style>
+
+	<?php
+	require_once '../studio/index_tool_bar.php';
+	?>
+		
+	<div class="index_inner " >
+	<form id="channal_edit" action="##" onsubmit="return false"  method="POST" >
+	<div class="file_list_block">
+		<div class="tool_bar">
+			<div style="display:flex;">
+				<a href="../channal/my_channal_index.php">返回</a>
+				<span id="channal_title"></span>
+			</div>
+			<div style="display:flex;">
+				<div id="aritcle_status"></div>
+				<span class="icon_btn_div">
+					<span class="icon_btn_tip">保存</span>
+					<button id="edit_save" type="button" class="icon_btn" title=" " onclick="my_channal_save()">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_save"></use>
+						</svg>
+					</button>
+				</span>
+				
+				<span class="icon_btn_div">				
+					<span class="icon_btn_tip">回收站</span>
+					<button id="to_recycle" type="button" class="icon_btn" onclick="channal_del()" title=" ">
+						<svg class="icon">
+							<use xlink:href="../studio/svg/icon.svg#ic_delete"></use>
+						</svg>
+					</button>
+				</span>	
+			</div>
+		</div>
+
+		<div id="channal_info"  class="file_list_block" style="">
+
+		</div>
+
+	</div>
+</form>
+	</div>
+	
+<script>
+my_channal_edit("<?php echo $_GET["id"] ?>");
+</script>
+<?php
+require_once '../studio/index_foot.php';
+?>
+

+ 25 - 0
app/channal/my_channal_get.php

@@ -0,0 +1,25 @@
+<?php
+//查询term字典
+
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../ucenter/function.php';
+
+
+if(isset($_GET["id"])){
+    PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
+    $id=$_GET["id"];
+    $query = "SELECT * FROM channal  WHERE id = ? ";
+    $Fetch = PDO_FetchRow($query,array($id));
+    echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+}
+else{
+    PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
+    $query = "SELECT * FROM channal  WHERE owner = ? ";
+    $Fetch = PDO_FetchAll($query,array($_COOKIE["userid"]));
+    echo json_encode($Fetch, JSON_UNESCAPED_UNICODE);
+}
+
+
+?>

+ 9 - 9
app/channal/my_channal_list.php → app/channal/my_channal_index.php

@@ -1,10 +1,11 @@
 <?php
 require_once '../studio/index_head.php';
 ?>
-<body id="file_list_body" onLoad="course_list()">
+<body id="file_list_body" onLoad="channal_list_init()">
 
-	<script language="javascript" src="../course/my_couse.js"></script>
 	<script language="javascript" src="../ucenter/name_selector.js"></script>
+	<script language="javascript" src="../channal/channal_add_dlg.js"></script>
+	<script language="javascript" src="../channal/channal.js"></script>
 	<script >
 	var gCurrPage="channal";
 	</script>
@@ -35,14 +36,13 @@ require_once '../studio/index_head.php';
 
 	<div>
 		<span class="icon_btn_div">
-			<span class="icon_btn_tip"><?php echo $_local->gui->add;?></span>
-			<button id="file_add" type="button" class="icon_btn" title=" ">
-				<a href="../course/my_channal_new.php">
+			<span class="icon_btn_tip"><?php echo "Add";?></span>
+			<button id="file_add" type="button" class="icon_btn" title=" "  onclick="channal_add_dlg_show()">
 				<svg class="icon">
 					<use xlink:href="../studio/svg/icon.svg#ic_add_circle"></use>
 				</svg>
-				</a>
 			</button>
+			<div id='channal_add_div' class="float_dlg"></div>
 		</span>
 		
 		<span class="icon_btn_div">				
@@ -57,9 +57,9 @@ require_once '../studio/index_head.php';
 				
 </div>
 
-<div id="userfilelist">
+<div id="my_channal_list">
 <?php
-//
+/*
 
 require_once "../path.php";
 require_once "../public/_pdo.php";
@@ -82,7 +82,7 @@ foreach($Fetch as $row){
     
     echo '</div>';
 }
-
+*/
 ?>				
 </div>
 			

+ 56 - 0
app/channal/my_channal_post.php

@@ -0,0 +1,56 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+
+#先查询对此channal是否有权限修改
+   PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
+$cooperation = 0;
+if(isset($_POST["id"])){
+    $query = "SELECT owner FROM channal WHERE id=?";
+    $fetch = PDO_FetchOne($query,array($_POST["id"]));
+    if($fetch && $fetch==$_COOKIE["userid"]){
+        #自己的channal
+        $cooperation = 1;
+    }
+    else{
+        $query = "SELECT count(*) FROM cooperation WHERE channal_id= ? and user_id=? ";
+        $fetch = PDO_FetchOne($query,array($_POST["id"],$_COOKIE["userid"]));
+        if($fetch>0){
+            #有协作权限
+            $cooperation = 1;
+        }
+        else{
+            #无协作权限
+            $cooperation = 0;
+        }
+    }
+}
+else{
+    $respond["status"] = 1;
+    $respond["message"] = 'error channal id';
+    echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+if($cooperation==0){
+    $respond["status"] = 1;
+    $respond["message"] = 'error 无修改权限';
+    echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+
+
+$query="UPDATE channal SET name = ? ,  summary = ?,  status = ? , lang = ? , receive_time= ?  , modify_time= ?   where  id = ?  ";
+$sth = $PDO->prepare($query);
+$sth->execute(array($_POST["name"] , $_POST["summary"], $_POST["status"] , $_POST["lang"] ,  mTime() , mTime() , $_POST["id"]));
+$respond=array("status"=>0,"message"=>"");
+if (!$sth || ($sth && $sth->errorCode() != 0)) {
+	$error = PDO_ErrorInfo();
+	$respond['status']=1;
+	$respond['message']=$error[2];
+}
+
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 20 - 0
app/channal/my_channal_put.php

@@ -0,0 +1,20 @@
+<?php
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once '../public/function.php';
+require_once '../hostsetting/function.php';
+$respond=array("status"=>0,"message"=>"");
+if(isset($_COOKIE["userid"])){
+	PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
+	$query="INSERT INTO channal ( id,  owner  , name  , summary ,  status  , lang, create_time , modify_time , receive_time   )  VALUES  ( ? , ? , ? , ? , ? , ? , ? , ? , ?  ) ";
+	$sth = $PDO->prepare($query);
+	$sth->execute(array(UUID::v4() , $_COOKIE["userid"] , $_POST["name"] , "" , 1 ,$_POST["lang"]  ,  mTime() ,  mTime() , mTime() ));
+	$respond=array("status"=>0,"message"=>"");
+	if (!$sth || ($sth && $sth->errorCode() != 0)) {
+		$error = PDO_ErrorInfo();
+		$respond['status']=1;
+		$respond['message']=$error[2];
+	}	
+}
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 10 - 11
app/guide/guide.css

@@ -46,20 +46,19 @@ guide ol {
   color: var(--main-color);
   z-index: 200;
 }
-/*
+
 .guide_contence:after {
-    content: "\00a0";
-    width: 0;
-    height: 0;
-    display: block;
-    border-style: solid;
-    border-width: 10px;
-    border-color: transparent transparent white transparent;
-    position: absolute;
-    top: -20px;
+  content: "\00a0";
+  width: 0;
+  height: 0;
+  display: block;
+  border-style: solid;
+  border-width: 10px;
+  border-color: transparent transparent var(--drop-bg-color) transparent;
+  position: absolute;
+  top: -20px;
 }
 
-*/
 .guide_contence h1 {
   font-size: 1.5em;
   font-weight: 700;

+ 0 - 6
app/guide/guide.js

@@ -40,12 +40,6 @@ function guide_init() {
         }
       }
     );
-    /*        if ($(this).offset().left < $(document.body).width() / 2) {
-                    $(".guide_contence:after").css("left", "0");
-                }
-                else {
-                    $(".guide_contence:after").css("right", "0");
-                }*/
   });
 }
 

+ 1 - 2
app/guide/guide_icon.svg

@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 <!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
-	y="0px" width="14px" height="14px" viewBox="0 0 14 14" style="fill: #6baaff;" xml:space="preserve">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="14px" height="14px" viewBox="0 0 14 14" style="fill: #6baaff;" xml:space="preserve">
 	<path d="M7,0C3.134,0,0,3.134,0,7s3.134,7,7,7s7-3.134,7-7S10.866,0,7,0z M7,2c0.552,0,1,0.447,1,1S7.552,4,7,4S6,3.553,6,3
 	S6.448,2,7,2z M9,11H5v-1h1V6H5V5h3v5h1V11z" />
 </svg>

+ 48 - 0
app/hostsetting/function.php

@@ -0,0 +1,48 @@
+<?php
+require_once '../path.php';
+
+class Hostsetting
+{
+    public $dbh;
+    public function __construct() {
+        $dns = "sqlite:"._FILE_DB_HOSTSETTING_;
+        $this->dbh = new PDO($dns, "", "",array(PDO::ATTR_PERSISTENT=>true));
+        $this->dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);  
+    }
+
+    public function get($key){
+        if($this->dbh){
+            $query = "SELECT value FROM setting WHERE key= ? ";
+            $stmt = $this->dbh->prepare($query);
+            $stmt->execute(array($key));
+            $row = $stmt->fetch(PDO::FETCH_NUM);
+            if ($row) {
+                return $row[0];
+            } else {
+                return false;
+            }
+        }
+        else{
+            return false;
+        }
+    }
+
+    public function set($key,$value){
+        if($this->dbh){
+            $query = "UPDATE setting SET value = ?  WHERE key= ? ";
+            $stmt = $this->dbh->prepare($query);
+            $stmt->execute(array($value,$key));
+            if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
+                $error = PDO_ErrorInfo();
+                return false;
+            }
+            else{
+                return true;
+            }
+        }
+        else{
+            return false;
+        }
+    }
+}
+?>

+ 21 - 0
app/lang/tran_lang_select.js

@@ -0,0 +1,21 @@
+var _tran_lang_select_div;
+function tran_lang_select_init(div) {
+  _tran_lang_select_div = div;
+  $.getJSON("../lang/lang_list.json", function (result) {
+    let lang_list = new Array();
+    let langCode = $("#" + _tran_lang_select_div).attr("code");
+    let strLang;
+    for (const iterator of result) {
+      if (iterator.code == langCode) {
+        strLang = iterator.english + "-" + iterator.name + "-" + iterator.code;
+      }
+      lang_list.push(
+        iterator.english + "-" + iterator.name + "-" + iterator.code
+      );
+    }
+    $("#" + _tran_lang_select_div).val(strLang);
+    $("#" + _tran_lang_select_div).autocomplete({
+      source: lang_list,
+    });
+  });
+}

+ 0 - 0
app/like/get.php


+ 18 - 0
app/like/like.css

@@ -0,0 +1,18 @@
+.like_icon {
+  position: relative;
+  display: inline-block;
+  width: auto;
+  min-width: 14px;
+  height: auto;
+  min-height: 14px;
+  cursor: pointer;
+  background: url(like.svg);
+  background-repeat: no-repeat;
+  background-size: contain;
+  margin: 0 6px;
+  color: var(--tool-color);
+}
+
+.i_like {
+  background: url(like1.svg);
+}

+ 9 - 0
app/like/like.js

@@ -0,0 +1,9 @@
+function like_init() {
+  $("like").each(function () {
+    if ($(this).html().length == 0) {
+      $(this).append(
+        "<span class='like_icon'></span></span><span class='like_count'>0</span>"
+      );
+    }
+  });
+}

+ 1 - 0
app/like/like.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1602127746076" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3073" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M667.786667 117.333333C832.864 117.333333 938.666667 249.706667 938.666667 427.861333c0 138.250667-125.098667 290.506667-371.573334 461.589334a96.768 96.768 0 0 1-110.186666 0C210.432 718.368 85.333333 566.112 85.333333 427.861333 85.333333 249.706667 191.136 117.333333 356.213333 117.333333c59.616 0 100.053333 20.832 155.786667 68.096C567.744 138.176 608.170667 117.333333 667.786667 117.333333z m0 63.146667c-41.44 0-70.261333 15.189333-116.96 55.04-2.165333 1.845333-14.4 12.373333-17.941334 15.381333a32.32 32.32 0 0 1-41.770666 0c-3.541333-3.018667-15.776-13.536-17.941334-15.381333-46.698667-39.850667-75.52-55.04-116.96-55.04C230.186667 180.48 149.333333 281.258667 149.333333 426.698667 149.333333 537.6 262.858667 675.242667 493.632 834.826667a32.352 32.352 0 0 0 36.736 0C761.141333 675.253333 874.666667 537.6 874.666667 426.698667c0-145.44-80.853333-246.218667-206.88-246.218667z" p-id="3074"></path></svg>

+ 1 - 0
app/like/like1.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1602127733716" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2928" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M667.786667 117.333333C832.864 117.333333 938.666667 249.706667 938.666667 427.861333c0 138.250667-125.098667 290.506667-371.573334 461.589334a96.768 96.768 0 0 1-110.186666 0C210.432 718.368 85.333333 566.112 85.333333 427.861333 85.333333 249.706667 191.136 117.333333 356.213333 117.333333c59.616 0 100.053333 20.832 155.786667 68.096C567.744 138.176 608.170667 117.333333 667.786667 117.333333z" p-id="2929"></path></svg>

+ 0 - 0
app/like/put.php


+ 1 - 0
app/path.php

@@ -70,5 +70,6 @@ define("_FILE_DB_USER_STATISTICS_"  , __DIR__."/../tmp/user/statistics.db3");
 define("_FILE_DB_CHANNAL_"  , __DIR__."/../tmp/user/channal.db3");
 define("_FILE_DB_USER_DICT_"  , __DIR__."/../tmp/user/udict.db3");
 define("_FILE_DB_USER_ARTICLE_"  , __DIR__."/../tmp/user/article.db3");
+define("_FILE_DB_HOSTSETTING_"  , __DIR__."/../tmp/user/hostsetting.db3");
 
 ?>

+ 96 - 77
app/pcdl/css/basic_style.css

@@ -1,21 +1,21 @@
 body {
-    font-family: 'Noto Sans', 'Noto Sans SC', 'Noto Sans TC', Arial, Verdana;
-    font-style: normal;
-    color: var(--main-color);
-    font-weight: 400;
-    font-size: 13px;
-    overflow-x:hidden; 
-    margin:0;
+  font-family: "Noto Sans", "Noto Sans SC", "Noto Sans TC", Arial, Verdana;
+  font-style: normal;
+  color: var(--main-color);
+  font-weight: 400;
+  font-size: 13px;
+  overflow-x: hidden;
+  margin: 0;
 }
 div {
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    box-sizing: border-box;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
 }
-hr{
-    margin: 14px 0;
-    border:1px solid var(--tool-line-color);
-    transform: scaleY(.4);
+hr {
+  margin: 14px 0;
+  border: 1px solid var(--tool-line-color);
+  transform: scaleY(0.4);
 }
 
 input,
@@ -23,98 +23,117 @@ button,
 textarea,
 select,
 optgroup,
-option, 
+option,
 hr,
-h1, 
-h2, 
+h1,
+h2,
 h3 {
-    font-family: inherit;
-    font-size: inherit;
-    font-style: inherit;
-    font-weight: inherit;
-    color: inherit;
-    background-color: inherit;
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-    box-sizing: border-box;
+  font-family: inherit;
+  font-size: inherit;
+  font-style: inherit;
+  font-weight: inherit;
+  color: inherit;
+  background-color: inherit;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  box-sizing: border-box;
 }
 
 input[type="text"],
-input[type="input"], 
+input[type="input"],
 textarea {
-    font-weight: 300;
-    width: 100%;
-    border: 1px solid var(--btn-border-line-color);
-    border-radius: 4px;
-    padding: 0.1em 0.3em;
-    font-size: 100%;
-    min-height: 1.2em;
-    margin: 2px 0;
+  font-weight: 300;
+  width: 100%;
+  border: 1px solid var(--btn-border-line-color);
+  border-radius: 4px;
+  padding: 0.1em 0.3em;
+  font-size: 100%;
+  min-height: 1.2em;
+  margin: 2px 0;
 }
 select {
-    font-weight: 400;
-    border: 1px solid #aaaaaa;
-    padding: 2px 4px;
-    min-height: 2em;
-    border-radius: 4px;
-    cursor: pointer;
-    margin: 3px 0;
+  font-weight: 400;
+  border: 1px solid #aaaaaa;
+  padding: 2px 4px;
+  min-height: 2em;
+  border-radius: 4px;
+  cursor: pointer;
+  margin: 3px 0;
 }
 
 ul,
 li {
-    white-space: normal;
-    color: inherit;
-    margin: 0px;
-    padding: 0px;
-    word-break: keep-all;
-    text-overflow: ellipsis;
-	list-style-type: none;
+  white-space: normal;
+  color: inherit;
+  margin: 0px;
+  padding: 0px;
+  word-break: keep-all;
+  text-overflow: ellipsis;
+  list-style-type: none;
 }
 a,
 a:link,
 a:visited {
-    color: var(--link-color);
-    text-decoration: none;
-    cursor:pointer;
+  color: var(--link-color);
+  text-decoration: none;
+  cursor: pointer;
 }
 
 a:focus {
-    outline: 1px dotted;
+  outline: 1px dotted;
 }
 
 a:hover,
 a:active {
-    color: var(--tool-link-hover-color);
-    outline: none;
+  color: var(--tool-link-hover-color);
+  outline: none;
 }
-.footer_navbar{
-	display: flex;
-    flex-wrap: wrap;
-    width: 100%;
+.footer_navbar {
+  display: flex;
+  flex-wrap: wrap;
+  width: 100%;
 }
 
-.icon{
-    height: 1.4em;
-    width: 1.4em;
-    fill: #555;
-    transition: all 0.2s ease;
+.icon {
+  height: 1.4em;
+  width: 1.4em;
+  fill: #555;
+  transition: all 0.2s ease;
 }
 
-.small_icon{
-    height: 1em;
-    width: 1em;
-    fill: #555;
-    -webkit-transition-duration: 0.2s;
-    transition-duration: 0.2s;
+.small_icon {
+  height: 1em;
+  width: 1em;
+  fill: #555;
+  -webkit-transition-duration: 0.2s;
+  transition-duration: 0.2s;
 }
 
-.broder-1{
-    border: 1px solid var(--border-line-color);
+.broder-1 {
+  border: 1px solid var(--border-line-color);
 }
-.broder-2{
-    border: 2px solid var(--border-line-color);
+.broder-2 {
+  border: 2px solid var(--border-line-color);
+}
+.broder-r {
+  border-radius: 5px;
+}
+
+.tran:hover .edit_button {
+  display: inline-block;
+}
+.edit_button {
+  position: absolute;
+  display: none;
+  width: auto;
+  min-width: 24px;
+  height: auto;
+  min-height: 24px;
+  cursor: pointer;
+  background: url(edit.svg);
+  background-repeat: no-repeat;
+  background-size: contain;
+  margin: 0 6px;
+  margin-left: -24px;
+  color: var(--tool-color);
 }
-.broder-r{
-    border-radius: 5px;
-}

+ 7 - 0
app/pcdl/css/edit.svg

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="14px" height="14px" viewBox="0 0 24 24" style="fill: #6baaff;" xml:space="preserve">
+		<path
+			d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 0 0 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z" />
+</svg>

+ 11 - 1
app/pcdl/js/reader.js

@@ -194,7 +194,7 @@ function reader_init() {
     window.location.assign("../wiki/wiki.php?op=get&word=" + word);
   });
 
-  $("sent").click(function (e) {
+  $("palitext").click(function (e) {
     let book = $(this).attr("book");
     let para = $(this).attr("para");
     let begin = $(this).attr("begin");
@@ -440,3 +440,13 @@ function sent_apply(sentId) {
     );
   }
 }
+
+function copy_ref(obj) {
+  let pali_sent_node = obj.parentNode.parentNode.parentNode.parentNode;
+  let book = pali_sent_node.getAttributeNode("book").value;
+  let para = pali_sent_node.getAttributeNode("para").value;
+  let begin = pali_sent_node.getAttributeNode("begin").value;
+  let end = pali_sent_node.getAttributeNode("end").value;
+  let strRef = "{{" + book + "-" + para + "-" + begin + "-" + end + "}}";
+  copy_to_clipboard(strRef);
+}

+ 50 - 3
app/pcdl/reader.php

@@ -18,7 +18,9 @@ $_channal = new Channal();
 	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
 	<meta name="viewport" content="width=device-width, initial-scale=1.0">
 	<link type="text/css" rel="stylesheet" href="../studio/css/font.css"/>
+	<link type="text/css" rel="stylesheet" href="../pcdl/css/color_day.css" id="colorchange" />
 	<link type="text/css" rel="stylesheet" href="css/reader.css"/>
+	<link type="text/css" rel="stylesheet" href="../guide/guide.css"/>
 	<link type="text/css" rel="stylesheet" href="css/reader_mob.css" media="screen and (max-width:767px)">
 	<title id="page_title">PCD Reader</title>
 
@@ -30,6 +32,10 @@ $_channal = new Channal();
 	<script src="../public/js/notify.js"></script>
 	<script src="../term/term.js"></script>
 	<script src="../term/note.js"></script>
+	<script src="../public/js/marked.js"></script>
+	<script src="../public/js/mermaid.min.js"></script>
+	<script src="../guide/guide.js"></script>
+	<link type="text/css" rel="stylesheet" href="../guide/guide.css"/>
 </head>
 <body class="reader_body" >
 <a name="page_head"></a>
@@ -43,11 +49,19 @@ $_channal = new Channal();
 	</script>
 
 <style>
+.term_link {
+    background: unset;
+    position: relative;
+}
+	.term_link:hover .guide_contence {
+		display: inline-block;
+	}
 .par_translate_div{
 	margin-left: 1em;
     border-left: 1px solid gray;
     padding-left: 0.5em;
     margin-top: 0.5em;
+	font-size: 1.1em
 }
 	.edit_icon{
 		display:inline-block;
@@ -255,6 +269,21 @@ note{
 	color:blue;
 	cursor: pointer;
 }
+more{
+    position: absolute;
+    display: none;
+    width: 1.4em;
+    height: 1.4em;
+}
+more .icon{
+	display: inline-block;
+    width: 1.4em;
+    height: 1.4em;
+    background: url(../public/images/svg/more.svg);
+}
+sent:hover more{
+	display: inline-block;
+}
 </style>
 		<!-- tool bar begin-->
 		<div id="main_tool_bar" class='reader_toolbar'>
@@ -659,7 +688,9 @@ else{
 			foreach ($FetchSent as $key => $value) {
 				echo "<div id='sent-pali-b$book-$iPar-{$value["begin"]}' class='par_pali_div'>";
 				$pali_sent=$value["html"];
-				echo "<sent  class='{$sentClass}' book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >".$pali_sent."</sent>";
+				echo "<sent  class='{$sentClass}' book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >";
+				echo "<palitext book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >".$pali_sent."</palitext>";
+				echo "</sent>";
 				echo "</div>";
 				echo "<div id='sent-wbwdiv-b$book-$iPar-{$value["begin"]}' class='par_wbw_div'>";
 				echo "</div>";
@@ -692,7 +723,9 @@ else{
 			}
 			foreach ($FetchSent as $key => $value) {
 				$pali_sent=$value["html"];
-				echo "<sent class='{$sentClass}'  book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >{$pali_sent}</sent>";
+				echo "<sent class='{$sentClass}'  book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >";
+				echo "<palitext book='{$book}' para='{$iPar}' begin='{$value["begin"]}' end='{$value["end"]}' >{$pali_sent}</palitext>";
+				echo "</sent>";
 			}
 			echo "</div>";
 			echo "<div id='par-wbwdiv-b$book-$iPar' class='par_wbw_div'>";
@@ -908,7 +941,7 @@ function render_sent($sent_data,$sn,$display_mode,$sent_count,$class=""){
 		if($display_mode=="sent"){
 			if((isset($_GET["channal"]) || $_GET["view"]=="sent")  ){
 				if($sent_data["editor"] == $_COOKIE["userid"]){
-					$output .= "<svg class='edit_icon';'><use xlink:href='../studio/svg/icon.svg#ic_mode_edit'></use></svg>";
+					$output .= "<svg class='edit_icon'><use xlink:href='../studio/svg/icon.svg#ic_mode_edit'></use></svg>";
 				}
 				
 			}
@@ -1252,6 +1285,20 @@ function render_sent($sent_data,$sn,$display_mode,$sent_count,$class=""){
 
 <script>
 reader_init();
+var htmlDropdown  = "<div class='case_dropdown'>";
+htmlDropdown  +="<svg class='icon' >";
+htmlDropdown  +="<use xlink:href='svg/icon.svg#ic_more'></use>";
+htmlDropdown  +="</svg>";
+htmlDropdown  +="<div class='case_dropdown-content'>";
+htmlDropdown  +="<a onclick='copy_ref(this)'>复制引用</a>";
+htmlDropdown  +="<a onclick='copy_text(this)'>复制纯文本</a>";
+htmlDropdown  +="<a onclick='add_to_list()'>添加到选择列表</a>";
+htmlDropdown  +="</div>";
+htmlDropdown  +="</div>";
+$("sent").each(function(){
+	$(this).prepend("<more>"+htmlDropdown+"</more>")
+})
+
 </script>
 	
 </body>

+ 6 - 0
app/public/images/svg/more.svg

@@ -0,0 +1,6 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1602127459811" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5274"  xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs><style type="text/css"></style></defs>
+<path d="M1024 512C1024 229.236 794.764 0 512 0S0 229.236 0 512s229.236 512 512 512 512-229.236 512-512z m-232.727-93.09c51.386 0 93.09 41.704 93.09 93.09s-41.704 93.09-93.09 93.09c-51.433 0-93.091-41.657-93.091-93.09s41.658-93.09 93.09-93.09zM232.727 605.09c-51.432 0-93.09-41.657-93.09-93.09s41.658-93.09 93.09-93.09c51.386 0 93.091 41.704 93.091 93.09s-41.705 93.09-93.09 93.09zM418.91 512c0-51.433 41.658-93.09 93.091-93.09 51.386 0 93.09 41.704 93.09 93.09s-41.704 93.09-93.09 93.09c-51.433 0-93.09-41.657-93.09-93.09z" p-id="5275" fill="#515151"></path>
+</svg>

+ 15 - 0
app/public/js/comm.js

@@ -133,3 +133,18 @@ function setCookie(c_name, value, expiredays) {
     escape(value) +
     (expiredays == null ? "" : "; expires=" + exdate.toGMTString() + ";path=/");
 }
+
+function copy_to_clipboard(strInput) {
+  const input = document.createElement("input");
+  input.setAttribute("readonly", "readonly");
+  input.setAttribute("value", strInput);
+  document.body.appendChild(input);
+  //	input.setSelectionRange(0, strInput.length);
+  //	input.focus();
+  input.select();
+  if (document.execCommand("copy")) {
+    document.execCommand("copy");
+    console.log("复制成功");
+  }
+  document.body.removeChild(input);
+}

+ 13 - 1
app/studio/css/style.css

@@ -4362,7 +4362,9 @@ note {
   display: none;
   text-align: center;
 }
-
+.icon_btn_div {
+  position: relative;
+}
 .icon_btn_div:hover .icon_btn_tip {
   display: inline-block;
 }
@@ -4403,3 +4405,13 @@ note {
 .input_bar {
   flex: 9;
 }
+.float_dlg {
+  display: none;
+  width: 25em;
+  position: absolute;
+  right: 0;
+  background-color: var(--btn-hover-bg-color);
+  padding: 10px;
+  border-radius: 5px;
+  box-shadow: 0 0 10px var(--main-color);
+}

+ 6 - 0
app/studio/editor.php

@@ -64,6 +64,8 @@ else{$currDevice="computer";}
 	
 	<script language="javascript" src="module/editor/language/default.js"></script>	
 	<script src="js/jquery-3.3.1.min.js"></script>
+	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>
+
 	<script src="../term/term.js"></script>
 	<script src="../term/note.js"></script>
 	<script src="./js/message.js"></script>
@@ -119,6 +121,10 @@ else{$currDevice="computer";}
 	</style>
 
 	<style>
+	.term_link:hover .guide_contence {
+		display: inline-block;
+	}
+	
 	.trans_text_block{
 		border-left: 5px solid #d1d1d1;
 		background-color: #f1f1f1;

+ 1 - 1
app/studio/index_tool_bar.php

@@ -75,7 +75,7 @@
 					</span>
 				</li>
 
-				<li id="channal"  onclick="goto_url(this,'../channal/my_channal_list.php')">
+				<li id="channal"  onclick="goto_url(this,'../channal/my_channal_index.php')">
 					<span  class="navi_icon">
 						<svg class="icon">
 							<use xlink:href="../studio/svg/icon.svg#class_video"></use>

ファイルの差分が大きいため隠しています
+ 475 - 471
app/studio/js/common.js


+ 62 - 11
app/studio/js/render.js

@@ -60,12 +60,20 @@ function palitext_calculator() {
   }
 }
 //添加新的段落块
-function addNewBlockToHTML(bookId, parId) {
+function addNewBlockToHTML(bookId, parId, begin = -1, end = -1) {
   parHeadingLevel = 0;
   parTitle = "";
   var divBlock = document.createElement("div");
   var typId = document.createAttribute("id");
-  typId.nodeValue = "par_" + bookId + "_" + (parId - 1);
+  if (begin == -1 && end == -1) {
+    //基于段落的块
+    typId.nodeValue = "par_" + bookId + "_" + (parId - 1);
+  } else {
+    //基于句子的块
+    typId.nodeValue =
+      "par_" + bookId + "_" + (parId - 1) + "_" + begin + "_" + end;
+  }
+
   divBlock.attributes.setNamedItem(typId);
   var typClass = document.createAttribute("class");
   typClass.nodeValue = "pardiv";
@@ -260,16 +268,29 @@ function insertBlockToHtml(element) {
   xmlParInfo = element.getElementsByTagName("info")[0];
   xmlParData = element.getElementsByTagName("data")[0];
 
-  bookId = getNodeText(xmlParInfo, "book");
-  paragraph = getNodeText(xmlParInfo, "paragraph");
+  let bookId = getNodeText(xmlParInfo, "book");
+  let paragraph = getNodeText(xmlParInfo, "paragraph");
+  let base_on = getNodeText(xmlParInfo, "base");
+  let begin = getNodeText(xmlParInfo, "begin");
+  let end = getNodeText(xmlParInfo, "end");
+
   type = getNodeText(xmlParInfo, "type");
   language = getNodeText(xmlParInfo, "language");
   bId = getNodeText(xmlParInfo, "id");
 
-  blockId = "par_" + bookId + "_" + (paragraph - 1);
-  var htmlBlock = document.getElementById(blockId);
-  if (htmlBlock == null) {
-    addNewBlockToHTML(bookId, paragraph);
+  let htmlBlock;
+  if (base_on == "sentence") {
+    blockId = "par_" + bookId + "_" + (paragraph - 1) + "_" + begin + "_" + end;
+    htmlBlock = document.getElementById(blockId);
+    if (htmlBlock == null) {
+      addNewBlockToHTML(bookId, paragraph, begin, end);
+    }
+  } else {
+    blockId = "par_" + bookId + "_" + (paragraph - 1);
+    htmlBlock = document.getElementById(blockId);
+    if (htmlBlock == null) {
+      addNewBlockToHTML(bookId, paragraph);
+    }
   }
 
   if (!isParInView(getParIndex(bookId, paragraph))) {
@@ -1842,7 +1863,7 @@ function render_tran_sent_block(
   let id =
     "tran_pre_" + book + "_" + para + "_" + begin + "_" + end + "_" + channal;
   output +=
-    "<div class='trans_text_content' id = '" +
+    "<div class='trans_text_content' tid = '" +
     id +
     "'  pcds='sent-net' " +
     " book='" +
@@ -1860,7 +1881,9 @@ function render_tran_sent_block(
     output += sent_text;
   } else {
     output +=
-      "<span onclick=\"sent_edit_click('" +
+      "<span id='" +
+      id +
+      "' onclick=\"sent_edit_click('" +
       book +
       "','" +
       para +
@@ -1894,6 +1917,17 @@ function render_tran_sent_block(
       " onkeyup = \"updateTranslationPreview('" +
       id +
       "',this)\" " +
+      " onchange=\"trans_text_save('" +
+      book +
+      "','" +
+      para +
+      "','" +
+      begin +
+      "','" +
+      end +
+      "','" +
+      channal +
+      "')\"" +
       "class='trans_sent_edit' style='background-color: #f8f8fa;color: black;border-color: silver;' " +
       "sent_id='" +
       objSent.id +
@@ -1930,6 +1964,19 @@ function render_tran_sent_block(
       "','" +
       channal +
       "')\">保存</button>";
+    output +=
+      "<button onclick=\"trans_text_send('" +
+      book +
+      "','" +
+      para +
+      "','" +
+      begin +
+      "','" +
+      end +
+      "','" +
+      channal +
+      "')\">发送</button>";
+
     output += "</div>";
     output += "</div>";
   }
@@ -4122,8 +4169,12 @@ function repeat_combine(list) {
 }
 
 function show_pop_note(wordid) {
+  let html = $("wnc[wid='" + wordid + "']")
+    .parent()
+    .html();
   $("#word_note_pop_content").html(
-    note_init(doc_word("#" + wordid).val("note"))
+    html
+    /*note_init(doc_word("#" + wordid).val("note"))*/
   );
   $("#word_note_pop").show("500");
 }

+ 117 - 0
app/studio/project_load_article.php

@@ -0,0 +1,117 @@
+<?php
+/*
+get xml doc from db
+*/
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once "../public/function.php";
+
+$id=$_GET["id"];
+
+PDO_Connect("sqlite:"._FILE_DB_USER_ARTICLE_);
+$query = "select * from article where id=".$PDO->quote($id);
+$Fetch = PDO_FetchAll($query);
+if(count($Fetch)>0){
+	echo "<set>\n";
+	echo $Fetch[0]["doc_info"];
+	echo "\n<dict></dict>\n";
+	echo "<message></message>\n";
+	echo "<body>\n";
+	
+	$dh_wbw = new PDO("sqlite:"._FILE_DB_USER_WBW_, "", "",array(PDO::ATTR_PERSISTENT=>true));
+    $dh_wbw->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
+
+	$dh_sent = new PDO("sqlite:"._FILE_DB_SENTENCE_, "", "",array(PDO::ATTR_PERSISTENT=>true));
+    $dh_sent->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
+	
+	$blockList = explode("\n",$Fetch[0]["content"]) ;
+	
+	foreach($blockList as $block){
+		$info = explode("-",$block); 
+		switch($block->type){
+			case "6":
+			{
+				$albumId = UUID::v4();
+				$query="select * from wbw_block where id='".$block->block_id."'";
+				$stmt = $dh_wbw->query($query);
+				$FetchBlock = $stmt->fetchAll(PDO::FETCH_ASSOC);
+				echo "\n<block>";
+				echo "<info>\n";
+				
+				echo "<type>wbw</type>";
+				echo "<book>{$FetchBlock[0]["book"]}</book>";
+				echo "<paragraph>{$FetchBlock[0]["paragraph"]}</paragraph>";
+				echo "<level>100</level>";
+				echo "<title>title</title>";
+				echo "<album_id>{$block->channal}</album_id>";
+				echo "<album_guid>{$block->channal}</album_guid>";
+				echo "<author>{$FetchBlock[0]["owner"]}</author>";
+				echo "<language>{$FetchBlock[0]["lang"]}</language>";
+				echo "<version>1</version>";
+				echo "<edition>1</edition>";
+				echo "<id>{$block->block_id}</id>";
+				echo "</info>\n";		
+				echo "<data>\n";
+				$query="select * from wbw where block_id='".$block->block_id."'";
+				$stmt = $dh_wbw->query($query);
+				$wbw_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
+				foreach($wbw_data as $word){
+					echo $word["data"];	
+					echo "\r\n";	
+				}
+				echo "</data>";
+				echo "</block>\n";
+				break;
+			}
+			case 2:
+			{
+				$albumId = UUID::v4();
+				$query="select * from sent_block where id='".$block->block_id."'";
+				$stmt = $dh_sent->query($query);
+				$FetchBlock = $stmt->fetchAll(PDO::FETCH_ASSOC);
+				if(count($FetchBlock)>0){
+					echo "\n<block>\n";
+					echo "<info>\n";
+					
+					echo "<type>translate</type>";
+					echo "<book>{$FetchBlock[0]["book"]}</book>";
+					echo "<paragraph>{$FetchBlock[0]["paragraph"]}</paragraph>";
+					echo "<level>100</level>";
+					echo "<title>title</title>";
+					echo "<album_id>{$block->channal}</album_id>";
+					echo "<album_guid>{$block->channal}</album_guid>";
+					echo "<author>{$FetchBlock[0]["author"]}</author>";
+					echo "<editor>{$FetchBlock[0]["editor"]}</editor>";
+					echo "<language>{$FetchBlock[0]["lang"]}</language>";
+					echo "<version>1</version>";
+					echo "<edition>1</edition>";
+					echo "<id>{$block->block_id}</id>";
+					echo "<parent>{$FetchBlock[0]["parent_id"]}</parent>";
+					echo "</info>\n";
+					echo "<data>\n";
+					$query="select * from sentence where block_id='".$block->block_id."'";
+					$stmt = $dh_sent->query($query);
+					$sent_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
+					foreach($sent_data as $sent){
+						echo "<sen>";
+						echo "<id>{$sent["id"]}</id>";
+						echo "<begin>{$sent["begin"]}</begin>";
+						echo "<end>{$sent["end"]}</end>";
+						echo "<text>{$sent["text"]}</text>";
+						echo "<status>{$sent["status"]}</status>";
+						echo "</sen>";						
+					}
+					echo "</data>\n";
+					echo "</block>\n";
+				}
+				break;
+			}
+		}
+		
+	}
+				
+	echo "</body>\n";
+	echo "</set>";
+}
+
+?>

+ 1 - 1
app/studio/project_load_db.php

@@ -9,7 +9,7 @@ require_once "../public/function.php";
 $id=$_GET["id"];
 
 PDO_Connect("sqlite:"._FILE_DB_FILEINDEX_);
-$query = "select * from fileindex where id='$id'";
+$query = "select * from fileindex where id=".$PDO->quote($id);
 $Fetch = PDO_FetchAll($query);
 if(count($Fetch)>0){
 	echo "<set>\n";

+ 9 - 4
app/term/channal_list.php

@@ -45,9 +45,12 @@ foreach ($_data as $key => $value) {
 		$Fetch = $stmt->fetchAll(PDO::FETCH_ASSOC);
 		foreach ($Fetch as $key => $value) {
             # code...
-            if(!empty($value["channal"])){
-                $channal[$value["channal"]] = 1;
-            }
+            if(isset($value["channal"])){
+                $channal[$value["channal"]] ++;
+			}
+			else{
+				$channal[$value["channal"]] = 1;
+			}
             
         }
 	}
@@ -65,7 +68,9 @@ foreach ($channal as $key => $value) {
     $channalInfo = $_channal->getChannal($key);
     $name = $_userinfo->getName($channalInfo["owner"]);
     $channalInfo["username"] = $name["username"];
-    $channalInfo["nickname"] = $name["nickname"];
+	$channalInfo["nickname"] = $name["nickname"];
+	$channalInfo["count"] = $value;
+	$channalInfo["all"] = count($_data);
     $output[]= $channalInfo;
 }
 

+ 287 - 50
app/term/note.js

@@ -1,3 +1,12 @@
+var _display = "";
+var _word = "";
+var _channal = "";
+var _lang = "";
+var _author = "";
+
+var _arrData;
+var _channalData;
+
 /*
 {{203-1654-23-45@11@en@*}}
 <note>203-1654-23-45@11@en@*</note>
@@ -21,43 +30,32 @@
 <note id="guid" book=203 para=1654 begin=23 end=45 author=11 lang=en tag=*></note>
 
 */
-var _display = "";
-var _word = "";
-var _channal = "";
-var _lang = "";
-var _author = "";
-
+function note_create() {
+  $("#dialog").dialog({
+    autoOpen: false,
+    width: 550,
+    buttons: [
+      {
+        text: "Save",
+        click: function () {
+          note_sent_save();
+          $(this).dialog("close");
+        },
+      },
+      {
+        text: "Cancel",
+        click: function () {
+          $(this).dialog("close");
+        },
+      },
+    ],
+  });
+}
 function note_init(input) {
   let output = "<div>";
   let newString = input.replace(/\{\{/g, '<note info="');
   newString = newString.replace(/\}\}/g, '"></note>');
   output = marked(newString);
-  /*
-  let arrInput = input.split("\n");
-  for (x in arrInput) {
-    if (arrInput[x].slice(0, 2) == "==" && arrInput[x].slice(-2) == "==") {
-      output += "</div></div>";
-      output += '<div class="submenu1">';
-      output +=
-        '<p class="submenu_title1" onclick="submenu_show_detail(this)">';
-      output += arrInput[x].slice(2, -2);
-      output += '<svg class="icon" style="transform: rotate(45deg);">';
-      output += '<use xlink:href="svg/icon.svg#ic_add"></use>';
-      output += "</svg>";
-      output += "</p>";
-      output += '<div class="submenu_details1" >';
-    } else {
-      let row = arrInput[x];
-      row = row.replace(/\{\{/g, '<note info="');
-      row = row.replace(/\}\}/g, '"></note>');
-      if (row.match("{") && row.match("}")) {
-        row = row.replace("{", "<strong>");
-        row = row.replace("}", "</strong>");
-      }
-      output += row;
-    }
-  }
-  */
   output += "</div>";
   return output;
 }
@@ -114,12 +112,24 @@ function note_refresh_new() {
       function (data, status) {
         if (status == "success") {
           try {
-            let arrData = JSON.parse(data);
-            for (const iterator of arrData) {
+            _arrData = JSON.parse(data);
+            for (const iterator of _arrData) {
               let id = iterator.id;
               let strHtml = "<a name='" + id + "'></a>";
               if (_display && _display == "para") {
-                let strPalitext = "<pali>" + iterator.palitext + "<pali>";
+                //段落模式
+                let strPalitext =
+                  "<pali book='" +
+                  iterator.book +
+                  "' para='" +
+                  iterator.para +
+                  "' begin='" +
+                  iterator.begin +
+                  "' end='" +
+                  iterator.end +
+                  "' >" +
+                  iterator.palitext +
+                  "</pali>";
                 let divPali = $("#" + id)
                   .parent()
                   .children(".palitext");
@@ -133,17 +143,21 @@ function note_refresh_new() {
                   .children(".palitext")
                   .first()
                   .append(strPalitext);
-                let htmlTran =
-                  "<span class='tran'>" +
-                  marked(term_std_str_to_tran(iterator.tran)) +
-                  "</span>";
+                let htmlTran = "";
+                for (const oneTran of iterator.translation) {
+                  htmlTran +=
+                    "<span class='tran'>" +
+                    marked(term_std_str_to_tran(oneTran.text)) +
+                    "</span>";
+                }
+
                 $("#" + id).html(htmlTran);
               } else {
+                //句子模式
                 strHtml += note_json_html(iterator);
                 $("#" + id).html(strHtml);
               }
             }
-
             $(".palitext").click(function () {
               let sentid = $(this).parent().attr("info").split("-");
               window.open(
@@ -157,6 +171,18 @@ function note_refresh_new() {
                   sentid[3]
               );
             });
+            $("pali").click(function () {
+              window.open(
+                "../pcdl/reader.php?view=sent&book=" +
+                  $(this).attr("book") +
+                  "&para=" +
+                  $(this).attr("para") +
+                  "&begin=" +
+                  $(this).attr("begin") +
+                  "&end=" +
+                  $(this).attr("end")
+              );
+            });
             note_ref_init();
             term_get_dict();
             note_channal_list();
@@ -191,12 +217,42 @@ function note_channal_list() {
       function (data, status) {
         if (status == "success") {
           try {
-            let arrData = JSON.parse(data);
+            let active = JSON.parse(data);
+            _channalData = active;
+            for (const iterator of _my_channal) {
+              let found = false;
+              for (const one of active) {
+                if (iterator.id == one.id) {
+                  found = true;
+                  break;
+                }
+              }
+              if (found == false) {
+                _channalData.push(iterator);
+              }
+            }
             let strHtml = "";
-            for (const iterator of arrData) {
-              strHtml += render_channal_list(iterator);
+            for (const iterator of _channalData) {
+              if (_channal.indexOf(iterator.id) >= 0) {
+                strHtml += render_channal_list(iterator);
+              }
+            }
+            for (const iterator of _channalData) {
+              if (_channal.indexOf(iterator.id) == -1) {
+                strHtml += render_channal_list(iterator);
+              }
             }
+
             $("#channal_list").html(strHtml);
+            $("[channal_id]").change(function () {
+              let channal_list = new Array();
+              $("[channal_id]").each(function () {
+                if (this.checked) {
+                  channal_list.push($(this).attr("channal_id"));
+                }
+              });
+              set_channal(channal_list.join());
+            });
           } catch (e) {
             console.error(e);
           }
@@ -206,21 +262,40 @@ function note_channal_list() {
   }
 }
 
+function find_channal(id) {
+  for (const iterator of _channalData) {
+    if (id == iterator.id) {
+      return iterator;
+    }
+  }
+  return false;
+}
 function render_channal_list(channalinfo) {
   let output = "";
   output += "<div class='list_with_head'>";
-
+  let checked = "";
+  if (_channal.indexOf(channalinfo.id) >= 0) {
+    checked = "checked";
+  }
+  output +=
+    '<div><input type="checkbox" ' +
+    checked +
+    " channal_id='" +
+    channalinfo.id +
+    "'></div>";
   output += "<div class='head'>";
   output += "<span class='head_img'>";
   output += channalinfo.nickname.slice(0, 2);
   output += "</span>";
   output += "</div>";
 
-  output += "<div>";
+  output += "<div style='width: 100%;'>";
 
   output += "<div>";
-  output += "<a href='../wiki/wiki.php?word=" + _word;
-  output += "&channal=" + channalinfo.id + "' >";
+
+  //  output += "<a href='../wiki/wiki.php?word=" + _word;
+  //  output += "&channal=" + channalinfo.id + "' >";
+  output += "<a onclick=\"set_channal('" + channalinfo.id + "')\">";
 
   output += channalinfo["nickname"];
   output += "/" + channalinfo["name"];
@@ -231,7 +306,15 @@ function render_channal_list(channalinfo) {
   output += "<div>";
   output += "@" + channalinfo["username"];
   output += "</div>";
+  output += "<div style='background-color: #e0dfdffa;'>";
+  output +=
+    "<span  style='display: inline-block;background-color: #65ff65;width: " +
+    (channalinfo["count"] * 100) / channalinfo["all"] +
+    "%;'>";
+  output += channalinfo["count"] + "/" + channalinfo["all"];
+  output += "</span>";
 
+  output += "</div>";
   output += "</div>";
   output += "</div>";
   return output;
@@ -265,10 +348,164 @@ ref
 function note_json_html(in_json) {
   let output = "";
   output += "<div class='palitext'>" + in_json.palitext + "</div>";
+  for (const iterator of in_json.translation) {
+    output += "<div class='tran'>";
+    output +=
+      "<span class='edit_button' onclick=\"note_edit_sentence('" +
+      in_json.book +
+      "' ,'" +
+      in_json.para +
+      "' ,'" +
+      in_json.begin +
+      "' ,'" +
+      in_json.end +
+      "' ,'" +
+      iterator.channal +
+      "')\"></span>";
+
+    output +=
+      "<div class='text' id='tran_text_" +
+      in_json.book +
+      "_" +
+      in_json.para +
+      "_" +
+      in_json.begin +
+      "_" +
+      in_json.end +
+      "_" +
+      iterator.channal +
+      "'>";
+    if (iterator.text == "") {
+      //let channal = find_channal(iterator.channal);
+      output += "<span style='color:var(--border-line-color);'>新建译文</span>";
+    } else {
+      output += marked(term_std_str_to_tran(iterator.text));
+    }
+    output += "</div>";
+
+    output += "</div>";
+  }
+
+  output += "<div class='ref'>" + in_json.ref;
   output +=
-    "<div class='tran'>" +
-    marked(term_std_str_to_tran(in_json.tran)) +
+    "<span class='sent_no'>" +
+    in_json.book +
+    "-" +
+    in_json.para +
+    "-" +
+    in_json.begin +
+    "-" +
+    in_json.end +
+    "<span>" +
     "</div>";
-  output += "<div class='ref'>" + in_json.ref + "</div>";
   return output;
 }
+
+function note_edit_sentence(book, para, begin, end, channal) {
+  let channalInfo;
+  for (const iterator of _channalData) {
+    if (iterator.id == channal) {
+      channalInfo = iterator;
+      break;
+    }
+  }
+  for (const iterator of _arrData) {
+    if (
+      iterator.book == book &&
+      iterator.para == para &&
+      iterator.begin == begin &&
+      iterator.end == end
+    ) {
+      for (const tran of iterator.translation) {
+        if (tran.channal == channal) {
+          let html = "";
+          html +=
+            "<div style='color:blue;'>" +
+            channalInfo.nickname +
+            "/" +
+            channalInfo.name +
+            "</div>";
+          html +=
+            "<textarea id='edit_dialog_text' sent_id='" +
+            tran.id +
+            "' book='" +
+            iterator.book +
+            "' para='" +
+            iterator.para +
+            "' begin='" +
+            iterator.begin +
+            "' end='" +
+            iterator.end +
+            "' channal='" +
+            tran.channal +
+            "' style='width:100%;min-height:260px;'>" +
+            tran.text +
+            "</textarea>";
+          $("#edit_dialog_content").html(html);
+          break;
+        }
+      }
+    }
+  }
+
+  $("#dialog").dialog("open");
+}
+
+function note_sent_save() {
+  let id = $("#edit_dialog_text").attr("sent_id");
+  let book = $("#edit_dialog_text").attr("book");
+  let para = $("#edit_dialog_text").attr("para");
+  let begin = $("#edit_dialog_text").attr("begin");
+  let end = $("#edit_dialog_text").attr("end");
+  let channal = $("#edit_dialog_text").attr("channal");
+  let text = $("#edit_dialog_text").val();
+
+  $.post(
+    "../usent/sent_post.php",
+    {
+      id: id,
+      book: book,
+      para: para,
+      begin: begin,
+      end: end,
+      channal: channal,
+      text: text,
+      lang: "zh",
+    },
+    function (data) {
+      let result = JSON.parse(data);
+      if (result.status > 0) {
+        alert("error" + result.message);
+      } else {
+        alert("成功");
+        $(
+          "#tran_text_" +
+            result.book +
+            "_" +
+            result.para +
+            "_" +
+            result.begin +
+            "_" +
+            result.end +
+            "_" +
+            result.channal
+        ).html(marked(result.text));
+        for (const iterator of _arrData) {
+          if (
+            iterator.book == result.book &&
+            iterator.para == result.para &&
+            iterator.begin == result.begin &&
+            iterator.end == result.end
+          ) {
+            for (const tran of iterator.translation) {
+              if (tran.channal == result.channal) {
+                tran.text = result.text;
+                break;
+              }
+            }
+          }
+        }
+      }
+    }
+  );
+}

+ 42 - 8
app/term/note.php

@@ -60,6 +60,12 @@ foreach ($_data as $key => $value) {
 		$begin=$arrSent[2];
 		$end=$arrSent[3];
 	}
+	else{
+		$bookId=0;
+		$para=0;
+		$begin=0;
+		$end=0;
+	}
 
 	$query="SELECT html FROM 'pali_sent' WHERE book = ? AND paragraph = ? AND begin = ? AND end = ? ";
 	$sth = $db_pali_sent->prepare($query);
@@ -73,25 +79,43 @@ foreach ($_data as $key => $value) {
 
 	//find out translation
 	$tran="";
+	$translation = array();
 	try{
 		if(!empty($_setting["channal"])){
 			$queryChannal = " AND channal = ? ";
+			$query="SELECT * FROM sentence WHERE book= ? AND paragraph= ? AND begin= ? AND end= ?  AND strlen >0  AND channal = ?  limit 0 ,1 ";
+			$channal = $_setting["channal"];
 		}
 		else{
-			$queryChannal ="";
+			$query="SELECT * FROM sentence WHERE book= ? AND paragraph= ? AND begin= ? AND end= ?  AND strlen >0   order by modify_time DESC limit 0 ,1 ";
+			$channal = "";
 		}
-		$query="SELECT * FROM sentence WHERE book= ? AND paragraph= ? AND begin= ? AND end= ?  AND strlen >0  $queryChannal order by modify_time DESC limit 0 ,1 ";
+		
 		$stmt = $db_trans_sent->prepare($query);
 		if(empty($_setting["channal"])){
 			$stmt->execute(array($bookId,$para,$begin,$end));
+			$Fetch = $stmt->fetch(PDO::FETCH_ASSOC);
+			if($Fetch){
+				$tran = $Fetch["text"];
+				$translation[]=array("id"=>$Fetch["id"],"text"=>$Fetch["text"],"channal"=>$Fetch["channal"]);
+			}
 		}
 		else{
-			$stmt->execute(array($bookId,$para,$begin,$end,$_setting["channal"]));
-		}
-		$Fetch = $stmt->fetch(PDO::FETCH_ASSOC);
-		if($Fetch){
-			$tran = $Fetch["text"];
+			$arrChannal = explode(",",$_setting["channal"]);
+			foreach ($arrChannal as $key => $value) {
+				# code...
+				$stmt->execute(array($bookId,$para,$begin,$end,$value));
+				$Fetch = $stmt->fetch(PDO::FETCH_ASSOC);
+				if($Fetch){
+					$translation[]=array("id"=>$Fetch["id"],"text"=>$Fetch["text"],"channal"=>$value);
+				}
+				else{
+					$translation[]=array("id"=>"","text"=>"","channal"=>$value);
+				}
+			}
 		}
+		
+
 		$tran_count = 1;
 	}
 	catch (Exception $e) {
@@ -101,7 +125,17 @@ foreach ($_data as $key => $value) {
 	
 	$para_path=_get_para_path($bookId,$para);
 
-	$output[]=array("id"=>$id,"palitext"=>$palitext,"tran"=>$tran,"ref"=>$para_path,"tran_count"=>$tran_count);
+	$output[]=array("id"=>$id,
+							   "palitext"=>$palitext,
+							   "tran"=>$tran,
+							   "translation"=>$translation,
+							   "ref"=>$para_path,
+							   "tran_count"=>$tran_count,
+							   "book"=>$bookId,
+							   "para"=>$para,
+							   "begin"=>$begin,
+							   "end"=>$end
+							);
 
 }
 

+ 58 - 0
app/term/term.css

@@ -0,0 +1,58 @@
+.term_link:hover .guide_contence {
+  display: inline-block;
+}
+
+.term_meaning {
+  font-weight: 700;
+}
+.term_author {
+  font-size: 80%;
+  color: gray;
+}
+.term_tag {
+  font-size: 80%;
+  font-weight: 500;
+  margin: 0 8px;
+}
+.term_link {
+  cursor: pointer;
+  position: relative;
+}
+
+.term_link,
+.term_link_new {
+  color: blue;
+  padding-left: 2px;
+  padding-right: 2px;
+}
+.term_link_new {
+  color: red;
+}
+
+note:hover chapter {
+  display: inline;
+}
+.ref > chapter:first-child {
+  display: inline;
+}
+chapter {
+  display: none;
+  color: var(--box-bg-color1);
+  text-decoration: none;
+  cursor: pointer;
+}
+chapter:hover {
+  color: var(--link-color);
+  text-decoration: underline;
+}
+para {
+  background-color: var(--drop-bg-color);
+  padding: 2px 8px;
+  text-decoration: none;
+  cursor: pointer;
+  color: var(--btn-border-color);
+  border-radius: 5px;
+}
+para:hover {
+  text-decoration: underline;
+}

+ 77 - 0
app/term/term.js

@@ -153,6 +153,41 @@ function note_lookup_guid_json(guid, showto) {
   );
 }
 
+function term_load_preview(guid, showto) {
+  $.get(
+    "../term/term.php",
+    {
+      op: "load_id",
+      id: guid,
+      format: "json",
+    },
+    function (data, status) {
+      let html = "";
+      if (status == "success") {
+        try {
+          let result = JSON.parse(data)[0];
+          html = "<div class='term_block'>";
+
+          html += "<h2>" + result.word + "</h2>";
+          html += "<div class='meaning'>" + result.meaning + "</div>";
+          html +=
+            "<div class='term_note' status='1'>" +
+            note_init(result.note) +
+            "</div>";
+          html +=
+            "<div ><a href='../wiki/wiki.php?word=" +
+            result.word +
+            "' target='_blank'>更多</a></div>";
+          html += "</div>";
+          $("#" + showto).html(html);
+        } catch (e) {
+          console.error("note_lookup_guid_json:" + e + " data:" + data);
+        }
+      }
+    }
+  );
+}
+
 var term_get_word_to_div_callback = null;
 function term_get_word_to_div(strWord, div, callback) {
   term_get_word_to_div_callback = callback;
@@ -569,6 +604,10 @@ function term_updata_translation() {
           "[",
           "<span class='" +
             linkclass +
+            "' id='term_link_" +
+            guid +
+            "' gid='" +
+            guid +
             "' onclick=\"" +
             str_term_fun_word_link +
             "('" +
@@ -621,6 +660,7 @@ function term_updata_translation() {
       $(this).html(noteText);
     }
   });
+  term_popup_init();
 }
 
 function term_show_win(guid, keyWord = "") {
@@ -773,3 +813,40 @@ function term_get_dict() {
     }
   );
 }
+
+function term_popup_init() {
+  $(".term_link").each(function () {
+    if ($(this).attr("init") != "1") {
+      if ($(this).text().length > 0) {
+        $(this).css("background", "unset");
+      }
+      let gid = $(this).attr("gid");
+      if ($(this).offset().left < $(document.body).width() / 2) {
+        //出现在左侧
+        $(this).append(
+          '<div id="gid_' +
+            gid +
+            '" class="guide_contence" style="left: -5px;"></div>'
+        );
+        $(".guide_contence:after").css("left", "0");
+      } else {
+        //出现在右侧
+        $(this).append(
+          '<div id="gid_' +
+            gid +
+            '" class="guide_contence" style="right: -5px;"></div>'
+        );
+        $(".guide_contence:after").css("right", "0");
+      }
+      $(this).attr("init", "1");
+    }
+  });
+
+  $(".term_link").mouseenter(function () {
+    if ($(this).children(".guide_contence").first().html().length > 0) {
+      return;
+    }
+    let gid = $(this).attr("gid");
+    term_load_preview(gid, "gid_" + gid);
+  });
+}

+ 37 - 0
app/term/term_popup.js

@@ -0,0 +1,37 @@
+function term_popup_init() {
+  $(".term_link").each(function () {
+    if ($(this).attr("init") != "1") {
+      if ($(this).text().length > 0) {
+        $(this).css("background", "unset");
+      }
+      let gid = $(this).attr("gid");
+      if ($(this).offset().left < $(document.body).width() / 2) {
+        //出现在左侧
+        $(this).append(
+          '<div id="gid_' +
+            gid +
+            '"  class="guide_contence" style="left: -5px;"></div>'
+        );
+        $(".guide_contence:after").css("left", "0");
+      } else {
+        //出现在右侧
+        $(this).append(
+          '<div id="gid_' +
+            gid +
+            '" class="guide_contence" style="right: -5px;"></div>'
+        );
+        $(".guide_contence:after").css("right", "0");
+      }
+      $(this).attr("init", "1");
+    }
+  });
+
+  $(".term_link").mouseenter(function () {
+    if ($(this).children(".guide_contence").first().html().length > 0) {
+      return;
+    }
+    let gid = $(this).attr("gid");
+    let id = "gid_" + gid;
+    note_lookup_guid_json(gid, id);
+  });
+}

+ 1 - 0
app/time.php

@@ -1,3 +1,4 @@
 <?php
 echo time();
+phpinfo();
 ?>

+ 2 - 1
app/ucenter/setting.php

@@ -55,11 +55,12 @@ require_once '../public/function.php';
 	<title id="page_title">Setting</title>
 
 	<script src="../public/js/jquery-3.5.1.js"></script>
+	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>	
 	<script src="../public/js/fixedsticky.js"></script>
 	<script src="../lang/lang.js"></script>
 	<script src="../public/js/comm.js"></script>
 	<script src="../public/js/notify.js"></script>
-	<script src="../public/js/jquery-ui-1.12.1/jquery-ui.js"></script>
+
 	<script src="./setting.js"></script>
 
 </head>

+ 156 - 0
app/usent/sent_post.php

@@ -0,0 +1,156 @@
+<?php
+#更新一个句子
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once "../public/function.php";
+
+$respond=array("status"=>0,"message"=>"");
+$respond['book']=$_POST["book"];
+$respond['para']=$_POST["para"];
+$respond['begin']=$_POST["begin"];
+$respond['end']=$_POST["end"];
+$respond['channal']=$_POST["channal"];
+$respond['text']=$_POST["text"];
+
+#检查是否登陆
+if(!isset($_COOKIE["userid"])){
+    $respond["status"] = 1;
+    $respond["message"] = 'not login';
+    echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+
+#先查询对此channal是否有权限修改
+$cooperation = 0;
+if(isset($_POST["channal"])){
+   PDO_Connect("sqlite:"._FILE_DB_CHANNAL_);
+    $query = "SELECT owner FROM channal WHERE id=?";
+    $fetch = PDO_FetchOne($query,array($_POST["channal"]));
+    if($fetch && $fetch==$_COOKIE["userid"]){
+        #自己的channal
+        $cooperation = 1;
+    }
+    else{
+        $query = "SELECT count(*) FROM cooperation WHERE channal_id= ? and user_id=? ";
+        $fetch = PDO_FetchOne($query,array($_POST["channal"],$_COOKIE["userid"]));
+        if($fetch>0){
+            #有协作权限
+            $cooperation = 1;
+        }
+        else{
+            #无协作权限
+            $cooperation = 0;
+        }
+    }
+}
+else{
+    $respond["status"] = 1;
+    $respond["message"] = 'error channal id';
+    echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+    exit;
+}
+
+
+PDO_Connect("sqlite:"._FILE_DB_SENTENCE_);
+if(isset($_POST["id"])){
+    if(empty($_POST["id"])){
+        #没有id新建
+        if($cooperation == 1){
+            #有权限
+            $query = "INSERT INTO sentence (id, 
+														parent,
+														book,
+														paragraph,
+														begin,
+														end,
+														channal,
+														tag,
+														author,
+														editor,
+														text,
+														language,
+														ver,
+														status,
+														strlen,
+														modify_time,
+														receive_time,
+														create_time
+														) 
+										VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";
+            $stmt = $PDO->prepare($query);
+            $stmt->execute(array(UUID::v4(),
+										  "",
+										  $_POST["book"], 
+										  $_POST["para"], 
+										  $_POST["begin"], 
+										  $_POST["end"], 
+										  $_POST["channal"], 
+										  "", 
+										  "[]", 
+										  $_COOKIE["userid"],
+										  $_POST["text"],
+										  $_POST["lang"],
+										  1,
+										  7,
+										  mb_strlen($_POST["text"],"UTF-8"),
+										  mTime(),
+										  mTime(),
+										  mTime()
+                                        ));
+            if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
+                /*  识别错误  */
+                $error = PDO_ErrorInfo();
+                $respond['message']=$error[2];
+                $respond['status']=1;
+                echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+                exit;
+            }
+            else{
+                $respond['data']=array();
+            }
+        }
+        else{
+            #没权限
+            $respond['message']="没有权限";
+            $respond['status']=1;
+        }
+    }
+    else{
+        /* 修改现有数据 */
+        #判断是否有修改权限
+        if($cooperation == 1){
+            #有权限
+            $query="UPDATE sentence SET text= ?  , strlen = ? , editor = ? , receive_time= ?  , modify_time= ?   where  id= ?  ";
+            $stmt  = PDO_Execute($query,
+                                            array($_POST["text"],
+                                                    mb_strlen($_POST["text"],"UTF-8"), 
+                                                    $_COOKIE["userid"] ,
+                                                    mTime(),
+                                                    mTime(),
+                                                    $_POST["id"]));
+            if (!$stmt || ($stmt && $stmt->errorCode() != 0)) {
+                /*  识别错误  */
+                $error = PDO_ErrorInfo();
+                $respond['message']=$error[2];
+                $respond['status']=1;
+                echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+                exit;
+            }
+            else{
+                #没错误
+
+            }
+        }
+        else{
+            #没权限 建议
+            $respond['message']="没有权限";
+            $respond['status']=1;
+        }
+    }
+}
+else{
+# error
+}
+
+echo json_encode($respond, JSON_UNESCAPED_UNICODE);
+?>

+ 3 - 3
app/usent/update.php

@@ -2,9 +2,9 @@
 /*
 get xml doc from db
 */
-include "../path.php";
-include "../public/_pdo.php";
-include "../public/function.php";
+require_once "../path.php";
+require_once "../public/_pdo.php";
+require_once "../public/function.php";
 
 
 $aData=json_decode($_POST["data"],TRUE);

+ 4 - 0
app/wiki/wiki.js

@@ -94,3 +94,7 @@ function wiki_pre_search(keyword) {
     }
   );
 }
+
+function set_channal(channalid) {
+  location.assign("../wiki/wiki.php?word=" + _word + "&channal=" + channalid);
+}

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