OA项目之左侧菜单动态选项卡

news2024/11/19 5:26:30

目录

  1.左侧导航

  参考地址: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/955935.html

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

相关文章

无涯教程-Flutter - 简介

Flutter是一个由谷歌开发的开源移动应用软件开发工具包&#xff0c;用于为Android、iOS、 Windows、Mac、Linux、Google Fuchsia开发应用。 通常&#xff0c;创建移动应用程序是一个非常复杂和具有挑战性的任务。有许多框架可用&#xff0c;它提供了开发移动应用程序的出色函数…

yolov5的pytorch配置

1. conda create -n rdd38 python3.82、pip install torch1.8.0 torchvision0.9.0 torchaudio0.8.0 -f https://download.pytorch.org/whl/cu113/torch_stable.html -i https://pypi.tuna.tsinghua.edu.cn/simple 3、conda install cudatoolkit10.2

Flutter的未来与趋势,23年还学吗?

随着移动应用市场的不断扩大&#xff0c;跨平台开发框架的需求也越来越大。Flutter框架可以帮助开发者在不同平台上快速开发高质量的移动应用程序&#xff0c;这种趋势将进一步推动Flutter的发展和普及。 作为一名前端开发工程师&#xff0c;学习Flutter框架是非常有必要的。因…

NameError: name ‘_mysql‘ is not defined

报错信息 Traceback (most recent call last):File "/Users/xuruilong/Desktop/cmabc_back/.enve/lib/python3.9/site-packages/MySQLdb/__init__.py", line 18, in <module>from . import _mysql ImportError: dlopen(/Users/xuruilong/Desktop/cmabc_back/.…

报文信息转换器

HttpMessageConverter HttpMessageConverter:报文信息转换器&#xff0c;将请求报文转换为Java对象&#xff0c;或将Java对象转换为响应报文。它提供了两个注解和两个类型&#xff1a; RequestBody, ResponseBody, RequestEntity, ResponseEntity(响应用的较多) 准备 创建模块并…

HCIP学习--扩展知识点

端口镜像-SPAN 抓包软件只能抓取经过本地的网卡的流量 也就是抓取流量只能抓取本设备的流量 [r1]observe-port interface GigabitEthernet 0/0/2 定义一个SPAN的会话&#xff0c;然后定义监控接口&#xff08;也就是你要用的接口&#xff0c;你连接这个接口来对其他接口抓包…

IDEA批量处理行尾注释

前言 行尾注释写起来比较方便&#xff0c;所以很多时候我们都会习惯把注释写在行尾。 但这个是不符合编程规范的&#xff0c;写的代码注释主要是给后续接手人进行阅读帮助的。按照正常的阅读方式都是先读注释&#xff0c;然后再看代码&#xff0c;如果先看代码再看注释&#…

创建智能问答机器人:上线智能机器人客服,实时为客户提供解决方案

随着企业扩大规模和业务增长&#xff0c;客户咨询和服务请求增加。传统人工客服难以处理大量咨询&#xff0c;而智能化的AI客服可以同时满足多个客户需求。 智能问答机器人 创建智能问答机器人后&#xff0c;能自动化处理大量客户咨询&#xff0c;显著降低企业运营成本&#xf…

Multimedia-播放器-架构1

目录 引言 概念 播放器 播放器的工作流程 播放器的架构 IO模块 Parser&Demuxer模块 Decoder模块 渲染模块 小结 引言 什么是播放器&#xff1f; 播放器是做什么的&#xff1f;怎么做的&#xff1f; 概念 播放器 可以指软件&#xff0c;也可以指硬件 软件&am…

代码随想录算法训练营之JAVA|第四十一天|139. 单词拆分

今天是第 天刷leetcode&#xff0c;立个flag&#xff0c;打卡60天。 算法挑战链接 139. 单词拆分https://leetcode.cn/problems/word-break/ 第一想法 看完之后完全没有想法。 看完代码随想录之后的想法 这是一个完全背包的问题&#xff0c;使用完全背包的解法。 单词就…

「C++程序设计 (面向对象进阶)」学习笔记・一

0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ &#x1f600; 有关于现代 C 的基本介绍&#xff0c;请前往《现代C基本介绍》&#xff01; &#x1f514; 先决条件 本专栏的系列…

微信小程序发布一个npm包

参考:https://developers.weixin.qq.com/miniprogram/dev/devtools/npm.html 同npm一样流程 npm install weixin_heath_apis

gRPC-Gateway 快速实战

今天来分享一波 gRPC-Gateway &#xff0c; 之前咱们有分享过什么是 gRPC 及其使用方式&#xff0c;可以看看这些关于 gRPC 的历史文章&#xff1a; gRPC介绍 gRPC 客户端调用服务端需要连接池吗&#xff1f; gRPC的拦截器 gRPC的认证 分享一下 gRPC- HTTP网关 I 今天主要是分…

大门设得好,财旺运也旺

大门作为我们家庭里一扇保护家人的屏障&#xff0c;可以说是非常重要的&#xff0c;它不仅能起到安全作用&#xff0c;在风水上也是非常关键的。大门在风水中是财运进气的门道&#xff0c;大门风水的好坏直接影响到房屋的整体风水&#xff0c;好的大门风水可以让主人旺财又旺运…

Jaeger的经典BUG原创

前端&#xff0c;笔者在使用Jaeger进行Trace监控的时候&#xff0c;当数据量增大到一定数量级时&#xff0c;出现了一次CPU暴增导致节点服务器挂了的经典案例&#xff0c;这里对案例进行一个简单的抽象&#xff0c;供大家参考&#xff1a; 首先通过pprof对耗时的函数进行定位&…

华为云CodeArts IDE快速入门和使用详解

华为云CodeArts IDE使用详解 一、用户界面1. 初始界面2. 打开项目界面3. 资源管理器4. 编辑器5. 命令面板6. 扩展应用7. Git管理 二、设置1. 设置编辑器2. settings.json 三、代码编辑1. 快捷操作2. 代码补全 四、RemoteShell1. 添加主机连接 文档参考: 华为云CodeArts IDE文档…

【高级程序设计语言C++】异常与智能指针

1. 异常2. 智能指针2.1. auto_ptr2.2. unique_ptr2.3. shared_ptr2.4. 循环引用2.5. weak_ptr2.6. 定制删除器 1. 异常 当我们编写程序时&#xff0c;可能会遇到各种错误和异常情况&#xff0c;例如除以零、访问无效的内存地址等。为了能够处理这些异常情况&#xff0c;C提供了…

(笔记六)利用opencv进行图像滤波

&#xff08;1&#xff09;自定义卷积核图像滤波 import numpy as np import matplotlib.pyplot as plt import cv2 as cvimg_path r"D:\data\test6-6.png" img cv.imread(img_path)# 图像滤波 ker np.ones((6, 6), np.float32)/36 # 构建滤波器&#xff08;卷积…

Three.js后处理后物体表面出现条纹

初始化 WebGLRenderer 时简单启用 logarithmicDepthBuffer: true 解决了问题。 根据文档&#xff0c;启用可能会导致性能下降&#xff0c;因此请根据您的性能预算考虑使用它。 缩小相机的near和far 后处理对于深度精度非常敏感。大视锥体很快就会使此类 AO 通道变得无法使用 th…

小兔鲜儿 - 微信登录

目录 微信登录​ 登录方式 静态结构​ 获取登录凭证​ 获取手机号码​ 微信登录接口(生产环境) 模拟手机登录(开发环境) 用户信息持久化存储​ 涉及知识点&#xff1a;微信授权登录&#xff0c;文件上传&#xff0c;Store 状态管理等。 微信登录​ 微信小程序的开放…