目录
1.动态菜单的实现
1.菜单实现代码
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>layout 后台大布局 - Layui</title>
<%@ include file="common/head.jsp" %>
<style type="text/css">
/* css:first-child 获取首元素 */
#fundiv ul li:first-child i{
display: none;
}
</style>
</head>
<body class="layui-layout-body">
<div class="layui-layout layui-layout-admin">
<div class="layui-header">
<div class="layui-logo">layui 后台布局</div>
<!-- 头部区域(可配合layui已有的水平导航) -->
<ul class="layui-nav layui-layout-right">
<li class="layui-nav-item">
<a href="javascript:;">
<img src="http://t.cn/RCzsdCq" class="layui-nav-img">
贤心
</a>
<dl class="layui-nav-child">
<dd><a href="">基本资料</a></dd>
<dd><a href="">安全设置</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a href="">退了</a></li>
</ul>
</div>
<div class="layui-side layui-bg-black">
<div class="layui-side-scroll">
<!-- 左侧导航区域(可配合layui已有的垂直导航) -->
<ul class="layui-nav layui-nav-tree" id="ullb" lay-filter="test">
<!-- <li class="layui-nav-item layui-nav-itemed">
<a class="" href="javascript:;">所有商品</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">列表一</a></dd>
<dd><a href="javascript:;">列表二</a></dd>
<dd><a href="javascript:;">列表三</a></dd>
<dd><a href="">超链接</a></dd>
</dl>
</li>
<li class="layui-nav-item">
<a href="javascript:;">解决方案</a>
<dl class="layui-nav-child">
<dd><a href="javascript:;">列表一</a></dd>
<dd><a href="javascript:;">列表二</a></dd>
<dd><a href="">超链接</a></dd>
</dl>
</li>
<li class="layui-nav-item"><a href="">云市场</a></li>
<li class="layui-nav-item"><a href="">发布商品</a></li> -->
</ul>
</div>
</div>
<div class="layui-body" >
<!-- 内容主体区域 -->
<div style="padding: 15px;">
•
<div class="layui-tab " id="fundiv" lay-filter="demo" lay-allowclose="true">
<ul class="layui-tab-title">
<li class="layui-this ">主页</li>
</ul>
<div class="layui-tab-content" >
<div class="layui-tab-item layui-show" >
1. 我个人比较喜欢卡片风格的,所以你发现又是以卡片的风格举例
2. 删除功能适用于所有风格
</div>
</div>
</div>
</div>
</div>
<div class="layui-footer">
<!-- 底部固定区域 -->
© layui.com - 底部固定区域
</div>
</div>
<!-- <script src="../src/layui.js"></script> -->
<script>
let element =null;
let $ =null;
let layer =null;
//JavaScript代码区域
layui.use(['element','jquery','layer'], function(){
//定义需要的元素
element = layui.element;
$ = layui.jquery;
layer=layui.layer;
//请求菜单数据 map 进行传的值
$.post("moduleAction.action?methodName=queryModule",{},function(ms){
let nod;
$.each(ms.data,function(index,value){
//第一行默认打开
let opened=index==0?"layui-nav-itemed":"";
nod=$('<li class="layui-nav-item '+opened+'"></li>');
nod.append('<a class="" href="javascript:;">'+value.name+'</a>');
let d2=$(' <dl class="layui-nav-child"></dl>');
console.log(value.modules)
$.each(value.modules,function(i,v){
d2.append('<dd><a href="javascript:openFuncTab(\''+v.name+'\',\''+v.id+'\',\''+v.url+'\') ;">'+v.name+'</a></dd>');
})
nod.append(d2);
//将拼接号的菜单 追加到 ul中
$("#ullb").append(nod);
})
// console.log(nod)
//刷新ui
element.render("ullb")
//保证是 传过来的数据自动转为json
},'json')
});
//定义选项卡的方法
/**
* name 选项卡名字
id 选项卡的id 就是数据库菜单id 用于切换选项卡
*/
function openFuncTab(name,id,url){
let tag=$("li[lay-id="+id+"]").length;
if(tag==0){
element.tabAdd('demo', {
title:name //用于演示
//引入页面
,content:'<iframe class="myiframe" frameborder="0" src="' + url+ '" scrolling="auto" style="width:100%;height:100%;"></iframe>'
,id:id //实际使用一般是规定好的id,这里以时间戳模拟下
})
}
element.tabChange('demo', id); //切换到:用户管理
•
//调用自适应高度的方法
setIframeHeight();
//窗口改变时 自动刷新
$(window).resize(function(){
setIframeHeight();
})
}
//设置自适应高度
function setIframeHeight(){
//获取最外部 的高度
let bodyheig= $(".layui-body").height();
//调整引入的 iframe 的高度
$(".myiframe").css("height",bodyheig-85);
// console.log(bodyheig)
}
</script>
</body>
</html>
2.获取动态菜单数据
2. layui from 提交事件
layui使用原始的from自动提交事件 可能会导致数据丢失 所以我们采用layui给我们提供的提交事件
1.在此介绍一下时间组件 laydate 组件
主要功能:年选择器、年月选择器、日期选择器、时间选择器、日期时间选择器 五种类型的选择方式为基本核心,并且均支持范围选择(即双控件)。 模块加载名称:laydate,独立版本:http://www.layui.com/laydate/
一·基础参数选项 通过核心方法:laydate.render(options) 来设置基础参数,也可以通过方法:laydate.set(options) 来设定全局基础参数. elem - 绑定元素是必填项;用于绑定执行日期渲染的元素,值一般为选择器,或DOM对象 laydate.render({ elem: '#test' //或 elem: document.getElementById('test')、elem: lay('#test') 等 });
二·type - 控件选择类型:用于单独提供不同的选择器类型
年选择器
年月选择器
时间选择器
日期时间选择器
三·range - 开启左右面板范围选择 类型:Boolean/String,默认值:false
如果设置 true,将默认采用 “ - ” 分割。 你也可以直接设置 分割字符。五种选择器类型均支持左右面板的范围选择。
image.png
laydate.render({ elem: '#test6' ,range: true }); 四·format - 自定义格式:类型:String,默认值:yyyy-MM-dd;通过日期时间各自的格式符和长度,来设定一个你所需要的日期格式。layDate 支持的格式如下:
//自定义日期格式 laydate.render({ elem: '#test' ,format: 'yyyy年MM月dd日' //可任意组合 }); 五·value - 初始值:类型:String,默认值:new Date() //传入符合format格式的字符给初始值
laydate.render({ elem: '#test' ,value: '2018-08-18' //必须遵循format参数设定的格式 });
//传入Date对象给初始值 laydate.render({ elem: '#test' ,value: new Date(1534766888000) //参数即为:2018-08-20 20:08:08 的时间戳 }); 六·控件初始打开的回调 控件在打开时触发,回调返回一个参数:初始的日期时间对象 laydate.render({ elem: '#test' ,ready: function(date){ console.log(date); //得到初始的日期时间对象:{year: 2017, month: 8, date: 18, hours: 0, minutes: 0, seconds: 0} } }); 七·日期时间被切换后的回调 年月日时间被切换时都会触发。回调返回三个参数,分别代表:生成的值、日期时间对象、结束的日期时间对象 laydate.render({ elem: '#test' ,change: function(value, date, endDate){ console.log(value); //得到日期生成的值,如:2017-08-18 console.log(date); //得到日期时间对象:{year: 2017, month: 8, date: 18, hours: 0, minutes: 0, seconds: 0} console.log(endDate); //得结束的日期时间对象,开启范围选择(range: true)才会返回。对象成员同上。 } }); 八·控件选择完毕后的回调 点击日期、清空、现在、确定均会触发。回调返回三个参数,分别代表:生成的值、日期时间对象、结束的日期时间对象 laydate.render({ elem: '#test' ,done: function(value, date, endDate){ console.log(value); //得到日期生成的值,如:2017-08-18 console.log(date); //得到日期时间对象:{year: 2017, month: 8, date: 18, hours: 0, minutes: 0, seconds: 0} console.log(endDate); //得结束的日期时间对象,开启范围选择(range: true)才会返回。对象成员同上。 } }); 九·弹出控件提示 事实上,执行核心方法 laydate.render(options) 会返回一个当前实例对象。其中包含一些成员属性和方法,比如:hint方法 var ins1 = laydate.render({ elem: '#test' ,change: function(value, date, endDate){ ins1.hint(value); //在控件上弹出value值 } }); 十·其他
2.layui 提交事件
须知 form是layui中的组件之一 所以使用之前需要放在包裹在 组件中 引入 form 或者 layui.from
//提交表单
form.on('submit(meetinginfo)', function(data) {
console.log(data);
//获取form提交的时间输入框数据 进行分割
let dt = data.field.meetingDt;
let start = dt.split("至")[0].trim();
let end = dt.split("至")[1].trim();
//添加属性
//将时间分别保存下来
data.field["startTime"] = start;
data.field["endTime"] = end;
console.log(data);
//发送异步请求
$.ajax({
url: ctx + '/meetingInfoAction.action?methodName=addMeetingInfo',
data: data.field,
type: 'post',
dataType: 'json',
success: function(resp) {
//判断是否成功
if(resp.code==0){
layer.msg(resp.msg,{icon:1});
}else{
layer.msg(resp.msg,{icon:5})
}
}
})
return false;
});
3.layer 怎么实现自定义组件
首先编写 引入文件 config文件 ⬇
layui.config({
base : 'static/js/module/' // 假设这是test.js所在的目录
}).extend({ // 设定模块别名
test : 'test' // 如果test.js是在根目录,也可以不用设定别名
});`
在编写自己需要的组件
layui.define(function(exports) {
var obj = {
hello : function(str) {
alert('Hello ' + (str || 'test'));
},
hello02: function(str) {
alert('Hello02 ' + (str || 'test'));
}
};
// 输出test接口
exports('test', obj);
});
目录结构
最后引入组件 进行使用
查看一下效果
4.排座与保存下图片的插件介绍
1,排座源代码 需要自己添加一个桌位图
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<base href="${pageContext.request.contextPath }/static/"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="js/layui/css/layui.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="js/layui/layui.js"></script>
<script type="text/javascript" src="js/html2canvas/html2canvas.js"></script>
<title>会议座位安排</title>
</head>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
body {
width: 100%;
height: 100%;
/* background: red; */
}
.tips {
/* position: absolute; */
background: #eee;
display: inline-block;
height: 60px;
/* width: 60px; */
line-height: 60px;
text-align: center;
margin: 5px;
padding: 0 10px;
}
.add {
position: fixed;
right: 10px;
top: 10px;
display:inline;
}
#tu {
width: 100%;
height: 100%;
/* background: lightblue; */
/*background: url('u=3318199716,2583790385&fm=26&gp=0.jpg');*/
}
.layui-input{
height:30px;
}
</style>
<body id="screen_body">
<div id="tu"></div>
<!-- 下面不要使用layui的表单行内模式,会导致canvas的toDataURL()数据为 data:, -->
<div class="add">
<div style="display:inline-block;">
<input id="dan_input" type="text" value="" class="layui-input">
</div>
<div style="display:inline-block;">
<button onclick="return addDanMu()" class="layui-btn layui-btn-sm">添加座位</button><input id="jie_input" type="button" class="layui-btn layui-btn-sm" value='确定'>
</div>
</div>
</body>
<script type="text/javascript">
var $id = function(id) {
return document.getElementById(id);
}
//会议排座拖拽
var dragF = {
locked: false,
lastObj: undefined,
drag: function(obj) {
$id(obj).onmousedown = function(e) {
var e = e ? e : window.event;
if (!window.event) {
e.preventDefault();
} /* 阻止标注<a href='/site/js-5791-1.html' target='_blank'><u>浏览器</u></a>下拖动a,img的默认事件 */
dragF.locked = true;
$id(obj).style.position = "absolute";
$id(obj).style.zIndex = "100";
if (dragF.lastObj && dragF.lastObj != $id(obj)) { /* 多元素拖动需要恢复上次元素状态 */
dragF.lastObj.style.zIndex = "1";
}
dragF.lastObj = $id(obj);
var tempX = $id(obj).offsetLeft;
var tempY = $id(obj).offsetTop;
dragF.x = e.clientX;
dragF.y = e.clientY;
document.onmousemove = function(e) {
var e = e ? e : window.event;
if (dragF.locked == false) return false;
$id(obj).style.left = tempX + e.clientX - dragF.x + "px";
$id(obj).style.top = tempY + e.clientY - dragF.y + "px";
if (window.event) {
e.returnValue = false;
} /* 阻止ie下a,img的默认事件 */
}
document.onmouseup = function() {
dragF.locked = false;
}
}
}
}
</script>
<script type="text/javascript">
var layer;
layui.use(['layer'],function(){
layer=layui.layer;
//TODO 初始化会议排座:根据会议ID获取参会的所有人员的名字(主持人+参会人+列席人)
arrangeSeat();
//绘制会议排座图片
$("#jie_input").on("click", function(event) {
$('.add').hide();
event.preventDefault();
html2canvas(document.getElementById("screen_body")).then(function(canvas) {
var dataUrl = canvas.toDataURL();
//console.log(dataUrl);
var param = {};
param['seatPic'] = dataUrl;
param['id'] = '${param.id}';
//console.log(param);
//TODO 此处需要完成会议排座图片上传操作
$.ajax({
//此处保存的是base64 数据 需要转换成图片
url: '../meetingInfoAction.action?methodName=addArrangeSeat',
data: param,
type: 'post',
dataType: 'json',
success: function(resp) {
if(resp.code == 0) {
layer.msg("保存成功!",{icon: 1},function (){
//先得到当前iframe层的索引
var index = parent.layer.getFrameIndex(window.name);
//再执行关闭
parent.layer.close(index);
//调用父窗口的查询方法更新数据
//parent.loadMeetingInfo();
})
}else{
layer.msg(resp.msg);
}
}
})
});
});
});
//初始化排座人员信息
//默认加载坐席人员
function arrangeSeat() {
$.ajax({
url: "../meetingInfoAction.action?methodName=listUsersMeetingInfo",
data: {
id: '${param.id}'
},
type: 'get',
dataType: 'json',
success: function(resp) {
//console.log(resp);
$.each(resp.data, function(i,v) {
$("#dan_input").val(v.name);
addDanMu();
});
}
});
}
//添加会议排座
function addDanMu() {
var dan = document.getElementById("dan_input").value;
if (dan == "") {
layer.msg('请输入弹幕~', {icon: 4});
//alert("请输入弹幕~");
return false;
} else {
document.getElementById("dan_input").value = ""; //清空 弹幕输入框
// var br = document.createElement("BR"); // <br />
var node = document.createElement("DIV"); // <div>
var tipsArr = document.getElementsByClassName('tips');
var i;
// console.log(parseInt(tipsArr[tipsArr.length-1].id.substr(4))+1);
if (tipsArr.length == 0) {
i = 1
} else {
i = parseInt(tipsArr[tipsArr.length - 1].id.substr(4)) + 1;
}
// var aNode = document.createElement("P"); // <p>
node.setAttribute("class", "tips");
node.setAttribute("id", "tips" + i);
node.setAttribute("onmouseover", "dragF.drag('tips" + i + "');");
var textnode = document.createTextNode(dan); // 创建个 文本节点, 将用户输入的弹幕,存入 创建的 元素节点 <p> 中
// aNode.appendChild(textnode);
node.appendChild(textnode);
// document.body.appendChild(br);
// document.body.appendChild(node);
document.getElementById("tu").appendChild(node);
return true;
}
}
//下载
/* function downloadFile(fileName, content) {
let aLink = document.createElement('a');
let blob = this.base64ToBlob(content); //new Blob([content]);
let evt = document.createEvent("HTMLEvents");
evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为
aLink.download = fileName;
aLink.href = URL.createObjectURL(blob);
// aLink.dispatchEvent(evt);
//aLink.click()
aLink.dispatchEvent(new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
})); //兼容火狐
} */
//base64转blob
/* function base64ToBlob(code) {
let parts = code.split(';base64,');
let contentType = parts[0].split(':')[1];
let raw = window.atob(parts[1]);
let rawLength = raw.length;
let uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {
type: contentType
});
} */
</script>
</html>
2.将base64转为图片文件方法 java
//base64字符串转化成图片
public static boolean GenerateImage(String imgStr)
{ //对字节数组字符串进行Base64解码并生成图片
if (imgStr == null) //图像数据为空
return false;
BASE64Decoder decoder = new BASE64Decoder();
try
{
//Base64解码
byte[] b = decoder.decodeBuffer(imgStr);
for(int i=0;i<b.length;++i)
{
if(b[i]<0)
{//调整异常数据
b[i]+=256;
}
}
//生成jpeg图片
String imgFilePath = "D:\\课件与作业\\作业\\1.jpg";//新生成的图片
OutputStream out = new FileOutputStream(imgFilePath);
out.write(b);
out.flush();
out.close();
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
5.select插件多选演示
formSelects-v4.js 基于Layui的多选解决方案
文档地址分享 ↓
formSelects 基于Layui的多选解决方案 (hnzzmsf.github.io)
效果图:
6.签字插件介绍 签字后保存图片
效果演示 保存后像后天发送base64数据
签字前端代码实现
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<%@include file="/common/head.jsp" %>
<link rel="stylesheet" type="text/css" href="${ctx}/static/js/sign/css/www.jsdaima.com.css">
<link rel="stylesheet" type="text/css" href="${ctx}/static/js/sign/font/iconfont.css">
<script type="text/javascript" src="${ctx}/static/js/sign/layui-sign.js"></script>
</head>
<style>
body{
margin:5px;
}
</style>
<script>
layui.use(['form'], function() {
let form = layui.form;
//根据用户选择的会议记录填写会议标题及会议内容 此处可越过
form.val('audit', $.extend({}, parent.row||{}));
});
//获取签字图片数据
function getData() {
return document.getElementById("canvas").toDataURL("image/png");
}
</script>
<body>
<div style="padding:10px 20px 10px 10px;">
<form class="layui-form layui-form-pane" lay-filter="audit">
<input type="hidden" id="id" name="id"/>
<input type="hidden" id="auditor" value="${sessionScope.user.id }"/>
<div class="layui-form-item">
<label class="layui-form-label">会议标题</label>
<div class="layui-input-block">
<input type="text" name="title" autocomplete="off" class="layui-input" readonly="readonly">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">会议内容</label>
<div class="layui-input-block">
<textarea placeholder="请输入内容" name="content" class="layui-textarea" readonly="readonly"></textarea>
</div>
</div>
<div class="canvasBox">
<div class="contro">
<ul class="drawType">
<li data-name="pen" data-nameNum="0">
<span class="icon iconfont icon-qianbi"></span>
<span class="iconAlert">铅笔</span>
</li>
<!-- <li class="downLoad">
<span class="icon iconfont icon-baocun"></span>
<span class="iconAlert">保存</span>
<img src="" alt="" class="downImg">
</li> -->
<!-- <li data-name="eraser" >
<span class="icon iconfont icon-xiangpi"></span>
<span class="iconAlert">橡皮</span>
</li> -->
<li class="remote">
<span class="icon iconfont icon-delete"></span>
<span class="iconAlert">清空</span>
</li>
</ul>
</div>
<div class="canvasDraw">
<div class="drawFont" data-type="hide">
<span class="intoFont"></span>
<input type="text" class="intoFontInput">
</div>
<!-- 为更好的处理图片,此处高度宽度使用数值,不要使用百分比 -->
<canvas id="canvas" width="624" height="150"></canvas>
</div>
</div>
<div class="layui-form-item" style="text-align:center;">
<button type="button" lay-submit="audit" lay-filter="user" class="layui-btn layui-btn-normal">审核</button>
<button type="reset" class="layui-btn">重置</button>
</div>
</form>
</div>
</body>
</html>
获取的数据发送至后台 使用上面给的base64方法可解析成图片