02深入探究:OA项目会议发布、左侧菜单和动态选项卡的完美合盘

news2024/11/26 10:15:13

目录

  1.左侧导航

  导航一般指页面引导性频道集合,多以菜单的形式呈现,可应用于头部和侧边,是整个网页画龙点晴般的存在。  面包屑结构简单,支持自定义分隔符。    注:千万不要忘了加载 element模块。虽然大部分行为都是在加载完该模块后自动完成的,但一些交互操作,      如呼出二级菜单等,需借助element模块才能使用。

  参考地址:http://layui.org.cn/doc/element/nav.html

  2.导入数据表及无限级分类

  1) 数据导入(此步骤在第一次文章已完成)    2) 无限级分类:父亲找儿子的过程,将对应的儿子放在父亲下面,形成树结构。(递归算法)

  3.实现左侧菜单后台代码接口

  4.前端左侧菜单绑定 

  5.Tab选项卡

   Tab广泛应用于Web页面,因此我们也对其进行了良好的支持(简约风格、卡片风格、响应式Tab以及带删除的Tab等等)。Layui内置多种Tab风格,支持删除选项卡、并提供响应式支持。

     Tab分类

     参考地址:http://layui.org.cn/doc/element/tab.html

     1)Tab简约风格

     2)Tab卡片风格       

     3)响应式Tab        当容器的宽度不足以显示全部的选项时,即会自动出现展开图标。

     4)带删除的Tab

        与默认相比没有什么特别的结构,就是多了个属性 lay-allowClose="true"

       

                          5)动态Tab

     1)根据模块名称判断是否已经存在tab选项卡          $(".layui-tab-title li[lay-id='" + name + "']").length > 0

     2)切换到指定选项卡     element.tabChange('tabs', name);

     3)动态添加选项卡

     // 新增一个Tab项     element.tabAdd('tabs', {    title : name,    content : tabContent,    id : name     })     // 切换刷新     element.tabChange('tabs', name);

     注:tabs为tab选项卡的lay-filter=""     

附录一:什么是lay-filter事件过滤器。你可能会在很多地方看到他,他一般是用于监听特定的自定义事件。你可以把它看作是一个ID选择器

附录二:iframe

注:在index.jsp首页页面中请将更改成:不然会导致使用iframe动态打开页面的高度无法100%填充父容器;

附录三:如何隐藏tab第一个选项卡的删除图标

附录四:首页tab选项卡及body样式处理.layui-tab>.layui-tab-content{    padding:0px;}body,html{    padding:0px;    margin:0px;    overflow:hidden;}

一.会议发布

二.动态选项卡&左侧菜单

三.效果展示

左侧菜单

 动态选项卡

 会议发布界面


 

  1.左侧导航

  导航一般指页面引导性频道集合,多以菜单的形式呈现,可应用于头部和侧边,是整个网页画龙点晴般的存在。
  面包屑结构简单,支持自定义分隔符。
  
  注:千万不要忘了加载 element模块。虽然大部分行为都是在加载完该模块后自动完成的,但一些交互操作,
      如呼出二级菜单等,需借助element模块才能使用。

  参考地址:http://layui.org.cn/doc/element/nav.html

  2.导入数据表及无限级分类

  1) 数据导入(此步骤在第一次文章已完成)
  
  2) 无限级分类:父亲找儿子的过程,将对应的儿子放在父亲下面,形成树结构。(递归算法)

  3.实现左侧菜单后台代码接口

  4.前端左侧菜单绑定 


  5.Tab选项卡

   Tab广泛应用于Web页面,因此我们也对其进行了良好的支持(简约风格、卡片风格、响应式Tab以及带删除的Tab等等)。Layui内置多种Tab风格,支持删除选项卡、并提供响应式支持。

     Tab分类

     参考地址:http://layui.org.cn/doc/element/tab.html

     1)Tab简约风格

        <div class="layui-tab layui-tab-brief" lay-filter="docDemoTabBrief">
      <ul class="layui-tab-title">
        <li class="layui-this">网站设置</li>
        <li>用户管理</li>
        <li>权限分配</li>
        <li>商品管理</li>
        <li>订单管理</li>
      </ul>
      <div class="layui-tab-content"></div>
    </div>  

     2)Tab卡片风格

        <div class="layui-tab layui-tab-card">
      <ul class="layui-tab-title">
        <li class="layui-this">网站设置</li>
        <li>用户管理</li>
        <li>权限分配</li>
        <li>商品管理</li>
        <li>订单管理</li>
      </ul>
      <div class="layui-tab-content" style="height: 100px;">
        <div class="layui-tab-item layui-show">1</div>
        <div class="layui-tab-item">2</div>
        <div class="layui-tab-item">3</div>
        <div class="layui-tab-item">4</div>
        <div class="layui-tab-item">5</div>
        <div class="layui-tab-item">6</div>
      </div>
    </div>

     3)响应式Tab
    
    当容器的宽度不足以显示全部的选项时,即会自动出现展开图标。

     4)带删除的Tab

        与默认相比没有什么特别的结构,就是多了个属性 lay-allowClose="true"

        <div class="layui-tab" lay-allowClose="true">
      <ul class="layui-tab-title">
        <li class="layui-this">网站设置</li>
        <li>用户基本管理</li>
        <li>权限分配</li>
        <li>全部历史商品管理文字长一点试试</li>
        <li>订单管理</li>
      </ul>
      <div class="layui-tab-content">
        <div class="layui-tab-item layui-show">1</div>
        <div class="layui-tab-item">2</div>
        <div class="layui-tab-item">3</div>
        <div class="layui-tab-item">4</div>
        <div class="layui-tab-item">5</div>
        <div class="layui-tab-item">6</div>
      </div>
    </div>
     
     5)动态Tab

     1)根据模块名称判断是否已经存在tab选项卡
     
     $(".layui-tab-title li[lay-id='" + name + "']").length > 0

     2)切换到指定选项卡
     element.tabChange('tabs', name);

     3)动态添加选项卡

     // 新增一个Tab项
     element.tabAdd('tabs', {
    title : name,
    content : tabContent,
    id : name
     })
     // 切换刷新
     element.tabChange('tabs', name);

     注:tabs为tab选项卡的lay-filter=""
     <div class="layui-tab" lay-filter="tabs" lay-allowClose="true" style="margin:0px;">


附录一:什么是lay-filter
事件过滤器。你可能会在很多地方看到他,他一般是用于监听特定的自定义事件。你可以把它看作是一个ID选择器

附录二:iframe
<iframe frameborder='0' src='"+url+"' scrolling='auto' style='width:100%;height:100%;'></iframe>

注:在index.jsp首页页面中请将
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
更改成:
<!DOCTYPE>
不然会导致使用iframe动态打开页面的高度无法100%填充父容器

附录三:如何隐藏tab第一个选项卡的删除图标
<style>
    .layui-tab-title>li:first-child>i{
        display:none;
    }
</style>

附录四:首页tab选项卡及body样式处理
.layui-tab>.layui-tab-content{
    padding:0px;
}
body,html{
    padding:0px;
    margin:0px;
    overflow:hidden;
}

一.会议发布

初始化会议发布页面

addMeeting.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<%@include file="/common/head.jsp" %>
<style type="text/css">
.layui-form  {
	margin: 10px 10px 30px 10px;
}
</style>

</head>
<body>

	<form class="layui-form layui-form-pane" lay-filter="meetinginfo" >
	
		<div class="layui-form-item">
		    <label class="layui-form-label">会议标题</label>
		    <div class="layui-input-block">
		      <input type="text" name="title" autocomplete="off" placeholder="请输入会议标题" class="layui-input">
		    </div>
		</div>
		
		<div class="layui-form-item layui-form-text">
		    <label class="layui-form-label">会议内容</label>
		    <div class="layui-input-block">
		      <textarea placeholder="请输入内容" name="content" class="layui-textarea"></textarea>
		    </div>
	  	</div>
	  	
	  	<div class="layui-form-item">
		    <label class="layui-form-label">参与者</label>
		    <div class="layui-input-block">
		      	<select name="canyuze" xm-select="canyuze">
			        <option value="" disabled="disabled">--请选择--</option>
      			</select>
		    </div>
	  	</div>
	  	
	  	<div class="layui-form-item">
		    <label class="layui-form-label">列席者</label>
		    <div class="layui-input-block">
		      	<select name="liexize" xm-select="liexize">
			        <option value="" disabled="disabled">--请选择--</option>
			        
      			</select>
		    </div>
	  	</div>
	  	
	  	<div class="layui-form-item">
		    <label class="layui-form-label">主持人员</label>
		    <div class="layui-input-block">
		      <input type="text"  readonly="readonly" value="${sessionScope.user.name}" placeholder="会议标题" class="layui-input">
		   	  <input type="hidden" name="zhuchiren" readonly="readonly" value="${sessionScope.user.id}">
		    </div>
		</div>
		
		<div class="layui-form-item">
		    <label class="layui-form-label">会议地点</label>
		    <div class="layui-input-block">
		      <input type="text" name="location" placeholder="请输入会议地点" class="layui-input">
		    </div>
		</div>
		
		<div class="layui-form-item">
	        <label class="layui-form-label">会议时间</label>
	        <div class="layui-input-block">
	        	<input type="text" class="layui-input" id="meetingdt" name="meetingDt" placeholder="请输入会议时间">
	        </div>
	    </div>
	    
	    <div class="layui-form-item layui-form-text">
		    <label class="layui-form-label">备注</label>
		    <div class="layui-input-block">
		      <textarea placeholder="请输入备注" name="remark" class="layui-textarea"></textarea>
		    </div>
	  	</div>
	    
	    <div class="layui-form-item" style="text-align:center;">
		   <button type="button" lay-submit="" lay-filter="meetinginfo" class="layui-btn layui-btn-normal">保存</button>
		   <button type="reset" class="layui-btn">重置</button>
		</div>
	  	
	</form>
</body>
</html>

addMeeting.js

<script>
let formSelects = null;
let laydate = null;
let form = null;
let $ = null;
layui.use(['jquery', 'formSelects','laydate','form'], function() {
	formSelects = layui.formSelects;
	laydate = layui.laydate;
	form = layui.form;
	$ = layui.$;
	
	//参与者多选
	formSelects.btns('canyuze', ['select', 'remove', 'reverse']);
	formSelects.data('canyuze', 'server', {
	    url: ctx + '/meetinginfoAction.action?methodName=listMeetingMember'
	});
	
	//列席者多选
	formSelects.btns('liexize', ['select', 'remove', 'reverse']);
	formSelects.data('liexize', 'server', {
	    url: ctx + '/meetinginfoAction.action?methodName=listMeetingMember'
	});
	
	//日期时间范围
    laydate.render({
	    elem: '#meetingdt',
	    type: 'datetime',
	    range: '至'
    });
	
	//提交表单
    form.on('submit(meetinginfo)', function(data) {
    	//console.log(data);
    	let dt = data.field.meetingDt;
    	let start = dt.split("至")[0].trim();
    	let end = dt.split("至")[1].trim();
    	data.field["startTime"] = start;
    	data.field["endTime"] = end;
    	//console.log(data);
    	
    	$.ajax({
    		url: ctx + '/meetinginfoAction.action?methodName=addMeetinginfo',
    		data: data.field,
    		type: 'post',
    		dataType: 'json',
    		success: function(resp) {
    			layer.msg(resp.msg);
    		}
    	}) 
    });
	
});
</script>

会议发布功能实现

IMeetingInfoDao.java

package com.zking.oa.dao;

import java.util.List;
import java.util.Map;

import org.lisen.mvc.util.PageBean;

import com.zking.oa.model.MeetingMember;
import com.zking.oa.model.Meetinginfo;
import com.zking.oa.model.User;

public interface IMeetinginfoDao {

	List<MeetingMember> listMeetingMember();

	/**
	 * 增加
	 * @param meetinginfo
	 */
	void addMeetinginfo(Meetinginfo meetinginfo);

	/**
	 * 获取我的会议信息
	 * @param meetingInfo
	 * @param pageBean
	 * @return
	 */
	List<Map<String,Object>> listMeetingInfo(Meetinginfo meetingInfo, PageBean pageBean);

	
	List<User> listMeetingMembersById(Integer id);

	void updateSeatPicById(Meetinginfo meetingInfo);

	/**
	 * 更新送审信息
	 * @param meetingInfo
	 */
	void sendAudit(Meetinginfo meetingInfo);

	/**
	 * 更新审核记录到指定装
	 * @param meetingInfo
	 */
	void updateMeetingState(Meetinginfo meetingInfo);

	/**
	 * 查询与当前登录用户相关的状态为待开的会议信息
	 * @param uid
	 * @param pageBean
	 * @return
	 */
	List<Meetinginfo> listRelatedMeetingInfoByUserId(Integer uid,String title,Integer state, PageBean pageBean);

	/**
	 * 历史会议
	 * @param uid
	 * @param title
	 * @param state
	 * @param pageBean
	 * @return
	 */
	List<Meetinginfo> listRelatedMeetingInfoByUserId2(Integer uid, String title, Integer state, PageBean pageBean);




}

MeetingInfoDao.java

package com.zking.oa.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.lisen.mvc.util.DbTemplate;
import org.lisen.mvc.util.PageBean;

import com.mysql.cj.util.StringUtils;
import com.zking.oa.model.MeetingMember;
import com.zking.oa.model.Meetinginfo;
import com.zking.oa.model.User;
import com.zking.oa.util.BaseDao;
import com.zking.oa.util.CommonUtils;


@SuppressWarnings("unchecked")
public class MeetinginfoDao extends BaseDao implements IMeetinginfoDao {

	@Override
	public List<MeetingMember> listMeetingMember(){
		
		String sql="select name,id from t_oa_user";
	
		return DbTemplate.query(sql, MeetingMember.class);
	}
	
	@Override
	public void addMeetinginfo(Meetinginfo meetinginfo) {
		DbTemplate.save(meetinginfo);
	}
	
	/**
	 * 封装sql:作为我的会议、我的审批、会议通知、代开会议、
	 * 历史会议级所有会议的基础SQL语句
	 * @return
	 */
	private String getSql() {
		return "SELECT \r\n" + 
				"m.id,m.title,m.content,m.canyuze,m.zhuchiren,m.liexize,u.name\r\n" + 
				",m.location,\r\n" + 
				"DATE_FORMAT(m.startTime,'%Y-%m-%d %H:%i:%s') as startTime,\r\n" + 
				"DATE_FORMAT(m.endTime,'%Y-%m-%d %H:%i:%s') as endTime,\r\n" + 
				"(case m.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,m.state,m.seatPic,m.remark,m.auditor,\r\n" + 
				"u2.name as auditName\r\n" + 
				"from \r\n" + 
				"t_oa_meeting_info m inner join t_oa_user u\r\n" + 
				"on m.zhuchiren=u.id\r\n" + 
				"LEFT JOIN t_oa_user u2\r\n" + 
				"on u2.id=m.auditor where 1=1 ";
	}
	
	@Override
	public List<Map<String,Object>> listMeetingInfo(Meetinginfo meetingInfo, PageBean pageBean) {
		
		String sql=this.getSql();
		//按照会议标题模糊查询
		if(!StringUtils.isNullOrEmpty(meetingInfo.getTitle())) 
			sql+=" and title like '%"+meetingInfo.getTitle()+"%'";
		//按照 当前登录ID作为主持人字段条件
		sql+=" and zhuchiren="+meetingInfo.getZhuchiren();
		//sql +=" and state="+meetingInfo.getState();
		//按照会议ID降序排序
		sql+=" order by m.id desc";
		return super.executeQuery(sql, pageBean, new convert<Map<String, Object>>() {
			@Override
			public List<Map<String, Object>> forEach(ResultSet rs) throws SQLException, Exception {
				return CommonUtils.toList(rs);
			}
		});
	}
	
	@Override
	public void updateMeetingState(Meetinginfo meetingInfo) {
		String sql = "update t_oa_meeting_info set state = ? where id = ?";
		DbTemplate.update(sql, new Object[] {meetingInfo.getState(), meetingInfo.getId()});
	}
	
	@Override
public List<Meetinginfo> listRelatedMeetingInfoByUserId(Integer uid, String title,Integer state,PageBean pageBean) {
		
		String sql = "SELECT t1.id,t1.auditor,t1.canyuze,t1.liexize,t1.content,DATE_FORMAT(t1.endTime,'%Y-%m-%d %H:%i:%s') as endTime,t1.fujian,\r\n" + 
				"       t1.location,t1.seatPic,DATE_FORMAT(t1.startTime,'%Y-%m-%d %H:%i:%s') as startTime,"
				+ "(case t1.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,"
				+ "t1.title,t1.zhuchiren\r\n" + 
				"   FROM t_oa_meeting_info t1 INNER JOIN \r\n" + 
				"	(SELECT a.id,\r\n" + 
				"	        SUBSTRING_INDEX(SUBSTRING_INDEX( a.canyuze, ',', b.help_topic_id + 1 ), ',',- 1) AS userid \r\n" + 
				"	   FROM t_oa_meeting_info AS a\r\n" + 
				"		JOIN mysql.help_topic AS b ON b.help_topic_id < ( LENGTH( a.canyuze ) - LENGTH( REPLACE ( a.canyuze, ',', '' ) ) + 1 )\r\n" + 
				"          UNION ALL\r\n" + 
				"	  SELECT a.id,\r\n" + 
				"		 SUBSTRING_INDEX(SUBSTRING_INDEX( a.liexize, ',', b.help_topic_id + 1 ), ',',- 1) AS userid \r\n" + 
				"	     FROM t_oa_meeting_info AS a\r\n" + 
				"		  JOIN mysql.help_topic AS b ON b.help_topic_id < ( LENGTH( a.liexize ) - LENGTH( REPLACE ( a.liexize, ',', '' ) ) + 1 )\r\n" + 
				"         ) tmp ON t1.id = tmp.id\r\n" + 
				"WHERE tmp.userid = "+uid+" and t1.state ="+state;
		
		if(title!=null&&!"".equals(title)) {
			sql+=" and  t1.title like '"+title+"%'";
		}
		
		return super.executeQuery(sql, pageBean, new convert<Map<String, Object>>() {
			@Override
			public List<Map<String, Object>> forEach(ResultSet rs) throws SQLException, Exception {
				return CommonUtils.toList(rs);
			}
		});
	}
	
	@Override
	public List<Meetinginfo> listRelatedMeetingInfoByUserId2(Integer uid, String title,Integer state,PageBean pageBean) {
		
		String sql = "SELECT t1.id,t1.auditor,t1.canyuze,t1.liexize,t1.content,DATE_FORMAT(t1.endTime,'%Y-%m-%d %H:%i:%s') as endTime,t1.fujian,\r\n" + 
				"       t1.location,t1.seatPic,DATE_FORMAT(t1.startTime,'%Y-%m-%d %H:%i:%s') as startTime,(case t1.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,t1.title,t1.zhuchiren\r\n" + 
				"   FROM t_oa_meeting_info t1\r\n" + 
				"WHERE t1.state=7 and FIND_IN_SET("+uid+",concat(t1.zhuchiren,',',t1.canyuze,',',t1.liexize))";
		
		if(title!=null&&!"".equals(title)) {
			sql+=" and  t1.title like '"+title+"%'";
		}
		
		return super.executeQuery(sql, pageBean, new convert<Map<String, Object>>() {
			@Override
			public List<Map<String, Object>> forEach(ResultSet rs) throws SQLException, Exception {
				return CommonUtils.toList(rs);
			}
		});
	}

	@Override
	public List<User> listMeetingMembersById(Integer id) {
		String sql = "SELECT id,name,loginName,pwd,rid "
				+ "FROM t_oa_user id "
				+ "WHERE FIND_IN_SET(id, (SELECT CONCAT(t.canyuze,',',t.liexize,',',t.zhuchiren) FROM t_oa_meeting_info t WHERE t.id = ?))";
		
		return DbTemplate.query(sql, new Object[] {id}, User.class);
	}
	
	@Override
	public void updateSeatPicById(Meetinginfo meetingInfo) {
		String sql = "UPDATE t_oa_meeting_info SET seatPic = ? WHERE id = ? ";
		DbTemplate.update(sql, new Object[] {meetingInfo.getSeatPic(), meetingInfo.getId()});
	}
	
	@Override
	public void sendAudit(Meetinginfo meetingInfo) {
		String sql = "update t_oa_meeting_info set state = 2, auditor=? where id = ?";
		DbTemplate.update(sql, new Object[] {meetingInfo.getAuditor(), meetingInfo.getId()});
	}
	
	
	
	
	
	
	public static void main(String[] args) {
		MeetinginfoDao md = new MeetinginfoDao();
		Meetinginfo info = new Meetinginfo();
//		info.setZhuchiren("1");
//		List<Map<String,Object>> listMeetingInfo = md.listMeetingInfo(info, new PageBean());
//		System.out.println(listMeetingInfo);
		//List<Meetinginfo> listRelatedMeetingInfoByUserId = md.listRelatedMeetingInfoByUserId(1, 4, new PageBean());
		//System.out.println(listRelatedMeetingInfoByUserId);
	
}
}

MeetingInfoAction.java

package com.zking.oa.action;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.lisen.mvc.framework.AbstractDispatchAction;
import org.lisen.mvc.framework.ModelDrive;
import org.lisen.mvc.util.PageBean;

import com.zking.oa.dao.MeetinginfoDao;
import com.zking.oa.model.MeetingMember;
import com.zking.oa.model.Meetinginfo;
import com.zking.oa.model.User;
import com.zking.oa.service.IMeetinginfoService;
import com.zking.oa.service.MeetinginfoService;
import com.zking.oa.util.Base64ImageUtils;
import com.zking.oa.util.CommonUtil;



public class MeetinginfoAction extends AbstractDispatchAction implements ModelDrive{

	private Meetinginfo meetinginfo = new Meetinginfo();
	
	private IMeetinginfoService service = new MeetinginfoService();

		
	@Override
	public Object getModel() {
		//日期转换器
		DateConverter converter = new DateConverter();
		converter.setPattern("yyyy-MM-dd HH:mm:ss");
		ConvertUtils.register(converter, Date.class);
		return meetinginfo;
	}
	
	
	public void listMeetingMember(HttpServletRequest req,HttpServletResponse resp) {
		try {
			List<MeetingMember> list = service.listMeetingMember();
			CommonUtil.sendResponse(0, "成功", list,resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "获取会议参与人员失败", resp);
		}
	
	}
	
	public void addMeetinginfo(HttpServletRequest req,HttpServletResponse resp) {
		try {
			 service.addMeetinginfo(meetinginfo);
			CommonUtil.sendResponse(0, "会议发布成功", resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "会议发布失败", resp);
		}
	
	}

	/**
	 * 获取以当前用户为主持人的会议信息,即我的会议功能
	 * @param req
	 * @param resp
	 */
	public void listMeetingInfo(HttpServletRequest req, HttpServletResponse resp) {
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			
			//从session中获取当前用户放入条件
			User user = (User)req.getSession().getAttribute("user");
			meetinginfo.setZhuchiren(user.getId().toString());
			
			List<Map<String,Object>> list = service.listMeetingInfo(meetinginfo, pageBean);
			CommonUtil.sendResponse(0, "会议信息查询成功", pageBean.getTotal(), list, resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "会议信息查询失败",resp);
		}
		
	}
	
	
	/**
	 * 查询与当前登录用户相关的状态为待开的会议信息
	 * @return
	 */
	public void listRelatedMeetingInfoByUserId(HttpServletRequest req, HttpServletResponse resp) {
		MeetinginfoDao ma=new MeetinginfoDao();
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			
			//从session中获取当前用户,并且只查询待审记录
			User user = (User)req.getSession().getAttribute("user");
			List<Meetinginfo> list = ma.listRelatedMeetingInfoByUserId(user.getId(),meetinginfo.getTitle(),4, pageBean);
			CommonUtil.sendResponse(0, "会议信息查询成功", pageBean.getTotal(), list, resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "会议信息查询失败",resp);
		}
		
	}
	
	
	/**
	 * 历史会议
	 * @return
	 */
	public void listRelatedMeetingInfoNotify(HttpServletRequest req, HttpServletResponse resp) {
		MeetinginfoDao ma=new MeetinginfoDao();
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			
			//从session中获取当前用户,并且只查询待审记录
			User user = (User)req.getSession().getAttribute("user");
			List<Meetinginfo> list = ma.listRelatedMeetingInfoByUserId2(user.getId(),meetinginfo.getTitle(),7, pageBean);
			CommonUtil.sendResponse(0, "历史会议查询成功", pageBean.getTotal(), list, resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "历史会议查询失败",resp);
		}
		
	}
	
	/**
	 * 通过会议的Id获取与本次会议相关的参与人员信息
	 * @param req
	 * @param resp
	 */
	public void listMeetingMemberById(HttpServletRequest req, HttpServletResponse resp) {
		
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			List<User> list = service.listMeetingMembersById(meetinginfo.getId().intValue());
			CommonUtil.sendResponse(0, "会议信息查询成功", pageBean.getTotal(), list, resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "会议信息查询失败",resp);
		}
		
	}
	
	/**
	 * 保存排座图片到服务器的指定目录,并更新相关会议信息的排座图片字段
	 * @param req
	 * @param resp
	 */
	public void addArrangeSeat(HttpServletRequest req, HttpServletResponse resp) {
		
		try {
			String fName = UUID.randomUUID().toString().replace("-", "").concat(".jpg");
			String path = "D:\\temp\\images\\seatPic\\uploads\\" + fName;
			String base64Image = meetinginfo.getSeatPic().replace("data:image/png;base64,", "");
			//生成图片
			Base64ImageUtils.GenerateImage(base64Image, path);
			
			//更新会议信息表中的排座信息,需要设置tomcat的设置增加一个扩展web模块
			meetinginfo.setSeatPic("/uploads/"+fName);
			service.updateSeatPicById(meetinginfo);
			CommonUtil.sendResponse(0, "排座成功", resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "排座失败", resp);
		}
		
	}
	
	
	/**
	 * 我的审核,会议的审核人员是当前登录的用户,且会议的状态为待审
	 * @param req
	 * @param resp
	 */
	public void listMyAuditMeetingInfo(HttpServletRequest req, HttpServletResponse resp) {
		
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			
			//从session中获取当前用户,并且只查询待审记录
			User user = (User)req.getSession().getAttribute("user");
			meetinginfo.setAuditor(user.getId().toString());
			meetinginfo.setState(2);
			
			List<Map<String,Object>> list = service.listMeetingInfo(meetinginfo, pageBean);
			CommonUtil.sendResponse(0, "会议信息查询成功", pageBean.getTotal(), list, resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "会议信息查询失败",resp);
		}
		
	}
	
	/**
	 * 会议送审,能够送审的前提是该会议已经排座,否则不能送审,此外
	 * 对于审核通过,结束,取消,进行中等状态的会议不能执行送审
	 * @param rep
	 * @param resp
	 */
	public void sendAudit(HttpServletRequest rep, HttpServletResponse resp) {
		
		try {
			service.sendAudit(meetinginfo);
			CommonUtil.sendResponse(0, "送审成功", resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtil.sendResponse(-1, "送审失败", resp);
		}
		
	}
	
	
	

}

二.动态选项卡&左侧菜单

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE>
<html>
<head>
  <%@include file="/common/head.jsp" %>
</head>
<style>
	.layui-tab-title>li:first-child>i{
		display:none;
	}
	.layui-tab>.layui-tab-content{
		padding:0px;
	}
	body,html{
		padding:0px;
		margin:0px;
		overflow:hidden;
	}
	.layui-body{
			background: url(images/壁纸03.jpg) ;
		}
</style>
<body>
<div class="layui-layout layui-layout-admin">
  <div class="layui-header ">
    <div class="layui-logo layui-hide-xs layui-bg-black">会议OA管理系统</div>
    <!-- 头部区域(可配合layui 已有的水平导航) -->
    <ul class="layui-nav layui-layout-left">
      <!-- 移动端显示 -->
      <li class="layui-nav-item layui-show-xs-inline-block layui-hide-sm" lay-header-event="menuLeft">
        <i class="layui-icon layui-icon-spread-left"></i>
      </li>
    </ul>
    <!-- 个人头像及账号操作 -->
    <ul class="layui-nav layui-layout-right">
      <li class="layui-nav-item layui-hide layui-show-md-inline-block">
        <a href="javascript:;">
          <img src="${ctx }/images/壁纸3.png" class="layui-nav-img">
          ${sessionScope.user.name }
        </a>
        <dl class="layui-nav-child">
          <dd><a href="#">个人中心</a></dd>
          <dd><a href="#">系统设置</a></dd>
          <dd><a href="#" id="logout">安全退出</a></dd>
        </dl>
      </li>
      <li class="layui-nav-item" lay-header-event="menuRight" lay-unselect>
        <a href="javascript:;">
          <i class="layui-icon layui-icon-more-vertical"></i>
        </a>
      </li>
    </ul>
  </div>
  
  <div class="layui-side layui-bg-black">
    <div class="layui-side-scroll">
      <!-- 左侧导航区域(可配合layui已有的垂直导航) -->
      <ul id="menu" class="layui-nav layui-nav-tree">
      </ul>
    </div>
  </div>
  
  <div class="layui-body">
    <div class="layui-tab" lay-filter="tabs" lay-allowClose="true" style="margin:0px;">
	  <ul class="layui-tab-title">
	    <li class="layui-this">首页</li>
	  </ul>
	  <div class="layui-tab-content">
	    <div class="layui-tab-item layui-show">
	    	<!-- <i class="bi bi-balloon-heart">欢迎来到瑶大头工作室</i> -->
	    	<!-- <img alt="" src="/images/壁纸3.png"> -->
	    </div>
	  </div>
	</div>
  </div>
  
  <div class="layui-footer" style="text-align:center;">
    <!-- 底部固定区域 -->
           Copyright @ 2008-2022 www.zking.com
  </div>
</div>
<script>
//JS 
var element, $, layer, util;
layui.use(['element', 'layer', 'util', 'jquery'], function(){
   element = layui.element
  ,layer = layui.layer
  ,util = layui.util
  ,$ = layui.$;
  
  //头部事件
  util.event('lay-header-event', {
    //左侧菜单事件
    menuLeft: function(othis){
      layer.msg('展开左侧菜单的操作', {icon: 0});
    }
    ,menuRight: function(){
      layer.open({
        type: 1
        ,content: '<div style="padding: 15px;">处理右侧面板的操作</div>'
        ,area: ['260px', '100%']
        ,offset: 'rt' //右上角
        ,anim: 5
        ,shadeClose: true
      });
    }
  });
  
  //动态生成菜单
  $.ajax({
	  url: ctx+"/permissionAction.action?methodName=listPermission",
	  type: "get",
	  dataType: 'json',
	  success:function(resp) {
		  
		  //循环生成菜单
		  $.each(resp.data, function(index, val) {
			  
			  //默认打开第一个菜单,layui-nav-itemed样式为打开菜单样式
			  let selected = index == 0 ? 'layui-nav-itemed' : '';
			  let li = $('<li class="layui-nav-item ' + selected + '"></li>');
			  
			  //一级菜单
			  li.append('<a class="" href="javascript:;"><i class="layui-icon '
			  		+ val.icon
			  		+ '" style="font-size:16px;margin-right:10px;"></i>' 
			  		+ val.name + '</a>');
			  
			  //如果有子菜单,则生成子菜单
			  let chidren=val.children;
			  let dl = $('<dl class="layui-nav-child"></dl>');
			  
			  $.each(chidren, function(i, n) {
				  
				  //dl.append('<dd style="margin-left:40px;">'+n.name+'</dd>');
				  //添加菜单点击事件
				  dl.append('<dd style="margin-left:40px;"><a href="javascript:openFuncTab(\''+n.name+'\', \''+n.url+'\', \''+n.id+'\');">'+n.name+'</a></dd>');
				  
			  });
			  
			  li.append(dl);
			  
			  //将生成的菜单挂载到menu容器
			  $("#menu").append(li);
		  });
		  
		  //动态的生成菜单后,调用render方法进行重新渲染,可以使用init()方法进行初始化达到同样的效果
		  element.render('menu');
	  }
  });
  
  //安全退出
  $("#logout").click(function() {
	  layer.confirm('亲,你舍得走吗?', {icon: 3, title:'提示'}, function(index) {
		  $.ajax({
			 url: ctx+"/userAction.action?methodName=logout",
			 type: 'get',
			 dataType: "json",
			 success: function(resp) {
				 if(resp.code == 1) {
					 layer.msg("安全退出");
					 location.href="login.jsp";
				 }
			 }
		  });
	  });
  });
  
});


//动态打开TAB页
function openFuncTab(name, url,id) {
	  let exit = $("li[lay-id='"+id+"']").length;
	  debugger;
	  //如果不存在对应的TAB则动态生成
	  if(exit == 0) {
		  //注意此处的tabs,要与TAB页容器的lay-filter="tabs"报错保持一致
		  element.tabAdd('tabs', {
			  title: name,
			  //在TAB页中打开指定的页面
			  content: '<iframe id="myiframe" frameborder="0" src="' + url+ '" scrolling="auto" style="width:100%;height:100%;"></iframe>',
			  id: id
		  });
	  }
	  //将点击的功能设置为当前TAB
	  element.tabChange('tabs', id);
	  
	  setIframHeight();
	  
	  //添加页面尺寸变化的监听事件
	  $(window).resize(function() {
		  setIframHeight();
	  })
}

//解决页面的自适应高度问题
function setIframHeight() {
	  let h = $('.layui-body').height() - 40;
	  $('#myiframe').css("height", h+"px");
}
</script>
</body>
</html>

三.效果展示

左侧菜单

 动态选项卡

 会议发布界面

 

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

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

相关文章

Redis之集群模式

一、Redis集群 一个节点就是一个运行在集群模式下的Redis服务器&#xff0c;Redis服务器在启动时会根据cluster-enabled配置选项是否为yes来决定是否开启服务器的集群模式。 Redis节点不会互相发现&#xff0c;连接各个节点的工作需要使用cluster meet命令来完成 CLUSTER MEE…

Nginx-报错no live upstreams while connecting to upstream

1、问题描述 生产环境Nginx间歇性502的事故分析过程 客户端请求后端服务时一直报错 502 bad gateway&#xff0c;查看后端的服务是正常启动的。后来又查看Nginx的错误日志&#xff0c;发现请求后端接口时Nginx报错no live upstreams while connecting to upstream&#xff0c…

快速收集form表单元素的值-----serialize函数

form-serialize–github 下载下来之后在页面引用 <form id"form"><input type"text" name"username" value"123"><input type"text" name"password"></form><script src"./seria…

新SDK平台下载开源全志V853的SDK

获取SDK SDK 使用 Repo 工具管理&#xff0c;拉取 SDK 需要配置安装 Repo 工具。 Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workflow. Repo is…

实力认可 | 开源网安入选中国信通院“业务安全推进计划”成员单位

8月25日&#xff0c;由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;与中国通信标准化协会联合主办的“2023首届SecGo云和软件安全大会”在京召开。开源网安凭借在软件供应链安全领域多年积累的技术实力与口碑&#xff0c;成功入选中国信通院“业务安全推…

【allegro 17.4软件操作保姆级教程十二】插件器件封装制作

&#x1f449;个人主页&#xff1a; highman110 &#x1f449;作者简介&#xff1a;一名硬件工程师&#xff0c;持续学习&#xff0c;不断记录&#xff0c;保持思考&#xff0c;输出干货内容 目录 制作插件焊盘 放置pin脚 绘制丝印线和装配线 放置位号和value 放置1脚标识…

wps会员可以退款吗

刚刚购买了wps会员&#xff0c;后来发现学校已经为学生开通了wps会员&#xff0c;因此想退掉自己买的。 网上大多数的说辞是可以退掉&#xff0c;但是其实是不能退的。 网上怎么可以一本正经胡说八道呢&#xff1f; &#xff08;以后购买之前要看清了&#xff0c;要不然吃亏了&…

Android studio打包生成jar包文件

将应用模块application转换成库模块library后生成jar包 1、首先打开build.gradle文件&#xff0c;注意这里是module目录下的&#xff0c;在这个文件我们需要做两个操作&#xff1a; 将com.android.application改成com.android.library注释掉applicationId 2、打开清单文件And…

扬杰科技携手企企通,召开SRM采购供应链协同系统项目启动会

近日&#xff0c;中国功率半导体领先企业扬州扬杰电子科技股份有限公司&#xff08;以下简称“扬杰科技”&#xff09;与企企通召开SRM采购供应链协同系统项目启动会&#xff0c;双方项目团队成员一同出席本次会议。 会上&#xff0c;双方就扬杰科技采购供应链管理平台项目的目…

双基证券:港股内房股“仙股”扎堆!

受职业继续低迷及部分房企本身因素影响&#xff0c;多家内房股已跌成“仙股”。 8月25日&#xff0c;世茂集团发布2023年中报成绩&#xff0c;上半年归属于股东净利润亏本51亿元&#xff0c;受此影响&#xff0c;公司股价继续下跌&#xff0c;到收盘报0.59港元/股&#xff0c;总…

服务体验:为什么海底捞会推出免费“洗头”的服务?

Guofu 第 106⭐️ 篇原创文章分享 先来了解一下背景。 近日&#xff0c;中国无锡的海底捞餐厅引发网民热议&#xff0c;因其提供了令人意外的洗头服务。这一举措引发了消费者的好奇和兴趣&#xff0c;网友纷纷表示希望这种创新能够在全国范围内推广。 根据店内的提示牌显示&…

设计模式备忘录+命令模式实现Word撤销恢复操作

文章目录 前言思路代码实现uml类图总结 前言 最近学习设计模式行为型的模式&#xff0c;学到了备忘录模式提到这个模式可以记录一个对象的状态属性值&#xff0c;用于下次复用&#xff0c;于是便想到了我们在Windows系统上使用的撤销操作&#xff0c;于是便想着使用这个模式进…

【注册岩土】Python土力学与基础工程计算.PDF-土中的应力

Python 求解代码如下&#xff1a; 1&#xff0e;&#xff03;计算竖向有效自重应力2.h12#m3.h21.5#m4.h31#m5.gamma1 19# kN/m^36.gamma218# kN/m^37.gamma317# kN/m^38.sigma_c gammal * h1 gamma2*h2 gamma3 *h39&#xff0e;print&#xff08;&#xff02;竖向有效自重应力…

STL-空间配置器的了解

前言 空间配置器&#xff0c;顾名思义就是为了各个容器高效的管理空间&#xff08;空间的申请与回收&#xff09;的&#xff0c;在默默的工作的。虽然在常规上使用STL时&#xff0c;可能用不上它&#xff0c;但是站在学习研究的角度&#xff0c;学习它的实现原理对我们有很大的…

Python+Yolov8手势特征识别检测

程序示例精选 PythonYolov8手势特征识别检测 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonYolov8手势特征识别检测>>编写代码&#xff0c;代码整洁&#xff0c;规则&am…

Matlab论文插图绘制模板第109期—特征渲染的标签气泡散点图

在之前的文章中&#xff0c;分享了Matlab标签散点图的绘制模板&#xff1a; 特征渲染的标签散点图&#xff1a; 进一步&#xff0c;再来分享一下特征渲染的标签气泡散点图的绘制模板&#xff0c;从而可以再添加一个维度的信息。 先来看一下成品效果&#xff1a; 特别提示&…

python之socket编程

本章内容 1、socket 2、IO多路复用 3、socketserver Socket socket起源于Unix&#xff0c;而Unix/Linux基本哲学之一就是“一切皆文件”&#xff0c;对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现&#xff0c;socket即是一种特殊的文件&#xff0…

简单工厂模式概述和使用

目录 一、简单工厂模式简介1. 定义2. 使用动机 二、简单工厂模式结构1.模式结构2. 时序图 三、简单工厂的使用实例四、简单工厂模式优缺点五、简单工厂模式在Java中的应用 一、简单工厂模式简介 原文链接 1. 定义 简单工厂模式(Simple Factory Pattern)&#xff1a;又称为静…

Remmina在ubuntu22.04中无法连接Windows

Remmina在ubuntu22.04中无法连接Windows 问题 提示为&#xff1a; 无法通过TLS到RDP服务器… 分析 原因是Remmina需要使用openssl通过RDP加密与Windows计算机连接&#xff0c;而ubuntu22.04系统中OpenSSL版本为3.0&#xff0c;Openssl3 将 tls<1.2 和 sha1 的默认安全级别…

checkstyle检查Java编码样式:源文件和文本文件末尾要有一个空行

背后的原理&#xff1a; 源文件和文本文件末尾应该有一个行分隔符&#xff0c;以便于他人在后面增加新的内容&#xff0c;而“diff”命令不会将前面的行作为改动过来显示。 https://checkstyle.sourceforge.io/checks/misc/newlineatendoffile.html#NewlineAtEndOfFile 例如&a…