会议OA之我的会议(会议排座送审)

news2024/11/16 9:33:08

目录

前言:

2.我的会议:

2.1实现的特色功能:

 2.2思路:

2.3功能实现:

我的会议页面:myMeeting.jsp

myMeeting.js

Dao方法

在mvc中配置info信息

Meeting InfoAction

2.4会议排座的思路:

具体实现功能:

2.4.1.根据id查看的sql语句:

2.4.2.点击可以有一个弹窗的功能:

myMeeting.js层

弹窗层jsp

2.4.3.将查询的内容显示到页面上:

2.4.4.将已经画好的会议座位图,保存下来:

先分析思路:

4.1当我们的座位调整好了,点击下载,将生成的字符串传递到后台去。

4.2借助我们创建的工具类:propertiesUtil(用于存放路径/请求路径的),使用UUID随机去生成一个存放地址的路径,因为我们保存的路径不能带盘符的,在我们获取了路径上,我们还得写一个修改路径的方法,用于去保存更改的会议地址

4.3保存图片

4.4保存图片的步骤:


前言:

今天我给大家分享的是在我的会议功能实现,其中有两个特色的功能点是:实现会议排座,送审。

2.我的会议:

效果展示:

2.1实现的特色功能:

将不同登录人员看到不同的会议通知,具有会议排座

 2.2思路:

注意:这里我们要对sql语句进行优化:根据主持人,id降序查询

这里需要两张表:info,user表
需求:这里要显示审批人(不为空)新建user表通过字段auditor连接

当会议通知没有审批人时,我们也要显示出来:把会议信息表作为主表,用户表作为从表

 这里我们还要优化:将我们需要显示的字段列出来,
-- 时间的格式化,会议状态将数字转成中文
注意:这里我们时间转换后要起名字,因为我们返回的是map集合

-- 1
-- 根据主持人,id降序查询
-- 这里需要两张表:info,user表
-- 需求:这里要显示审批人(不为空)新建user表通过字段auditor连接
SELECT
	a.*,
	b.NAME zhuchirenname,
	c.NAME auditorname 
FROM
	t_oa_meeting_info a,
	t_oa_user b,
	t_oa_user c 
WHERE
	a.zhuchiren = b.id 
	AND a.auditor = c.id 
ORDER BY
	id DESC -- 	2
SELECT
	a.id,
	a.title,
	a.content,
	a.canyuze,
	a.liexize,
	a.zhuchiren,
	a.location,
	date_format( a.startTime, '%Y-%M-%D %H-%M-%S' )as startTime,
	date_format( a.endTime, '%Y-%M-%D %H-%M-%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
	'开启会议' 
	WHEN 7 THEN
	'结束会议' ELSE '其他' 
END 
	) mettingname,
	a.seatPic,
	a.remark,
	a.auditor,
	b.NAME zhuchirenname,
	c.NAME 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 
ORDER BY
	id DESC

--状态:0取消会议 1新建 2待审核 3驳回 4待开 5进行中 6开启投票 7结束会议,默认值为1 

2.3功能实现:

我的会议页面:myMeeting.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="static/js/meeting/myMeeting.js"></script>
<title>我的会议</title>
</head>
<style>
body {
	margin: 15px;
}
element.style{
	height:100%;
}
.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: 15px;">
		<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>

myMeeting.js

let layer, table, $, form;
let 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();
	});

});

//1.初始化数据表格
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 "尚未排座";
				else
					return "<img width='120px' src='" + d.seatPic + "'/>";
			}
		}, {
			field : 'auditName',
			title : '审批人',
			width : 120
		}, {
			field : '',
			title : '操作',
			width : 200,
			toolbar : '#tbar'
		}, ] ]
	});
}

//2.点击查询
function query() {
	table.reload('tb', {
		url : $("#ctx").val() + '/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);
		console.log("delee"+row.id);
		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();
		} else if (layEvent === "del") { //删除
			opendel(row.id);
		} else if (layEvent === "back") { //反馈详情
			openLayerFeedBack(row.id);
		} else {

		}
	});
}

//打开会议排座对话框
function open(id) {
	layer.open({
		type : 2, //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
		title : '会议排座', //对话框标题
		area : [ '560px', '640px' ], //宽高
		skin : 'layui-layer-rim', //样式类名
		content : 'jsp/meeting/seatPic.jsp?id=' + id, //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
	});
}
layui.use([ 'layer', 'table', 'jquery', 'form' ], function() {
	layer = layui.layer, table = layui.table, form = layui.form,
			$ = layui.jquery;

	initTable();

	//查询事件
	$('#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;
	});

});

//会议送审
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() + '/user.action', {
		'methodName' : 'queryUserAll'
	}, function(rs) {
		let data = rs.data;
		$.each(data, function(i, e) {
			$('#auditor').append(new Option(e.name, e.value));
		});
		//重新渲染
		form.render('select');
	});
}

//删除
function opendel(id) {
	//弹出对话框
	layer.open({
	    type: 1
	    ,title: '删除该会议' //不显示标题栏
	    ,closeBtn: false
	    ,area: '300px;'
	    ,shade: 0.8
	    ,id: 'LAY_layuipro' //设定一个id,防止重复弹出
	    ,btn: ['确定删除','我再想想']
	    ,btnAlign: 'c'
	    ,moveType: 1 //拖拽模式,0或者1
	    ,content: '<div style="padding: 50px; line-height: 22px; background-color: #393D49; color: #fff; font-weight: 300;">确定删除该会议?</div>'
	    ,yes:function(index,layero){
        	//调用子页面中提供的getData方法,快速获取子页面的form表单数据
            addMeetingFeedBack(id);
            layer.msg('删除成功');
          //关闭对话框
			layer.closeAll();
			//刷新列表
			query();
        },
        btn2:function(){
        	layer.closeAll();
        }
	  });
}

//对会议通知确定删除的
function addMeetingFeedBack(id){
	$.post($("#ctx").val() + '/info.action', {
		'methodName' : 'delnotesById',
		'id' : id,
	}, function(rs) {
		if (rs.success) {
			//关闭对话框
			layer.closeAll();
			//刷新列表
			query();
		} else {
			layer.msg(rs.msg, {
				icon : 5
			}, function() {
			});
		}
	}, 'json');
	return false;
}

//反馈详情
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: ['426px', '420px'],   //宽高
		        skin: 'layui-layer-rim',    //样式类名
		        content: $('#feedback'),   //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
		        btn:['关闭'],
		        yes:function(index,layero){
		        	layer.closeAll();
		        }
		    });
		}
	});
	}

Dao方法


	/**
	 * 显示我的会议
	 * 
	 * @param meetingInfo
	 * @param pageBean
	 * @return
	 * @throws Exception
	 */
	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作为主持人字段的条件
		if (StringUtils.isNotBlank(info.getZhuchiren())) {
			sql += " and zhuchiren=" + info.getZhuchiren();
		}
		// 按照会议ID降序排序
		sql += " order by a.id desc";
		return super.executeQuery(sql, pageBean);
	}

在mvc中配置info信息

	<action path="/info" type="com.lya.web.MeetingInfoAction">
	</action>

Meeting InfoAction

	@Override
	public MeetingInfo getModel() {
		// 注册一个转接器(用于时间date类型转页面显示)
//		ConvertUtils.register(new MysqlxDatatypes, Date.class);
		return info;
	}
//查看我的会议
	public String myInfos(HttpServletRequest req, HttpServletResponse resp) {
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			List<Map<String, Object>> infos = meetingInfoDao.myInfos(info, 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;
	}

/**
	 * 会议排座
	 * 下载图片
	 * 
	 * @param req
	 * @param resp
	 * @throws Exception 
	 */
	public void updateSeatPicById(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		// 1.接收图片存放的地址(字符串)
		// 2.生成图片,放到指定的路径下
		// 3.添加服务器
		// 4.将地址保存至数据库中
		// dirPath=E:/temp/images/t_oao/(这是保存下载图片的位置)

		// 1.接收图片存放的地址(字符串)
		String dirPath = PropertiesUtil.getValue("dirPath");// dirPath=E:/temp/images/t_oao/(这是保存下载图片的位置)

		// 接收浏览器请求的地址➡用于保存到数据库中
		String serverPath = PropertiesUtil.getValue("serverPath");

		// 保存图片前先去设置一个随机的路径字符将-换成空的因为这里我们保存路径是连着的
		String savepic = UUID.randomUUID().toString().replaceAll("-", "") + ".png";

		// 2.调用无参获取当前的保存的地址
		//info.getSeatPic();
		
		// 3.图片转换工具Baseutil中的generataImage并且重新保存路径
		Base64ImageUtils.GenerateImage(info.getSeatPic().toString().replaceAll("data:image/png;base64,", ""), dirPath+savepic);
		// 调用无参去重新保存的地址
		info.setSeatPic(serverPath+savepic);
		
		// 4.将地址保存至数据库中修改对应的字段
			int rs = meetingInfoDao.updateSeatPicById(info);
			if (rs > 0) {
				ResponseUtil.writeJson(resp, R.ok(200, "会议图片保存成功"));
			} else {
				ResponseUtil.writeJson(resp, R.error(0, "会议图片保存失败"));
			}
	}
	

2.4会议排座的思路:

1.查询出本场会议中的所有参与人员
2.需要完成在页面上元素的拖动功能,把对应的参会人员放在指定位置,如:重要的人就放在主位
3.将已经画好的会议座位图,保存下来,并且绑定到本次会议数据上去;
代码的实现顺序是2、1、3

2.页面上元素的拖动功能(特殊的功能)
    出发点:可以自己写、网上会有素材(在网上找到50%相似的资源。改成与业务相关的模板。)
    流程:先找网上素材,改动素材中的源码,变为自己想要的
    1.找网上素材,多找几个,挑出一个最适合的
    2.分析现有素材的不足
        ①、发现元素重叠,无法判定有几个人参会
        ②、元素块太小看不清
    3.修改现有素材的不足
    4.分析现有素材,怎么与业务需求进行关联(最重要的一步)
        其实需要做的是,查看源代码,分析图片生成的原因/步骤
        下载 按钮是绑定了一个方法,这个主要的方法是downloadFile方法
        downloadFile方法有两个参数:FileName、content,接下就是思考哪个参数与图片有关系
        结论:通过分析downloadFile方法中content参数就代表了那张图片-前端

        5.content需要传递到后台,并且生成图片,只有这样,我们才能通过代码决定图片存放在哪里
        ①、怎么传后台-$.post
            $.get(不行的,因为参数太大)    错
        ②、String content 字符串要转换成图片

具体实现功能:

2.4.1.根据id查看的sql语句:

SELECT * FROM t_oa_user where FIND_IN_SET(id,(SELECT CONCAT(canyuze,',',liexize,',',zhuchiren) uid FROM t_oa_meeting_info where id = 4))
	

2.4.2.点击可以有一个弹窗的功能:

myMeeting.js层

//打开会议排座对话框
function open(id){
	layer.open({
        type: 2,                    //layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)
        title: '会议排座',                   //对话框标题
        area: ['960px', '640px'],   //宽高
        skin: 'layui-layer-rim',    //样式类名
        content: 'jsp/meeting/seatPic.jsp?id='+id,                //弹出内容。可以传入普通的html内容,还可以指定DOM,更可以随着type的不同而不同
    });
}

弹窗层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>

2.4.3.将查询的内容显示到页面上:

3.1当我们弹出窗口时,我们通过初始化页面内容的ajax发送请求到user.action

 这里我们的数据还是未显示出来:通过开发者工具得到问题:

我们导入jquery插件,html的js就可以解决了

2.4.4.将已经画好的会议座位图,保存下来:

先分析思路:

1.当我们的座位调整好了,点击下载,将生成的字符串传递到后台去。

2.我们使用后台工具将得到的字符串生成一张图片,保存到指定的文件夹中。

3.添加服务器,硬盘,请求路径的映射,访问

4.将地址保存至数据库中

4.1当我们的座位调整好了,点击下载,将生成的字符串传递到后台去。

4.2借助我们创建的工具类:propertiesUtil(用于存放路径/请求路径的),使用UUID随机去生成一个存放地址的路径,因为我们保存的路径不能带盘符的,在我们获取了路径上,我们还得写一个修改路径的方法,用于去保存更改的会议地址

4.3保存图片

我们从前台获取到的数据是这样的

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABpAAAAQFCAYAAAC2F4sYAAAAAXNSR0IArs4c6QAAIABJREFUeF7s3QnU7mO9N/DL3tuwzXOZjiEZkxKhNBAaRIpEyqFBDnWInE719nY6TadDRUlKb6l4SZFoEA0qUlGRk8zZkXme2Wzvuu669/vsvZ/R87tu/5/9udc6y1rt+/49v//nd1/PWev6Ptf/v8Djjz/+ePEiQIAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAg8A+BBQRIvgsECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJDBQRIvg8ECBAgQIAAAQIECBAgQIAAAQIECBAgQIAAAQJzCAiQfCEIECBAgAABAgQIECBAgAABAgQIECBAgAABAgQESL4DBAgQIECAAAECBAgQIECAAAECBAgQIECAAAECIws4geTbQYAAAQIECBAgQIAAAQIECBAgQIAAAQIECBAgMIeAAMkXggABAgQIECBAgAABAgQIECBAgAABAgQIECBAQIDkO0CAAAECBAgQIECAAAECBAgQIECAAAECBAgQIDCywNgnkO66l1+0wNJLTL6iuUzecO4Kk52LmXRvJrUjc4mfS+uKk12LrftTnwABAgQIECBAgAABAgQIECBAgMB8IDC+AOniy+cDigFdYt0Y3Xjdyf+wOhMb45N37FeoM5nspnWdh7USNxNrJc4yU6WouWe6Zr0SIECAAAECBAgQIECAAAECBAgQ6KCAAGnQQ4naHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDolIEAa9DiiNkcFSLGTEyDFekZUs1YiFPPViJp7vivXMQECBAgQIECAAAECBAgQIECAAIFOCQiQBj2OqM1RAVLs5ARIsZ4R1ayVCMV8NaLmnu/KdUyAAAECBAgQIECAAAECBAgQIECgUwICpEGPI2pzVIAUOzkBUqxnRDVrJUIxX42ouee7ch0TIECAAAECBAgQIECAAAECBAgQ6JSAAGnQ44jaHBUgxU5OgBTrGVHNWolQzFcjau75rlzHBAgQIECAAAECBAgQIECAAAECBDol0MkA6YGHHirfPe/nZYlFFy0v32zLsuC0aZ1Cm1QzUZujT0KA9JPfX1DO+NUvyiG7vamstuLTJsXQuQ8LkDo3ktLxtfKHKy8vx5x+StlsvQ3K3q/YsUybOnVEwx9dcH45+Wc/LrttvW3vd5rXKAJRc4dMgAABAgQIECBAgAABAgQIECBAgMCkBAYaIF19w/Xl9rvvHrbhqVOnlPX+aY2y2CLTy1333VsOOfqIsuoKK5b37blPWWShhUa8yMdmzSpTp0yZFMJAPxy1OfokBEhn/OqX5cvfP60c8c5DyporrTxQtuY/TIDUnHjCP6DDa+We++8vH/zKMeXK6/9aPvPOg8u6q60+4uXV977/y5/v/e47fP+DyirLrzBhiv4HZj76aKlh1I233z6hGjXkes7a68zxmSdaa2iR4epOqLHh3hw190k3ogABAgQIECBAgAABAgQIECBAgACB+VtgoAHS0ad9uxx5yonDitfwqB9MjCdAevzxx8sv/3hR+dY5Py7v23PvsvI/NmUfmTmzXDrjL6X+N+pVg6x+/UnXjNocTRYg/f6Ky8oeH/nApPmGFjhwlz3K/jvvGlOzgwHSRVddUS647NKY6yulLDRtWtlhy63K8kstXR565JHyiRO+Wk766Vlh9fuFTvzgx8om66w3+bodXSs1tP7KD04vh3/zG2WrjZ5TNl//WWWBBRaY53pXWm65sv2mW5Qzf3t+OfSYI0d9b/3wM1ddrcy46cbyyKOPDmtX57fNJpv1QtyJzu3wfzmo7PiCF81RN+I7MFzdSQ8+au6TbkQBAgQIECBAgAABAgQIECBAgAABAvO3wEADpHprukcenTfY+eoPzyjnXPS7cQdIs2bNKt//9XnlI1//cu/E0gfe/Jay7fOe35tkP3w695KLwiYbukkatTkaGCD96dpryqdPPmFMrzvuuafMuPnGsv7qa456KqwWWmm55cu/7b5XWXKxxXp1BUhj8s7zhnri6z1fOGLiHxzhE0ND2odnPlKO+e6p5Y/XXDnsu+usL51xTVnz6auUVVaY2ImZg3fbs2y4xlqT77uDa6UG1987/9zyoa9+sdz/0IOjXuPu22xfdtt6u/Lh444tF199xZgeh+6+V+8WkZf99dph31vn91/7vrMXHs24+aby4X32LUsttnjvvdfdcnN5/7FHl2022bTs88odZ3/+kmuuKm877KNltACpBpUTPVXY/26G/m7sdx019zHFvYEAAQIECBAgQIAAAQIECBAgQIAAgdEEBhogjdRIPZlUb8s0nhNI9a/m61//17/Cr8/h+dA/v70895nrzj4BUG8X9d8nfb3cePttYZN/47avKC/bZLOYelGbo4EBUotwp57M+NT+B5WlF1+i59b/GcOdGuqfTBt6cuUvN9

4.4保存图片的步骤:

    // 1.接收图片存放的地址(字符串)
    // 2.生成图片,放到指定的路径下
    // 3.添加服务器
    // 4.将地址保存至数据库中
    // dirPath=E:/temp/images/T280/(这是保存下载图片的位置)

如果在写完保存图片的位置后,出现了这样的错误,可以去查看你自己电脑上是不是没有指定的文件目录。

总结:在会议排座中,比较难的地方在于当我们获取到了请求路径后,该如何去保存到指定的路径。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/807788.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第四代SHARC® ADSP-21479KBCZ-2A、ADSP-21479BSWZ-2A、ADSP-21479KSWZ-2A高性能DSP(数字信号处理器)

第四代SHARC Processors 现在内置低功耗浮点DSP产品&#xff08;ADSP-21478和ADSP-21479&#xff09;&#xff0c;可提供改进的性能、基于硬件的滤波器加速器、面向音频与应用的外设以及能够支持单芯片解决方案的新型存储器配置。所有器件都彼此引脚兼容&#xff0c;而且与以往…

【Android知识笔记】UI体系(二)

什么是UI线程? 常说的UI线程到底是哪个线程?UI线程一定是主线程吗? 下面先给出两条确定的结论: UI线程就是刷新UI所在的线程UI是单线程刷新的关于第二条为什么UI只能是单线程刷新的呢?道理很简单,因为多线程访问的话需要加锁,太卡,所以一般系统的UI框架都是采用单线程…

《重构的时机和方法》,值得程序员仔细研读的一本书

现有代码结构及框架沿用的比较久&#xff0c;持续在其上新增功能&#xff0c;可维护性与可扩展性变得越来越差&#xff0c;随着需求不断增加&#xff0c;现有代码变得越来越臃肿复杂&#xff0c;变得很难维护&#xff0c;甚至出现较严重的性能瓶颈&#xff0c;一般这个时候我们…

Thymeleaf入门

Thymeleaf是前端开发模板&#xff0c;springboot默认支持。前端模板用法大多数是类似的jsp、thymeleaf、vue.js都有while\for\if\switch等使用&#xff0c;页面组件化等。 1.前端模板区别 jsp是前后端完全不分离的&#xff0c;jsp页面写一堆Java逻辑。 thymeleaf好处是html改…

域名解析优先级

浏览器访问过程解析 访问网址——>首先在本地电脑看看hosts里面是否有域名对应IP地址&#xff0c;如何有直接访问对应IP&#xff0c; 如果没有&#xff0c;则联网询问DNS服务器&#xff08;一般网卡那边都配置了DNS服务器IP&#xff09; linux hosts 路径&#xff1a; w…

苍穹外卖-day07

苍穹外卖-day07 本项目学自黑马程序员的《苍穹外卖》项目&#xff0c;是瑞吉外卖的Plus版本 功能更多&#xff0c;更加丰富。 结合资料&#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…

中国气象局:到2030年,人工智能在气象应用领域取得世界领先地位

最近&#xff0c;中国气象局发布了《2023-2030年人工智能气象应用工作方案》&#xff0c;旨在加快推进国内人工智能气象应用技术体系建设&#xff0c;提升基础支撑能力&#xff0c;构建健全的人工智能气象应用政策环境&#xff0c;促进人工智能技术在气象观测、预报和服务领域的…

华为H12-821更新了32题,大家注意了

&#xff08;多选题&#xff09;使用堆叠和集群技术构建园区网的优势包括以下哪些项&#xff1f; A、业务中断时间大大减少 B、简化网络管理&#xff0c;降低网络部署规划的复杂度 C、可有效减少网络功耗 D、提高网络设备和链路的利用率 正确答案是…

教雅川学缠论02-K线

传统行情上的K线是下图中这样子的 而在缠论中K线是下面这样子的&#xff0c;它没有上影线和下影线 下图是武汉控股2023年7月的日K线 接下来我们将它转换成缠论K线&#xff08;画图累死我了&#xff09; K线理解了我们才能进行下一步&#xff0c;目前位置应该很好理解的

C++笔记之vector的resize()和clear()用法

C笔记之vector的resize()和clear()用法 code review! 文章目录 C笔记之vector的resize()和clear()用法1.resize()2.clear() 1.resize() 运行 2.clear() 运行

Python自动计算Excel数据指定范围内的区间最大值

本文介绍基于Python语言&#xff0c;基于Excel表格文件内某一列的数据&#xff0c;计算这一列数据在每一个指定数量的行的范围内&#xff08;例如每一个4行的范围内&#xff09;的区间最大值的方法。 已知我们现有一个.csv格式的Excel表格文件&#xff0c;其中有一列数据&#…

设计模式行为型——责任链模式

目录 什么是责任链模式 责任链模式的实现 责任链模式角色 责任链模式类图 责任链模式举例 责任链模式代码实现 责任链模式的特点 优点 缺点 使用场景 注意事项 实际应用 什么是责任链模式 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;又叫职…

【面试题】前端中 JS 发起的请求可以暂停吗?

这个问题非常有意思&#xff0c;我一看到就想了很多可以回复的答案&#xff0c;但是评论区太窄&#xff0c;就直接开一篇文章来写了。 审题 JS 发起的请求可以暂停吗&#xff1f;这一句话当中有两个概念需要明确&#xff0c;一是什么样的状态才能称之为 暂停&#xff1f;二是…

Appium+python自动化(三十五)- 命令启动appium之 appium服务命令行参数(超详解)

简介 前边介绍的都是通过按钮点击启动按钮来启动appium服务&#xff0c;有的小伙伴或者童鞋们乍一听可能不信&#xff0c;或者会问如何通过命令行启动appium服务呢&#xff1f;且听一一道来。 一睹为快 其实相当的简单&#xff0c;不看不知道&#xff0c;一看吓一跳&#xf…

TCP 三次握手四次挥手浅析

大家都知道传输层中的TCP协议是面向连接的&#xff0c;提供可靠的连接服务&#xff0c;其中最出名的就是三次握手和四次挥手。 一、三次握手 三次握手的交互过程如下 喜欢钻牛角尖的我在学习三次握手的时候就想到了几个问题&#xff1a;为什么三次握手是三次&#xff1f;不是…

shell脚本:使用mysqldump实现分库分表备份

一.什么是分库分表备份 分库分表备份是一种数据库备份策略&#xff0c;用于处理大型数据库系统中的数据分布和备份需求。当数据库的数据量非常大时&#xff0c;单个数据库可能无法满足性能和可扩展性的要求。为了解决这个问题&#xff0c;使用分库分表技术将数据库拆分成多个库…

解决eclipse 打开报错 An error has occurred. See the log file null.

解决eclipse 打开报错an error has ocurred. See the log file null 出现原因&#xff1a;安装了高版本的jdk,更换 jdk 版本&#xff0c;版本太高了。 解决方案&#xff1a;更改环境变量 改成 jkd 1.8

【RTT驱动框架分析00】-应用层函数调用流程-串口为例

应用层函数调用流程分析以-串口为例 1. rt_device_find调用流程 RTT内部有一个全局变量数组rt_object_container数组的数量就是 rt_object_info_type 内核对象的种类&#xff0c;其中包含一个RT_USING_DEVICE (设备的数据类型)&#xff0c;数组内部的每一个变量包含一个链表&…

Codeforces算法心得——A. Escalator Conversations

大家好&#xff0c;我是晴天学长&#xff0c;今天开始尝试一些外国的题目了&#xff0c;不得不说&#xff0c;创新性挺高的&#xff0c;然后是全英文&#xff0c;也可以练练英文的水平&#xff0c;后面我会持续的更新的&#xff01;加油&#xff01;&#x1f4aa;&#x1f4aa;…

新零售行业如何做会员管理和会员营销

蚓链数字化营销系统全渠道会员管理解决方案&#xff0c;线上线下统一管理&#xff0c;打造私域流量&#xff0c;微信、门店会员全渠道管理&#xff0c;打通私域流量池&#xff0c;实现裂变营销&#xff1a; 开启新零售之路&#xff0c;必然要摒弃原有的管理模式&#xff0c;大…