会议OA项目----我的审批

2023-11-17

前言

上一篇博客我将我的会议的送审和会议排座这两个功能完成。

送审之后就到了审批阶段,那么这次做的就是 我的审批


一、 实现思路

根据产品原型图。

 见产品原型图,我的审批界面与我的会议界面大同小异。那么我们可以调用之前的写好的SQL语句,只不过将会议状态改为待审核,将当前登录账号作为审批人进行查询就行了。

 可见,之前专门定义了一个界面数据绑定的SQL语句的方法,只是需要根据实际需求增加查询的条件。

我们试着在数据加上条件进行查询,看一下语句是否正确

 既然能查出数据,那么我们考虑审批功能。

 会议的审批还是点击审批,出现一个弹出层,这次弹出层用的是内嵌页面。

会议的审批,主要需要实现,审批人签字。

会议的审批人在线签字,我最先想到的就是

 那我们找一下有没有类似的插件,我们拿过来进行优化说不定就能解决这个问题。

 两个我都看了一下,wPaint有点一言难尽,咱就是说还是喜欢好看点的。

上图看一下吧。觉得那个好看评论区留言。

 

功能都差不多咱还是选个好看点的。 

鼠标写的,有点丑别介意。 

将插件下载下来进行优化,只保留签字、保存和清除。

优化完的就不展示了。

 

批处理:

审批通过后,我们要将审批通过的会议增加到会议审批表里,同时要更改审批通过的会议的状态。这里要同时执行两条SQL语句。

既然实现思路明确了,我们就开始编码阶段的工作吧。

二、编码

        1、我的审批界面数据绑定

                后端代码:

        MeetingInfoDao

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>> myAudit(MeetingInfo info,PageBean pageBean) throws Exception{
		String sql=this.getSQL();
		String title = info.getTitle();
		if(!StringUtils.isNotBlank(title))
			sql+=" and title like '%"+title+"%'";
		sql+=" and auditor="+info.getAuditor();
		sql+=" and state=2";
		sql+=" order by a.id desc";
		System.out.println(sql);
		return super.executeQuery(sql, pageBean);
	}

MeetingInfoAction

//	我的审批
	public String myAudit(HttpServletRequest req, HttpServletResponse resp) {
		try {
			PageBean pageBean = new PageBean();
			pageBean.setRequest(req);
			List<Map<String, Object>> infos = infoDao.myAudit(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;
	}

        前端代码:

        myAudit.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="${pageContext.request.contextPath }/static/js/meeting/myAudit.js"></script>
</head>
<style>
body{
	margin:15px;
}
 .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="auditor" 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>

<script type="text/html" id="tbar">
  <a class="layui-btn layui-btn-xs" lay-event="edit">审批</a>
</script>
</body>
</html>

        myAudit.js

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

//初始化数据表格(我的审批)
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: '', title: '操作', width: 200,toolbar:'#tbar'},
        ]]
   });
}

//点击查询
function query(){
	table.reload('tb', {
        url: $("#ctx").val()+'/info.action',     //请求地址
        method: 'POST',                    //请求方式,GET或者POST
        loading: true,                     //是否显示加载条(默认 true)
        page: true,                        //是否分页
        where: {                           
        	'methodName':'myAudit',
        	'auditor':$('#auditor').val(),
        	'title':$('#title').val(),
        },  
        request: {                         
            pageName: 'page', 
            limitName: 'rows' 
        },
        done: function (res, curr, count) {
        	console.log(res);
        }
   });
	
	//工具条事件
	table.on('tool(tb)', function(obj){ 
	  row = obj.data; 
	  var layEvent = obj.event; 
	  var tr = obj.tr; 
	  console.log(row);
	  if(layEvent === 'edit'){ //审批
		  
	  } else {
		  
	  }
	});
}

        执行效果:

         既然界面的数据绑定没问题了。我们就开始进入审批功能的编码。

        2、我的审批--审批功能(含会议签字)

        思路:

         后台编码:

        MeetingAudit

package com.zking.entity;

import java.io.Serializable;
import java.util.Date;

public class MeetingAudit implements Serializable {
	private Integer id;
	private Long meetingId;
	private String auditor;
	private String sign;
	private Date createdate;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public Long getMeetingId() {
		return meetingId;
	}
	public void setMeetingId(Long meetingId) {
		this.meetingId = meetingId;
	}
	public String getAuditor() {
		return auditor;
	}
	public void setAuditor(String auditor) {
		this.auditor = auditor;
	}
	public String getSign() {
		return sign;
	}
	public void setSign(String sign) {
		this.sign = sign;
	}
	public Date getCreatedate() {
		return createdate;
	}
	public void setCreatedate(Date createdate) {
		this.createdate = createdate;
	}
	public MeetingAudit() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public String toString() {
		return "MeetingAudit [id=" + id + ", meetingId=" + meetingId + ", auditor=" + auditor + ", sign=" + sign
				+ ", createdate=" + createdate + "]";
	}
	
	
}

MeetingAuditDao

package com.zking.dao;

import com.zking.entity.MeetingAudit;
import com.zking.util.BaseDao;
import com.zking.util.StringUtils;

public class MeetingAuditDao extends BaseDao<MeetingAudit> {

	/**
	 * 新增会议审批记录
	 * @param audit
	 */
	public void add(MeetingAudit audit) {
		//1.新增会议审批记录
		String sql="insert into t_oa_meeting_audit(meetingId,auditor,sign)"
				+ " values("+audit.getMeetingId()+","+audit.getAuditor()+",'"+audit.getSign()+"')";
		//2.根据会议ID更新会议的状态(3=驳回,4=待开)
		int state=StringUtils.isBlank(audit.getSign())?3:4;
		String sql1="update t_oa_meeting_info set state="+state+" where id="+audit.getMeetingId();
		//如何一次执行两条SQL,使用数据库事务?
		super.executeUpdateBatch(new String[] {sql,sql1});
	}
}

MeetingInfoAction

package com.zking.web;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

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

import com.zking.dao.MeetingAuditDao;
import com.zking.entity.MeetingAudit;
import com.zking.framework.ActionSupport;
import com.zking.framework.DispatchServlet;
import com.zking.framework.ModelDriver;
import com.zking.util.Base64ImageUtils;
import com.zking.util.CommonUtils;
import com.zking.util.ImageUtils;
import com.zking.util.PropertiesUtil;
import com.zking.util.StringUtils;

public class MeetingAuditAction extends ActionSupport implements ModelDriver<MeetingAudit> {
	private MeetingAudit audit=new MeetingAudit();
	private MeetingAuditDao auditDao=new MeetingAuditDao();
	
	/**
	 * 审批
	 * @param req
	 * @param resp
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	public String add(HttpServletRequest req,
			HttpServletResponse resp) throws ServletException,IOException{
		try {
			//1.保存会议签字的图片
			if(StringUtils.isNotBlank(audit.getSign())) {
				//定义保存路径	dirPathSign=E:/temp/images/T280/sign/
				String sourceFilePath=PropertiesUtil.getValue("dirPathSign");
				//定义请求地址	serverPathSign=/test_layui/upload/sign/
				String requestFilePath = PropertiesUtil.getValue("serverPathSign");
				//定义会议签字图片名称(原图名称)
				String sourcefileName=UUID.randomUUID().toString().replace("-", "")+".jpg";
				//定义会议签字图片名称(裁剪后的名称)
				String targetfileName=UUID.randomUUID().toString().replace("-", "")+".jpg";
				//拼接图片完成路径(原图)
				String realPath=sourceFilePath+sourcefileName;
				//拼接裁剪图路径
				String targetPath=sourceFilePath+targetfileName;
				//上传签字图片并保存到指定位置
				Base64ImageUtils.GenerateImage(audit.getSign().replace("data:image/png;base64,", ""), realPath);
				//裁剪原图
				ImageUtils.shearImg(realPath, targetPath);
				//替换sign的图片路径
				audit.setSign(requestFilePath+targetfileName);
				//删除原图
				File file=new File(realPath);
				if(file.exists())
					file.delete();
			}
			//2.新增会议审批记录及更新会议状态
			auditDao.add(audit);
			CommonUtils.toJson(true, "审批成功!", resp);
		} catch (Exception e) {
			e.printStackTrace();
			CommonUtils.toJson(false, "审批失败!", resp);
		}
		return null;
	}

	@Override
	public MeetingAudit getModel() {
		return audit;
	}
}

配置文件,配置一下。就不展示了。

<

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

会议OA项目----我的审批 的相关文章

  • 如何在Eclipse中集成CSS预处理? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 Eclipse 中编辑 SCSS 文件 最好使用语法突出显示 scss files 我发现这些资
  • 使用 Ant 将非代码资源添加到 jar 文件

    我正在将 java 应用程序打包成 jar 文件 我正在使用 ant 和 eclipse 我实际上需要在 jar 中直接在根文件夹下包含几个单独的非代码文件 xml 和 txt 文件 而不是与代码位于同一位置 我正在尝试使用includes
  • 是否有任何简单(且最新)的 Java 框架可用于在 Swing 应用程序中嵌入电影?

    我正在构建一个小型 Swing 应用程序 我想在其中嵌入一部电影 重要的是 这个应用程序是一个 WebStart 应用程序 并且该库应该能够打包在我启动的 jnlp 中 即 不依赖于本机库 我知道并尝试过 JMF 但我认为与其他框架相比 其
  • 如何在 Antlr4 中为零参数函数编写语法

    我的函数具有参数语法 如下面的词法分析器和解析器 MyFunctionsLexer g4 lexer grammar MyFunctionsLexer FUNCTION FUNCTION NAME A Za z0 9 DOT COMMA L
  • 通往楼梯顶部的可能路径

    这是一个非常经典的问题 我听说谷歌在他们的面试中使用过这个问题 问题 制定一个递归方法 打印从楼梯底部到楼梯顶部的所有可能的独特路径 有 n 个楼梯 您一次只能走 1 步或 2 步 示例输出 如果它是一个有 3 级楼梯的楼梯 1 1 1 2
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 套接字的读写如何同步?

    我们创建一个套接字 在套接字的一侧有一个 服务器 在另一侧有一个 客户端 服务器和客户端都可以向套接字写入和读取 这是我的理解 我不明白以下事情 如果服务器从套接字读取数据 它在套接字中是否只看到客户端写入套接字的内容 我的意思是 如果服务
  • Java Swing For mac 中的 DJ Native Swing 浏览器

    我有一个用 Swing 制作的 Java 应用程序 并且使用了一个 DJ Native Swing 浏览器 当我尝试在 OS X 上使用它时 它抛出了一个NoClassDefFoundError尽管我添加了 swt jar 但始终如此 有人
  • 流中的非终结符 forEach() ?

    有时 在处理 Java Stream 时 我发现自己需要一个非终端 forEach 来触发副作用但不终止处理 我怀疑我可以用 map item gt f item 之类的方法来做到这一点 其中方法 f 执行副作用并将项目返回到流中 但这似乎
  • 如何在 Java 中创建接受多个值的单个注释

    我有一个名为 Retention RetentionPolicy SOURCE Target ElementType METHOD public interface JIRA The Key Bug number JIRA referenc
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • JMenu 中的文本居中

    好吧 我一直在网上寻找有关此问题的帮助 但我尝试的任何方法似乎都不起作用 我想让所有菜单文本都集中在菜单按钮上 当我使用setHorizontalTextPosition JMenu CENTER 没有变化 事实上 无论我使用什么常量 菜单
  • Resteasy 可以查看 JAX-RS 方法的参数类型吗?

    我们使用 Resteasy 3 0 9 作为 JAX RS Web 服务 最近切换到 3 0 19 我们开始看到很多RESTEASY002142 Multiple resource methods match request警告 例如 我们
  • stm32l0: 执行MI命令失败。使用 vFlashErase 数据包擦除闪存时出错

    我正在使用 Nucleo STM32L031 和 AC6 STM32 工作台 eclipse 我编写应用程序并进入调试模式 一切正常 直到我在应用程序中添加另一个功能 我注意到当我删除 评论 新函数 软件可以再次进入调试模式 但是当我添加
  • Java中HashMap和ArrayList的区别?

    在爪哇 ArrayList and HashMap被用作集合 但我不明白我们应该在哪些情况下使用ArrayList以及使用时间HashMap 他们两者之间的主要区别是什么 您具体询问的是 ArrayList 和 HashMap 但我认为要完
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • 洪水填充优化:尝试使用队列

    我正在尝试创建一种填充方法 该方法采用用户指定的初始坐标 检查字符 然后根据需要更改它 这样做之后 它会检查相邻的方块并重复该过程 经过一番研究 我遇到了洪水填充算法并尝试了该算法 它可以工作 但无法满足我对 250 x 250 个字符的数
  • Spring表单ModelAttribute字段验证避免400 Bad Request错误

    我有一个ArticleFormModel包含正常发送的数据html form由 Spring 使用注入 ModelAttribute注释 即 RequestMapping value edit method RequestMethod PO

随机推荐

  • JAVA单元测试框架-14-实现TestNG失败案例重跑

    前面是通过java代码指定重跑 本节是讲解通过实现IAnnotationTransformer接口实现失败案例重跑 创建MyRetry 实现IRetryAnalyzer 接口 package Listener import org test
  • MMsegmentation文档学习

    1 了解配置 config文件结构 config base 下有4种基本组件类型 dataset model schedule default runtime 同一文件夹下的所有配置 建议只具有一个原始配置 所有其他配置从原始配置继承 这样
  • JDK8升级JDK11最全实践干货来了

    1 前言 截至目前 2023年 Java8发布至今已有9年 2018年9月25日 Oracle发布了Java11 这是Java8之后的首个LTS版本 那么从JDK8到JDK11 到底带来了哪些特性呢 值得我们升级吗 而且升级过程会遇到哪些问
  • Ts接口的使用

    TypeScript 的核心原则之一是对值所具有的结构进行类型检查 我们使用接口 Interfaces 来定义对象的类型 接口是对象的状态 属性 和行为 方法 的抽象 描述 接口初探 需求 创建人的对象 需要对人的属性进行一定的约束 id是
  • 工作10年我面试过上百个程序员,真想对他们说…

    V xin ruyuanhadeng获得600 页原创精品文章汇总PDF 一 写在前面 最近收到不少读者反馈 说自己在应聘一些中大型互联网公司的Java工程师岗位时遇到了不少困惑 这些同学说自己也做了精心准备 网上搜集了不少Java面试题
  • Edit Distance

    Given two words word1 and word2 find the minimum number of steps required to convert word1 to word2 each operation is co
  • 【转载】探索推荐引擎内部的秘密

    原网址 https www ibm com developerworks cn web 1103 zhaoct recommstudy1 index html icomments 这是2011年ibm发布的文章 较为通俗易懂 适合想入门推荐
  • 配置msf连接postgresql数据库

    BackTrack 5 R3版本的Metasploit在每次的升级后总会出现奇奇怪怪的错误 主要是Ruby的库出错 网上找了一些解决的办法 但每次更新后又会出错 蛋碎 解决方法 BackTrack 5中默认自动开启端口7337 1 查看Po
  • Zabbix监控MariaDB服务

    文章目录 1 概述监控MariaDB服务主机 2 安装MariaDB服务和配置MariaDB 3 配置Zabbix的userparameter mysql conf 文件模板 4 在Web配置模板 5 在server进行压力测试mysql服
  • svg实现文本的垂直居中对齐样式

    项目中用到表格内画折线趋势图 本人使用的svg绘制简单折线 没有数据的单元格显示文字 为了不影响表格的宽度自适应 就想到在svg上写文字 于是就有了在svg上对文字样式进行垂直居中的需求 上代码
  • Linux教程:在虚拟机中如何配置Linux系统网络环境 ?

    对于很多初学Linux 的同学 大多选择使用虚拟机来展开学习 可以方便的做实验 修改 测试 不必害怕出问题 可以随便折腾 大不了换一个虚拟机 原来的系统不受任何影响 但由于不是实体pc机 使用难免受限 如果配置不好 后期开发必受其累 比如
  • C++Primer(4-8章)

    第四章 表达式 求值顺序 C 中没有明确规定大多数运算符的求值顺序 因此我们要避免 改变了某个运算对象的值 又在表达式其他地方使用这个运算对象 这种情况出现 赋值运算满足右结合律 在输出表达式中使用条件运算符 条件运算符的优先级非常低 因此
  • java修改AD域用户密码使用SSL连接方式

    正常情况下 JAVA修改AD域用户属性 只能修改一些普通属性 如果要修改AD域用户密码和userAccountControl属性就得使用SSL连接的方式修改 SSL连接的方式需要操作以下步骤 1 安装AD域证书服务 2 证书颁发机构中设置以
  • 【C语言】结构体中的函数指针

    目录 一 函数指针是什么 二 结构体中的函数指针 一 函数指针是什么 函数指针是指向函数的指针变量 通常我们说的指针变量是指向一个整型 字符型或数组等变量 而函数指针是指向函数 函数指针可以像一般函数一样 用于调用函数 传递参数 正确形式
  • 2.【Python】分类算法—Logistic Regression

    2 Python 分类算法 Logistic Regression 文章目录 2 Python 分类算法 Logistic Regression 前言 一 Logistic Regression模型 1 线性可分和线性不可分 2 Logis
  • 二.全局定位--开源定位框架livox-relocalization实录数据集测试

    相关博客 二十五 SLAM中Mapping和Localization区别和思考 goldqiu的博客 CSDN博客 二十五 SLAM中Mapping和Localization区别和思考 goldqiu的博客 CSDN博客 基于固态雷达的全局
  • 【Flink系列】- RocksDB增量模式checkpoint大小持续增长的问题及解决

    背景 Flink版本 1 13 5 一个使用FlinkSQL开发的生产线上任务 使用Tumble Window做聚和统计 并且配置table exec state ttl为7200000 设置checkpoint周期为5分钟 使用rocks
  • cr2格式缩略图不显示_苹果HEIC格式照片如何快速在windows电脑上查看

    相信很多人一定遇到这样的一个情况 出去旅游玩了一阵 辛辛苦苦回来将iphone拍的照片拷贝到windows电脑 windows7系统 上 想寻找一些心仪的照片 却发现是如下的样子 OMG 欺负我买不起苹果电脑是吧 我拍的是啥 什么也看不到
  • Linux —— XShell6远程操控开机、重启和用户登录注销

    1 关机 重启命令 shutdown h now 表示立即关机 shutdown h 1 表示一分钟后关机 shutdown r now 表示立即重启 halt 直接使用 等价于关机 reboot 就是重启系统 sync 把内存的数据同步到
  • 会议OA项目----我的审批

    前言 上一篇博客我将我的会议的送审和会议排座这两个功能完成 送审之后就到了审批阶段 那么这次做的就是 我的审批 一 实现思路 根据产品原型图 见产品原型图 我的审批界面与我的会议界面大同小异 那么我们可以调用之前的写好的SQL语句 只不过将