目录
一、会议OA项目介绍
二、项目原型图介绍
三、数据库表结构
四、发布会议功能&多功能下拉框
一、会议OA项目介绍
为什么要开发OA会议管理
会议是公司日常管理的重要手段之一,为了更好的协调部门与部门之间、员工与员工之间的工作,并保证公司的日常事物高效并且有序的进行。开发OA会议管理是希望通过这个系统完成会议发起、审批、进行、投票、会议室管理的规范化管理;
会议是一个涉及多个部门,存在一定流程的工作,会议开展的效率决定整个公司的各项事务的开展效率;该会议OA系统将确保会议的高效进行,并且在线记录会议纪要及整个会议中的详细过程
会议OA管理的作用
1、OA办公系统中的会议管理可以帮助规范企业运作中的会议时间、决策内容、决策方式;
2、OA系统可营造流程与会议、决策与会议及报告与会议的和谐体系,有效提高高层的决策效率;
3、OA系统支持沉淀会议决策,建立高层决策的知识积累框架;跟踪会议决议执行情况,最终达成问题的解决
二、项目原型图介绍
本项目基于动态的Web工程完成OA会议系统,利用自定义MVC框架,数据库使用MySQL,开发工具为eclipse,项目界面使用layui搭
1)会议管理
通过之后,主持人可以在 我的会议 中看到自己发布的会议结状态是待开还是驳回,如若是待开等待该会议中的参会人员在会议召开之前选择是否参会
假如接收到该会议的人是张三、李四、王五、赵六,那么这些人在登录自己的账户后会收到会议通知
并点击是否参会选择如下:
这些人反馈之后,主持人在我的会议中的 反馈详情 里看到参会人员、缺席人员、以及未读人员(原形图中没有详细列出)
后可在 待开会议 中可以看到自己要开哪些会议
也可在历史会议中查看以往会议
可在所有会议中进行投票
2)投票管理
3)会议室管理
三、数据库表结构
四、发布会议功能&多功能下拉框
发布会议页面⬇⬇⬇⬇
LayUI之formSelects多选组件定义
文档地址:https://hnzzmsf.github.io/example/example_v4.html#download
下载地址:https://github.com/hnzzmsf/layui-formSelects
使用步骤:
1)导入formSelects
将资料中的layui-formSelects-master.zip解压并导入dist目录中的核心js和css到项目的指定路径中
2)在使用界面引入,addMeeting.jsp界面中引入核心JS和CSS<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!-- 引入formSelects核心css --> <link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.css" /> <!-- 引入formSelects核心js --> <script src="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" src="${pageContext.request.contextPath }/static/js/meeting/addMeeting.js"></script> </head>
代码
addMeeting.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="/common/header.jsp"%>
<!DOCTYPE html>
<html>
<!-- 引入formSelects核心css -->
<link rel="stylesheet" href="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.css" />
<!-- 引入formSelects核心js -->
<script src="${pageContext.request.contextPath }/static/js/plugins/formSelects/formSelects-v4.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" src="${pageContext.request.contextPath }/static/js/meeting/addMeeting.js"></script>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>发布会议</title>
</head>
<body>
<form class="layui-form layui-form-pane">
<div class="layui-form-item">
<button id="btn_add" type="submit" class="layui-btn" lay-submit="" lay-filter="meeting">立即提交</button>
<button id="btn_reset" type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
<div class="layui-form-item">
<label class="layui-form-label">会议标题</label>
<div class="layui-input-block">
<input type="text" name="title" lay-verify="required" 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 name="content" lay-verify="required" placeholder="请输入内容" 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" lay-verify="required" lay-vertype="tips">
<option value="">---请选择---</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" lay-verify="required" lay-vertype="tips">
<option value="">---请选择---</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" name="zhuchirenname" value="${user.name }" autocomplete="off" placeholder="请输入标题" class="layui-input">
<input type="hidden" name="zhuchiren" value="${user.id }"/>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">会议地点</label>
<div class="layui-input-block">
<input type="text" lay-verify="required" name="location" autocomplete="off" 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" readonly="readonly" lay-verify="required" id="dt" name="dt" 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 name="remark" placeholder="请输入备注" class="layui-textarea"></textarea>
</div>
</div>
</form>
</body>
</html>
addMeeting.js
let form,layer,$,formSelects,laydate;
layui.use(['form','layer','jquery','laydate'],function(){
form=layui.form,
layer=layui.layer,
$=layui.jquery,
laydate=layui.laydate,
//非模块化处理方式
formSelects=layui.formSelects;
//必须进行初始化操作
formSelects.btns('canyuze', ['select', 'remove', 'reverse']);
formSelects.btns('liexize', ['select', 'remove', 'reverse']);
//会议时间组件初始化
laydate.render({
elem: '#dt',
type: 'datetime',
range: '至'
});
//初始化多选下拉框
initFormSelects();
form.on('submit(meeting)', function(data){
console.log(data.elem) //被执行事件的元素DOM对象,一般为button对象
console.log(data.form) //被执行提交的form对象,一般在存在form标签时才会返回
console.log(data.field) //当前容器的全部表单字段,名值对形式:{name: value}
let rs=data.field;
rs['startTime']=rs.dt.split('至')[0].trim();
rs['endTime']=rs.dt.split('至')[1].trim();
rs['methodName']='add';
console.log(rs);
$.post($("#ctx").val()+'/info.action',rs,function(res){
if(res.success){
layer.msg(res.msg,{icon:6},function(){});
$('#btn_reset').click();
}else{
layer.msg(res.msg,{icon:5},function(){});
}
},'json');
return false; //阻止表单跳转。如果需要表单跳转,去掉这段即可。
});
});
//初始化多选下拉框
function initFormSelects(){
$.getJSON($("#ctx").val()+'/user.action',{
methodName:'queryUserAll'
},function(rs){
console.log(rs);
formSelects.data('liexize', 'local',{arr:rs.data});
formSelects.data('canyuze', 'local',{arr:rs.data});
});
}
MeetingInfo实体类
package com.zking.entity;
import java.util.Date;
public class MeetingInfo {
private Long id;
private String title;
private String content;
private String canyuze;
private String liexize;
private String zhuchiren;
private String location;
private Date startTime;
private Date endTime;
private String fujian;
private Integer state;
private String seatPic;
private String remark;
private String auditor;
public String getAuditor() {
return auditor;
}
public void setAuditor(String auditor) {
this.auditor = auditor;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getCanyuze() {
return canyuze;
}
public void setCanyuze(String canyuze) {
this.canyuze = canyuze;
}
public String getLiexize() {
return liexize;
}
public void setLiexize(String liexize) {
this.liexize = liexize;
}
public String getZhuchiren() {
return zhuchiren;
}
public void setZhuchiren(String zhuchiren) {
this.zhuchiren = zhuchiren;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getFujian() {
return fujian;
}
public void setFujian(String fujian) {
this.fujian = fujian;
}
public Integer getState() {
return state;
}
public void setState(Integer state) {
this.state = state;
}
public String getSeatPic() {
return seatPic;
}
public void setSeatPic(String seatPic) {
this.seatPic = seatPic;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public MeetingInfo() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "MeetingInfo [id=" + id + ", title=" + title + ", content=" + content + ", canyuze=" + canyuze
+ ", liexize=" + liexize + ", zhuchiren=" + zhuchiren + ", location=" + location + ", startTime="
+ startTime + ", endTime=" + endTime + ", fujian=" + fujian + ", state=" + state + ", seatPic=" + seatPic + ", remark=" + remark + "]";
}
}
MeetingInfoDao
package com.zking.dao;
import com.zking.entity.MeetingInfo;
import com.zking.util.BaseDao;
public class MeetingInfoDao extends BaseDao<MeetingInfo> {
// 添加会议信息
public int add(MeetingInfo info) throws Exception {
String sql = "insert into t_oa_meeting_info(title,content,canyuze,liexize,zhuchiren,\r\n"
+ "location,startTime,endTime,remark) values(?,?,?,?,?,?,?,?,?)";
return super.executeUpdate(sql, info, new String[] { "title", "content", "canyuze", "liexize", "zhuchiren",
"location", "startTime", "endTime", "remark" });
}
}
MeetingInfoAnction
package com.zking.web;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.ConvertUtils;
import com.zking.dao.MeetingInfoDao;
import com.zking.entity.MeetingInfo;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.MyDateConverter;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
public class MeetingInfoAction extends ActionSupport implements ModelDriver<MeetingInfo>{
private MeetingInfo info = new MeetingInfo();
private MeetingInfoDao meetingInfoDao = new MeetingInfoDao();
@Override
public MeetingInfo getModel() {
//注册一个转接器
ConvertUtils.register(new MyDateConverter(),Date.class);
return info;
}
// 会议发布
public String add(HttpServletRequest req, HttpServletResponse resp) {
try {
int rs = meetingInfoDao.add(info);
if (rs > 0) {
ResponseUtil.writeJson(resp, R.ok(200, "会议信息数据成功"));
}else {
ResponseUtil.writeJson(resp, R.error(0, "会议信息数据失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "会议信息数据失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
}
UserDao
package com.zking.dao;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import com.zking.entity.User;
import com.zking.util.BaseDao;
import com.zking.util.PageBean;
import com.zking.util.StringUtils;
public class UserDao extends BaseDao<User>{
public User login(User user) throws Exception {
String sql = "select * from t_oa_user where loginName = '"+user.getLoginName()+"' and pwd = '"+user.getPwd()+"'";
List<User> users = super.executeQuery(sql, User.class,null);
return users == null || users.size() == 0 ? null : users.get(0);
}
// 查询用户信息以及对应角色,角色通过case when得出
public List<Map<String,Object>> list(User user,PageBean pageBean) throws Exception{
String sql = "SELECT * \r\n" +
",( CASE rid \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" +
"ELSE '其他' END ) roleName \r\n" +
"FROM \r\n" +
"t_oa_user where 1=1";
String name = user.getName();
if(StringUtils.isNotBlank(name)) {
sql += " and name like '%"+name+"%'";
}
return super.executeQuery(sql, pageBean);
}
public int add(User user) throws Exception {
String sql = "insert into t_oa_user(name,loginName,pwd) values(?,?,?)";
return super.executeUpdate(sql, user, new String[] {"name","loginName","pwd"});
}
public int del(User user) throws Exception {
String sql = "delete from t_oa_user where id = ?";
return super.executeUpdate(sql, user, new String[] {"id"});
}
public int edit(User user) throws Exception {
String sql = "update t_oa_user set name=?,loginName=?,pwd=? where id=?";
return super.executeUpdate(sql, user, new String[] {"name","loginName","pwd","id"});
}
// 查询所有用户用于绑定多功能下拉框
public List<Map<String, Object>> queryUserAll(User user, PageBean pageBean) throws Exception {
String sql = "SELECT name,id as value from t_oa_user";
return super.executeQuery(sql, pageBean);
}
}
UserAction
package com.zking.web;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zking.dao.UserDao;
import com.zking.entity.User;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
import com.zking.util.PageBean;
import com.zking.util.R;
import com.zking.util.ResponseUtil;
public class UserAction extends ActionSupport implements ModelDriver<User>{
private User user = new User();
private UserDao userDao = new UserDao();
public String login(HttpServletRequest req, HttpServletResponse resp) {
try {
User u = userDao.login(user);
if(u != null) {
// ResponseUtil.writeJson(resp, new R()
// .data("code", 200)
// .data("msg","成功")
// );
ResponseUtil.writeJson(resp, R.ok(200, "成功"));
}else {
// /*ResponseUtil.writeJson(resp, new R()
// .data("code", 0)
// .data("msg","账户或密码错误")
// );*/
ResponseUtil.writeJson(resp, R.error(0, "账户或密码错误"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "账户或密码错误"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
// 用户查询
public String list(HttpServletRequest req, HttpServletResponse resp) {
try {
PageBean pageBean = new PageBean();
pageBean.setRequest(req);
List<Map<String, Object>> list = userDao.list(user, pageBean);
// 遵循layui中的格式
ResponseUtil.writeJson(resp, R.ok(0, "用户数据查询成功",pageBean.getTotal(),list));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "用户数据查询失败"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
//增加
public String add(HttpServletRequest req, HttpServletResponse resp) {
try {
int rs = userDao.add(user);
if(rs>0) {
ResponseUtil.writeJson(resp, R.ok(0, "用户数据新增成功"));
}else {
ResponseUtil.writeJson(resp, R.error(0, "用户数据新增失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "用户数据新增失败"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
//删除
public String del(HttpServletRequest req, HttpServletResponse resp) {
try {
int rs = userDao.del(user);
if(rs>0) {
ResponseUtil.writeJson(resp, R.ok(0, "用户数据删除成功"));
}else {
ResponseUtil.writeJson(resp, R.error(0, "用户数据删除失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "用户数据删除失败"));
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return null;
}
//修改
public String edit(HttpServletRequest req, HttpServletResponse resp) {
try {
int rs = userDao.add(user);
if(rs>0) {
ResponseUtil.writeJson(resp, R.ok(0, "用户数据修改成功"));
}else {
ResponseUtil.writeJson(resp, R.error(0, "用户数据修改失败"));
}
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "用户数据修改失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
//查询所有用户用于绑定多功能下拉框
public String queryUserAll(HttpServletRequest req, HttpServletResponse resp) {
try {
List<Map<String, Object>> users = userDao.queryUserAll(user,null);
ResponseUtil.writeJson(resp, R.ok(0, "多功能下拉框数据查询成功", users));
} catch (Exception e) {
e.printStackTrace();
try {
ResponseUtil.writeJson(resp, R.error(0, "多功能下拉框数据查询失败"));
} catch (Exception e1) {
e1.printStackTrace();
}
}
return null;
}
@Override
public User getModel() {
return user;
}
}
配置mvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<action path="/user" type="com.zking.web.UserAction">
</action>
<action path="/permission" type="com.zking.web.PermissionAction">
</action>
<action path="info" type="com.zking.web.MeetingInfoAction">
</action>
</config>
当我们从登录界面进去时,发布会议内容编辑完立即提交时控制台会报错
原因是前端拿的时间是string类型 实体类是date类型
页面效果