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

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

bhikkhu-kosalla-china 4 лет назад
Родитель
Сommit
ca08d4ce2a

+ 12 - 0
api/config.toml

@@ -0,0 +1,12 @@
+[postgresql]
+server = "127.0.0.1"
+port = 5432
+name = "mint"
+sslmode = "disable"
+user = "postgres"
+password = ""
+[redis]
+hosts = ["127.0.0.1:6376", "127.0.0.1:6377", "127.0.0.1:6378"]
+password = ""
+db = 0
+prefix="aaa://"

+ 23 - 46
app/article/article.js

@@ -26,6 +26,7 @@ function articel_load(id, collection_id) {
 					let result = JSON.parse(data);
 					if (result) {
 						$("#article_title").html(result.title);
+						$("#article_path_title").html(result.title);
 						$("#page_title").text(result.title);
 						$("#article_subtitle").html(result.subtitle);
 						$("#article_author").html(result.username.nickname + "@" + result.username.username);
@@ -67,7 +68,7 @@ function collect_load(id) {
 						$("#contents").html(marked(result.summary));
 
 						let article_list = JSON.parse(result.article_list);
-						render_article_list(article_list, id);
+						render_article_list(article_list);
 					}
 				} catch (e) {
 					console.error(e);
@@ -79,24 +80,26 @@ function collect_load(id) {
 	);
 }
 
-function articel_load_collect(article_id) {
+function articel_load_article_list(articleId,collectionId) {
 	$.get(
 		"../article/collect_get.php",
 		{
-			article: article_id,
+			id: collectionId,
 			setting: "",
 		},
 		function (data, status) {
 			if (status == "success") {
 				try {
 					let result = JSON.parse(data);
-					if (result && result.length > 0) {
-						//$("#collect_title").html(result[0].title);
-						let strTitle = "<a href='../article/?collect=" + result[0].id + "'>" + result[0].title + "</a>";
-						$("#pali_pedia").html(strTitle);
+					if (result) {
+						let article_list = JSON.parse(result.article_list);
+						render_article_list(article_list,collectionId,articleId);
 
-						let article_list = JSON.parse(result[0].article_list);
-						render_article_list(article_list, result[0].id);
+						let strTitle = "<a href='../article/?collection=" + result.id + "'>" + result.title + "</a> / ";
+						for (const iterator of tocActivePath) {
+							strTitle += "<a href='../article/?id="+iterator.key+"&collection=" + result.id + "'>" + iterator.title + "</a> / ";
+						}
+						$("#article_path").html(strTitle);						
 					}
 				} catch (e) {
 					console.error(e);
@@ -109,44 +112,15 @@ function articel_load_collect(article_id) {
 }
 
 //在collect 中 的article列表
-function render_article_list(article_list, collection_id) {
-	let html = "";
-	html += "<ul>";
-	let display = "";
-	if (_display == "para") {
-		display = "&display=para";
-	}
-	let prevArticle = "无";
-	let nextArticle = "无";
-	let urlCollection = "&collection=" + collection_id;
-	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 onclick=\"gotoArticle('" + prev.article + "')\">" + prev.title + "</a>";
-			}
-			if (index < article_list.length - 1) {
-				const next = article_list[index + 1];
-				nextArticle = "<a onclick=\"gotoArticle('" + next.article + "')\">" + next.title + "</a>";
-			}
-			$("#contents_nav_left").html(prevArticle);
-			$("#contents_nav_right").html(nextArticle);
+function render_article_list(article_list,collectId="",articleId="") {
+	$("#toc_content").fancytree({
+		autoScroll: true,
+		source: tocGetTreeData(article_list,articleId),
+		activate: function(e, data) {
+			gotoArticle(data.node.key,collectId);
+			return false;
 		}
-		html +=
-			"<li class='level_" +
-			element.level +
-			"'>" +
-			"<a onclick=\"gotoArticle('" +
-			element.article +
-			"')\">" +
-			element.title +
-			"</a></li>";
-	}
-
-	html += "</ul>";
-
-	$("#toc_content").html(html);
+	});
 }
 
 function set_channal(channalid) {
@@ -188,6 +162,9 @@ function setMode(mode = "read") {
 //跳转到另外一个文章
 function gotoArticle(articleId) {
 	let url = "../article/index.php?id=" + articleId;
+	if (_collection_id != "") {
+		url += "&collection=" + _collection_id;
+	}
 	if (_channal != "") {
 		url += "&channal=" + _channal;
 	}

+ 33 - 7
app/article/index.php

@@ -22,7 +22,7 @@ require_once "../pcdl/html_head.php";
 		echo "_articel_id='".$_GET["id"]."';";
 	}
 	if(isset($_GET["collect"])){
-		echo "_collect_id='".$_GET["collect"]."';";
+		echo "_collection_id='".$_GET["collect"]."';";
 	}
 	if(isset($_GET["collection"])){
 		echo "_collection_id='".$_GET["collection"]."';";
@@ -101,16 +101,40 @@ require_once "../pcdl/html_head.php";
 
 
 <link type="text/css" rel="stylesheet" href="style.css"  />
+<link type="text/css" rel="stylesheet" href="pad.css" media="screen and (max-width:1280px)" />
 <link type="text/css" rel="stylesheet" href="mobile.css" media="screen and (max-width:800px)" />
 <link type="text/css" rel="stylesheet" href="print.css" media="print" />
 
+<link href="../../node_modules/jquery.fancytree/dist/skin-win7/ui.fancytree.css" rel="stylesheet" type="text/css" class="skinswitcher">
+<script src="../tree/jquery.fancytree.js" type="text/javascript"></script>
+<script src="../article/my_collect.js" type="text/javascript"></script>
+
+<style>
+#toc_content ul.fancytree-container{
+	border:unset;
+}
+.fancytree-container .active {
+    font-weight: 700;
+    color: var(--main-color);
+	background: linear-gradient(to right, var(--link-color), var(--nocolor));
+    border-radius: 5px;
+}
+span.fancytree-title{
+	color: var(--main-color1);
+}
+span.fancytree-node{
+	display: flex;
+}
+</style>
 
 <?php
     require_once("../pcdl/head_bar.php");
 ?>
 <div id="head_bar" >
-	<div id="pali_pedia" style="display:flex;">
-		<span><?php echo $_local->gui->anthology; ?></span>
+	<div style="display:flex;">
+	<div id="article_path" >
+	</div>
+	<div id="article_path_title"></div>
 	</div>
 
 	<div style="margin: auto 0;">
@@ -189,12 +213,14 @@ require_once "../pcdl/html_head.php";
 	click_dropdown_init();
 	note_create();
 	historay_init();
-	if(_collect_id==""){
-		articel_load(_articel_id,_collection_id);
-		articel_load_collect(_articel_id);
+	if(_articel_id==""){
+		collect_load(_collection_id);
 	}
 	else{
-		collect_load(_collect_id);
+		articel_load(_articel_id,_collection_id);
+		if(_collection_id!=""){
+			articel_load_article_list(_articel_id,_collection_id);
+		}
 	}
 	});
 

+ 11 - 22
app/article/my_article.js

@@ -24,7 +24,6 @@ function my_article_list() {
 					html += "<div style='flex:0.5;'>No.</div>";
 					html += "<div style='flex:4;'>" + gLocal.gui.title + "</div>";
 					html += "<div style='flex:2;'>" + gLocal.gui.privacy + "</div>";
-					html += "<div style='flex:1;'>" + gLocal.gui.edit + "</a></div>";
 					html += "<div style='flex:1;'>" + gLocal.gui.preview + "</a></div>";
 					html += "<div style='flex:1;'>" + gLocal.gui.copy_link + "</div>";
 					html += "<div style='flex:1;'>" + gLocal.gui.share_to + "</div>";
@@ -33,28 +32,18 @@ function my_article_list() {
 					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:0.5;'>" + key++ + "</div>";
-						html += "<div style='flex:4;'>" + iterator.title + "</div>";
-						html += "<div style='flex:2;'>" + render_status(iterator.status) + "</div>";
-						html +=
-							"<div style='flex:1;'><a href='../article/my_article_edit.php?id=" +
-							iterator.id +
-							"' title='" +
-							gLocal.gui.edit +
-							"'>";
-						html += "<button class='icon_btn'>";
-						html += "<svg class='icon'>";
-						html += "<use xlink:href='../studio/svg/icon.svg#ic_mode_edit'></use>";
-						html += "</svg>";
-						html += "</button>";
+						html += "<div style='flex:0.5;'>" + key + "</div>";
 
-						html += "</a></div>";
-						html +=
-							"<div style='flex:1;'><a href='../article/?id=" +
-							iterator.id +
-							"' target='_blank' title='" +
-							gLocal.gui.preview +
-							"' >";
+						html += "<div style='flex:4;'>" ;
+						html += "<a href='../article/my_article_edit.php?id=" + iterator.id + "' title='" + gLocal.gui.edit + "'>";						
+						html += iterator.title ;
+						html += "</a>";
+						html += "</div>";
+
+						html += "<div style='flex:2;'>" + render_status(iterator.status) + "</div>";
+						
+						html += "<div style='flex:1;'>";
+						html += "<a href='../article/?id=" + iterator.id + "' target='_blank' title='" + gLocal.gui.preview + "' >";
 						html += "<button class='icon_btn'>";
 						html += "<svg class='icon'>";
 						html += "<use xlink:href='../studio/svg/icon.svg#preview'></use>";

+ 20 - 1
app/article/my_article_edit.php

@@ -14,6 +14,7 @@ require_once '../studio/index_head.php';
 	<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="article";
 	</script>
@@ -55,9 +56,27 @@ require_once '../studio/index_head.php';
 #preview_inner{
 	background-color: var(--bg-color);
 	color: var(--main-color);
-	padding: 0.5em;
+	padding: 1em;
 }
 
+#preview_inner ul{
+	display: block;
+    list-style-type: none;
+    margin-block-start: 1em;
+    margin-block-end: 1em;
+    margin-inline-start: 0px;
+    margin-inline-end: 0px;
+    padding-inline-start: 40px;
+	text-indent: -1em;
+
+}
+#preview_inner p{
+	text-indent: 2em;
+}
+#preview_inner h3 {
+    font-size: 110%;
+	text-align: center;
+}
 	</style>
 
 	<?php

+ 4 - 5
app/article/my_article_index.php

@@ -40,16 +40,15 @@ require_once '../studio/index_head.php';
 			<div class="tool_bar">
 				<div><?php echo $_local->gui->text.$_local->gui->list ?></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()">
+					<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" onclick="article_add_dlg_show()" title=" ">
 							<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>					
 					<span class="icon_btn_div">				
 						<span class="icon_btn_tip"><?php echo $_local->gui->recycle_bin ;?></span>
 						<button id="to_recycle" type="button" class="icon_btn" onclick="file_del()" title=" ">

+ 175 - 39
app/article/my_collect.js

@@ -22,23 +22,18 @@ function my_collect_list() {
 						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;'>" ;
+						html += "<a href='../article/my_collect_edit.php?id=" + iterator.id + "'>" ;
+						html += iterator.title ;
+						html += "</a>";
+						html += "</div>";
 						html += "<div style='flex:2;'>" + render_status(iterator.status) + "</div>";
-						html += "<div style='flex:1;'>" + gLocal.gui.copy_link + "</div>";
-						html +=
-							"<div style='flex:1;'><a href='../article/my_collect_edit.php?id=" +
-							iterator.id +
-							"'>" +
-							gLocal.gui.edit +
-							"</a></div>";
-						html +=
-							"<div style='flex:1;'><a href='../article/?collect=" +
-							iterator.id +
-							"' target='_blank'>" +
-							gLocal.gui.preview +
-							"</a></div>";
+						//html += "<div style='flex:1;'>" + gLocal.gui.copy_link + "</div>";
+						html += "<div style='flex:1;'>";
+						html += "<a href='../article/?collect=" + iterator.id + "' target='_blank'>" + gLocal.gui.preview + "</a>";
+						html += "</div>";
 						html += "<div style='flex:1;'>";
-						html += "<a onclick=\"collection_share('" + iterator.id + "')\">share</a>";
+						html += "<a onclick=\"collection_share('" + iterator.id + "')\">"+gLocal.gui.share+"</a>";
 						html += "</div>";
 						html += "</div>";
 					}
@@ -63,9 +58,13 @@ function my_collect_edit(id) {
 		},
 		function (data, status) {
 			if (status == "success") {
-				try {
 					let html = "";
-					let result = JSON.parse(data);
+					let result;				
+				try {
+					result = JSON.parse(data);
+				} catch (e) {
+					console.error(e);
+				}
 					$("#article_collect").attr("a_id", result.id);
 					html += '<div class="" style="padding:5px;">';
 					html += '<div style="max-width:2em;flex:1;"></div>';
@@ -84,7 +83,7 @@ function my_collect_edit(id) {
 					html += "</div></div>";
 
 					html += "<div style='display:flex;'>";
-					html += "<div style='flex:2;'>" + gLocal.gui.summary + "</div>";
+					html += "<div style='flex:2;'>" + gLocal.gui.introduction + "</div>";
 					html += "<div style='flex:8;'>";
 					html += "<input type='input' name='summary' value='" + result.summary + "'/>";
 					html += "</div></div>";
@@ -108,16 +107,8 @@ function my_collect_edit(id) {
 					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 id='ul_article_list'>";
+					html += "</div>";
 
 					html += "</div>";
 
@@ -130,27 +121,170 @@ function my_collect_edit(id) {
 					$("#article_list").html(html);
 					$("#collection_title").html(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]);
+					_arrArticleList = JSON.parse(result.article_list);
+
+
+					$("#ul_article_list").fancytree({
+						autoScroll: true,
+						extensions: ["dnd"],
+						source: tocGetTreeData(_arrArticleList),
+						click: function(e, data) {
+							if( e.ctrlKey ){
+							  window.open("../article/?id="+data.node.key,"_blank");
+							  return false;
+							}
+						  },
+						  dblclick: function(e, data) {
+							editNode(data.node);
+							return false;
+						  },
+						  keydown: function(e, data) {
+							switch( e.which ) {
+							case 113: // [F2]
+							  editNode(data.node);
+							  return false;
+							case 13: // [enter]
+							  if( isMac ){
+								editNode(data.node);
+								return false;
+							  }
+							}
+						  },
+						dnd: {
+							preventVoidMoves: true, // Prevent dropping nodes 'before self', etc.
+							preventRecursiveMoves: true, // Prevent dropping nodes on own descendants
+							autoExpandMS: 400,
+							onDragStart: function(node) {
+								return true;
+							},
+							onDragEnter: function(node, sourceNode) {
+
+							   return true;
+							},
+							onDrop: function(node, sourceNode, hitMode, ui, draggable) {
+
+								sourceNode.moveTo(node, hitMode);
+								node.setExpanded(true);
 							}
-							$("#form_article_list").val(JSON.stringify(_arrArticleOrder));
 						},
+						activate: function(e, data) {
+			//				alert("activate " + data.node);
+						}
 					});
-				} catch (e) {
-					console.error(e);
-				}
+				
+
 			} else {
 				console.error("ajex error");
 			}
 		}
 	);
 }
+var tocActivePath;
+function tocGetTreeData(articles,active=""){
+	let treeData = new Array()
 
+	let treeParents = [];
+	let rootNode = {key:0,title:"root",level:0};
+	treeData.push(rootNode);
+	let lastInsNode = rootNode;
+	let iLastParentNodeLevel = 0;
+	let currParentNode = null;
+	let iCurrLevel = 0;
+	for (let index = 0; index < articles.length; index++) {
+		const element = articles[index];
+
+		let newNode = {key:element.article,title:element.title,level:element.level};
+		if(active==element.article){
+			newNode["extraClasses"]="active";
+		}
+		if(newNode.level>iCurrLevel){
+			treeParents.push(lastInsNode);					
+			lastInsNode.children = new Array();
+			lastInsNode.children.push(newNode);
+			currParentNode = lastInsNode;
+		}
+		else if(newNode.level==iCurrLevel){
+			currParentNode = treeParents[treeParents.length-1];
+			treeParents[treeParents.length-1].children.push(newNode);
+		}
+		else{
+			// 小于
+			do {
+				treeParents.pop();
+			} while (treeParents[treeParents.length-1].level>=newNode.level);
+			
+			currParentNode = treeParents[treeParents.length-1];
+			treeParents[treeParents.length-1].children.push(newNode);
+			iLastParentNodeLevel = treeParents[treeParents.length-1].level;	
+		}
+		lastInsNode = newNode;
+		iCurrLevel = newNode.level;
+
+		if(active==element.article){
+			tocActivePath = new Array();
+			for (let index = 1; index < treeParents.length; index++) {
+				treeParents[index]["expanded"]=true;
+				tocActivePath.push(treeParents[index]);				
+			}
+		}
+	}
+	return treeData[0].children;
+}
+function editNode(node){
+	var prevTitle = node.title,
+	  tree = node.tree;
+	// Disable dynatree mouse- and key handling
+	tree.widget._unbind();
+	// Replace node with <input>
+	$(".fancytree-title", node.span).html("<input id='editNode' value='" + prevTitle + "'>");
+	// Focus <input> and bind keyboard handler
+	$("input#editNode")
+	  .focus()
+	  .keydown(function(event){
+		switch( event.which ) {
+		case 27: // [esc]
+		  // discard changes on [esc]
+		  $("input#editNode").val(prevTitle);
+		  $(this).blur();
+		  break;
+		case 13: // [enter]
+		  // simulate blur to accept new value
+		  $(this).blur();
+		  break;
+		}
+	  }).blur(function(event){
+		// Accept new value, when user leaves <input>
+		var title = $("input#editNode").val();
+		node.setTitle(title);
+		// Re-enable mouse and keyboard handlling
+		tree.widget._bind();
+		//node.focus();
+	  });
+  }
+
+var arrTocTree = new Array();
+var iTocTreeCurrLevel = 1;
+function getTocTreeData(){
+	let tree = $("#ul_article_list").fancytree("getTree");
+    let d = tree.toDict(false);
+	for (const iterator of d) {
+		getTreeNodeData(iterator);
+	}
+}
+function getTreeNodeData(node){
+	let children = 0;
+	if( typeof node.children != "undefined"){
+		children = node.children.length;
+	}
+	arrTocTree.push({article:node.key,title:node.title,level:iTocTreeCurrLevel,children:children});
+	if(children>0){
+		iTocTreeCurrLevel++;
+		for (const iterator of node.children) {
+			getTreeNodeData(iterator);
+		}
+		iTocTreeCurrLevel--;
+	}
+}
 function my_collect_render_article(index, article) {
 	let html = "";
 	html += "<li id='article_item_" + index + "' article_index='" + index + "' class='file_list_row'>";
@@ -202,6 +336,8 @@ function article_preview(id) {
 }
 
 function my_collect_save() {
+	getTocTreeData();
+	$("#form_article_list").val( JSON.stringify(arrTocTree))
 	$.ajax({
 		type: "POST", //方法类型
 		dataType: "json", //预期服务器返回的数据类型

+ 4 - 0
app/article/my_collect_edit.php

@@ -10,6 +10,10 @@ require_once '../studio/index_head.php';
 	<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>
+	
+	<link href="../../node_modules/jquery.fancytree/dist/skin-win7/ui.fancytree.css" rel="stylesheet" type="text/css" class="skinswitcher">
+	<script src="../tree/jquery.fancytree.js" type="text/javascript"></script>
+	<script src="../tree/jquery.fancytree.dnd.js" type="text/javascript"></script>
 
 	<script >
 	var gCurrPage="collect";

+ 2 - 2
app/article/my_collect_post.php

@@ -52,10 +52,10 @@ else{
     if(count($arrList)>0){
         /* 开始一个事务,关闭自动提交 */
         $PDO->beginTransaction();
-        $query = "INSERT INTO article_list (collect_id, article_id,level,title) VALUES ( ?, ?, ? , ? )";
+        $query = "INSERT INTO article_list (collect_id, article_id,level,title,children) VALUES ( ? , ?, ?, ? , ? )";
         $sth = $PDO->prepare($query);
         foreach ($arrList as $row) {
-            $sth->execute(array($_POST["id"],$row->article,$row->level,$row->title));
+            $sth->execute(array($_POST["id"],$row->article,$row->level,$row->title,$row->children));
 			if($redis){
 				#删除article权限缓存
 				$redis->del("power://article/".$row->article);

+ 3 - 0
app/article/pad.css

@@ -0,0 +1,3 @@
+#right_pannal {
+    display:none;
+}

+ 1 - 0
app/article/style.css

@@ -83,6 +83,7 @@
 }
 #right_pannal {
 	flex: 3;
+	max-width: 270px;
 }
 #head_bar {
 	height: unset;

+ 13 - 14
app/group/group.js

@@ -180,12 +180,13 @@ function group_list(id, list) {
 					if (result.file && result.file.length > 0) {
 						for (const iterator of result.file) {
 							html += '<div class="file_list_row" style="padding:5px;">';
-							html += "<div style='flex:1;'>" + key++ + "</div>";
+							html += "<div style='flex:1;'>" + key+ "</div>";
 							html += "<div style='flex:1;'>";
 							//资源类型
 							html += "<svg class='icon'>";
 							let cardUrl = "";
 							let doing = "";
+							let viewLink = "<a>";
 							switch (parseInt(iterator.res_type)) {
 								case 1: //pcs
 									html += "<use xlink:href='../studio/svg/icon.svg#article'></use>";
@@ -193,7 +194,7 @@ function group_list(id, list) {
 									doing +=
 										"<a href='../studio/project.php?op=open&doc_id=" +
 										iterator.res_id +
-										"'>打开</a>";
+										"'>"+gLocal.gui.open+"</a>";
 									break;
 								case 2: //channel
 									html += "<use xlink:href='../studio/svg/icon.svg#channel_leaves'></use>";
@@ -202,24 +203,20 @@ function group_list(id, list) {
 								case 3: //article
 									html += "<use xlink:href='../studio/svg/icon.svg#article_1'></use>";
 									cardUrl = "../article/card.php";
+									viewLink = "<a href='../article/?id=" + iterator.res_id + "' target='_blank'>";
 									doing +=
-										"<a href='../article/?id=" + iterator.res_id + "' target='_blank'>查看</a>";
-									doing +=
-										"|<a href='../article/my_article_edit.php?id=" +
+										"<a href='../article/my_article_edit.php?id=" +
 										iterator.res_id +
-										"' target='_blank'>编辑</a>";
+										"' target='_blank'>"+gLocal.gui.edit+"</a>";
 									break;
 								case 4: //collection
 									html += "<use xlink:href='../studio/svg/icon.svg#collection'></use>";
 									cardUrl = "../collect/card.php";
+									viewLink ="<a href='../article/?collection=" + iterator.res_id + "' target='_blank'>";
 									doing +=
-										"<a href='../article/?collect=" +
-										iterator.res_id +
-										"' target='_blank'>查看</a>";
-									doing +=
-										"|<a href='../article/my_collect_edit.php?id=" +
+										"<a href='../article/my_collect_edit.php?id=" +
 										iterator.res_id +
-										"' target='_blank'>编辑</a>";
+										"' target='_blank'>"+gLocal.gui.edit+"</a>";
 									break;
 								case 5: //channel片段
 									break;
@@ -231,8 +228,10 @@ function group_list(id, list) {
 							html += "</svg>";
 							html += "</div>";
 							html += "<div style='flex:2;'>";
-							html += "<guide url='" + cardUrl + "' gid='" + iterator.res_id + "'>";
-							html += iterator.res_title + "</guide></div>";
+							html += viewLink+iterator.res_title+"</a>" ;
+							html += "<guide url='" + cardUrl + "' gid='" + iterator.res_id + "'></guide>";
+							
+							html += "</div>";
 							html += "<div style='flex:2;'>";
 							switch (parseInt(iterator.power)) {
 								case 10:

+ 5 - 1
app/public/casesuf.inc

@@ -3139,7 +3139,11 @@ array("oti","ā",".2p.$.sg.$.aor."),
 array("oti","ttha",".2p.$.pl.$.aor."),
 array("oti","se",".2p.$.sg.$.aor."),
 array("oti","vhaṃ",".2p.$.pl.$.aor."),
-array("ati","ittha",".2p.$.pl.$.aor.")
+array("ati","ittha",".2p.$.pl.$.aor."),
+array("ati","ituṃ",".v:ind.$.inf."),
+array("ati","atuṃ",".v:ind.$.inf."),
+array("ati","itvā",".v:ind.$.abs."),
+array("ati","atvā",".v:ind.$.abs.")
 
 
 

+ 3 - 1
composer.json

@@ -1,6 +1,8 @@
 {
 	"require": {
 		"elasticsearch/elasticsearch": "~7.0",
-		"guzzlehttp/guzzle": "7.0"
+		"guzzlehttp/guzzle": "7.0",
+		"catfan/medoo": "^2.1",
+		"casbin/casbin": "^3.9"
 	}
 }