目录
5.4、 UserServlet--后端,查询会议对应的人员
前言
上一篇博客讲到了会议的发布功能,之后就是送给自己的上级进行审批了,但是此时有个新的功能插件,就是排座功能,本章就带大家一起来看看,我们如何实现排座功能吧
1、效果图演示
2、功能分析
- 我的会议查询
- 获取到当前用户的id,查询当前用户创建未结束的所有会议
- 会议排座功能
- 当我们点击送审时,需要先进行排座
- 首先,排座中包含个查询的功能,也就是查询当前会议参与的人员,然后展示在我们的排座界面中
- 点击下载,我们就会使用到我们的插件,来将元素进行截取,然后转化成一个对象,再将对象转化成一个数据,再利用工具类进行解码然后将其画成一张图片
- 最后,将其存到数据库,如果成功,关闭子页面,然后,关闭弹窗,至此整个功能完成
3、插件分享--html2canvas
html2canvas
是一个JavaScript库,用于将HTML元素转换为Canvas图像。具体的使用看我的源码如何操作吧,上面有具体的注释
简要介绍如下:
-
功能:
html2canvas
库的主要功能是将指定的HTML元素(包括其子元素)渲染为一个Canvas图像对象。 -
兼容性:
html2canvas
支持大多数现代浏览器,包括Chrome、Firefox、Safari等。 -
使用方法:
a. 引入
html2canvas
库:在HTML文件中引入html2canvas
库的JavaScript文件,可以通过直接下载并引用的方式,或者使用CDN来加载该库。b. 选择需要转换的HTML元素:通过选择器、ID或类名等方式选择需要转换的HTML元素。
c. 调用
html2canvas
函数:使用html2canvas(element [, options])
方法,传入需要转换的HTML元素作为参数,可选地传入一些配置选项来调整转换的行为。d. 处理结果:
html2canvas
方法会返回一个Promise对象,你可以使用.then()
方法来处理转换完成后的Canvas对象。e. 使用Canvas对象:将转换后的Canvas对象用于你的需求,比如将其显示在页面上、保存为图片等。
-
配置选项:
html2canvas
提供了一些配置选项,可以通过传入一个包含配置参数的对象来自定义转换的行为,例如设置转换的宽高、忽略某些元素等。
总的来说,html2canvas
是一个方便实用的库,可用于将HTML元素转换为Canvas图像,使得在前端将网页内容截图、生成图片等操作变得更加简单易用。
4、sql分析
- 当我们点击我的会议时,查询当前用户所有的会议,而当前用户,也就是自己发布会议的人,而这个人,在发布会议的时候就已经设定死了,就是登录的人,所以,只需根据会议的主持人字段来进行条件查询
SELECT a.id,a.title,a.content,a.canyuze,a.liexize,a.zhuchiren,b.`name`,a.location ,DATE_FORMAT(a.startTime,'%Y-%m-%d %H:%i:%s') as startTime ,DATE_FORMAT(a.endTime,'%Y-%m-%d %H:%i:%s') as endTime ,a.state ,(case a.state when 0 then '取消会议' when 1 then '新建' when 2 then '待审核' when 3 then '驳回' when 4 then '待开' when 5 then '进行中' when 6 then '开启投票' else '结束会' end ) as meetingState ,a.seatPic,a.remark,a.auditor,c.`name` as auditorName FROM t_oa_meeting_info a inner join t_oa_user b on a.zhuchiren = b.id left JOIN t_oa_user c on a.auditor = c.id where 1=1 and and zhuchiren = ?
- 点击排座功能时,需要将人员数据带到子界面,也就是排座界面进行遍历,所以可以将会议的id,带到子界面,根据id查询出所有的参会人员
String sql="select * from t_oa_user where FIND_IN_SET(id," + "(select concat(canyuze,',',liexize,',',zhuchiren) " + "from t_oa_meeting_info where id=?))";
这个SQL语句的意思是从表t_oa_user中选择所有行,其中id在另一个子查询中的结果集中找到。子查询是从表t_oa_meeting_info中选择一行,然后将该行的canyuze、liexize和zhuchiren列值连接成一个字符串。然后使用FIND_IN_SET函数来检查表t_oa_user的id是否在这个字符串中存在。该字符串使用逗号作为分隔符。这条SQL语句的目的是找到在t_oa_meeting_info表中特定id的记录中,指定的id是否存在于t_oa_user表中。
当用户点击确认排座,也就是下载了这个按钮的时候呢,就要修改会议的会议排座图片了
public int updatesetpic(MeetingInfo info) throws Exception { String sql="update t_oa_meeting_info set seatPic=? where id=?"; return super.executeUpdate(sql, info, new String[] {"seatPic","id"}); }
5、 源码展示
5.1、我的会议界面--Mymeeting.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="/common/public.jsp"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="static/js/meeting/myMeeting.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="zhuchiren" 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>
<!-- 对话框(送审) -->
<div id="audit" style="display:none;">
<form style="margin:20px 15px;" class="layui-form layui-form-pane" lay-filter="audit">
<div class="layui-inline">
<label class="layui-form-label">送审人</label>
<div class="layui-input-inline">
<input type="hidden" id="meetingId" value=""/>
<select id="auditor" style="poistion:relative;z-index:1000">
<option value="">---请选择---</option>
</select>
</div>
<div class="layui-input-inline">
<button id="btn_auditor" class="layui-btn">送审</button>
</div>
</div>
</form>
</div>
<!-- 对话框(反馈详情) -->
<div id="feedback" style="display:none;padding-left:15px; margin-bottom:60px;">
<fieldset class="layui-elem-field layui-field-title">
<legend>参会人员</legend>
</fieldset>
<blockquote class="layui-elem-quote" id="meeting_ok"></blockquote>
<fieldset class="layui-elem-field layui-field-title">
<legend>缺席人员</legend>
</fieldset>
<blockquote class="layui-elem-quote" id="meeting_no"></blockquote>
<fieldset class="layui-elem-field layui-field-title">
<legend>未读人员</legend>
</fieldset>
<blockquote class="layui-elem-quote" id="meeting_noread"></blockquote>
</div>
<script type="text/html" id="tbar">
{{# if(d.state==1 || d.state==3){ }}
<a class="layui-btn layui-btn-xs" lay-event="seat">会议排座</a>
<a class="layui-btn layui-btn-xs" lay-event="send">送审</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
{{# } }}
{{# if(d.state!=1 && d.state!=2 && d.state!=3){ }}
<a class="layui-btn layui-btn-xs" lay-event="back">反馈详情</a>
{{# } }}
</script>
</body>
</html>
5.2、我的会议js页面--Mymeeting.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();
query();
//查询事件
$('#btn_search').click(function(){
query();
});
//初始化审批人
initFormSelects();
//送审
$('#btn_auditor').click(function(){
$.post($("#ctx").val()+'/info.action',{
'methodName':'updateAuditorById',
'id':$('#meetingId').val(),
'auditor':$('#auditor').val()
},function(rs){
if(rs.success){
//关闭对话框
layer.closeAll();
//刷新列表
query();
}else{
layer.msg(rs.msg,{icon:5},function(){});
}
},'json');
return false;
});
});
//1.初始化数据表格
function initTable(){
table.render({ //执行渲染
// url: 'info.action?methodName=myInfos',
elem: '#tb', //指定原始表格元素选择器(推荐id选择器)
height: 700, //自定义高度
loading: false, //是否显示加载条(默认 true)
page: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 "尚未排座";
else
return "<img width='100px' height='60px' src='"+d.seatPic+"'/>";
}
},
{field: 'auditorName', title: '审批人', width: 120},
{field: '', title: '操作', width: 200,toolbar:'#tbar'},
]]
});
}
//2.点击查询
function query(){
table.reload('tb', {
url: 'info.action', //请求地址
method: 'POST', //请求方式,GET或者POST
loading: true, //是否显示加载条(默认 true)
page: true, //是否分页
where: { //设定异步数据接口的额外参数,任意设
'methodName':'myInfos',
'zhuchiren':$('#zhuchiren').val(),
'title':$('#title').val(),
},
request: { //自定义分页请求参数名
pageName: 'page', //页码的参数名称,默认:page
limitName: '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 === 'seat'){ //会议排座
open(row.id)
} else if(layEvent === 'send'){ //送审
//会议送审功能
// 判断是进行排座了
if(row.seatPic==null || row.seatPic==""){
layer.msg('先请完成会议排座,再进行送审操作!',function(){});
return false;
}
//在打开送审页面之前,先请完成会议ID的赋值操作
$('#meetingId').val(row.id);
openLayerAudit();
// 点击送审时,弹出层中会议送审人员查出来,也就是调用dao方法
// 打开会议送审页面层
} else if(layEvent==="back"){ //反馈详情
openLayerFeedBack(row.id);
} else {
layer.msg('删除');
}
});
}
//打开会议排座对话框
function open(id){
layer.open({
type: 2, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
title: '会议排座', //对话框标题
area: ['460px', '340px'], //宽高
skin: 'layui-layer-rim', //样式类名
content: $("#ctx").val()+'/jsp/meeting/seatPic.jsp?id='+id, //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
});
}
//会议送审
function openLayerAudit(){
//每次打开都对送审人进行初始化默认值设置
$('#auditor').val("");
//必须重新渲染
form.render('select');
//弹出对话框
layer.open({
type: 1, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
title:'会议送审',
area: ['426px', '140px'], //宽高
skin: 'layui-layer-rim', //样式类名
content: $('#audit'), //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
});
}
//初始化审批人
function initFormSelects(){
$.getJSON($("#ctx").val()+'/addmeeting.action',{
'methodName':'listtwo'
},function(rs){
console.log(rs);
let data=rs.data;
$.each(data,function(i,e){
$('#auditor').append(new Option(e.name,e.value));
});
//重新渲染
form.render('select');
});
}
//打开查看本会议的反馈详情
function openLayerFeedBack(id){
$.getJSON('feedBack.action',{
methodName:'queryMeetingBackByMeetingId',
meetingId:id
},function(data){
$('#meeting_ok').html("");
$('#meeting_no').html("");
$('#meeting_noread').html("");
if(data.success){
console.log(data.data);
$.each(data.data,function(i,e){
if(e.result==1)
$('#meeting_ok').html(e.names);
else if(e.result==2)
$('#meeting_no').html(e.names);
else
$('#meeting_noread').html(e.names);
});
//弹出对话框
layer.open({
type: 1, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
title:'反馈详情',
area: ['626px', '320px'], //宽高
skin: 'layui-layer-rim', //样式类名
content: $('#feedback'), //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
btn:['关闭'],
yes:function(index,layero){
layer.closeAll();
}
});
}
});
}
中间是会议审批、会议反馈的一些功能,后面会讲,我们只需要关乎会议排座的方法就行
5.3、会议排座jsp页面--seatPic.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<base href="${pageContext.request.contextPath }/"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="static/js/layui/css/layui.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="static/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="static/js/layui/layui.js"></script>
<script type="text/javascript" src="static/js/plugins/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: pink;
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;
//初始化会议排座:根据会议ID获取参会的所有人员的名字(主持人+参会人+列席人)
initMeetingUsers();
//绘制会议排座图片
$("#jie_input").on("click", function(event) {
//隐藏了会议排座div
$('.add').hide();
event.preventDefault();
//使用html2canvas库将id为"screen_body"的元素及其内容转换为Canvas对象。
html2canvas(document.getElementById("screen_body")).then(function(canvas) {
//将Canvas对象转换为数据URL,以便在上传或显示之前进行操作。
var dataUrl = canvas.toDataURL();
console.log(dataUrl);
//创建一个名为param的空对象,用于存储上传的参数
var param = {};
// 将数据URL赋值给param对象的属性"seatPic",这是要上传的会议排座图片
param['seatPic'] = dataUrl;
//动态获取传过来的参数id
param['id'] = '${param.id}';
// 将"updatesetpic"赋值给param对象的属性"methodName",表示要调用的方法名。应根据具体情况进行修改。
param['methodName']='updatesetpic';
//输出param对象的内容到控制台,以便调试和查看参数。
console.log(param);
//此处需要完成会议排座图片上传操作
$.post('${pageContext.request.contextPath }/info.action',param,function(rs){
if(rs.success){
//先得到当前iframe层的索引
var index = parent.layer.getFrameIndex(window.name);
//再执行关闭
parent.layer.close(index);
//调用父页面的刷新方法
parent.query();
}else{
//如果上传失败,则使用layer.msg()方法弹出错误消息,并显示错误图标。
layer.msg(rs.msg,{icon:5},function(){});
}
},'json');
});
});
});
function initMeetingUsers(){
//http://localhost:8080/xxx/seatPic.jsp?id=12 -> ${param.id}
//发送请求到useraction,然后查询当前会议的人员
$.getJSON('${pageContext.request.contextPath }/User.action',{
'methodName':'meetingpeople',
'meetingId':'${param.id}'
},function(rs){
console.log(rs);
let data=rs.data;
$.each(data,function(i,e){
//有几个人,就增加几个模块
$('#dan_input').val(e.name);
addDanMu();
});
});
}
//添加会议排座
function addDanMu() {
var dan = document.getElementById("dan_input").value;
if (dan == "") {
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;
}
}
</script>
</html>
会议排座界面的js也在这个页面中了,其中大家可能不懂的就是插件的使用了,我在这里也暂时解释不清楚,但是跟着我的代码走就行了,上面有我的注释,基本还是看的懂的,插件的底层我也还没有研究明白,
还有一个就是
param['id'] = '${param.id}';
关于这一行也有小伙伴不懂,这个$ { param.id }其实就是动态获取父页面传过来的参数id啦,回头去看我的会议js
![]()
在这一行其实就把会议的id带过来了
5.4、 UserServlet--后端,查询会议对应的人员
package Servlet;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.PageBean;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
import Dao.Userdao;
import Entity.User;
public class UserServlet extends ActionSupport implements ModelDriver<User>{
private User user= new User();
private PageBean page= new PageBean();
private Userdao ud= new Userdao();
//查询对应会议的人员
public String meetingpeople(HttpServletRequest req, HttpServletResponse resp) {
try {
String m= req.getParameter("meetingId");
PageBean pageBean = new PageBean();
List<User> users = ud.queryUserByMeetingId(Integer.valueOf(m));
// layui 的code 返回一定要是 0,不能是200,否者返回不了数据
ResponseUtil.writeJson(resp, R.ok(0, "会议用户数据初始化成功", users));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "查询失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
@Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
5.5、查询相关会议人员--Dao层
// 根据会议ID查询相关用户
public List<User> queryUserByMeetingId(Integer integer) throws Exception{
String sql="select * from t_oa_user where FIND_IN_SET(id,"
+ "(select concat(canyuze,',',liexize,',',zhuchiren) "
+ "from t_oa_meeting_info where id="+integer+"))";
return super.executeQuery(sql, User.class, null);
}
5.6、 我的会议后端--查询会议、排座图片下载
package Servlet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.Base64ImageUtils;
import com.zking.util.PageBean;
import com.zking.util.PropertiesUtil;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
import Dao.Meetingdao;
import Entity.MeetingInfo;
public class MeetinginfoServlet extends ActionSupport implements ModelDriver<MeetingInfo>{
private MeetingInfo m= new MeetingInfo();
Meetingdao md= new Meetingdao();
// 我的会议
public String myInfos(HttpServletRequest req, HttpServletResponse resp) {
try {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map<String, Object>> infos = md.myInfos(m, pageBean);
ResponseUtil.writeJson(resp, R.ok(0, "我的会议查询成功!!!", pageBean.getTotal(), infos));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "我的会议查询失败!!!"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
// 下载图片的方法
public String updatesetpic(HttpServletRequest req, HttpServletResponse resp) throws Exception {
// 获取到图片的存放地址
String dirPath = PropertiesUtil.getValue("dirPath");
// 获取浏览器请求路径,为了后续保存到数据库
String serverPath = PropertiesUtil.getValue("serverPath");
// 随机生成一个图片的名
String filename = UUID.randomUUID().toString().replaceAll("-", "")+ ".png";
// 将base64编码生成一张图片,保存在目录中
Base64ImageUtils.GenerateImage(m.getSeatPic().replaceAll("data:image/png;base64,", ""), dirPath+filename);
// 将seatpic中的内容改变成请求地址
m.setSeatPic(serverPath+filename);
// 修改会议排座中数据库图片对应的数据库列段
int r = md.updatesetpic(m);
if(r>0) {
ResponseUtil.writeJson(resp, R.ok(200, "会议排座成功"));
}else {
ResponseUtil.writeJson(resp, R.ok(0, "会议排座失败"));
}
return null;
}
// 我的审批
public String myAudit(HttpServletRequest req, HttpServletResponse resp) {
try {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map<String, Object>> infos = md.myAudit(m, pageBean);
ResponseUtil.writeJson(resp, R.ok(0, "我的审批查询成功!!!", pageBean.getTotal(), infos));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "我的审批查询失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
// 会议送审
public String updateAuditorById(HttpServletRequest req, HttpServletResponse resp) throws Exception {
int r = md.updateAuditorById(m);
if(r>0) {
ResponseUtil.writeJson(resp, R.ok(200, "会议送审成功"));
}else {
ResponseUtil.writeJson(resp, R.ok(0, "会议送审失败"));
}
return null;
}
// 待开会议、历史会议
public String queryMeetingInfoByState(HttpServletRequest req, HttpServletResponse resp) {
try {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map<String, Object>> infos = md.queryMeetingInfoByState(m, pageBean);
ResponseUtil.writeJson(resp, R.ok(0, "会议查询成功!!!", pageBean.getTotal(), infos));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "会议查询失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
// 所有会议
public String allInfos(HttpServletRequest req, HttpServletResponse resp) {
try {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map<String, Object>> infos = md.allInfos(m, pageBean);
ResponseUtil.writeJson(resp, R.ok(0, "会议查询成功!!!", pageBean.getTotal(), infos));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "会议查询失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
@Override
public MeetingInfo getModel() {
// TODO Auto-generated method stub
return m;
}
}
关于图片下载相信大家会有一些疑问,这里就来解释一下,关于PropertiesUtil
package com.zking.util; import java.io.IOException; import java.io.InputStream; import java.util.Properties; public class PropertiesUtil { public static String getValue(String key) throws IOException { Properties p = new Properties(); InputStream in = PropertiesUtil.class.getResourceAsStream("/resource.properties"); p.load(in); return p.getProperty(key); } }
配置文件
dirPath=D:/pic/picc/ serverPath=/upload/paizuo/ dirPathSign=D:/pic/picc/sign/ serverPathSign=/upload/sign/
大家可以看到,这个类通过流的方式获取到了配置文件,并且通过Properties类中的getProperty方法通过配置文件中的键获取值,从而拿到了配置文件中定义的本地路径已经服务器的访问路径,然后,通过Base64ImageUtils类来生成图片并且输出到了指定的本地目录,其中为什么getseatpic有值呢,因为前端传过来的时候,直接赋值给了会议对象(mvc框架中配置的)
package com.zking.util; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class Base64ImageUtils { public static String GetImageStr(String imgFilePath) {// 将图片文件转化为字节数组字符串,并对其进行Base64编码处理 byte[] data = null; // 读取图片字节数组 try { InputStream in = new FileInputStream(imgFilePath); data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } // 对字节数组Base64编码 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data);// 返回Base64编码过的字节数组字符串 } public static boolean GenerateImage(String imgStr, String imgFilePath) {// 对字节数组字符串进行Base64解码并生成图片 if (imgStr == null) // 图像数据为空 return false; BASE64Decoder decoder = new BASE64Decoder(); try { // Base64解码 byte[] bytes = decoder.decodeBuffer(imgStr); for (int i = 0; i < bytes.length; ++i) { if (bytes[i] < 0) {// 调整异常数据 bytes[i] += 256; } } // 生成jpeg图片 OutputStream out = new FileOutputStream(imgFilePath); out.write(bytes); out.flush(); out.close(); return true; } catch (Exception e) { return false; } } }
后端拿到了这个图像数据,去掉了data:image/png;base64,这个字符串,然后解码放入指定的目录,也就是我们从配置文件获取过来的本地目录dirpath,然后拼接上通过
UUID.randomUUID().toString().replaceAll("-", "")
生成一个随机的图片文件名,确保文件名的唯一性,并将其后缀设置为.png
。从而将图片成功下载
但是从常规企业级项目来说,我们服务区访问路径是不会带项目名字的,所以我们还需要配置服务器的访问数据库的图片路径,也就是从配置文件获取到的服务器访问路径拼接图片名称,最后我们将其设置到我们的对象中,将对象利用sql语句也就是dao方法进行修改,
5.7、配置tomcat服务器磁盘访问路径
上一个段落讲到了我们的图片实际路径和数据库的路径是不一样的,所以如果只做到这一步,服务器是找不到我们的图片的,所以我们就需要去配置我们服务器访问的映射路径了
1、
双击tomccat服务器
点击最底下的moudles
点击右侧第二个按钮
第一行输入的是我们配置文件中的磁盘目录
第二行就是我们服务器的访问目录,点击ok即可
这样我们的服务器,就可以通过我们配置的磁盘映射路径找到对应的图片了
5.8、我的会议dao层--会议排座图片修改,我的会议遍历
package Dao;
import java.util.List;
import java.util.Map;
import com.zking.util.BaseDao;
import com.zking.util.PageBean;
import com.zking.util.StringUtils;
import Entity.MeetingInfo;
import Entity.User;
public class Meetingdao extends BaseDao<MeetingInfo> {
// 通用的会议查询SQL语句,包含会议信息表数据,主持人姓名、审批人姓名、会议状态
private String getSQL() {
return "SELECT a.id,a.title,a.content,a.canyuze,a.liexize,a.zhuchiren,b.`name`,a.location\r\n" +
",DATE_FORMAT(a.startTime,'%Y-%m-%d %H:%i:%s') as startTime\r\n" +
",DATE_FORMAT(a.endTime,'%Y-%m-%d %H:%i:%s') as endTime\r\n" +
",a.state\r\n" +
",(case a.state\r\n" +
"when 0 then '取消会议'\r\n" +
"when 1 then '新建'\r\n" +
"when 2 then '待审核'\r\n" +
"when 3 then '驳回'\r\n" +
"when 4 then '待开'\r\n" +
"when 5 then '进行中'\r\n" +
"when 6 then '开启投票'\r\n" +
"else '结束会' end\r\n" +
") as meetingState\r\n" +
",a.seatPic,a.remark,a.auditor,c.`name` as auditorName\r\n" +
"FROM t_oa_meeting_info a\r\n" +
"inner join t_oa_user b on a.zhuchiren = b.id\r\n" +
"left JOIN t_oa_user c on a.auditor = c.id where 1=1 ";
}
// 我的会议
public List<Map<String, Object>> myInfos(MeetingInfo info, PageBean pageBean) throws Exception {
String sql = getSQL();
String title = info.getTitle();
if(StringUtils.isNotBlank(title)) {
sql += " and title like '%"+title+"%'";
}
//根据当前登陆用户ID作为主持人字段的条件
sql+=" and zhuchiren="+info.getZhuchiren();
//按照会议ID降序排序
sql+=" order by a.id desc";
System.out.println(sql);
return super.executeQuery(sql, pageBean);
}
// 根据会议ID更新会议的排座图片
public int updatesetpic(MeetingInfo info) throws Exception {
String sql="update t_oa_meeting_info set seatPic=? where id=?";
return super.executeUpdate(sql, info, new String[] {"seatPic","id"});
}
}
至此,我的会议排座功能就完毕了
6、总结
总的来说,会议排座这个功能还是比较吸引人的,对于一些政府的项目会经常用到,所以在此记录一下,再把流程分析一遍吧,
- 点击排座---
- 弹出子页面--遍历参会人员--点击下载,获取图片数据-----
- 传入后端--后端获取服务器访问路径,获取磁盘路径,创建随机图片名,通过工具类将图片数据解码然后传入指定的磁盘路径拼接图片名,设置数据库路径为服务器路径拼接图片名--
- 判断如果修改成功,抓取到父页面的iframe索引,然后通过索引关闭父页面的弹窗,调取父页面的刷新方法