当前位置:网站首页>OA项目之我的会议(会议排座&送审)
OA项目之我的会议(会议排座&送审)
2022-08-11 05:35:00 【雨沐笙】
目录
一、会议排座插件介绍
1、会议排座背景
参会人员每个人位置是有讲究的,不是随便坐的;就像请人吃饭,请客的人是坐在主位;参会的人并且重要的人,他也会坐主位上面
2、需求分析
①、查询出本场会议中的所有参与人员
②、需要完成在页面上元素的拖动功能,把对应的参会人员放在指定位置,如:重要的人就放在主位
③、将已经画好的会议座位图,保存下来,并且绑定到本次会议数据上去
流程:
①找网上素材,多找几个,挑出一个最适合的
例如:
第一种:
效果:
第二种:
效果:
根据以上两种的效果的对比,可以知道第一种的效果,是比较贴近的。所以选择第一种。
③、插件改进
根据效果分析得知:①、元素重叠,无法判断有几人参加、②、元素模块太小看不清。
将position这个样式去掉后,可以看见每一个元素占一行。
改进后:
样式改进:
.tips {
/* position: absolute; */
background: #eee;
display: inline-block;
height: 60px;
width: 60px;
line-height: 60px;
text-align: center;
margin: 5px;
}
④、分析怎么和项目进行关联
当我们点击下载后,可以发现他默认下载的地址是在D:\TSBrowserDownloads
查看源代码,分析图片生成的原因/步骤
下载 按钮是绑定了一个方法,这个主要的方法是downloadFile方法
downloadFile方法有两个参数:FileName、content,接下就是思考哪个参数与图片有关系
结论:通过分析downloadFile方法中content参数就代表了那张图片-前端
⑤、content需要传递到后台,并且生成图片,只有这样,我们才能通过代码决定图片存放在哪里
①、怎么传后台-$.post
$.get(不行的,因为参数太大) 错
②、String content 字符串要转换成图片
二、会议参会用户数据初始化
seatPic.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<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) {
$('.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}';
param['methodName']='updateSeatPicById';
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(rs.msg,{icon:5},function(){});
}
},'json');
});
});
});
function initMeetingUsers(){
//http://localhost:8080/xxx/seatPic.jsp?id=12 -> ${param.id}
$.getJSON('${pageContext.request.contextPath }/user.action',{
'methodName':'queryUserByMeetingId',
'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>
将以下方法加入到myMeeting.js中
//打开会议排座对话框
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的不同而不同
});
}
修改部分:
原本是layer.msg("排座")给改为open(row.id);
效果:
效果中的abcd那些均为点击添加座位的效果
sql语句编写
-- 会议排座用户查询
select * from t_oa_meeting_info where id = 8
-- 期望结果
select * from t_oa_meeting_info where id in (1,2,3,4)
select concat(canyuze,',',liexize,',',zhuchiren) from t_oa_meeting_info where id = 8
select * from t_oa_meeting_info where id in (select concat(canyuze,',',liexize,',',zhuchiren) from t_oa_meeting_info where id = 8)
-- 实际结果
select * from t_oa_meeting_info where id in ('1,2,3,4,5')
-- FIND_IN_SET
-- 第一个参数:数据库列段
-- 第二个参数:是列段的条件
select * from t_oa_user WHERE FIND_IN_SET(id,(select concat(canyuze,',',liexize,',',zhuchiren) from t_oa_meeting_info where id = 8
))
效果:
将以下红框中的加入到项目中
将以下方法加入到UserAction中
public String queryUserByMeetingId(HttpServletRequest req, HttpServletResponse resp) {
try {
String parameter = req.getParameter("meetingId");
List<User> users = userDao.list(Integer.valueOf(parameter));
// 注意:layui中的数据表格的格式
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;
}
将以下方法加入到UserDao中
public List<User> list(Integer valueOf) 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 = "+valueOf+" ))";
return super.executeQuery(sql, User.class, null);
}
效果:
可以点击会议排座后,该会议参加的人员展现出来了
三、会议排座图片生产及展示
将以下方法放入MeetingInfoAction中
public String updateSeatPicById(HttpServletRequest req, HttpServletResponse resp) {
/*
* 1.接收前端页面传递到后台的图片对应的字符串
* 2.借助工具类将字符串生成一个图片,保存到配置文件中所配置的路径下
* 3.添加服务器硬盘与请求地址的映射,即可访问
* 4.将请求地址保存到数据库中
*/
try {
// E:/temp/images/T280/abcde.png
// 获取图片存放地址
String dirPath = PropertiesUtil.getValue("dirPath");
// 获取浏览器请求路径,为了后续保存到数据库
String serverPath = PropertiesUtil.getValue("serverPath");
// 随机生产一个图片名称
String fileName=UUID.randomUUID().toString().replaceAll("-", "")+".png";
meetingInfo.getSeatPic();//图字符串
Base64ImageUtils.GenerateImage(meetingInfo.getSeatPic()
.replaceAll("data:image/png;base64,", ""), dirPath+fileName);
// 将seatPic中内容修改为请求地址
meetingInfo.setSeatPic(serverPath+fileName);
// 修改会议排座数据库图片对应的数据库列段
int rs = meetingInfoDao.updateSeatPicById(meetingInfo);
if(rs>0) {
ResponseUtil.writeJson(resp, R.ok(200, "会议排座成功"));
}
else {
ResponseUtil.writeJson(resp, R.ok(0, "会议排座失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.ok(0, "会议排座失败"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
将以下方法放入MeetingInfoDao
// 设置会议排座图片
public int updateSeatPicById(MeetingInfo meetingInfo) throws Exception {
String sql=" update t_oa_meeting_info set seatPic=? where id=?";
return super.executeUpdate(sql, meetingInfo, new String[] {"seatPic","id"});
}
效果:
四、会议送审
前端:
myMeeting.js:
let layer,$,table,form;
var row;
layui.use(['jquery', 'layer', 'table','form'], function(){
layer = layui.layer
,$ = layui.jquery
,form = layui.form
,table = layui.table;
//初始化数据表格
initTable();
//绑定查询按钮的点击事件
$('#btn_search').click(function(){
query();
});
//绑定新增按钮的点击事件
$('#btn_add').click(function(){
row=null;
open('新增');
});
// 初始化审批人
initFormSelects();
});
//1.初始化数据表格
function initTable(){
table.render({ //执行渲染
elem: '#tb', //指定原始表格元素选择器(推荐id选择器)
// url: 'user.action?methodName=list', //请求地址
height: 340, //自定义高度
loading: false, //是否显示加载条(默认 true)
cols: [[ //设置表头
{field: 'id', title: '会议编号', width: 120},
{field: 'title', title: '会议标题', width: 120},
{field: 'location', title: '会议地点' , width: 140},
{field: 'startTime', title: '开始时间', width: 120},
{field: 'endTime', title: '结束时间', width: 120},
{field: 'meetingstate', title: '会议状态', width: 140},
{field: 'seatPic', title: '会议排座', width: 120,templet: function(d){
console.log(d.LAY_INDEX); //得到序号。一般不常用
console.log(d.LAY_COL); //得到当前列表头配置信息(layui 2.6.8 新增)。一般不常用
console.log(d)
//得到当前行数据,并拼接成自定义模板
return '<img src="'+d.seatPic+'">'}},
{field: 'auditorname', title: '审批人', width: 120},
{field: '', title: '操作', width: 220,toolbar:'#tbar'},
]]
});
//在页面中的<table>中必须配置lay-filter="tb_goods"属性才能触发属性!!!
table.on('tool(tb)', function (obj) {
row = obj.data;
if (obj.event == "seat") {
open(row.id);
}else if(obj.event == "send"){
// layer.msg("送审");
// 判断有是否已经排座
if(row.seatPic==null||row.seatPic==""){
layer.msg('先请完成会议排座,在进行送审操作!',function(){});
return false;
}
// 弹出层中的会议送审人员必须查询出来后台已经完成,在多功能下拉框中已经完成
//在打开送审页面之前,先请完成会议ID的赋值操作
$('#meetingId').val(row.id);
// 打卡会议送审HTML页面层
openLayerAudit();
}else if(obj.event == "del"){
layer.msg("取消会议");
}else if(obj.event == "back"){
layer.msg("反馈详情");
}else{
}
});
}
//2.点击查询
function query(){
// console.log($("#ctx").val());
table.reload('tb', {
url: 'info.action', //请求地址
method: 'POST', //请求方式,GET或者POST
loading: true, //是否显示加载条(默认 true)
page: true, //是否分页
where: { //设定异步数据接口的额外参数,任意设
'methodName':'myInfos',
'title':$('#title').val(),
'zhuchiren':$("#zhuchiren").val()
},
request: { //自定义分页请求参数名
pageName: 'page', //页码的参数名称,默认:page
limitName: 'rows' //每页数据量的参数名,默认:limit
}
});
}
//打开会议排座对话框
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 initFormSelects(){
$.getJSON($("#ctx").val()+'/user.action',{
'methodName':'queryUserAll'
},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 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的不同而不同
});
}
效果:
将以下方法加入到MeetingInfoDao
// 会议送审
public int updateAuditorById(MeetingInfo meetingInfo) throws Exception {
String sql=" update t_oa_meeting_info set auditor=?,state=2 where id=?";
return super.executeUpdate(sql, meetingInfo, new String[] {"auditor","id"});
}
将以下方法加入到 MeetingInfoAction
// 会议送审
public String updateAuditorById(HttpServletRequest req, HttpServletResponse resp) {
try {
// rs是sql语句执行的影响行数
int rs = meetingInfoDao.updateAuditorById(meetingInfo);
if(rs>0) {
ResponseUtil.writeJson(resp, R.ok(200, "会议送审成功"));
}
else {
ResponseUtil.writeJson(resp, R.ok(0, "会议送审失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.ok(0, "会议送审失败"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
将以下方法加入到myMeeting.js中
就该方法放到初始化审批人下
//送审 $('#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; });
//会议送审
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的不同而不同
});
}
效果暂时还要错误还在解决中
边栏推荐
- Project Notes - Take Notes
- (3) Software testing theory (understanding the knowledge of software defects)
- HCIA知识复习
- Threatless Technology-TVD Daily Vulnerability Intelligence-2022-8-1
- ansible批量安装zabbix-agent
- uboot设置默认的bootdelay
- ansible batch install zabbix-agent
- 空间点模式方法_一阶效应和二阶效应
- 利用opencv读取图片,重命名。
- 推荐一个好用的IDEA插件---Translation—中英互译
猜你喜欢
ETCD集群故障应急恢复-本地数据可用
AUTOMATION DAY07 (Ansible Vault, ordinary users use ansible)
HCIP BGP建邻实验
CLUSTER DAY03 (Ceph overview, the deployment of Ceph CLUSTER, Ceph block storage)
Memory debugging tools Electric Fence
ETCD单节点故障应急恢复
查看CPU和其他硬件温度的软件
lvm 多盘挂载,合并使用
HCIP BGP建邻、联邦、汇总实验
MoreFileRename batch file renaming tool
随机推荐
iptables入门
iptables 流量统计
iptables 使用脚本来管理规则
推荐一个好用的IDEA插件---Translation—中英互译
ETCD容器化搭建集群
MoreFileRename batch file renaming tool
AUTOMATION DAY07( Ansible Vault 、 普通用户使用ansible)
消息中间件
Arcgis小工具_实现重叠分析
HPC平台搭建
Sturges规则
树莓派设置静态IP地址
buildroot设置dhcp
Map Reduce
【LeetCode】306.累加数(思路+题解)
Es common operations and classical case
SECURITY DAY04 (Prometheus server, Prometheus monitored terminal, Grafana, monitoring database)
Solve the problem that port 8080 is occupied
arcgis填坑_4
Threatless Technology-TVD Daily Vulnerability Intelligence-2022-8-5