Browse Source

企业微信打卡数据展示以及下载功能

user5 10 months ago
parent
commit
22e3e65ba8

+ 0 - 8
src/main/java/com/jeeplus/modules/wexintheorder/service/ClockInRecordService.java

@@ -1,27 +1,19 @@
 package com.jeeplus.modules.wexintheorder.service;
 
-import com.fasterxml.jackson.core.JsonParseException;
 import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.JsonMappingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.Lists;
 import com.jeeplus.common.persistence.Page;
 import com.jeeplus.common.service.CrudService;
-import com.jeeplus.common.utils.MenuStatusEnum;
 import com.jeeplus.common.utils.StringUtils;
 import com.jeeplus.modules.sys.entity.User;
-import com.jeeplus.modules.sys.utils.UserUtils;
 import com.jeeplus.modules.wexintheorder.Utils.OrderUtils;
 import com.jeeplus.modules.wexintheorder.dao.ClockInRecordDao;
 import com.jeeplus.modules.wexintheorder.entity.ClockInRecordInfo;
 import com.jeeplus.modules.wexintheorder.entity.ClockInRecordSaveInfo;
-import com.jeeplus.modules.workclientinfo.entity.WorkClientBank;
-import com.jeeplus.modules.workclientinfo.entity.WorkClientInfo;
-import com.jeeplus.modules.workclientinfo.entity.WorkClientLinkman;
 import net.sf.json.JSONObject;
 import org.springframework.stereotype.Service;
 
-import java.io.IOException;
 import java.util.List;
 
 /**

+ 0 - 3
src/main/java/com/jeeplus/modules/wexintheorder/web/ClockInRecordController.java

@@ -15,9 +15,6 @@ import com.jeeplus.modules.wexinpackage.access.util.encryption.WXBizMsgCrypt;
 import com.jeeplus.modules.wexintheorder.Utils.OrderUtils;
 import com.jeeplus.modules.wexintheorder.entity.ClockInRecordInfo;
 import com.jeeplus.modules.wexintheorder.service.ClockInRecordService;
-import com.jeeplus.modules.workclientinfo.entity.WorkClientInfo;
-import com.jeeplus.modules.workclientinfo.entity.WorkClientLinkman;
-import com.jeeplus.modules.workdevicerecord.entity.WorkDeviceRecord;
 import net.sf.json.JSONObject;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;

+ 67 - 0
src/main/java/com/jeeplus/modules/wexintheorder/web/HrUserController.java

@@ -0,0 +1,67 @@
+package com.jeeplus.modules.wexintheorder.web;
+
+import com.google.common.collect.Lists;
+import com.jeeplus.common.web.BaseController;
+import com.jeeplus.modules.sys.entity.User;
+import com.jeeplus.modules.sys.service.UserService;
+import com.jeeplus.modules.wexinpackage.access.util.encryption.AesException;
+import com.jeeplus.modules.wexinpackage.access.util.encryption.WXBizMsgCrypt;
+import com.jeeplus.modules.wexintheorder.Utils.OrderUtils;
+import com.jeeplus.modules.wexintheorder.service.ClockInRecordService;
+import net.sf.json.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * hr用户人员信息管理controller
+ * @author: 徐滕
+ * @version: 2024-08-09 13:56
+ */
+@Controller
+@RequestMapping(value = "${adminPath}/hrUserController")
+public class HrUserController extends BaseController {
+
+    //token 企业微信自建打卡token
+    public final static String TOKEN = "JdC2TJns5MtcEdeZbkyg";
+    // encodingAESKey   企业微信自建打卡encodingAESKey
+    public final static String ENCODINGAES_KEY = "lUVqXMkednWobzl8AWoxb8OiynhsDjTBuJAgHPUhatH";
+    //企业ID
+    public final static String CORP_ID = "wwb0b5e7c17a34ac8d";
+    //应用的凭证密钥(打卡)
+    public final static String CORPSECRET = "sWlZlltMnV8VpCD8Z5EDQ0Vij80kFUkX7iLi8hpwSpc";
+
+    @Autowired
+    private UserService userService;
+
+
+    /**
+     * 查询打卡记录信息
+     * @return
+     */
+    @RequestMapping(value = "getUserInfo")
+    @ResponseBody
+    @Transactional(readOnly = false)
+    public Map<String,Object> getUserInfo(){
+        Map<String,Object> map = new HashMap<>();
+        String accessToken = OrderUtils.getToken(CORP_ID, CORPSECRET);
+        //获取人员信息
+        List<User> allUserList = userService.disposeQWUserId(accessToken);
+
+        map.put("返回结果","处理完成");
+        return map;
+    }
+}

+ 172 - 0
src/main/resources/mappings/modules/wexintheorder/ClockInRecordDao.xml

@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.jeeplus.modules.wexintheorder.dao.ClockInRecordDao">
+	<sql id="lockInRecordColumns">
+		a.id,
+		a.create_by AS "createBy.id",
+		a.create_date as "createDate",
+		a.update_by AS "updateBy.id",
+		a.update_date as "updateDate",
+		a.del_flag as "",
+		a.remarks,
+		a.user_id as "userId",
+		a.group_name as "groupName",
+		a.checkin_type as "checkinType",
+		a.exception_type as "exceptionType",
+		a.checkin_time as "checkinTime",
+		a.location_title as "locationTitle",
+		a.location_detail as "locationDetail",
+		a.wifi_name as "wifiName",
+		a.notes,
+		a.wifi_mac as "wifiMac",
+		a.mediaids,
+		a.lat,
+		a.lng,
+		a.device_id as "deviceId",
+		a.sch_checkin_time as "schCheckinTime",
+		a.group_id as "groupId",
+		a.schedule_id as "scheduleId",
+		a.timeline_id as "timelineId",
+		a.sys_user_id as "sysUserId"
+	</sql>
+
+	<select id="findList" resultType="com.jeeplus.modules.wexintheorder.entity.ClockInRecordInfo" >
+		SELECT
+		<include refid="lockInRecordColumns"/>
+		,su.name as "userName"
+		from qw_clock_in_record_info a
+		left join sys_user su on su.id = a.sys_user_id
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			<if test="sqlMap.dsf !=null and sqlMap.dsf!=''">
+				${sqlMap.dsf}
+			</if>
+		</where>
+		<choose>
+			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
+				ORDER BY ${page.orderBy}
+			</when>
+			<otherwise>
+				ORDER BY sch_checkin_time desc,user_id asc
+			</otherwise>
+		</choose>
+	</select>
+
+	<select id="queryCount" resultType="int" >
+		SELECT
+		count(distinct a.id)
+		from qw_clock_in_record_info a
+		<where>
+			a.del_flag = #{DEL_FLAG_NORMAL}
+			<if test="sqlMap.dsf !=null and sqlMap.dsf!=''">
+				${sqlMap.dsf}
+			</if>
+		</where>
+	</select>
+
+
+	<select id="getByUserIdAndCheckinTime" resultType="com.jeeplus.modules.wexintheorder.entity.ClockInRecordInfo">
+		select
+		<include refid="lockInRecordColumns"/>
+		,su.name as "userName"
+		from qw_clock_in_record_info a
+		left join sys_user su on su.id = a.sys_user_id
+		<where>
+			a.user_id = #{userId} and a.checkin_time = #{checkinTime} and a.del_flag = 0
+		</where>
+	</select>
+
+	<insert id="insert">
+		INSERT INTO qw_clock_in_record_info(
+			id,
+			create_by,
+			create_date,
+			update_by,
+			update_date,
+			remarks,
+			del_flag,
+			user_id,
+			group_name,
+			checkin_type,
+			exception_type,
+			checkin_time,
+			location_title,
+			location_detail,
+			wifi_name,
+			notes,
+			wifi_mac,
+			mediaids,
+			lat,
+			lng,
+			device_id,
+			sch_checkin_time,
+			group_id,
+			schedule_id,
+			timeline_id,
+			sys_user_id
+		) VALUES (
+			#{id},
+			#{createBy.id},
+			#{createDate},
+			#{updateBy.id},
+			#{updateDate},
+			#{remarks},
+			#{delFlag},
+			#{userId},
+			#{groupName},
+			#{checkinType},
+			#{exceptionType},
+			#{checkinTime},
+			#{locationTitle},
+			#{locationDetail},
+			#{wifiName},
+			#{notes},
+			#{wifiMac},
+			#{mediaIds},
+			#{lat},
+			#{lng},
+			#{deviceId},
+			#{schCheckinTime},
+			#{groupId},
+			#{scheduleId},
+			#{timelineId},
+			#{sysUserId}
+
+		)
+	</insert>
+
+	<update id="update">
+		UPDATE qw_clock_in_record_info SET
+			update_date = #{updateDate},
+			user_id = #{userId},
+			group_name = #{groupName},
+			checkin_type = #{checkinType},
+			exception_type = #{exceptionType},
+			checkin_time = #{checkinTime},
+			location_title = #{locationTitle},
+			location_detail = #{locationDetail},
+			wifi_name = #{wifiName},
+			notes = #{notes},
+			wifi_mac = #{wifiMac},
+			mediaids = #{mediaIds},
+			lat = #{lat},
+			lng = #{lng},
+			device_id = #{deviceId},
+			sch_checkin_time = #{schCheckinTime},
+			group_id = #{groupId},
+			schedule_id = #{scheduleId},
+			timeline_id = #{timelineId},
+			sys_user_id = #{sysUserId}
+		WHERE id = #{id}
+	</update>
+
+
+
+	<select id="getUserByQwUSerId" resultType="User">
+		select * from sys_user a
+		<where>
+			a.qw_user_id = #{qwUserId} and a.del_flag = 0
+		</where>
+	</select>
+
+</mapper>

+ 263 - 0
src/main/webapp/webpage/modules/qw/clickInRecode/ClickInRecordList.jsp

@@ -0,0 +1,263 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ page isELIgnored="false"%>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+	<title>企业微信员工打卡记录</title>
+	<meta name="decorator" content="default"/>
+	<style>
+		/*body{
+			background-color:transparent;
+			filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#26FFFFFF, endColorstr=#26FFFFFF);
+			color:#ffffff;
+			background-color:rgba(255,255,255,0);
+			height:100%;
+		}*/
+		.layui-layer-btn1:hover{
+			color: #c2c2c2;
+		}
+	</style>
+	<script type="text/javascript">
+		$(document).ready(function() {
+            $("#cus_name").show();
+            $("#cus_name").siblings().hide();
+            //搜索框收放
+            $('#moresee').click(function(){
+                if($('#moresees').is(':visible'))
+                {
+                    $('#moresees').slideUp(0,resizeListWindow1);
+                    $('#moresee i').removeClass("glyphicon glyphicon-menu-up").addClass("glyphicon glyphicon-menu-down");
+                }else{
+                    $('#moresees').slideDown(0,resizeListWindow1);
+                    $('#moresee i').removeClass("glyphicon glyphicon-menu-down").addClass("glyphicon glyphicon-menu-up");
+                }
+            });
+            laydate.render({
+                elem: '#beginDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
+                event: 'focus', //响应事件。如果没有传入event,则按照默认的click
+                type : 'date'
+, trigger: 'click'
+            });
+            laydate.render({
+                elem: '#endDate', //目标元素。由于laydate.js封装了一个轻量级的选择器引擎,因此elem还允许你传入class、tag但必须按照这种方式 '#id .class'
+                event: 'focus', //响应事件。如果没有传入event,则按照默认的click
+                type : 'date'
+, trigger: 'click'
+            });
+		});
+        function switchInput(obj){
+            $("#"+obj).show();
+            $("#"+obj).siblings().hide();
+        }
+        //打开对话框(查看)
+        function openDialogNow(title,url,width,height){
+            if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){//如果是移动端,就使用自适应大小弹窗
+                width='auto';
+                height='auto';
+            }else{//如果是PC端,根据用户设置的width和height显示。
+
+            }
+            top.layer.open({
+                type: 2,
+                area: [width, height],
+                title: title,
+                maxmin: true, //开启最大化最小化按钮
+                content: url ,
+                btn: ['关闭'],
+                cancel: function(index){
+                }
+            });
+        }
+
+
+        //打开对话框(查看)
+        function deleteFun(url){
+            if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){//如果是移动端,就使用自适应大小弹窗
+                width='auto';
+                height='auto';
+            }else{//如果是PC端,根据用户设置的width和height显示。
+
+            }
+
+			layer.confirm('确定要删除该客户信息吗?', {
+				title: "删除",
+				btn: ['确定','关闭'] //可以无限个按钮
+			},function(index, layero){
+				$.ajax({
+					type: 'post',
+					url:url,
+					dataType: "json",
+					cache: false,
+					processData: false,
+					contentType: false,
+				}).success(function (result) {
+					if(result.result == "1"){
+						layer.close(index);
+						top.layer.msg(result.msg, {icon: 1});
+						window.location.reload();
+					}else{
+						layer.close(index);
+						top.layer.msg(result.msg, {icon: 2});
+					}
+				});
+			}, function(index){
+				layer.close(index);
+			});
+		}
+
+		function cBlur(obj) {
+			var id = $("#createId").val();
+			if(undefined != obj.value && null != obj.value && '' != obj.value){
+				$.ajax({
+					url:'${ctx}/sys/user/getUserByName?name='+obj.value,
+					type:"post",
+					success:function(data){
+						var user = data.body.data;
+						if(undefined == user || null == user || '' == user){
+							$("#createId").val("");
+						}else{
+							if(data.body.data.id != id){
+								if(undefined != id && null != id && '' != id){
+									$("#createId").val("");
+								}
+							}
+						}
+					}
+				});
+			}else{
+				$("#createId").val("");
+			}
+
+		}
+	</script>
+</head>
+<body class="gray-bg">
+<div class="wrapper wrapper-content">
+	<sys:message content="${message}"/>
+	<div class="layui-row">
+		<div class="full-width fl">
+			<div class="layui-row contentShadow shadowLR" id="queryDiv">
+				<form:form id="searchForm" modelAttribute="clockInRecordInfo" action="${ctx}/clockInRecordController/list" method="post" class="form-inline">
+					<input id="pageNo" name="pageNo" type="hidden" value="${page.pageNo}"/>
+					<input id="pageSize" name="pageSize" type="hidden" value="${page.pageSize}"/>
+					<input id="toflag" name="toflag" type="hidden" value="1"/>
+					<%--<table:sortColumn id="orderBy" name="orderBy" value="${page.orderBy}" callback="sortOrRefresh();"/><!-- 支持排序 -->--%>
+					<div class="commonQuery lw7">
+						<%--<div class="layui-item query athird">
+							<label class="layui-form-label">名称:</label>
+							<div class="layui-input-block">
+								<form:input path="userName" htmlEscape="false" maxlength="255"  class=" form-control layui-input"/>
+							</div>
+						</div>
+						<div class="layui-item query athird">
+							<label class="layui-form-label">地区:</label>
+							<div class="layui-input-block with-icon">
+								<sys:treeselect id="area" name="area.id" value="${clockInRecordInfo.area.id}" labelName="area.name" labelValue="${clockInRecordInfo.area.name}"
+												title="区域" url="/sys/area/treeData" cssClass="form-control layui-input" allowClear="true" notAllowSelectParent="false" allowInput="true"/>
+							</div>
+						</div>--%>
+
+						<%--<div class="layui-item athird">
+							<div class="input-group">
+								<a href="#" id="moresee"><i class="glyphicon glyphicon-menu-down"></i></a>
+								<div class="layui-btn-group search-spacing">
+									<button id="searchQuery" class="layui-btn layui-btn-sm layui-bg-blue" onclick="search()">查询</button>
+									<button id="searchReset" class="layui-btn layui-btn-sm " onclick="resetSearch()">重置</button>
+								</div>
+							</div>
+						</div>--%>
+						<div style="    clear:both;"></div>
+					</div>
+					<div id="moresees" style="clear:both;display:none;" class="lw7">
+						<%--<div class="layui-item query athird">
+							<label class="layui-form-label">创建时间:</label>
+							<div class="layui-input-block readOnlyFFF">
+								<input id="beginDate" placeholder="开始时间" name="beginDate" type="text" readonly="readonly" maxlength="20" class="laydate-icondate form-control layer-date layui-input laydate-icon query-group"
+									   value="<fmt:formatDate value="${clockInRecordInfo.beginDate}" pattern="yyyy-MM-dd"/>"/>
+								</input>
+								<span class="group-sep">-</span>
+								<input id="endDate" placeholder="结束时间" name="endDate" type="text" readonly="readonly" maxlength="20" class="laydate-icondate form-control layer-date layui-input laydate-icon query-group"
+									   value="<fmt:formatDate value="${clockInRecordInfo.endDate}" pattern="yyyy-MM-dd"/>"/>
+								</input>
+							</div>
+						</div>--%>
+
+					</div>
+				</form:form>
+			</div>
+		</div>
+
+		<div class="full-width fl">
+			<div class="contentShadow layui-form contentDetails">
+				<div class="nav-btns">
+					<div class="layui-btn-group">
+						<shiro:hasPermission name="clockInRecord:clockInRecord:export">
+							<table:exportExcel url="${ctx}/clockInRecordController/export"></table:exportExcel><!-- 导出按钮 -->
+						</shiro:hasPermission>
+						<button class="layui-btn layui-btn-sm" data-toggle="tooltip" data-placement="left" onclick="sortOrRefresh()" title="刷新"> 刷新</button>
+					</div>
+					<div style="clear: both;"></div>
+				</div>
+				<table class="oa-table layui-table" id="contentTable"></table>
+
+				<!-- 分页代码 -->
+				<table:page page="${page}"></table:page>
+				<div style="clear: both;"></div>
+			</div>
+		</div>
+	</div>
+	<div id="changewidth"></div>
+</div>
+<script src="${ctxStatic}/layer-v2.3/layui/layui.all.js" charset="utf-8"></script>
+<script>
+    layui.use('table', function(){
+        layui.table.render({
+            limit:${ page.pageSize }
+            ,elem: '#contentTable'
+            ,page: false
+            ,cols: [[
+				{field:'index',align:'center', title: '序号',width:40}
+				,{field:'userName',align:'center', title: '姓名',width:100}
+                ,{field:'checkinType',align:'center', title: '打卡类型',width:100}
+                ,{field:'exceptionType',align:'center', title: '异常类型', width:100}
+                ,{field:'locationDetail',align:'center', title: '打卡地点', minWidth:100}
+                ,{field:'checkinTime', align:'center',title: '实际打卡时间',width:150}
+				,{field:'schCheckinTime', align:'center',title: '理论打卡时间',width:150}
+                ,{field:'wifiName',align:'center', title: '打卡wifi名称', width:120}
+            ]]
+            ,data: [
+                <c:if test="${ not empty page.list}">
+                <c:forEach items="${page.list}" var="clockInRecordInfo" varStatus="index">
+                <c:if test="${index.index != 0}">,</c:if>
+                {
+                    "index":"${index.index+1}"
+                    ,"id":"${clockInRecordInfo.id}"
+                    ,"userName":"${clockInRecordInfo.userName}"
+					,"checkinType":"${clockInRecordInfo.checkinType}"
+					,"exceptionType":"${clockInRecordInfo.exceptionType}"
+					,"locationDetail":"${clockInRecordInfo.locationDetail}"
+					,"checkinTime":"${clockInRecordInfo.checkinTime}"
+					,"schCheckinTime":"${clockInRecordInfo.schCheckinTime}"
+                    ,"wifiName":"${clockInRecordInfo.wifiName}"
+                }
+                </c:forEach>
+                </c:if>
+            ]
+        });
+
+    })
+
+    resizeListTable();/*消除由于有竖向滚动条造成table出现横向滚动条*/
+    $("a").on("click",addLinkVisied);
+</script>
+
+<script type="text/javascript">
+    resizeListWindow1();
+    $(window).resize(function(){
+        resizeListWindow1();
+    });
+</script>
+</body>
+
+</html>
+