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

简介: 会议OA之我的会议(会议排座&送审)

前言:

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

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,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

4.4保存图片的步骤:

   // 1.接收图片存放的地址(字符串)

   // 2.生成图片,放到指定的路径下

   // 3.添加服务器

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

   // dirPath=E:/temp/images/T280/(这是保存下载图片的位置)

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

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

目录
相关文章
|
11月前
|
BI 数据安全/隐私保护 UED
以产品经理的角度去讲解原型图---会议OA项目
以产品经理的角度去讲解原型图---会议OA项目
108 1
|
6月前
|
SQL 存储 JavaScript
Layui之OA会议增删改查
Layui之OA会议增删改查
67 0
|
11月前
|
开发框架 JavaScript 前端开发
J2EE项目部署与发布(Windows版本)->会议OA单体项目Windows部署,spa前后端分离项目Windows部署
J2EE项目部署与发布(Windows版本)->会议OA单体项目Windows部署,spa前后端分离项目Windows部署
64 0
|
11月前
会议OA项目-其它页面->自定义组件应用,其它界面的布局
会议OA项目-其它页面->自定义组件应用,其它界面的布局
43 0
|
11月前
|
容器
会议OA项目-首页->flex弹性布局,轮播图后台数据获取及组件使用(后台数据交互mockjs),首页布局
会议OA项目-首页->flex弹性布局,轮播图后台数据获取及组件使用(后台数据交互mockjs),首页布局
79 0
|
11月前
|
JSON 小程序 前端开发
小程序之自定义组件 结合案例(会议OA的会议/投票管理及个人中心的搭建)详解 (4)
小程序之自定义组件 结合案例(会议OA的会议/投票管理及个人中心的搭建)详解 (4)
|
11月前
|
JSON 小程序 前端开发
小程序之实例会议OA的首页 (3)
小程序之实例会议OA的首页 (3)
|
11月前
|
JSON 小程序 JavaScript
微信小程序开发的OA会议之会议,个人中心的页面搭建及模板以及自定义组件
微信小程序开发的OA会议之会议,个人中心的页面搭建及模板以及自定义组件
73 0
|
11月前
|
JSON 小程序 前端开发
微信小程序----会议oa项目---首页
微信小程序----会议oa项目---首页
58 0
|
11月前
|
JavaScript Java
layui会议OA项目数据表格新增改查
layui会议OA项目数据表格新增改查
54 0