目录:

一,会议签字插件介绍

二,我的审批

三,会议签字功能实现

四,亮点知识总结


一,会议签字插件介绍

我们可以先去网上查找相关插件 如图小刘找到如下插件,功能较多:

签字效果如下:

我们只需要签字、消除、删除以及保存的功能,因此我们可以对此进行改造来进一步达到我们所需要的效果(如下图):

可在空白区域进行签字:

点击第二个储存按钮会保存签字图片:

二,我的审批

//我的审批public String myAudit(HttpServletRequest req, HttpServletResponse resp) {try {PageBean pageBean=new PageBean();pageBean.setRequest(req);List<Map<String, Object>> infos = infoDao.myAudit(info, pageBean);
//      注意:layui中的数据表格的格式ResponseUtil.writeJson(resp, R.ok(0, "我的会议数据查询成功",pageBean.getTotal(),infos));} catch (Exception e) {e.printStackTrace();try {ResponseUtil.writeJson(resp, R.error(0, "我的会议数据查询失败"));} catch (Exception e2) {e2.printStackTrace();}}return null;}

MeetingInfoDao:

public List<Map<String, Object>> myAudit(MeetingInfo info, PageBean pageBean) throws Exception, IllegalAccessException, SQLException {String sql=getSQL();String title = info.getTitle();if(StringUtils.isNotBlank(title)) {sql+=" and title like '%"+title+"%'";}//当前登录账号是会议信息表中 审批人 字段值sql+=" and a.auditor = "+info.getAuditor();
//      值查询会议状态为2 即待审核的会议sql+=" and a.state =2";
//      排序按照降序展示sql+=" order by a.id desc";return super.executeQuery(sql, pageBean);}

运行效果:点击审批该条会议

数据回显:

我们根据审批人点击通过按钮或者驳回按钮来判断 该会议为待开状态或者驳回状态。不论审批人点击的是哪个按钮我们都需要将该会议的最新状态添加进数据库中,因为这时该会议已经成为被审批过的会议了。当我们再次查询未审批会议时就不出现。

三、会议签字功能实现

只有当会议状态为通过时才要进行签字,驳回则不用签字。所以我们可以根据审批人是否签字来判断该会议的最新状态为待开或者驳回状态。同时我们也可以查看该会议入库时Sign字段也就是签字图片存放的路径是否为空,为空则是驳回状态,非空则是待开状态。

准备 我的审批 页面和js及 添加会议审批 页面和js:

myAudit.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@include file="/common/header.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="${pageContext.request.contextPath }/static/js/meeting/myAudit.js"></script>
</head>
<style>
body{margin:15px;
}.layui-table-cell {height: inherit;}.layui-layer-page .layui-layer-content {  overflow: visible !important;}
</style>
<body>
<!-- 搜索栏 -->
<div class="layui-form-item" style="margin:15px 0px;"><div class="layui-inline"><label class="layui-form-label">会议标题</label><div class="layui-input-inline"><input type="hidden" id="auditor" value="${user.id }"/><input type="text" id="title" autocomplete="off" class="layui-input"></div></div><div class="layui-inline"><button id="btn_search" type="button" class="layui-btn"><i class="layui-icon layui-icon-search"></i> 查询</button></div>
</div>
<!-- 数据表格 -->
<table id="tb" lay-filter="tb" class="layui-table" style="margin-top:-15px"></table><script type="text/html" id="tbar"><a class="layui-btn layui-btn-xs" lay-event="edit">审批</a>
</script>
</body>
</html>

myAudit.js:

let layer,table,$,form;
var row;
layui.use(['layer','table','jquery','form'],function(){layer=layui.layer,table=layui.table,form=layui.form,$=layui.jquery;initTable();//查询事件$('#btn_search').click(function(){query();});});//初始化数据表格(我的审批)
function initTable(){table.render({          //执行渲染elem: '#tb',   //指定原始表格元素选择器(推荐id选择器)height: 400,         //自定义高度loading: false,      //是否显示加载条(默认 true)cols: [[             //设置表头{field: 'id', title: '会议编号', width: 90},{field: 'title', title: '会议标题', width: 120},{field: 'location', title: '会议地点', width: 140},{field: 'startTime', title: '开始时间', width: 120},{field: 'endTime', title: '结束时间', width: 120},{field: 'meetingState', title: '会议状态', width: 120},{field: 'seatPic', title: '会议排座', width: 120,templet: function(d){if(d.seatPic==null || d.seatPic=="")return "尚未排座";elsereturn "<img width='120px' src='"+d.seatPic+"'/>";}},{field: '', title: '操作', width: 200,toolbar:'#tbar'},]]});
}//点击查询
function query(){table.reload('tb', {url: $("#ctx").val()+'/info.action',     //请求地址method: 'POST',                    //请求方式,GET或者POSTloading: true,                     //是否显示加载条(默认 true)page: true,                        //是否分页where: {                           //设定异步数据接口的额外参数,任意设'methodName':'myAudit','auditor':$('#auditor').val(),'title':$('#title').val(),},  request: {                         //自定义分页请求参数名pageName: 'page', //页码的参数名称,默认:pagelimitName: 'rows' //每页数据量的参数名,默认:limit},done: function (res, curr, count) {console.log(res);}});//工具条事件table.on('tool(tb)', function(obj){ //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值"row = obj.data; //获得当前行数据var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)console.log(row);if(layEvent === 'edit'){ //审批openLayer(row.id);} else {}});
}// 打开审批页面
function openLayer(id){layer.open({type: 2,                    //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)title: '审批',                   //对话框标题area: ['600px', '500px'],   //宽高skin: 'layui-layer-rim',    //样式类名content: $("#ctx").val()+'/jsp/meeting/addMeetingAudit.jsp',                //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同btn:['审批通过','审批驳回'],yes:function(index,layero){//layer.msg('保存');//调用子页面中提供的getData方法,快速获取子页面的form表单数据let data= $(layero).find("iframe")[0].contentWindow.save();data['meetingId']=id;data['auditor']=$('#auditor').val();addMeetingAudit(data);},btn2:function(){let data={};data['sign']=null;data['meetingId']=id;data['auditor']=$('#auditor').val();addMeetingAudit(data);return false;}});
}// 添加审批意见
function addMeetingAudit(params){/*** 1、将图片的字符串 转成图片保存下来* 2、将审批人的意见数据入库 t_oa_meeting_audit* 3、修改会议状态   t_oa_meeting_info*/params['methodName']="add";console.log(params);$.post($("#ctx").val()+'/audit.action',params,function(rs){if(rs.success){layer.closeAll();query();}else{layer.msg(rs.msg,{icon:5},function(){});}},'json');
}

 addMeetingAudit.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<%@include file="/common/header.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/js/plugins/sign/css/www.jsdaima.com.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath }/static/js/plugins/sign/font/iconfont.css">
<script type="text/javascript" src="${pageContext.request.contextPath }/static/js/meeting/addMeetingAudit.js"></script>
<%-- <script type="text/javascript" src="${pageContext.request.contextPath }/static/js/jquery-3.3.1.min.js"></script> --%>
<%-- <script type="text/javascript" src="${pageContext.request.contextPath }/static/js/plugins/sign/index.js"></script>  --%>
<title>发布会议</title>
</head>
<style>
body{margin:5px;
}
</style>
<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="layui-form-item layui-form-text"> --><!-- <label class="layui-form-label">会议内容</label> --><!-- <div class="layui-input-block"> --><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="550" height="150"></canvas>          </div>        </div><!--   </div></div> --></form>
</div>
</body>
</html>

 addMeetingAudit.js:

let layer,table,$,form;
var row;
layui.use(['layer','table','jquery','form'],function(){layer=layui.layer,table=layui.table,form=layui.form,$=layui.jquery;if(parent.row!=null){form.val('audit',$.extend({}, parent.row||{}));}init();function init() {$('.strokeColorBox').css('border',"4px solid "+$('.strokeColor').val()).find('.icon').css('color',$('.strokeColor').val());$('.weightBox .icon').html($('.weight').val()+'px');$('.drawFont').css({'height': $('.font_box_size').val()})}/*** 右键按下不显示浏览器自带框*/$('#canvas').get(0).oncontextmenu = function (e) { showMyselfBox(e);return false;}; /*** 显示自定义框*/function showMyselfBox (e) {var left = e.offsetX;var top = e.offsetY;$('.myselfBox').css({left: left,top: top}).show();}/*** 鼠标滑过工具台*/$('.contro li').on('mouseover', function () {$(this).on('mouseout', function () {$('.contro li').find('.iconAlert').hide()});$(this).find('.iconAlert').show();});/*** 点击工具台*/$('.drawType li').on('click touchstart', function (e) {if (e.type == "touchstart") {e.preventDefault();}$(this).addClass('drawTypeChoose').siblings().removeClass('drawTypeChoose');initData.drawType = $(this).attr('data-name');initData.drayTypeNum= $(this).attr('data-nameNum')})/*** 改变线条颜色*/$('.strokeColor').on('change', function (e) {initData.color = $(this).val();$('.strokeColorBox').css('border','4px solid '+initData.color).find('.icon').css('color',initData.color);})/*** 改变背景色*/$('.backgroundColor').on('change', function (e) {initData.background = $(this).val();$('.backgroundColor').css('border','4px solid '+initData.background).find('.icon').css('color',initData.background);})$('.fillDraw').on('click touchstart',function (e) {if (e.type == "touchstart") {e.preventDefault()}if ($(this).attr('data-choose') == 'false') {$(this).attr('data-choose','true').addClass('fillBg');$('.backgroundColorBox').css({'border':'4px solid '+initData.background,'background':'#fff'}).find('.icon').css('color',initData.background);$('.backgroundColor').show();initData.isFill = true;} else {initData.isFill = false;$(this).attr('data-choose','false').removeClass('fillBg');$('.backgroundColor').hide();$('.backgroundColorBox').css({'border':'4px solid #07133d','background':'#07133d'}).find('.icon').css('color','#666');}})/*** 改变线条粗细*/$('.weight').on('change', function () {initData.size = $(this).val();$('.weightBox .icon').html($('.weight').val()+'px');})/*** 绘制还是移动*/$('.drawOrMove').on('click touchstart',function (e) {if (e.type == "touchstart") {e.preventDefault()}$(this).addClass('drawOrmoveChoose').siblings('.drawOrMove').removeClass('drawOrmoveChoose');if ($(this).attr('data-name') == 'move') {// if (initData.drawType == 'line' || initData.drawType == 'pen' || initData.drawType == 'line' || initData.drawType == 'signet' || initData.drawType == 'eraser') {//    alert('')// }$('.maskLi').show();initData.drawOrMove = $(this).attr('data-name');$('#canvas').css('cursor','move');} else {initData.drawOrMove = $(this).attr('data-name');$('.maskLi').hide();$('#canvas').css('cursor','crosshair');}})/*** 绘制文字*/$('.intoFontInput').on('input', function () {$('.intoFont').html($(this).val());initData.context = $(this).val();})$('.font_box_size').on('change',function () {initData.fontSize = $(this).val();})/*** 清除画布*/$('.remote').on('mousedown touchstart',function (e) {if (e.type == "touchstart") {e.preventDefault()}initData.context2d.clearRect(0,0,initData.canvasWidth,initData.canvasHeight);initData.drawHistoryArrData = [];initData.drawHistoryArrData.length = 0;})/*** 保存图片*/$('.downLoad').on('mousedown touchstart',function (a) {//debugger;save();})/*** 鼠标在canvas按下*/$('#canvas').on('mousedown touchstart',function (e) {if (e.type == "touchstart") {e.preventDefault()}if (e.button == '0' || e.type == "touchstart") { // 判断是左键按下$('.myselfBox').hide();initData.mouseDown(e);$(this).on('mousemove touchmove', function (e) {if (e.type == "touchmove") {e.preventDefault()}initData.mouseMove(e);})}})/*** 鼠标抬起*/$('html').on('mouseup touchend',function(){initData.mouseUp();})var initData= {drawHistoryArrData: [], // 存放所有绘制图形的数据context2d: $('#canvas').get(0).getContext('2d'), // canvas绘图2d环境canvasWidth: $('#canvas').width(),canvasHeight: $('#canvas').height(),relPosX: 0, // 鼠标在绘制图形中按下相对该图形左面的距离relPosY: 0, // 鼠标在绘制图形中按下相对该图形上面的距离relPosToX: 0, // 鼠标在绘制图形中按下相对该图形左面的距离relPosToY: 0, initLeft: 0,initTop: 0,chooseIndex: 0, // 选中图形在drawHistoryArrData数据中的indexdrawOrMove: 'draw', // 当前模式是拖拽还是绘制isMove: false, // 是否可以拖拽drawType: 'pen', // 绘制图形的类型drawTypeNum: '1', // 用于区分同一图形不同形状size: 2, // 绘制的粗细fontSize: $('.font_box_size').val(),context:'',color: $('.strokeColor').val(), // 绘制颜色isFill: false, // 是否填充background: $('.backgroundColor').val(),msgArr:[], // 画笔信息/*** 矩形绘制轨迹*/drawTypeArr: function (arr,j) {var drawTypeFn = { // 绘制方法rect: function () { // 矩形initData.context2d.beginPath();initData.context2d.lineWidth = arr[j].size;initData.context2d.strokeStyle = arr[j].color;initData.context2d.rect(arr[j].x, arr[j].y, arr[j].w,arr[j].h);if (arr[j].fill) {initData.context2d.fillStyle = arr[j].fill;initData.context2d.fill();}initData.context2d.stroke();},line: function () { // 线initData.context2d.beginPath();initData.context2d.moveTo (arr[j].x,arr[j].y);       //设置起点状态initData.context2d.lineTo (arr[j].toX,arr[j].toY);       //设置末端状态initData.context2d.lineWidth = arr[j].size;          //设置线宽状态initData.context2d.strokeStyle = arr[j].color;  //设置线的颜色状态initData.context2d.stroke(); },circle: function () { // 圆initData.context2d.beginPath();initData.context2d.lineWidth = arr[j].size;          //设置线宽状态initData.context2d.strokeStyle = arr[j].color;initData.context2d.arc(arr[j].x,arr[j].y,arr[j].r,0,2*Math.PI);if (arr[j].fill) {initData.context2d.fillStyle = arr[j].fill;initData.context2d.fill();}initData.context2d.stroke()},delta: function () { // 三角var w = arr[j].toX-arr[j].x;var h = arr[j].toY-arr[j].y;var harfDis = Math.tan(30/2)*h ;if (arr[j].toX-arr[j].x>0) {harfDis = harfDis} else {harfDis = -harfDis}initData.context2d.beginPath();initData.context2d.moveTo (arr[j].x,arr[j].y);       //设置起点状态initData.context2d.lineTo (arr[j].toX,arr[j].toY);initData.context2d.lineTo (arr[j].toX + 2*harfDis,arr[j].toY);initData.context2d.lineTo (arr[j].x,arr[j].y);       //设置末端状态initData.context2d.lineWidth = arr[j].size;          //设置线宽状态initData.context2d.strokeStyle = arr[j].color;  //设置线的颜色状态if (arr[j].fill) {initData.context2d.fillStyle = arr[j].fill;initData.context2d.fill();}initData.context2d.stroke(); },ellipse: function () {initData.context2d.beginPath();initData.context2d.lineWidth = arr[j].size;          //设置线宽状态initData.context2d.strokeStyle = arr[j].color;initData.context2d.ellipse(arr[j].x,arr[j].y,Math.abs(arr[j].toX - arr[j].x),Math.abs(arr[j].toY -arr[j].y),0,0,Math.PI*2); if (arr[j].fill) {initData.context2d.fillStyle = arr[j].fill;initData.context2d.fill();}initData.context2d.stroke();},polygon: function () {var y1 = (arr[j].toY-arr[j].y)/2;var tan = Math.tan((90-(arr[j].reg/2))*(2*Math.PI/360));var x1 = y1*tan;initData.context2d.beginPath();initData.context2d.moveTo (arr[j].x,arr[j].y);       //设置起点状态initData.context2d.lineTo (arr[j].toX,arr[j].y);initData.context2d.lineTo (arr[j].toX+x1,arr[j].y+y1);initData.context2d.lineTo (arr[j].toX,arr[j].toY);       //设置末端状态initData.context2d.lineTo (arr[j].x,arr[j].toY); initData.context2d.lineTo (arr[j].x-x1,arr[j].y+y1); initData.context2d.lineTo (arr[j].x,arr[j].y); initData.context2d.lineWidth = arr[j].size;          //设置线宽状态initData.context2d.strokeStyle = arr[j].color;  //设置线的颜色状态if (arr[j].fill) {initData.context2d.fillStyle = arr[j].fill;initData.context2d.fill();}initData.context2d.stroke(); },font: function () {// initData.context2d.beginPath();initData.context2d.font = arr[j].fontSize+'px  Verdana';initData.context2d.textAlign = 'center';initData.context2d.textBaseline = 'bottom';initData.context2d.fillStyle = arr[j].color;// if (arr[j].fill) {initData.context2d.fillText(arr[j].context, arr[j].x, arr[j].y); // }// initData.context2d.strokeText(arr[j].context, arr[j].x, arr[j].y);// initData.context2d.lineWidth = 1;// initData.context2d.strokeStyle = 'transparent';// initData.context2d.rect(arr[j].x, arr[j].y, arr[j].w,arr[j].h);// initData.context2d.stroke();$('.drawFont').hide();// initData.context = ""$('.intoFont').html('');$('.intoFontInput').val('');$('.drawFont').attr('data-type','hide');},signet: function () {var img = new Image();img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAHGCAMAAAC1uokeAAAC+lBMVEUAAAD1rhv1uh31uh31rhv1rhv1rhv1rhv1rhv1sRv1rhv1uR31rhv1rhv1rhv1rhv1rhv1rhv1wR/1rhv1rhv1rhv1rhv1rhv1rhv0yyH1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhvz3CX1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhvz3CX1rhv1rhvz3CX1rhv1rhvz3CX1rhv1rhv1rhv1rhv1rhvz3CX1rhvz3CX1rhvz3CXz3CXz3CXz3CXz3CXz3CX1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhv1rhvz3CXz3CXz3CX1rhv1rhv1rhv1rhvz3CX1rhvz3CX1rhvz3CXz3CX1rhv1rhv1rhvz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CX1rhvz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CXz3CX1rhvz3CXz3CX1rhvz3CXz3CX1rhvz3CXz3CXz3CXz3CX1rhv///8IBAQAAAHx1gDx1wXz2hjz5Cf//yvy2hPy2yT1qBrz3Cfz2xzy2Q7z3CLy2AkFAQPz3Sn1phn//ynz4Sb1rBry2CT1pBnz2x7z3iX/6Sf03zXz2iT1rRv/7Sf/8ynz2yDz4Cbz4yf44CX//Cn13iX//fT/+Sn2qhr01iP1vR72tBwTDgn03zr/9Snz3yX//vj+/O/9+t/89cb68af04EL2uR354iX00iL9+dnz3S/1wh/79L7787j/8Cfz4yb8983464f1yiH68rH25Fj0xyA5Mg7+++X25mT84yX1sBvw1QD+++n36HD35mn25V314Uf14kz0ziFCOhAlHwwcFwr9+NP46oH//vz67pr57IzgzCbBsCP68KH46Xj141Hl0SagkR6Zix0yKw2AcBlNRBPRvyTHtiOFeBluYxYNCge0pCGuniBcURRWTRP57ZJ1axfr1Cemlh+UhRz56SrXxCRoWxbw0wCOgBz05SfbxyXq2ylgVRS8qCL1oxnHc083AAAAfXRSTlMA8gUKHBP5NOgOpQEj18m+UfYIViwpGJyPEIo5L9pO7OTFWj3+182ggGcg3dFqJUpGOCbU0MGY4LtjFalcQ/Ln497JwHx0cbD8h4R3eW5LMey0rZSNLO6HYR37uF1AnKGQYlZE9qx9cVCzGZaCdmiwP6cheLtstrm3ZbS1tsFWbK8AADARSURBVHja7N0JV9NAEAfwf1t6QCk9KAUsYKHlEItWQQERFZCjgoCAyKkoyENRVDyfz8xn94DngdBmk9002+zvE1CmaXZ2ZmehWOl+NjtQlR9MN0JxiMoaOubrWIxUQhEs2L1Zu9G20dYy3NTtQUl4++lvvvUVDxRxPEsB+mM5FO7s2kgnYKlYlk7yVfmhiLJOp8hcnMzXXoVVJuk0HZehCDFNZ0stTMRhgRk6Q3MOCn85KuLi0lUIlqaztVZD4SwRoOLyEModokKWoPC1TnrchUhLVFhKrei4Gid9aiFOUs+XTuGmLkP6uCogzDUqbsANhZMF0msBolwgPVIVULhIk34tEKMxQLpE1Yudj3rSrwNinCO9hqGY5wlQyR/1ugzppjZqOPATi3WIUEUMklDMihCTOPhLEguX2p0zbYWY3AV/D4hJKAbFnEFiEgZ3w8RoEoo5E8TE5QVvYWI1DcWUaWKTBmctxE6l6+bMEJsNcNZKx2ywX+AU54jNJvi6TEbMQLEu6JkK8DVARvhU3mZh0EPga5iM6YRiWdAXAPDP0dVajoH1QR8HV34yqgqKkCKb+CpXFRlWB8WoTmIR9YKnOipItUoyEBf0a+BqkYxLqeYpi4KeB08VUTqh9LV9R2go4T/6Lv2isjar5YmBLwGOYikyI6VKrJakbK3gqYfM2YRiQdDz4KmGzHkPxYKgt4Cjy2TSCyjiS6vRBDh6QSaFUA68uZXBwSZYapoxS7fFxsyRjPwHXrzjNRn6KVwNC90n/boseK84qRu6opOhqsHTYIk23hvP09lscIxWvGBDyfo920i385WAbfK1n3ogsc3zdEJzAhZpYVkt2yhfk70rtoH+txyHNTZLU0vfJA7uQVaeVjrNVBqW8DM1q9ihkP5HFyTVnSrt+cyKDOl0MQhuKnxODnqTi84UgQW80VJUtcaJh/uQkt9HVNqou/tJpxXw00E8DEJG1a7Sn8CvIZ2qwU2OuJBygKi33wbTNl6QPh12W8ZJ2ht5jYrx+SFaPenTYLdlHLm8kM+iLeYujJM+EXBzn7hohXzaSI+UF2K1Wf9YtRIXi5BOhYt06XBDqDjpMgRukuTYddwQ6bQOoRpduitaNuh2/0svpBMh3a5DqLDFRws8AeJiBdLptc0R/AaL/4Q2xy7jLtinWyBCxQU84GaSfnBk20wzscg0QZzK83qqqnZL0vOQThux6fdCnHoqJgsANmqZkXPUUJgYDUCcTUun8IaJgykJd2Cb7HUc+4WF6cNV4qEN8nlvr88Zp4JCbgC2qqRL2ScVJna+OgjTQwUEKiCmyOSseTNeFxmQDUKYPJ0p7AFH1c7M0I1vPtdDnBk6XX8tuLpApoXkvGp5kIzZgDj+Zjppqrc+B86GqICyvrJpmoxxdUOglnUfHUtV1aZzSS+4C6bof8642GGJjtkpWwdQmevp6uqaqI0HIUj3lNmYS5igH2kgo8YhtybHxtzMVKUmSK3OsTE3s4S9Bqklok6NOdJETv2B7yfjAt2QmOeomOnE8fbrZFh/AlLrJOOGILMuMipbCbkNkwkRSCxJBg0EIbtPZFwWMss6qMZyQtyBJ3SPTDilOargZ2d3UeZJuN5lYncB5aGTjJuAxN4Tq6nyuTM9TIY1y7yoCYaITUruJPVfYZsc7gh6Xq5emvvlcPVloxuC5YhJuLyu7TAe9TB48Fy5ufv4c9/I/I7228787fbRD++2dg/2rhzGIMQ9YnAOZWaodDMYbuxtje5oRcz3fdl//WzuBjibtMnZntK4V5qsbW53VGOw1v5l62B7FdwEa0ifi+X0Ov8tYv1e7JWtEc2Qka+Pbj50gwd3h6Ov5unuJSOaYcylR3c0U+bHtnhE3t1KRfmk3m8urMGyGTuxp6MaF/PfXs3eEL1PMSl7gaWgZMCSS4Uv7d/SOFrr27+5ChNWqJCw5C1CxS2Kv35we0wToP2xicAnBugsC2UfcgDxkNig32zXhGnf2muEMZtZOkV/l+TdErr1+MQF/eC2Jtba2Os5GJKsitI/QksSTpgwzFMvKOgH85oV7jzei8EAz+X8g1AgGnUFeh+ca5O6C86I6gEBV07enNcss/PmaSMMiXkT3vLaYtcv2cH5WrzZEc1iYwc3oLDJhTi2TM31aaUw9rQRCpPLvZyGkdx4rpXK2ps9p/5YGzVcw2Nv5pVWUvP7c1BY+B+YvSFt9rZWcn1PZe7lK4HuxSgVEEdBqx80W9jZP4TCINbTbLQ5dFezjw9XoLBID00ZuI7syohmK32zUFhUXqhhfM7djzXbad+GwqT7bi/9LVuHAmZvaXakws6semIgSkd6Iygg9lyzq1H1bmfmGZ4Zqsl2+lHIsx3Nxj5cgsJb7I1mc0/U9qwBEr7N/7ULhR/3O00Kt1X+xs3beU0WY6sQKdFT35mvdcJ7ZF+TySMIE5+kX6aGyr2zcu6OJpfbbyFEZRX9MVnW3ZWvNPm8i4G/SLSMprQUdNinyejWLHirp5MG5BwMX9RHTVbPY+DJ20H/W/aj/DSOafK6tQ1+6gLlc6tTYc/WNKntg5fkVJmO0pWouqLXyCVwMZwp9wl0x7bl2Y8p4AAc5JwytGZLKw/vYFo644xRRZ5RrVyMHMIc/xQVcRfl4FC2PbiC9mBG9TIV1QP5PZShivqdvPMOiqOK4/iTFFOxRA1qjMYe0dhi7D1qbLHG3nvvdZz3zgfschcS4MpeDo+Du4BHC2cFFAVFEwU7ARuoSYgxJiaaOvYZ926XK2/73e7KHZ+/nM0MZvLl996vP5MKriNyM35bOqf5kG6QSYZHDX+6Nd2zNDMyzM7DzNzT4LXKY9K7/HJSRt3ng5w+w+CN0tkgjclKzwKLItcdncyEL1LPLJC+pH8aToq52kcCdkAaOBGkK1fDzOUUoJGDh8fjlbfBTOZWjdv3hseDRzMyLlhL5G6ggf2RVnJAOpI5ydfUVT9mF6SZdHwLJlOKLLqc8NOQdiam39s398BhwCmGPo9wAUgz9hwCa2RMYK6h71IfA9KLm+HwQE2WJmsfNCxe78zsaC2O02bo+DACyYFptXx2mBzuYc7cM+lHqTOstD4EV8kYxtmKbzgOjxdL58LhxE1Alr2GyePzB8FhhWySZkckSsZ1UwyldYCmcLtOaRmSfdNnvO2xDM+5Czn9JCDFESgFjgNpw3AJ0eN4WjKM2RfJkDnd0LfDYcgDQJxD0fC40jO+uKblWs9FQjKwU+4UOCw5c1fR+VSE0DBIzWQNs3BNPlo/EaXAvmnzfOvdcLhyT6olVZKLQJowjJLuJGeIHPDno+TJTZvXhNJxeZRe3K+v8z4VpAknaRpissLFZW1tbb5OmBk8oninZ+S4gxZDt3ZW0RXz/9y2bUUZ7SjzWmHac5ZYy0zG909oMHSmjPb1/7a8Z93zzzcM/L3ZT3cyMO0RVF7GXoWSYnQa7ZlSbejMYsfWLT04RsPvwcb0V/00QQ7+MpQMJ6dNsKbB0Jk2+pdeVurnBynBeBlVlf6q36/HpZ6bVm+yqy2pMlVtGzAu4fSOyt4TyABbn0euhtxB88mu/5LYEWON66AfqzJGZxx/9bCSk+DljWVp783dmWrfzGQ9S+i7T7/i3uyJ+4zZN3efY7OvH5dz0TWnHsP9fLM3vzJVK3px7FiPmnwJXkt7oW5Yqzt94XCwGpoKGbbtoWmeaacJQDfGXyxa7dnh2HuvnH7AHuY2STGNVA+OSr5uYKBh8G7H6/oqoD5YYZmDLtvU12d6OPgcILgIqWafG4F+nCh7sczJPe/QnXX4DbsVqsHaGfxxUGTcs2qFz7dpS8Pgh99oqAdWbxtduvnvgQaWgQ0r/Y5qE1W/Pdm59KtuAPoxRdV8xX7nzT41tUBB3Y5nK/07LuE1/9lHt3V2sgINYO5Lb2kZTB2mmS5d3RAXDq6nF5umutDUpyA1zJmtp7N1pQbHMfvKqaOMbZixVvStw7zmm2kfE/7kdfzF2XoJ/sUBU4apoFeu4z0F/hJZSXuhWQiTsdeoSbrqGZkfprXTfk72BQeMN3C9DP3zoOa/RO2PodfyH3+mYaqw8eBGjBPjAvyTg4Fmcaf2sst5I4GOHJlc9f6QqVmaW2ChKnybOKMOW1/0prUGf8Lc12W+ZpgKEvEgXtZmYlFnnsZhtuwpIAkM6L/dYa9RhmRgHauiNt0cu2fLmF5O9IYVPpgSTNVf3I8iMj+bHbrc6vMri+ZDCeRKrLORJBNPBbpyIUqBA6/UEsbvqi4xUx3cyKk70OiLU6HZt4y3/zWpBW1MxdYBnCh3CZf4qVgMdaBySWlhKZSDz8CTTJI6VPcHQ0hzltHn6t4OWVbagzlxHQyMF335oCdXBVPA2klvxPGKR+Bu9UaoA4te+BUWSNm67JjTHtPE/oUfBzozHaXM8apT/09DVbT9+XxEg9WJ7vTiih950Vel5L576S1x9zkbrG1f2f8L92u2loZ6kPfd23kLoQIzgRhTc8kr9NDIWfr/+3BJ9m/Mg+pojHhsuOcPn1UoOgvekoro1mBfCY5pXrK6lHYE6X6M9TvfC1+wfJqneMDPBeKyXz8nZuTXT1J0lg1aSqlM7gQ9V0MG/8E4bM80Aw2w9Gp6Q5zmPdvoNmhlP/6IeRdRD/Les5QWKx3wj0r2jU49dNxlT50368KjDKmYE1eIsTPSWZK7nv0BinL6nRTVHoIsFWFLxz1by6ABolur2J8ei9K2OiI5d6tjJS5hf/L6KqgH+e9b3sovgvLccRL4PzgU6ce5yW2Y8bB6+5nupa11dXWtS1sgFYDQF87H4d9pq4ToKR3v1XFeHB5oG+zJ8K1gUwPh/ynUg6KiVyzff6Rk6g8B81CehDdmn9nDUICTgi1LW5uQzW632+xuu62rtTbQ3lk2wBpjX4Wk6CtTEL1xW9TQ8boVDibhh+MNVVAX8n61WJbkK1zrT4D/geOQrpwDZLn2OkgQoGpb62tYuV3liKPc5q6pq6WqVmK8KgihuOgY/xOESUOv5jTncrxM4ne8rKwZ6kHxFxbLqwsKoDwzgOmciHRmkqbuCc8fTF2N21aOEnG5ba2hYN+KRo9VkLP5O/XkTGfZsqjoG+PzfVW/4JKwJ1cG9aCo6A2L5as8hQP+QWA2WblIZ0bvrqGo6gwsrXG7EAEnO6oN+gTV7WgZBvduSl6ZijUl0UL9miprfHJgHebSM7qQ943F8vUSBQ/+LGA25yLdmQakmUFo7m/6twZJYLO1UFCIY23qBZeIlx4Bb6CriSMgkn6HSVC5UOC/f2axsB78IiiH+ef7sUgCY1z4BwnN691ICinVqzbjklRLq/Rv0S6s9YnlFXo7TjonN7+AVL1g/scWi2KK5m5gLvsjA7hqlLrVE6H2JjnNw6oz7SJHM8bJOe+kM8hfEsLSHt6ejPu+4MNPBNd3/nus6B/DBeT3/9V/3wkZwWx1KVhqqRvJY6/3hyAHUWbD61JImzVzfpxYSa0xnInFGxuroWYKP3/59XxC3bzvLSzf5EE5rrsPmMkUZAjHZ6k53alamwsp4G6lhFnz/nBJbFUKsXQ4BTB4pQcT5S3b1IuTjNmKFr30BpmAW/C6JcwX+bKmfgpQZIgm4+KZpMJ39zjr7UiJGpfXCQm8wb61q38Kam9bJWvyXA1P5BDAPfFdl56Q3x8KqailFrzDxmfkty8tLK8Wy/pyNwMzORgZwyEqfHeqw40UEZo617VMN6bUoE6v5hsmSrZVkH7i3zh603ucgUC7H0Iv4w1XBpxQloXhC5yMz/Jfs4T5VDZYPxOYyG7IIHKVMzMhT5cNKVODvH6oO2WLB3CEVQ4vGc2txnx2JkDBlo7Wuqb6Lpb6prqOWiflUYrK38tbSF7qYd4okM3LXQIUGQJ9cUrsBsR4JsHQ7UgN7qUU1B2mwrm9oWTd8n6HoMudXhUWvc9HOVta6102Nj1sq3G5amrY/3I1dYfkZM97l5X3h/z5wktdPi9nbtA2DhnFVMXxZH+TDanB1uSE+sP4aGbbisYqwjHgE7GspVd0N9nchKPpstvru52UdCn1k3AqpjjB1Iusr1jCfGwthNLcCUxjfC4yiguVqqrO2ppypAZXlxHnO7RWl7X5xIZZqtazoq/r67Dbxf5+NndTC+WXrp+zvJ9g0wuL37ZE+Fba1E291CcciIwiB4hwExGjq6K8psUJTcTX14DxhibJX0m7rdUfkCyqRUy9kjjzI7xcKmfq84BZ7IwMYzIQ4cx4S6+zI1WU27oD0ESsFf3LVnfUu5AULne9lxLPziz5OmLqCbd63ocWRVNX7qQY0sWWQU4GQi6BMTywvgapwXzRPcHOOkJzArurllddmGlneTt/YYIn97UKU78fmMVkZBjjFLaCOmuRC6nAfNFD7UpnEFEJIsrnLJ8XwxgF8AMLx7uSpm5mefU8ZBizFBqlnC0q/ThW9JZ2aCJUqxspYrPVUuIpuTDf5cV7cgvesnB8UCkVqyu2R6ZBPo5lLyAgK36aqb3bplJ0F6r1Q2Mh8oRq/mI2F3Gvc/q+zYVnpQWEJ8fxvYypHw1MYh9kGEcAAUfDeNFb1Ipuq/d4oGkEamvU+Rr2rpATkuSxOVfOlSMaKTi+LCiC4hiQntl1yqRzcsZdPu58YuhxDDKMo0QrbNpF55LvxkMWgZRx17V7RPKwfPotYdDlJQvPZ1KmrrMnN3L/nGmxAZYTxoM4dkBGceBhCpsInLUuF1LGND+OzB4oU+7uoASif8uJ+1q+sNBG+PUE+nlyY3e+guyGutwc0Y9ViNJhyNul6hhVPt2t1VxiTQ/8ENmQWmzlgqpv/vecuO8ULiK6Z3heXwAlOH1XXdJt554wWmwYwRTRJyvOLTpVpd6V6y3W5opNW0nVjfHcSYQXT/6HfEj+JunJRRM0UIp5qddMDz1WxbjZVUg3lGfabk3qILV1wZCs5ovp3/HPbdJTpsxW2tHMqDV04viRx+VinGTyXcyi8z61qHDl5qa48PH8XLmuxdgCwP2QQYwZAQTcAmESl7rw4hRWQuWaoZkK/+otPrmVokS1Vz3cKUQm3zk+zI/PyX1uifJDPpTgwVTGjmdPRPLcS7Q/G8CVKp5gC9SpMHV3k1P2Rmcc/RjLTDJafY3LMf6NrobKkFeOMrb6EP+3I1Ou38cf4wVvvsx9lW2RvCVpz216NlLmGmKKTX8mSCyaIYI2RVO3ER1yQk2dvRj3/uWT7HVmx2FKMO53WNVoXlvuQlpwuWqdxBqCl3lt8xOys6z7rpCVS7oP+sjL56g7fPcEHCcjY5glWm3R7jW57C2U4tCC5IwpN2/Or5Zo1uV0J7Fz57swz/5ePlFSj/KZ1Pk+E2jnmL3Up1pyiJVlOrPDHqq2C/lDXfL/yC730j8UqqB/lrCibyFH2In1Y5EBVxWm3t6qWfS6ANEEzbXJsKOqlfH+3XeRj0RenuDSPYE2svbPRho48BhiYFVfnlW5O67d65K7Q1nNKeXpJHJvhHBkTfUIlLPOhrRhawqJltksr1iLBDkb/k8qpfz3Gdq89SuIgFtth/KpyAjGqd1FAKnaGmnbsrFnp0epp7VHfsS0ihtwVTe84PE0aRa9HoaIMptooP6JJcYPxVAMTSWX8ayRa4ebJh61C9KfbCDKTCiqOpKqabld3RRUINiPCdGF6wf5RULVZVAUsq9DG64uxp8geuGrg6IXEjkb5fzMbaoz6+drSrCQMVU20p2DR2h5p4eCdW6heUX6D70UVMLxOw5f2P2N0qsHDBYd1TpFRX/xhXjRi9+3xHi1sBKK8iRQxY3XI22Qj/DOQnpzHhDnEql7NNBdb7cLO407nAGoiONnzO1ylelx5EVv7jTgeOdFJwvqLC8tKSR636N8vUQi/36Xmnrp9FTK4UfwW0j1Zc50IMFcKAXl724qD2+ciRCeKShv6vBQHjXLYzdg4o0HYTczP5uqZiDRr9mRI4/3hcWk6Hz4/qIlxid5yWZnRu6VWrVkGvdTRiMdOf7Cscm8mu2hnLUddU1diNUcdRHTQ7KiN26MiD7g61TYJoT/roJGhGw19d6QtKWTKTme10RFV55inHI5ShVub/gJSC/2nbV38msinVTA461taWmp9YYU5wTJ7TOSCbfFFcsHRV/rsBqQnOHrvsqil35gifFGkXjQ9rB85i15/4scQbkY6cKYyUeNB7I8qnijhpws/pCCjZOzhvx+KLEqm7VxDY78ORfKG5CGRfY6JyREF3PkihZy4bt8Uf1sIM0NuUgPdtLtfM/NOUCnl3qUEY6dRUx9vdgLHF5+sYz6Za/OJo2mzqePyDudDNkK4CsWpUtdpncm6wi9+tpGj9Qj/T5n2oW7ATXMhAbg4x/2wb2BICMswPU9T+wY0ft8j7Vyke3OHyckZ4oWfWlRvtRnSkh+jkbvTbnP4SiUPGMO2X+U+sccDKA6+CPmVQ2SqjNVFdyKEW6BuxUqQo7MK8POVoYEje98GrZA7HNCMxXJmQZITnJlSr3vo4+bveN4oJr77oAGYHVsjsZkWx3V1oSGmq2xnZB4TaPqpnekAXtdO4RkcobskBGK/iJ39pMcBIScqHNz0/XJF12OzZk6FmhiBjSEzrbo7pjen+iqZshR3emg/+nFca/xLoaq8Gi71e18plio7lsLFkqLzrfFkwhF320i0pkxI5Jqn5k4+YaRQDOXQENgHOtxdN3nhjWNdFVFW0XQQZet/5H/zj/bZ1U962BTm4rl+/fEq2zvJfQ6F1XGvPdYWzzJ6SNM2PF3DB8NGCM4Od1iDIvpDbFDHC9bu37Nn9v6V23v4R5VjBp6sw5TTSS87y5eT/8uQfQCL/tZ0ZO7dE/jNUc7a3nXYXR2zqSRIGluh8bAVATijvEwsRe3efDzfwYZLV3Q/6qdt0LQD6F458y7eZAQXdGTIzvfD0BGMF3tTz/+5MdvHAtS4hFoEIxjGytrFFJxfp27tkllVbZOGDqRZP8kUfTSjy080QFHEvJO3zUX6Qo59nCFjN73XrDzYSB15kKjYOh+tmVKEoy30Nq2DPoD6lS31/ONumLltM+KIZF7T+ALYU6OFD0H6Qs5hTL+OLFc+rTJ5xw5EujEKdAorF56TQMukdR8JbfCX5vqNqRIjdiEevEPg+XTQigcYZTtjiTi9N2R7pAbQiZddvxo/u4eM/G4cedPP3VCFtCT26BhWL0O/3IsKjvGDf1JPIfubK9XVN3l7vhDYr0Uywfc+U1MO8T4Xig6kZE7BBnDZSCePXbbcccdp0zYIyp2uogOIdNIr2wgZOeu9+1/OCChuT45mvJ/WynRRXJEMyzZOcPzq9B9j+be9a55kyUXZYb+8R6GaaYDa3t5Hy7mz21cQ7cxMLkpdXnVy9nh9JCY6O8So8pEj5xMH3Rile1iZBAnAPO4BxqK1eujmzdv7MVRGpb/3kcnvSg6wNhkm7NZzf1ST3Lx2RdyPyxPLHdDEK2nq+pzSAvRDQjZSNnLHPT8n1au/W379t/Wrurf1Ei3pbAbnOq2S2XmuObsBM3Jlc+ko5bP/S7INkcmdM6MMmyI/GSglaGXnCEWfzY6HHRVkHY4gmVEtl276lK27nKXt/xBBGtEvYWrqAh/F+ImlgXZmYQeuaOQUYwD0qSdpceoroZ6QLWUi4XrbAtnHaTknmHjyy3CKrt8x1RCN+w5yChyQLIMmYKLkVCwTrATuMZta2ohe/iESZh384iMPPe7oDDbdDeIMgsZxbnAPObB9MNJtUS2f0eELy932dz2rroWcvO3WDz+RTH5u0CKvkhE9NvM2Oo4CZjHYzAdGdzzz2KrQfWt3V6qHcqQ/5no4b3gCwsBN+pG8Ajxtrkh7AjM46Q7YFoSoDy17APfrUs7WhgPRYWgLHlfkdsmyJ0zPC+yaVoB80CUw5FB7DAKmMeI02Ga4nEGqPb28Gv+HqhE3ndkYwy5XcoS65AmueMkE0TPBmZyEMx8eC/9lcoC8hVGZdETi2zZyCBmATOZCTOfoqJXyNOd3xipLHpi6v0pZBA3ADN5GmY+hUteIraGEeOLsqLfbMIi/gMnADO5GWY+nPP+ZeEiQb1VWfTESeULkDFMA6ZyNcx8OOf93TzhZ5IPoDBku9WEx3VmA1N5EGY+kW3vL72wgDwAuPk2peTM0Sb0zagbQUuTgvqQYFHhO2LtzUWVrHunnIa97lrAoWYYIQ06KLjG94znP/bu7SeKKwwA+McucltRCyqlIGwrKFTEegGBoqLYWluxYIsUrdfWS63ai72350wyO8k2szuTeduEPuwTbyRye4BAAqEJJMv1RdEE+RN85LlsbZtymJmdmZ3dPTPj74WEN/Jx5ty+830cmpQr/irOM+s8Ii9ckpMW+QbEi4p3TTQJDhKJUvIZFFFj669Wf0l80nsuJFmeZY/kNBOXiZbZSkcz0bvXMCLcle+pZNUbNqeczvjmiNeqRFs29XdNjQnvd73HBcl2A9mdb0auM49vmSHIFgAnGzt4dmCz1YMWLzfquvieMSO+sEwvH4Js1cgmchjmY5PVQPJdQ3a3GvRBHy+7jyPN+BDhJ4Xe9ta8SXfOns33bImVW9IT5KsS3AWS+7CVD+NeuHMB2Vyoh3iMKn+XTlaZe+EsrJP5noXPZZxyoy4FAhIihIP9DKPhQO5CJ6y3swyb5Xw6pMQ3yIFE2a/7qEg+cDkBcopMi/olSI2byIGItbviju0qyDrgtV4OLFGXwHkC3CNGxqwPEW6DPNc5i+7QLZ0FbQiZP0GaJ25fo1O6kvxXcLw+AV1eruRMuGHXkELRDMrctTg+JZBCl5HTBLsealvH3QU16TnYuKytkEr3kcPwMpt02YQq9DWoS3/V6Ee+zQXGOPcRo37kI1ZN53FNsSOT92kN1i8jgdP5huKSyoraty9urqvb3FZwpmQDyDqOHIVnZxk5vesO7q6AFuktF0uxHt6T2ZAI7qL6j7/IJb89GZv3bnBoGvT/hIJjjLYp/Tpo5Nm25YOCiwfPl+FYSusqisB8nuL62k2KU01ZzkYHXrStHejEfk2xHPDRQtDHvbGo5OczH+8+tXlXrvd82nsZGWXRoZaRkZa1Z1ddzqvvlmxzgelcO898kYVjqHU5L0/uf8JiPyNrXkRr3YgrFO4N6enpW4uLi99MTy/MgwQpfqctDWuRVey4lCmFga5eeqQR6FaYX+A1fs5/FTmH4kBfkvm6Uyy9pS4jrnSNz5Bj8OwcQ1CqC3sDqJX+YBfWL9fjsDzofwUUlu7M9Loz2OtAp8LK17ExZ5x5EiutaZmumv18zA00unSuDBuV5V5bLdQh/OFJRt4UGfQvgT7ulsPmvZ9ytyJniDxntH7d9wNtsk9n4PjUOvBQjvcNMozGtfsJoM3J+BMyqxyYPhMgtmtqly33gS7FXhw/r8txly585Bkjj3zrRt8mfSc2wyvbHfa6CUm+rkVGwTj51u0y0KXKpKA77fydU/64L/aQ2XEfAlXysUlBd1ptMfl8GbLNxwu/AV3exqbwupxVfEZiFxhF8yKP/oe60ziXNzHVSF1NyM4kMTTNKBklW7ccArpsxeaodNRLF55jRxhFC+RL5mtAl32JKjvcaefnqwJxFKfeo6kpD+jyCTZD2VZnpcqxs4yyeXKg3wLKVGIzvOGoVGhiERfrfq2VsoMZgJ+xCSpAzlfIniS25yGjaLGLXLrfA9rk4/jtTnm/rmSSWL6XUTZFHsYdywba7MRxawMFPyEbklhhklE2F0FrUDijAxwwt8yJ7XPl1GPePR9BhOMuoI7Lm8AeMb8iu5HYP1Ri3ieR33b69uh/24zjssvlpPpiPDs8zSga8fsktAaNyRPxt5R43eWgqkO8sDLfzSh6wgYlRDoLNCrBcahzUiVwPrAyxSibXeHIbzu1ye7x9PA+5aRSsZKffcoomuyJCDxapx3odA4bVQAxZdvm3YPkEycYRaN+lkfr3QVKvYENet9BBYJ5ITI8xCgal5vO6dyuvZBdig3ZC5o0IxuQ/Cuzi4yS3oVIgEcybgO1arER+5xUgoYNDjCK+kMskvUN0CsT61e6zTll/yVuZbBP7dMuSkhOawNQ7BTWa1M2aOaxejVB1qeyap+eX5H/tNNehOCSWct2G962Sf7IoMoKbsLPIlnUbtGN7toqHdPXhRdY/xNG0cPZSFBCcmj/uK8qxjpkZYJeJ5Al8cgXmZpWWcFJrMAjWdRlPcs4jTVrywPd2i2ZJMkHI4P9jKLFZxFRQvLoe8ckw5OLNWpxSg8niYtIA4yyEYkN8EhJObXHMvrXcnu2OqQ0NC+wwaeLKov2KVZlmNNYgkDOSazBq2CUx1K15aKT+ZzK1rx7nFOZzRF9r9GNr+C9RWBc9VFkFTwSWZXJfHHsscByElJkiQldY4Pf15zR2yUa8p4JRsHQwEyXyPp5pIzWbBlZ7iqsYtM2iNMtZAnh8Nwj2T350OjzqR6OZf0CUtfaCdahEvXSfDDCitVDua6BvrGxvsnp7qjpyb5HIxNLj2eWuwLiasBDKLbPwFLasKyMB6CXdZ+88MgvBrnfpeGuqGEJcUHRx7KiPyAgDayziPvPB3i9tAo3xGSnu3VBEEIBjvNHcRwXEgSkQwdYzkayTuiOvS4wjdtSGzcD6L5DV3apDv8nq7YITNVg91JjP4JFpdcX1Bysqsl5N9MDZuu0d1WSE1Y4fY3pZdT1KKez0nPq2Tjqx+/AS/IarJ4+9TLmBrgtmlNhasxdO1s+evviuYIzmeAQdqxWoCvm+3LS8L9yW+grVbHWy87LCg65QbNKL3HiWbARnOAespdmD2j1lhev94MjvvL2avPyDWjlPoXlbToC9tduo63bVdAq8zxWVFUCtpdtm63bfbPqc+7YAnZ3xx5j/fOvdV1iOj3stoj6oTvxxZyU+xbYW+qjLggoPlfML8NbtRNsLcVRD7JBkWV9fk4xK0ZA6hpBsyNYs9ftvYFLYdQ51tf1dGz0+czcoBQO+nyr0RfFoP8fQVFc/Y1/WFILe/m3oNn2UqzDRVsf16Tm+kXws6w0M7LIvNA7NDLwZHxmdm55oafrbz0Ly3Oz4yOjs0IYKeoAHX7A+uzeDvaV9BQqgRPZYNfMRDcj5+E/mKihqXAIKWnaDzrUY91O09YQwkSe71CyCAG/jxX55fH+h0xso4MREfFIwVXQw52F9UurBPu6ghIuzAWjeczhnqmnI72MBr1PetRCXt4OulRgQw7beP92F5mLjDfLBofnp549GelbZDQZmwlHgsohR/cSVraNVHMA7KoRmU8QAv7V4e3zSwszT/q7Gc16lxZEluORoh/vJLNTTq1tE+/2H0UmCQc4fzTYrE8MrA7vxwP9vYwO3ROzv7M+tXfIrWeTXF89w7ZTe6FZi/ie+YWF5T9nZ54OjD4ihreWiEssyyE1HaDfRhyfHbY9rLmMTBAajo7tacaAyaWpmBFHzZ1gQD2OV45dU6quITOEOIHvmp+dWNQ1xEfGFwIxI46azoIhBThuGT+DPVUfR2YQQlyQjQxPaF23jTz9c1hkxQCK4cI9MGgTNkGVtdfx2QcyV73pTuiOXVyZinkC83Bo4PGyJLI+TkAxXXaDQe4sbIrXwJoK91V8kZuG/1a6qXaLm0ydu4BMwgusWkmwyf6lx39GC0uIRMAVfFcNhm3EJvEWgeWkt9RlkFNVTjHxX9GMzCIFV+aHert7u1+M6t7u6b6hsf6JpeePp5YH/whG71RDSJvy/TS0K19VC5biyq/BsmqIajb3kXnEIL96ZTa4ar5nuIsPBTh/9ALdJwa5MNKs6XbKu1z+J8tCg337a2lY0UfEbWszMk2Ii96NR63+5AKBUFhAOh1rpKC1qQVndterWNVhYrBf/xzRovV7iFsRNtVBSyRYbEnT24A9j5KO+0TIDdqGTVYPtMtuwxq8Q7Z+oSArngi5Yell2GQ5QLctGViTM0BoPIpSqukaACVNjNfbQXMylSfHeL8IVwdKnfLbYJ5N2HSv0JsnnZmFtTsCpIZUTe3NX4OZcnACfAp0+gDrUboB1qn+BSXflWow1wOcCO8ChfLqsD7nQEb1Vyipjt0sBLMdwQnxAKiTWYr1yodUh72ZuDxNfedqS23d9hpZk3pAVudllAytHd9CYmzGiUHZam43NqISFBTebEUJ9tNtDyTKSWwacpTQY8MubEguKPJcP4ESp/xWAyii7iCWysVcpuE5rARUtH95FCXC8Y52SLAdODF2AS3ewIbtBlWuxmbTI351PyTexzgxDgIlKrBxeyCWznuHkGkO3f0QkiITJ0Yd0GE3jkcxxFZ904y4H/3lfifEQvv6/X2ggSfOvy4fNKm+13wBGXfhRMdneZBMW3BC5AMFsg/i+JwErRoarzQZGuHNHWcbQAsLDPU3IfW2e3GcToMe7bdu6An854cuf79f7win+SiWhsX7gTSc+KCTqv9q726bmgaCAABvaEOT0pYGSlvEUlsrhb6IFktH69uoCFb4ACiioDPq6IzjOH5zRj/sb/dtdBQtTXqbvbskzw9gJlyuSXb3dl89+XLh2ajtfeXjk+uXbZCoj78FqV6uYyDXop907fL1D+/f3L1w6+Yfy//s5u0Ldz6+ePvy9WMFjvt2akhOfs8CijXHDRAyMf/04uPLP1y8+HReqTk6y0itJ/365oxg3Lu+mUojsX2QLF5GAmUFfod9s4o/BCfJZjeRQh2CLImkMiBZBUmsgjbi2fuD5ZWFKXAvbyClz+CVkvdwCTRhPmzhT+WBLdCSQoQVA6keIo17oAV7Hf8wOetxWHkw/lkLSKOmQlRxlIkbD4yxgwupSaRyYIJUa0hjD5SXLxr4r2Vw6zNS2QapBkhE/VkWy8LZrr1gBGZSW0ijBYqzMziEZYJLZjkQB1z2kcgOEJnIx22gN5PGoYrgVjYIJTMxC2kYJlBI3etajuOUkscxoNXHU8zxbpIcjEW5RPE+EOjs4m9O0QRCWaosZwuFPYQxKPiNTnLznsG/1B4CnSOqL6gEipoGyfaQxiYIy7fwpDUTiDRqZEnhNoo5iINkLVQl7J4z8F9HQGSHMP1R1zz/bDpIogKiElu+Fowe4QgLXDtlA0So1Drp0K/CnSUgYRqUBWsdR+uukc8Vya/ZTX/jfM9pL2FR61h1VpHAzCYOs8n1kfIcPNjW9cX9u0OkULZBzFUcrsMUdywydP7vggqOkcIyiDEtgT9OlQlP+3/m5R0ogWSnT8ZpgzInF4NAF0dbAC9iafSqAGqoIoEiiGlM+l41ukRfyxK39EqhE9f1pkBMEU/1iKlQpOvrUYFJ6TEZ0uP2BRBjHvhfb7nmx1Mq56BrGROU0UBxcyBme/TDVlgaXaiC51XXsKUQwFRTfiPrkQuyzNTJeR28SlnoxrT0FMvfpqXnVFcZAvtTPXQhDZ6ZLRypp9wZkDPSN3qfoWPDjOXb/VsfteRVUE4VBZ0FMfFJHOmQqb3rCoxh1sHhKougoIbsjX6f42Ckafh4MbFHQ+7b0kDVWZtLghudI1bWZFr0EozHni2ka/gXa3MjB8oayN3oOZ5nyJbvL6X5S+0z9XfT093d5P5Gdk6lXr/UJ9nO8hRmtkFMx3UtSEhkhIJxorosPygpfcpaeLRxfB3gWY00iElp1NmNhV0WSK+JWkF3OjyL7qg8MI3UIxyTE2cru6+CkE4AG6gQhUf4mxjHLJ7miglN+kOMJD0Ua9kg6hJTQWFCp2JVHvNlHMcO4+1mxXgWvaf297X0F/g11lZmOaZaES2mm8tLsFZBWHyL6QhNLkA9VMjMySnbn+Wqsm7oODXLdzvo1Xne1ie7IKKjX8kqh76MGu4MVxujRk2rsSpcJtLohRFnDhA4eZ4ZuQkIk5TBPjAyy1eK1wtae1si59lHzgz4xlm9c51NCJlFdO0GUNhFD+6zXNsChM0sulSQ0MKuyBGJqED4rKIrlgkUzqIXmxwFQlchhBIOulCVcTa+whDmb0qfnyRFvoQj9YFGEb1Ig6BKlFgdP0pTzgONXd4WJ+Y5HMFR7MgZo0OmmNXMOfSiJrwinQM8VVrhQnXf5SssI+QaNeYiTGhYOJRVOA/hdugwTBPLojcJEBabxv8oZworYd7kv8wU8f+MhrTKDZKd2C45+EPNKTeXjuqDlUudGYj8ZK5Th+JOKsiZ9GencnPfNPJBHhE6NnNwQPqFftKn4I531NlU9pOP42ZK0aIryjxOWv7Uj80b0aKra+rsynq3t1XbiwOlnG6Tp8NnIj8PtFa9n4qO6O4Yf4oq0kNkA70xFGq5GGE6QLcGEe2t6zWpMkIhid6cgYj2+nrNIY7IWPQGRLSX1HHkTYS1000bIvq7il5YUSI0COKOt1YnkSC4H32kh1Ad3WraEAmIJLpzLrz16AG0gW5Uon0eKLmlqAtMCC2u4ak2o5/2IFqoGziEsR9VTgTVxGpxaQtPKhUWw3lyODzMG+1iv9vq9XrnSplPhe3FUCdYvgKoLp6WFjy2ewAAAABJRU5ErkJggg==';img.onload = function(){initData.context2d.drawImage(img, arr[j].x-50, arr[j].y-50,100,100);}},pen: function () {var lineWidth = arr[j].size;var radius=lineWidth/2;var lineColor =arr[j].color;initData.context2d.beginPath();$.each(arr[j].msgArr,function (index,val) {initData.context2d.lineWidth= lineWidth; initData.context2d.lineTo(val.x, val.y);  initData.context2d.strokeStyle = lineColor;initData.context2d.stroke();  initData.context2d.beginPath();  initData.context2d.arc(val.x, val.y, radius, 0, 360, false);initData.context2d.fillStyle = lineColor;initData.context2d.fill();  initData.context2d.beginPath();  initData.context2d.moveTo(val.x, val.y);  initData.context2d.stroke(); })},eraser: function () {$.each(arr[j].msgArr,function (index,val) {initData.context2d.clearRect(val.x,val.y,arr[j].size,arr[j].size);})}};switch (arr[j].drawType) {case 'rect':drawTypeFn.rect(); break;case 'line':drawTypeFn.line(); break;case 'circle':drawTypeFn.circle(); break;case 'delta':drawTypeFn.delta(); break;case 'ellipse':drawTypeFn.ellipse(); break;case 'polygon': drawTypeFn.polygon(); break;case 'font': drawTypeFn.font(); break;case 'signet': drawTypeFn.signet(); break;case 'pen': drawTypeFn.pen(); break;case 'eraser': drawTypeFn.eraser(); break;}},/*** 统一绘制方法*/drawArr: function (arr) {for (var j in arr) {this.drawTypeArr(arr,j)}},/*** 鼠标按下执行*/mouseDown: function (e) { // 鼠标按下initData.initLeft = e.offsetX?e.offsetX:e.originalEvent.targetTouches[0].pageX - $('#canvas').offset().left;//获取鼠标起始位置initData.initTop = e.offsetY?e.offsetY:e.originalEvent.targetTouches[0].pageY - $('#canvas').offset().top; initData.msgArr = [];if (initData.drawHistoryArrData.length>0) {function getChooseIndex() {for(var i in initData.drawHistoryArrData) {initData.drawArr([initData.drawHistoryArrData[i]]);if (initData.drawOrMove == 'move') {if(initData.context2d.isPointInPath(initData.initLeft,initData.initTop)) {initData.drawArr(initData.drawHistoryArrData);initData.relPosX = initData.initLeft - initData.drawHistoryArrData[i].x;initData.relPosY = initData.initTop - initData.drawHistoryArrData[i].y;initData.relPosToX = initData.initLeft - initData.drawHistoryArrData[i].toX;initData.relPosToY = initData.initTop - initData.drawHistoryArrData[i].toY;initData.isMove = true;return i; } }}if (initData.drawOrMove == 'move') {return -1;} else {return initData.drawHistoryArrData.length;}}initData.chooseIndex = getChooseIndex();} else {if (initData.drawOrMove == 'move') {initData.chooseIndex =  -1;} }if ($('.drawFont').attr('data-type') == 'hide') {if (this.drawType == 'font') {var x = initData.initLeft;var y = initData.initTop;$('.drawFont').attr('data-type','show');$('.drawFont').css({'left':initData.initLeft+"px",'top':initData.initTop+"px"}).show();$('.intoFontInput').on('blur', function () {initData.context = $('.intoFontInput').val();initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,fontSize: initData.fontSize,context:initData.context,color: initData.color,x: x,y: y,w: $('.intoFontInput').width(),h: $('.intoFontInput').height()};initData.drawArr(initData.drawHistoryArrData);})}}if (this.drawType == 'signet') {initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop};initData.drawArr(initData.drawHistoryArrData);}}, /*** 鼠标移动执行*/mouseMove: function (e) { // 鼠标移动initData.context2d.clearRect(0,0,initData.canvasWidth,initData.canvasHeight);var moveX = e.offsetX?e.offsetX:e.originalEvent.targetTouches[0].pageX - $('#canvas').offset().left;var moveY = e.offsetY?e.offsetY:e.originalEvent.targetTouches[0].pageY - $('#canvas').offset().top;var moveWidth = moveX - initData.initLeft;var moveHeight = moveY - initData.initTop;if (initData.isMove) {switch (initData.drawHistoryArrData[initData.chooseIndex].drawType) {case 'rect':initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawHistoryArrData[initData.chooseIndex].drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.drawHistoryArrData[initData.chooseIndex].size,color: initData.drawHistoryArrData[initData.chooseIndex].color,x: moveWidth + initData.initLeft  - initData.relPosX,y: moveHeight + initData.initTop - initData.relPosY,w: initData.drawHistoryArrData[initData.chooseIndex].w,h: initData.drawHistoryArrData[initData.chooseIndex].h}; break;case 'line':initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawHistoryArrData[initData.chooseIndex].drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.drawHistoryArrData[initData.chooseIndex].size,color: initData.drawHistoryArrData[initData.chooseIndex].color,x: initData.drawHistoryArrData[initData.chooseIndex].x+moveX,y: initData.drawHistoryArrData[initData.chooseIndex].y +moveY,toX: moveX,toY: moveY}; break;case 'circle':initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.size,color: initData.color,x: moveWidth + initData.initLeft  - initData.relPosX,y: moveHeight + initData.initTop - initData.relPosY,r: initData.drawHistoryArrData[initData.chooseIndex].r,}; break;case 'delta':initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.size,color: initData.color,x: moveWidth + initData.initLeft  - initData.relPosX,y: moveHeight + initData.initTop - initData.relPosY,toX: moveWidth + initData.initLeft  - initData.relPosToX,toY: moveHeight + initData.initTop - initData.relPosToY,}; break;case 'ellipse':initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.size,color: initData.color,x: moveWidth + initData.initLeft  - initData.relPosX,y: moveHeight + initData.initTop - initData.relPosY,toX: moveWidth + initData.initLeft  - initData.relPosToX,toY: moveHeight + initData.initTop - initData.relPosToY,}; break;case 'polygon':// 六边形initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawHistoryArrData[initData.chooseIndex].drawType,drawTypeNum: initData.drawTypeNum,fill: initData.drawHistoryArrData[initData.chooseIndex].fill,size: initData.size,color: initData.color,x: moveWidth + initData.initLeft  - initData.relPosX,y: moveHeight + initData.initTop - initData.relPosY,reg: initData.drawHistoryArrData[initData.chooseIndex].reg,toX: moveWidth + initData.initLeft  - initData.relPosToX,toY: moveHeight + initData.initTop - initData.relPosToY}; break;}} else {if (initData.chooseIndex != -1) {switch (this.drawType) {case 'rect': // 矩形initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,w: moveWidth,h: moveHeight}; break;case 'line': // 线initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,toX: moveX,toY: moveY}; break;case 'circle': //圆initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,r: Math.sqrt(moveWidth*moveWidth+moveHeight*moveHeight)}; break;case 'delta': // 三角initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,toX: moveX,toY: moveY,}; break;case 'ellipse': // 椭圆initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,toX: moveX,toY: moveY,}; break;case 'polygon':// 六边形initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,reg: $('.polygon_1_deg').val(),toX: moveX,toY: moveY,}; break;case 'pen':initData.msgArr.push({x: moveX,y: moveY})var msg = initData.msgArr.concat();initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,toX: moveX,toY: moveY,msgArr:msg}; break;case 'eraser': initData.msgArr.push({x: moveX,y: moveY})var msg = initData.msgArr.concat();initData.drawHistoryArrData[initData.chooseIndex] = {drawType: initData.drawType,drawTypeNum: initData.drawTypeNum,fill: initData.isFill?initData.background:'',size: initData.size,color: initData.color,x: initData.initLeft,y: initData.initTop,toX: moveX,toY: moveY,msgArr:msg}; break;}}}initData.drawArr(initData.drawHistoryArrData);},/*** 鼠标抬起执行*/mouseUp: function () {initData.msgArr = [];initData.isMove = false;initData.relPosX = 0;initData.relPosY = 0;$('#canvas').off('mousemove');}};});function save(){var mycanvas = document.getElementById("canvas");  var image    = mycanvas.toDataURL("image/png");  let params={'sign':image};return params;
}

 功能实现步骤:

1、将图片的字符串 转成图片保存下来
 2、将审批人的意见数据入库 t_oa_meeting_audit
 3、修改会议状态   t_oa_meeting_info

实体类

对应审批表 t_oa_meeting_audit

package com.zking.entity;import java.io.Serializable;
import java.util.Date;
/*** 审批*/
public class MeetingAudit implements Serializable {private Integer id;private Long meetingId;private String auditor;private String sign;private Date createdate;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Long getMeetingId() {return meetingId;}public void setMeetingId(Long meetingId) {this.meetingId = meetingId;}public String getAuditor() {return auditor;}public void setAuditor(String auditor) {this.auditor = auditor;}public String getSign() {return sign;}public void setSign(String sign) {this.sign = sign;}public Date getCreatedate() {return createdate;}public void setCreatedate(Date createdate) {this.createdate = createdate;}public MeetingAudit() {super();// TODO Auto-generated constructor stub}@Overridepublic String toString() {return "MeetingAudit [id=" + id + ", meetingId=" + meetingId + ", auditor=" + auditor + ", sign=" + sign+ ", createdate=" + createdate + "]";}}

在dao包内建一个     MeetingAuditDao:

package com.zking.dao;import com.zking.entity.MeetingAudit;
import com.zking.util.BaseDao;
import com.zking.util.StringUtils;public class MeetingAuditDao extends BaseDao<MeetingAudit>{/***  1、将图片的字符串 转成图片保存下来*    2、将审批人的意见数据入库 t_oa_meeting_audit*   3、修改会议状态   t_oa_meeting_info*/
//批处理public int add(MeetingAudit audit) {
//      将审批人的意见数据入库 t_oa_meeting_auditString sql1="insert into t_oa_meeting_audit (meetingId,auditor,sign)"+ " values ("+audit.getMeetingId()+","+audit.getAuditor()+",'"+audit.getSign()+"')";
//      修改会议状态   t_oa_meeting_info
//      state有两种,审批通过即 待开4,审批驳回 即 驳回3 状态boolean flag=StringUtils.isNotBlank(audit.getSign());int state=flag?4:3;String sql2="update t_oa_meeting_info set state="+state+" where id="+audit.getMeetingId();
//      同事执行多个sql语句,其目的在于事务的一致性,要么同时成功,要么同时失败return super.executeUpdateBatch(new String[] {sql1,sql2});}}

这里涉及到批处理: 当审批人审批该会议后,该会议作为一条被审批过的会议添加进数据库中与修改会议状态的两条sql语句应当同时进行。

Basedao:

/*** 批处理* @param sqlLst* @return*/public static int executeUpdateBatch(String[] sqlLst) {Connection conn = null;PreparedStatement stmt = null;try {conn = DBAccess.getConnection();// 设置不自动提交conn.setAutoCommit(false);for (String sql : sqlLst) {stmt = conn.prepareStatement(sql);stmt.executeUpdate();}conn.commit();} catch (Exception e) {try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();throw new RuntimeException(e1);}e.printStackTrace();throw new RuntimeException(e);} finally {DBAccess.close(conn, stmt, null);}return sqlLst.length;}

在web包内创建一个  MeetingAduditAction:

package com.zking.web;import java.util.Date;
import java.util.UUID;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.beanutils.ConvertUtils;import com.zking.dao.MeetingAuditDao;
import com.zking.entity.MeetingAudit;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.Base64ImageUtils;
import com.zking.util.MyDateConverter;
import com.zking.util.PropertiesUtil;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
import com.zking.util.StringUtils;public class MeetingAuditAction  extends ActionSupport implements ModelDriver<MeetingAudit>{private MeetingAudit audit=new MeetingAudit();private MeetingAuditDao auditDao=new MeetingAuditDao();@Overridepublic MeetingAudit getModel() {//注册一个转接器ConvertUtils.register(new MyDateConverter(), Date.class);return audit;}public String add(HttpServletRequest req, HttpServletResponse resp) {try {/***  1、将图片的字符串 转成图片保存下来*   2、将审批人的意见数据入库 t_oa_meeting_audit*   3、修改会议状态   t_oa_meeting_info*/if(StringUtils.isNotBlank(audit.getSign())) {
//              dirPathSign=E:/temp/images/T280/sign/
//              serverPathSign=/upload/sign/
//              拿到会议签字图片的存放地址String dirPath = PropertiesUtil.getValue("dirPathSign");//存储到数据库中地址,即浏览器访问地址String serverPath = PropertiesUtil.getValue("serverPathSign");
//              最终生成的图片名String fileName = UUID.randomUUID().toString().replace("-", "")+".jpg";//info.getSeatPic();//图片字符串Base64ImageUtils.GenerateImage(audit.getSign().replaceAll("data:image/png;base64,", ""), dirPath+fileName);//将seatPic中内容修改为 请求地址audit.setSign(serverPath+fileName);}
//          rs是sql语句执行的影响行数int rs = auditDao.add(audit);if(rs>0) {ResponseUtil.writeJson(resp, R.ok(200, "会议签字审批成功"));}else {ResponseUtil.writeJson(resp, R.error(0, "会议签字审批失败"));}} catch (Exception e) {e.printStackTrace();try {ResponseUtil.writeJson(resp, R.error(0, "会议签字审批失败"));} catch (Exception e2) {e2.printStackTrace();}}return null;}
}

配置mvc.xml:

 <action path="/audit" type="com.zking.web.MeetingAuditAction"></action>

效果演示:我们点击上文中签好的名字的审批

签字图片成功保存:

在企业与公司中,对会议签字要求都是有严格要求的,比如像图中一样的居中,当我们签字不居中时可以使用如下方法对字体进行居中处理:

ImageUtils:

package com.zking.util;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
import java.util.regex.Pattern;public class ImageUtils {private static int WHITE = new Color(255, 255, 255).getRGB();private static int BLACK = new Color(0, 0, 0).getRGB();public static int[] bufferedImageToIntArray(BufferedImage image, int width, int height) {try {int rgb = 0;int x1 = width;int y1 = height;int x2 = 0;int y2 = 0;int temp1 = 0;int temp2 = 0;// 方式一:通过getRGB()方式获得像素数组for (int i = 0; i < width; i++) {for (int j = 0; j < height; j++) {rgb = image.getRGB(i, j);if (rgb == -16777216) {temp1 = i;temp2 = j;// 计算最左侧if (x1 >= temp1) {x1 = temp1;}// 计算最右侧if (x2 <= temp1) {x2 = temp1;}// 计算最下方if (y2 <= temp2) {y2 = temp2;}// 计算最上方if (y1 >= temp2) {y1 = temp2;}}}}System.out.println("BLACK: " + BLACK);System.out.println("x1: " + x1);System.out.println("x2: " + x2);System.out.println("y1: " + y1);System.out.println("y2: " + y2);System.out.println("宽度: " + String.valueOf(x2 - x1));System.out.println("高度: " + String.valueOf(y2 - y1));return new int[] {x1, y1, x2 - x1, y2 - y1};} catch (Exception e) {e.printStackTrace();}return null;}/*** 剪切图片* @param source    原图片地址* @param o         目标地址* @throws IOException*/public static void shearImg(String source,String target) throws IOException {BufferedImage bufferedImage = ImageIO.read(new File(source));int width = bufferedImage.getWidth();int height = bufferedImage.getHeight();System.out.println("原图片宽度" + width);System.out.println("原图片高度" + height);int[] arr = bufferedImageToIntArray(bufferedImage, width, height);// blank是作为四周边距留白        int blank = 0;BufferedImage newBufferedImage = bufferedImage.getSubimage(arr[0] - blank, arr[1] - blank, arr[2] + blank * 2, arr[3] + blank * 2);ImageIO.write(newBufferedImage, "png", new File(target));}public static void main(String[] args) throws IOException {String source = "D:\\temp\\images\\T280\\sign\\df0862b3627649e7b36da63cf21ffd27.jpg";String target="D:\\temp\\images\\T280\\sign\\"+UUID.randomUUID().toString().replace("-", "")+".jpg";shearImg(source, target);}}

 MeetingAuditAction  :

package com.zking.web;import java.io.File;
import java.util.Date;
import java.util.UUID;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.beanutils.ConvertUtils;import com.zking.dao.MeetingAuditDao;
import com.zking.entity.MeetingAudit;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.Base64ImageUtils;
import com.zking.util.ImageUtils;
import com.zking.util.MyDateConverter;
import com.zking.util.PropertiesUtil;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
import com.zking.util.StringUtils;public class MeetingAuditAction  extends ActionSupport implements ModelDriver<MeetingAudit>{private MeetingAudit audit=new MeetingAudit();private MeetingAuditDao auditDao=new MeetingAuditDao();@Overridepublic MeetingAudit getModel() {//注册一个转接器ConvertUtils.register(new MyDateConverter(), Date.class);return audit;}public String add(HttpServletRequest req, HttpServletResponse resp) {try {if(StringUtils.isNotBlank(audit.getSign())) {
//              dirPathSign=E:/temp/images/T280/sign/
//              serverPathSign=/upload/sign/
//              拿到会议签字图片的存放地址String dirPath = PropertiesUtil.getValue("dirPathSign");//存储到数据库中地址,即浏览器访问地址String serverPath = PropertiesUtil.getValue("serverPathSign");
//              原图 图片名String fileName1 = UUID.randomUUID().toString().replaceAll("-", "")+".jpg";
//              裁剪后的图片名
//              生成签字图片String fileName2=UUID.randomUUID().toString().replaceAll("-", "")+".jpg";//info.getSeatPic();//图片字符串Base64ImageUtils.GenerateImage(audit.getSign().replaceAll("data:image/png;base64,", ""), dirPath+fileName1);
//              原图进行裁剪ImageUtils.shearImg(dirPath+fileName1, dirPath+fileName2);
//              删除掉原图File file=new File(dirPath+fileName1);if(file.exists())file.delete();audit.setSign(serverPath+fileName2);}
//          rs是sql语句执行的影响行数int rs = auditDao.add(audit);if(rs>0) {ResponseUtil.writeJson(resp, R.ok(200, "会议签字审批成功"));}else {ResponseUtil.writeJson(resp, R.error(0, "会议签字审批失败"));}} catch (Exception e) {e.printStackTrace();try {ResponseUtil.writeJson(resp, R.error(0, "会议签字审批失败"));} catch (Exception e2) {e2.printStackTrace();}}return null;}
}

使用该方法之后方可实现居中效果

四,亮点知识总结

1.批处理

2.签字图片的裁剪

3.会议信息详情界面,将会议的所有相关信息(标题、内容、时间、参与人、附件、审批签字)

转成PDF

会议OA项目之我的审批(查询会议签字)相关推荐

  1. 会议OA项目之我的审批

    目录 一.会议查询 1.后台 2.前端 二.会议签字审批 一.会议查询 1.后台 当前登录账号 是 会议信息表 中 审批人字段值 Dao: / 我的审批public List<Map<St ...

  2. 会议OA项目(三)---我的会议(会议排座、送审)

    目录 前言 一.需求分析 二.准备工作 三.编码 1.后台编码 2.前端编码 四.效果展示 前言 上篇分享了会议OA项目的我的会议功能的查询.取消会议.本篇文章将完善我的会议功能. 我的会议功能有一个 ...

  3. 会议OA项目(项目原型图介绍发布会议功能)

    目录 一.会议OA项目介绍 为什么要开发OA会议管理 会议OA管理的作用 二.项目原型图介绍 1)会议管理 2)投票管理 3)会议室管理 三.数据库表结构 四.发布会议功能&多功能下拉框 La ...

  4. 会议OA项目(待开会议历史会议所有会议)

                                                                    文章目录 一.会议OA项目名词介绍 二.SQL编写 待开会议SQL 所有 ...

  5. 会议OA项目之会议通知会议反馈反馈详情功能

    目录 一.需要的SQL语句 1.1 会议通知查询的SQL 1.2 反馈详情的SQL 二.会议通知的前台代码 2.1 会议通知的jsp文件 2.2 要封装的js文件 三.会议通知查询的后台代码 2.1  ...

  6. 会议OA项目之会议发布(一)

                                                     目录 前言: 会议发布的产品原型图: 1.会议发布 1.1实现的特色功能: 1.2思路: 使用的数据库 ...

  7. 微信小程序-会议OA项目03

    目录 1.Flex布局简介 1.1 什么是flex布局 1.2 flex属性 2.轮播图--组件的使用 3.会议OA项目-首页 1.Flex布局简介 布局的传统解决方案,基于盒状模型,依赖 displ ...

  8. 会议OA项目(六)--- (待开会议、历史会议、所有会议)

    前言 上一篇分享了会议通知以及会议反馈,根据需求来今天应该到了,历史会议.待开会议以及所有会议了. 一.需求分析 历史会议:登录人员,属于参与者列席者或者主人其中一个时,并且会议状态为已结束时,要将数 ...

  9. 微信小程序:会议OA项目-首页

    目录 一.flex布局 Flex布局简介 什么是flex布局? flex属性 flex的属性 二.轮播图组件及mockjs的使用 三.会议OA小程序首页布局 一.flex布局 Flex布局简介 布局的 ...

  10. 会议OA项目之会议排座功能会议送审的实现

    目录 一.会议排座插件 1.1 插件文件&&jQuery的js文件 1.2 导入js文件 1.3 会议排座的jsp文件 二.初始化参会用户 2.1 编写SQL语句 2.2 编写Dao方 ...

最新文章

  1. ubuntu18.04上安装TensorFlow2.0
  2. 小鱼易连获腾讯数亿C轮投资,云视频布局产业互联网
  3. OpenGL-渲染管线的流程(有图有真相)
  4. [CodeForces1070C]Cloud Computing(2018-2019 ICPC, NEERC, Southern Subregional Contest )
  5. Codeforces Round #268 (Div. 1) C. Hack it! 数位dp + 构造数位
  6. c语言凸包算法,基于C语言的凸包算法实现
  7. ㊙️【教你用python挣零花钱】自动化简历内推,学弟直呼牛逼!!
  8. 4.11_facade_结构型模式:外观模式
  9. myeclipse将普通java项目转换成maven项目_Myeclipse Java项目转换成Maven项目
  10. SSH中常见jar包缺少错误
  11. Regularized linear regression(正则化线性回归)----吴恩达机器学习
  12. MATLAB Simulink 中的过零检测与代数环
  13. 74ls20设计半加器_实验二++组合逻辑电路的设计与测试.ppt
  14. Win2000 Server***监测
  15. 用matlab求光谱的一阶导数二阶导数
  16. 清华大学推荐:这32本书籍你看过几本?
  17. Set集合的基本使用
  18. 求生之路2rpg服务器账号跨服,求生之路2官方地图指令大全及地图文件夹位置说明...
  19. TikTok || 一个正在冉冉上升的海外网红KOL营销市场
  20. C# 面向对象(多态)

热门文章

  1. Restlet 指南
  2. 小学三年级计算机认识键盘教案,第8课 认识键盘大家庭 教案
  3. Anylogic学习--------选项列表
  4. html主题网站设计代码示例,网页设计参考:很不错的15个HTML网页表单设计实例
  5. libreoffice word转pdf时中文乱码问题解决
  6. python读取二进制文件_Python读写二进制文件
  7. Java基础编程经典练习题
  8. 静态代码编码安全审计: PHP源代码审计工具RIPS
  9. Python教学视频(二)输出语句的使用
  10. 如何安装matlab?官网下载详细教程