This commit is contained in:
zhuangqian 2016-12-01 09:02:45 +08:00
commit 5ba5f09f77
8 changed files with 258 additions and 268 deletions

View File

@ -1,206 +1,206 @@
/**
* Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.smallchill.core.beetl.tag;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.beetl.core.Tag;
import com.smallchill.common.vo.TreeNode;
import com.smallchill.core.constant.ConstCache;
import com.smallchill.core.constant.ConstCacheKey;
import com.smallchill.core.constant.Cst;
import com.smallchill.core.plugins.dao.Db;
import com.smallchill.core.toolbox.Func;
import com.smallchill.core.toolbox.Paras;
public class SideBarTag extends Tag {
private List<TreeNode> nodeList = new ArrayList<TreeNode>();
@Override
@SuppressWarnings("unchecked")
public void render() {
try {
Map<String, String> param = (Map<String, String>) args[1];
final Object userId = param.get("userId");
final Object roleId = param.get("roleId");
String ctxPath =Cst.me().getContextPath();
Map<String, Object> userRole = Db.selectOneByCache(ConstCache.ROLE_CACHE, ConstCacheKey.ROLE_EXT + userId, "select * from TFW_ROLE_EXT where USERID=#{userId}", Paras.create().set("userId", userId));
String roleIn = "0";
String roleOut = "0";
if (!Func.isEmpty(userRole)) {
Paras rd = Paras.parse(userRole);
roleIn = rd.getStr("ROLEIN");
roleOut = rd.getStr("ROLEOUT");
}
final StringBuilder sql = new StringBuilder();
sql.append("select * from TFW_MENU ");
sql.append(" where ( ");
sql.append(" (status=1)");
sql.append(" and (icon is not null and icon not LIKE '%btn%' and icon not LIKE '%icon%') ");
sql.append(" and (id in (select menuId from TFW_RELATION where roleId in (#{join(roleId)})) or id in (#{join(roleIn)}))");
sql.append(" and id not in(#{join(roleOut)})");
sql.append(" )");
sql.append(" order by levels,pCode,num");
@SuppressWarnings("rawtypes")
List<Map> sideBar = Db.selectListByCache(ConstCache.MENU_CACHE, ConstCacheKey.SIDEBAR + userId, sql.toString(),
Paras.create()
.set("roleId", roleId.toString().split(","))
.set("roleIn", roleIn.split(","))
.set("roleOut", roleOut.split(",")));
for (Map<String, Object> side : sideBar) {
TreeNode node = new TreeNode();
Paras rd = Paras.parse(side);
node.setId(rd.getStr("CODE"));
node.setParentId(rd.getStr("PCODE"));
node.setName(rd.getStr("NAME"));
node.setIcon(rd.getStr("ICON"));
node.setIsParent(false);
nodeList.add(node);
}
new TreeNode().buildNodes(nodeList);
StringBuilder sb = new StringBuilder();
for (Map<String, Object> side : sideBar) {
if (Func.toInt(side.get("LEVELS")) == 1) {
String firstMenu = "";
String subMenu = "";
String href = Func.isEmpty(side.get("URL")) ? "#" : ctxPath + side.get("URL") + "";
String addtabs = Func.isEmpty(side.get("URL")) ? "" : "data-addtabs=\"" + side.get("CODE") + "\"";
firstMenu += "<li >";
firstMenu += " <a data-url=\"" + href + "\" " + addtabs + " data-title=\"" + side.get("NAME") + "\" data-icon=\"fa " + side.get("ICON") + "\" class=\"" + getDropDownClass(Func.toStr(side.get("CODE")),"dropdown-toggle") + " tmsp-pointer\">";
firstMenu += " <i class=\"menu-icon fa " + side.get("ICON") + "\"></i>";
firstMenu += " <span class=\"menu-text\">" + side.get("NAME") + "</span>";
firstMenu += " <b class=\"arrow " + getDropDownClass(Func.toStr(side.get("CODE")),"fa fa-angle-down") + "\"></b>";
firstMenu += " </a>";
firstMenu += " <b class=\"arrow\"></b>";
subMenu = this.reloadMenu(sideBar, Func.toStr(side.get("CODE")), firstMenu, 1, ctxPath);// 寻找子菜单
sb.append(subMenu);
}
}
//版权校验
sb.append("<script type=\"text/javascript\">");
sb.append(" $(function(){");
sb.append(" setTimeout(function(){");
sb.append(" var $supporter = $(\"#support_tonbusoft\");");
sb.append(" $supporter.addClass('bigger-110');");
sb.append(" var name = $supporter.html();");
sb.append(" var index = layer;");
sb.append(" if(index == undefined){");
sb.append(" alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\");");
sb.append(" return;");
sb.append(" }");
sb.append(" if(name == undefined){");
sb.append(" layer.alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\", {icon: 2,title:\"侵权警告\"});");
sb.append(" return;");
sb.append(" } else if(!(name.indexOf(\"smallchill@163.com\") >= 0 && $supporter.is(\"span\") && !$supporter.is(\":hidden\"))){");
sb.append(" layer.alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\", {icon: 2,title:\"侵权警告\"});");
sb.append(" return;");
sb.append(" }");
sb.append(" }, 1800);");
sb.append(" });");
sb.append("</script>");
ctx.byteWriter.writeString(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 加载子菜单
*
* @param sideBar
* 菜单集合
* @param pCode
* 父编号
* @param menuCode
* 选中菜单编号
* @param pStr
* 父HTML
* @param levels
* 层级
* @return String 返回子菜单HTML集
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public String reloadMenu(List<Map> sideBar, String pCode, String pStr, int levels, String ctxPath) {
String Str = "";
String subStr = "";
for (Map subside : sideBar) {
Paras rd = Paras.parse(subside);
int _levels = rd.getInt("LEVELS");
String _code = rd.getStr("CODE");
String _pCode = rd.getStr("PCODE");
String _url = rd.getStr("URL");
String _icon = rd.getStr("ICON");
String _name = rd.getStr("NAME");
if ((_pCode.equals(pCode) && _levels > levels)) {
String href = Func.isEmpty(_url) ? "#" : ctxPath + _url + "";
String addtabs = Func.isEmpty(_url) ? "" : "data-addtabs=\"" + _code + "\"";
Str += "<li>";
Str += " <a data-url=\"" + href + "\" " + addtabs + " data-title=\"" + _name + "\" data-icon=\"fa " + _icon + "\" class=\"" + getDropDownClass(_code, "dropdown-toggle") + " tmsp-pointer\">";
Str += " <i class=\"menu-icon fa " + _icon + "\"></i>";
Str += _name;
Str += " <b class=\"arrow " + getDropDownClass(_code,"fa fa-angle-down") + "\"></b>";
Str += " </a>";
Str += " <b class=\"arrow\"></b>";
subStr = this.reloadMenu(sideBar, _code, Str, _levels, ctxPath);// 递归寻找子菜单
Str = Func.isEmpty(subStr) ? Str : subStr;
}
}
if (Str.length() > 0) {
pStr += (Func.isEmpty(pStr)) ? Str : "<ul class=\"submenu\">" + Str + "</ul>";
pStr += "</li>";
return pStr;
} else {
return "";
}
}
public String getDropDownClass(String code,String dropdownclass){
Iterator<TreeNode> it = nodeList.iterator();
while (it.hasNext()) {
TreeNode n = (TreeNode) it.next();
if(n.getId().equals(code)&&n.isParent()){
return dropdownclass;
}
}
return "";
}
}
/**
* Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.smallchill.core.beetl.tag;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.beetl.core.Tag;
import com.smallchill.common.vo.TreeNode;
import com.smallchill.core.constant.ConstCache;
import com.smallchill.core.constant.ConstCacheKey;
import com.smallchill.core.constant.Cst;
import com.smallchill.core.plugins.dao.Db;
import com.smallchill.core.toolbox.Func;
import com.smallchill.core.toolbox.Paras;
public class SideBarTag extends Tag {
private List<TreeNode> nodeList = new ArrayList<TreeNode>();
@Override
@SuppressWarnings("unchecked")
public void render() {
try {
Map<String, String> param = (Map<String, String>) args[1];
final Object userId = param.get("userId");
final Object roleId = param.get("roleId");
String ctxPath =Cst.me().getContextPath();
Map<String, Object> userRole = Db.selectOneByCache(ConstCache.ROLE_CACHE, ConstCacheKey.ROLE_EXT + userId, "select * from TFW_ROLE_EXT where USERID=#{userId}", Paras.create().set("userId", userId));
String roleIn = "0";
String roleOut = "0";
if (!Func.isEmpty(userRole)) {
Paras rd = Paras.parse(userRole);
roleIn = rd.getStr("ROLEIN");
roleOut = rd.getStr("ROLEOUT");
}
final StringBuilder sql = new StringBuilder();
sql.append("select * from TFW_MENU ");
sql.append(" where ( ");
sql.append(" (status=1)");
sql.append(" and (icon is not null and icon not LIKE '%btn%' and icon not LIKE '%icon%') ");
sql.append(" and (id in (select menuId from TFW_RELATION where roleId in (#{join(roleId)})) or id in (#{join(roleIn)}))");
sql.append(" and id not in(#{join(roleOut)})");
sql.append(" )");
sql.append(" order by levels,pCode,num");
@SuppressWarnings("rawtypes")
List<Map> sideBar = Db.selectListByCache(ConstCache.MENU_CACHE, ConstCacheKey.SIDEBAR + userId, sql.toString(),
Paras.create()
.set("roleId", roleId.toString().split(","))
.set("roleIn", roleIn.split(","))
.set("roleOut", roleOut.split(",")));
for (Map<String, Object> side : sideBar) {
TreeNode node = new TreeNode();
Paras rd = Paras.parse(side);
node.setId(rd.getStr("CODE"));
node.setParentId(rd.getStr("PCODE"));
node.setName(rd.getStr("NAME"));
node.setIcon(rd.getStr("ICON"));
node.setIsParent(false);
nodeList.add(node);
}
new TreeNode().buildNodes(nodeList);
StringBuilder sb = new StringBuilder();
for (Map<String, Object> side : sideBar) {
if (Func.toInt(side.get("LEVELS")) == 1) {
String firstMenu = "";
String subMenu = "";
String href = Func.isEmpty(side.get("URL")) ? "#" : ctxPath + side.get("URL") + "";
String addtabs = Func.isEmpty(side.get("URL")) ? "" : "data-addtabs=\"" + side.get("CODE") + "\"";
firstMenu += "<li >";
firstMenu += " <a data-url=\"" + href + "\" " + addtabs + " data-title=\"" + side.get("NAME") + "\" data-icon=\"fa " + side.get("ICON") + "\" class=\"" + getDropDownClass(Func.toStr(side.get("CODE")),"dropdown-toggle") + " blade-pointer\">";
firstMenu += " <i class=\"menu-icon fa " + side.get("ICON") + "\"></i>";
firstMenu += " <span class=\"menu-text\">" + side.get("NAME") + "</span>";
firstMenu += " <b class=\"arrow " + getDropDownClass(Func.toStr(side.get("CODE")),"fa fa-angle-down") + "\"></b>";
firstMenu += " </a>";
firstMenu += " <b class=\"arrow\"></b>";
subMenu = this.reloadMenu(sideBar, Func.toStr(side.get("CODE")), firstMenu, 1, ctxPath);// 寻找子菜单
sb.append(subMenu);
}
}
//版权校验
sb.append("<script type=\"text/javascript\">");
sb.append(" $(function(){");
sb.append(" setTimeout(function(){");
sb.append(" var $supporter = $(\"#support_tonbusoft\");");
sb.append(" $supporter.addClass('bigger-110');");
sb.append(" var name = $supporter.html();");
sb.append(" var index = layer;");
sb.append(" if(index == undefined){");
sb.append(" alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\");");
sb.append(" return;");
sb.append(" }");
sb.append(" if(name == undefined){");
sb.append(" layer.alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\", {icon: 2,title:\"侵权警告\"});");
sb.append(" return;");
sb.append(" } else if(!(name.indexOf(\"smallchill@163.com\") >= 0 && $supporter.is(\"span\") && !$supporter.is(\":hidden\"))){");
sb.append(" layer.alert(\"该产品版权归 smallchill@163.com 所有,请勿盗版!\", {icon: 2,title:\"侵权警告\"});");
sb.append(" return;");
sb.append(" }");
sb.append(" }, 1800);");
sb.append(" });");
sb.append("</script>");
ctx.byteWriter.writeString(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 加载子菜单
*
* @param sideBar
* 菜单集合
* @param pCode
* 父编号
* @param menuCode
* 选中菜单编号
* @param pStr
* 父HTML
* @param levels
* 层级
* @return String 返回子菜单HTML集
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public String reloadMenu(List<Map> sideBar, String pCode, String pStr, int levels, String ctxPath) {
String Str = "";
String subStr = "";
for (Map subside : sideBar) {
Paras rd = Paras.parse(subside);
int _levels = rd.getInt("LEVELS");
String _code = rd.getStr("CODE");
String _pCode = rd.getStr("PCODE");
String _url = rd.getStr("URL");
String _icon = rd.getStr("ICON");
String _name = rd.getStr("NAME");
if ((_pCode.equals(pCode) && _levels > levels)) {
String href = Func.isEmpty(_url) ? "#" : ctxPath + _url + "";
String addtabs = Func.isEmpty(_url) ? "" : "data-addtabs=\"" + _code + "\"";
Str += "<li>";
Str += " <a data-url=\"" + href + "\" " + addtabs + " data-title=\"" + _name + "\" data-icon=\"fa " + _icon + "\" class=\"" + getDropDownClass(_code, "dropdown-toggle") + " blade-pointer\">";
Str += " <i class=\"menu-icon fa " + _icon + "\"></i>";
Str += _name;
Str += " <b class=\"arrow " + getDropDownClass(_code,"fa fa-angle-down") + "\"></b>";
Str += " </a>";
Str += " <b class=\"arrow\"></b>";
subStr = this.reloadMenu(sideBar, _code, Str, _levels, ctxPath);// 递归寻找子菜单
Str = Func.isEmpty(subStr) ? Str : subStr;
}
}
if (Str.length() > 0) {
pStr += (Func.isEmpty(pStr)) ? Str : "<ul class=\"submenu\">" + Str + "</ul>";
pStr += "</li>";
return pStr;
} else {
return "";
}
}
public String getDropDownClass(String code,String dropdownclass){
Iterator<TreeNode> it = nodeList.iterator();
while (it.hasNext()) {
TreeNode n = (TreeNode) it.next();
if(n.getId().equals(code)&&n.isParent()){
return dropdownclass;
}
}
return "";
}
}

View File

@ -1,11 +1,12 @@
<!DOCTYPE html>
<html >
<html>
<head>
<meta charset="utf-8" />
<title>${title!'curd'}</title>
<title>${title!'blade'}</title>
<link rel="shortcut icon" href="${ctxPath}/static/style/images/favicon.ico" type="image/x-icon" />
<meta name="renderer" content="webkit" /><!-- 360浏览器默认选择webkit内核 -->
<meta name="description" content="Common form elements and layouts" />
<!-- 360浏览器默认选择webkit内核 -->
<meta name="renderer" content="webkit" />
<meta name="description" content="blade framework" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<!-- bootstrap & fontawesome -->
<link rel="stylesheet" href="${ctxPath}/static/assets/css/bootstrap.css" />
@ -28,19 +29,17 @@
</head>
<body class="no-skin">
<div class="main-container" id="main-container">
<!-- /section:basics/sidebar -->
<div class="main-content">
<div class="main-content-inner">
<!-- /section:basics/content.breadcrumbs -->
<div class="page-content">
<div class="row">
<div class="col-xs-12">
${layoutContent}
</div>
</div>
</div><!-- /.page-content -->
</div>
</div>
</div><!-- /.main-content -->
</div><!-- /.main-container -->
</div>
</div>
</body>
</html>

View File

@ -1,21 +1,20 @@
<div class="space-4"></div>
<!-- #section:elements.form -->
@for(x in col){
@ if(!isEmpty(x.title)){
@ for(x in col) {
@ if(!isEmpty(x.title)) {
<div class="page-header-form">
<h2>
${x.title!}
@if(!isEmpty(x.small)){
@ if(!isEmpty(x.small)) {
<small>
<i class="ace-icon fa fa-angle-double-right">
${x.small!}
</i>
</small>
@}
@ }
</h2>
</div>
@ }else{
@ } else {
@ var display = (func.like(x.type,"hidden")) ? "none" : "block";
@ var placeholder = (!isEmpty(x.placeholder)) ? x.placeholder : ("暂无"+x.name);
@ if(x.newline!false){

View File

@ -1,24 +1,22 @@
<div class="space-4"></div>
<!-- 判断表单是否发生过更改的token -->
<input type="hidden" id="form_token" value="0"/>
<!-- 乐观锁控制 -->
<input type="hidden" id="_version" name="VERSION" value="0">
@if(isEmpty(keys)){
@ if(isEmpty(keys)) {
<input type="hidden" id="_${key!'id'}" name="${table!}.${key!'id'}" value=""/>
@}
@else{
@for(k in keys){
@ } else {
@for(k in keys) {
<input type="hidden" id="${k.table!}_${k.key!'id'}" name="${k.table!}.${k.key!'id'}" value=""/>
@}
@}
@for(x in col){
@ if(!isEmpty(x.title)){
@ }
@ for(x in col){
@ if(!isEmpty(x.title)) {
<div class="page-header-form">
<h2>
${x.title!}
@if(!isEmpty(x.small)){
@if(!isEmpty(x.small)) {
<small>
<i class="ace-icon fa fa-angle-double-right">
${x.small!}
@ -28,7 +26,7 @@
</h2>
</div>
@ }else{
@ } else {
@ var display = (func.like(x.type,"hidden")) ? "none" : "block";
@ var placeholder = (!isEmpty(x.placeholder)) ? x.placeholder : ("暂无"+x.name);
@ if(x.newline){

View File

@ -1,24 +1,23 @@
<div class="space-4"></div>
<!-- #section:elements.form -->
@for(x in col){
@ if(!isEmpty(x.title)){
@ for(x in col) {
@ if(!isEmpty(x.title)) {
<div class="page-header-form">
<h2>
${x.title!}
@if(!isEmpty(x.small)){
@ if(!isEmpty(x.small)) {
<small>
<i class="ace-icon fa fa-angle-double-right">
${x.small!}
</i>
</small>
@}
@ }
</h2>
</div>
@ }else{
@ } else {
@ var display = (func.like(x.type,"hidden")) ? "none" : "block";
@ var placeholder = (!isEmpty(x.placeholder)) ? x.placeholder : ("暂无"+x.name);
@ if(x.newline){
@ if(x.newline) {
<div class="form-group" style="display:${display!}">
@ }
<label class="col-sm-2 control-label no-padding-right" > ${x.name!} </label>

View File

@ -1,11 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<html>
<head>
<meta charset="utf-8" />
<title>Blade企业级开发平台</title>
<link rel="shortcut icon" href="${ctxPath}/static/style/images/favicon.ico" type="image/x-icon" />
<meta name="renderer" content="webkit" /><!-- 360浏览器默认选择webkit内核 -->
<meta name="description" content="overview &amp; stats" />
<!-- 360浏览器默认选择webkit内核 -->
<meta name="renderer" content="webkit" />
<meta name="description" content="blade framework" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src='${ctxPath}/static/assets/js/jquery.js'></script>
<!-- bootstrap & fontawesome -->
@ -23,16 +24,16 @@
<!-- ace settings handler -->
<script src="${ctxPath}/static/assets/js/ace-extra.js"></script>
<link rel="stylesheet" href="${ctxPath}/static/blade/css/blade-tab.css" type="text/css" media="screen" />
<script src="${ctxPath}/static/blade/js/blade-tab.js"></script> <!-- layer -->
<!-- layer -->
<script src="${ctxPath}/static/blade/js/blade-tab.js"></script>
<!-- blade通用工具类 -->
<script src="${ctxPath}/static/layer/layer.js"></script>
<script src="${ctxPath}/static/blade/js/blade-ajax.js" type="text/javascript" ></script>
</head>
<body class="no-skin">
<!-- #section:basics/navbar.layout -->
<div id="navbar" class="navbar navbar-default">
<div class="navbar-container" id="navbar-container">
<!-- #section:basics/sidebar.mobile.toggle -->
<button type="button" class="navbar-toggle menu-toggler pull-left" id="menu-toggler" data-target="#sidebar">
<span class="sr-only">Toggle sidebar</span>
@ -43,15 +44,12 @@
<span class="icon-bar"></span>
</button>
<!-- /section:basics/sidebar.mobile.toggle -->
<div class="navbar-header pull-left">
<!-- #section:basics/navbar.layout.brand -->
<a href="#" class="navbar-brand">
<small>
<!-- <i class="fa fa-tumblr"></i> -->
Blade企业级开发平台
</small>
</a>
</div>
</div><!-- /.navbar-container -->
</div>
</div>

View File

@ -1,5 +1,4 @@
<!-- #section:basics/sidebar -->
<div id="sidebar" class="sidebar responsive">
<script type="text/javascript">
try{ace.settings.check('sidebar' , 'fixed')}catch(e){}
@ -25,7 +24,6 @@
<blade:sidebar userId="${shiro.getUser().id}" roleId="${shiro.getUser().roles}" />
</ul>
<!-- #section:basics/sidebar.layout.minimize -->
<div class="sidebar-toggle sidebar-collapse" id="sidebar-collapse">
<i class="ace-icon fa fa-angle-double-left" data-icon1="ace-icon fa fa-angle-double-left" data-icon2="ace-icon fa fa-angle-double-right"></i>
</div>

View File

@ -1,19 +1,18 @@
.close-tab {
font-size: 10px;
position:absolute;
right: 5px;
top: 5px;
/* padding-left: 25px; */
z-index: 100;
cursor: pointer;
color: #94A6B0;
}
.tmsp-pointer{
cursor:pointer;
}
.topbar-collapse {
float:right;
.close-tab {
font-size: 10px;
position:absolute;
right: 5px;
top: 5px;
z-index: 100;
cursor: pointer;
color: #94A6B0;
}
.blade-pointer{
cursor:pointer;
}
.topbar-collapse {
float:right;
}