钉钉统计部门个人请假次数go

前言

最近小组需要统计部门各种请假次数,写了一个方法,第一次实战中用到递归函数,简单记录一下。

效果展示

在这里插入图片描述

这些数据不需要返回json,这里这样是为了方便测试。可以通过这些数据完成其它的操作。

功能实现

钉钉服务端调试工具API Explorer

在这里插入图片描述

感兴趣的可以在接口里面详细看一下参数,这里就不一 一解释了

定义model

请求参数

package model

type RequestDingLeave struct {
	UseridList string `json:"userid_list"` // 待查询用户的ID列表,每次最多100个。
	StartTime  int    `json:"start_time"`  // 开始时间 ,Unix时间戳,支持最多180天的查询。
	EndTime    int    `json:"end_time"`    // 结束时间,Unix时间戳,支持最多180天的查询。
	Offset     int    `json:"offset"`      // 支持分页查询,与size参数同时设置时才生效,此参数代表偏移量,偏移量从0开始。
	Size       int    `json:"size"`        // 支持分页查询,与offset参数同时设置时才生效,此参数代表分页大小,最大20。
}

响应参数

package model

// DingLeaveStatus 请假状态
type DingLeaveStatus struct {
	StartTime       int64  `json:"start_time"`
	DurationPercent int    `json:"duration_percent"`
	EndTime         int64  `json:"end_time"`
	LeaveCode       string `json:"leave_code"` // 请假类型 个人事假:d4edf257-e581-45f9-b9b9-35755b598952  非个人事假:baf811bc-3daa-4988-9604-d68ec1edaf50  病假:a7ffa2e6-872a-498d-aca7-4554c56fbb52
	DurationUnit    string `json:"duration_unit"`
	UserID          string `json:"userid"`
}

// DingLeaveResult 请假列表
type DingLeaveResult struct {
	LeaveStatus *[]DingLeaveStatus `json:"leave_status"`
	HasMore     bool               `json:"has_more"` // 是否有更多数据
}

// DingResponse 钉钉响应
type DingResponse struct {
	ErrCode   int             `json:"errcode"`
	Result    DingLeaveResult `json:"result"`
	Success   bool            `json:"success"`
	ErrMsg    string          `json:"errmsg"`
	RequestID string          `json:"request_id"`
}

type DingUser struct {
	Id   string `json:"id"`
	Name string `json:"name"`
	Type map[string]int
}
功能逻辑

我这里只是想简单的实现一下功能,并没有按照严格标准的mvc分层,还请见谅

package controller

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"leave/model"
	"net/http"
	"time"
)

var tmp = map[string]string{"d4edf257-e581-45f9-b9b9-35755b598952": "个人事假", "a7ffa2e6-872a-498d-aca7-4554c56fbb52": "病假", "baf811bc-3daa-4988-9604-d68ec1edaf50": "非个人事假"} // code与请假类型对应

// GetDepartmentLeaveStatus 统计部门请假状态
func GetDepartmentLeaveStatus(c *gin.Context) {
	userList := "323832232226246897,01320463195324064909,02280849645326263552,01546916272226288917"	// 模拟数据
	leave := model.RequestDingLeave{
		UseridList: userList,
		StartTime:  1698624000000,	
		EndTime:    int(time.Now().UnixMilli()), // 拿到当前的时间戳
		Offset:     0,
		Size:       2,
	}
	res := []model.DingLeaveStatus{}
	res, err := GetLeaveStatus(leave, res)
	if err != nil {
		return
	}
	statistics := map[string]model.DingUser{}
	for _, v := range res {
		_, exist := statistics[v.UserID]
		if !exist {
			statistics[v.UserID] = model.DingUser{Type: map[string]int{}}
		}
		statistics[v.UserID].Type[tmp[v.LeaveCode]]++
	}

	c.JSON(http.StatusOK, statistics)
	fmt.Println(int(time.Now().Weekday()))
	return
}

// GetLeaveStatus 获取请假状态
func GetLeaveStatus(leave model.RequestDingLeave, res []model.DingLeaveStatus) ([]model.DingLeaveStatus, error) {
	// 将json数据编码为字节数组
	var send func(leave model.RequestDingLeave) error

	// 切片作为函数参数传递时为值传递,如果每次传入新的切片需要增加返回值接收,这里直接使用的传入的res作为变量并返回
	send = func(leave model.RequestDingLeave) error {
		jsonLeave, err := json.Marshal(leave)
		if err != nil {
			fmt.Println("json.Marshal(leave) failed:", err)
			return err
		}
		url := fmt.Sprintf("https://oapi.dingtalk.com/topapi/attendance/getleavestatus?%s", "access_token=企业token") // access_token 填企业token
		buffer := bytes.NewBuffer(jsonLeave)
		response, err := http.Post(url, "application/json", buffer)
		if err != nil {
			fmt.Println("http.Post(\"https://oapi.dingtalk.com/topapi/attendance/getleavestatus\", \"application/json\", buffer) failed:", err)
			return err
		}
		var dingResp model.DingResponse
		err = json.NewDecoder(response.Body).Decode(&dingResp)	// 将响应的json绑定到dingResp中
		if err != nil {
			return err
		}
		res = append(res, *dingResp.Result.LeaveStatus...)
		if dingResp.Result.HasMore {	// 如果有更多的记录,再次请求并添加到切片后面
			leave.Offset += leave.Size
			send(leave)					// 递归
		}
		return nil
	}
	err := send(leave)
	return res, err
}

其他
package router

import (
	"github.com/gin-gonic/gin"
	"leave/controller"
)

func SetupRouter() *gin.Engine {
	r := gin.Default()
	r.GET("/test", controller.GetDepartmentLeaveStatus)
	return r
}

package main

import "leave/router"

func main() {
	router := router.SetupRouter()
	router.Run()
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【java进阶】集合的三种遍历(迭代器、增强for、Lambda)

目录 一、先谈集合: 二、单列集合的三种遍历方式 迭代器遍历 增强for遍历 Lambda表达式遍历 一、先谈集合: 🔥那我们平常用for循环依赖下标遍历不行嘛,这就与集合的分类有关了。 集合的体系结构: collection是单…

【论文笔记】Denoising Diffusion Probabilistic Models

Pre Knowledge 1.条件概率的一般形式 P ( A , B ) P ( B ∣ A ) P ( A ) P(A,B)P(B|A)P(A) P(A,B)P(B∣A)P(A) P ( A , B , C ) P ( C ∣ B , A ) P ( B , A ) P ( C ∣ B , A ) P ( B ∣ A ) P ( A ) P(A,B,C)P(C|B,A)P(B,A)P(C|B,A)P(B|A)P(A) P(A,B,C)P(C∣B,A)P(B,A)P…

[游戏中的图形学实时渲染技术] Part1 实时阴影技术

原理篇: 常见的渲染方程如下: 在不考虑自发光项与考虑阴影对于着色结果的影响之后可以将方程变化为如下形式: 如果射线在到达光源前击中了其他物体时,就认为这条来自光源的光线对着色点没有贡献。 利用上述渲染方程进行正确的着…

使用MybatisPlus时出现的java.lang.NullPointerException异常~

错误描述如下所示: 错误原因:Junit的导包错误 单元测试的包有如下所示两个 我们应该根据springboot的版本进行选择, 在Spring Boot 2.2.X以后使用import org.junit.jupiter.api.Test Junit5 在Spring Boot 2.2.x之前使用import org.junit.T…

基于SSM的校园二手物品交易平台设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

高防IP是什么?有什么优势?

一.高防IP的概念 高防IP是指高防机房所提供的IP段,一种付费增值服务,主要是针对网络中的DDoS攻击进行保护。用户可以通过配置高防IP,把域名解析到高防IP上,引流攻击流量,确保源站的稳定可靠。 二.高防IP的原理 高防I…

k8s 裸金属集群部署metalLB软负载均衡 —— 筑梦之路

metalLB 官方网站 Repo:https://github.com/metallb/metallb 官网:https://metallb.universe.tf/installation metalLB解决什么问题? MetalLB 是一个用于裸机 Kubernetes 集群的负载均衡器实现,使用标准路由协议。 k8s 并没有为裸…

CSS特效006:绘制不断跳动的心形

css实战中,怎么绘制不断跳动的心形呢? 绘图的时候主要用到了transform: rotate(-45deg); transform-origin: 0 100%; transform: rotate(45deg); transform-origin: 100% 100%; 动画使用keyframes 时间上为infinite。 效果图 源代码 /* * Author: 大剑…

两数之和问题

题目描述 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。 你可以按任意顺…

[头歌]第1关:动态学生信息管理

题目: C 面向对象 _ STL 的应用 (educoder.net) 考点: 1.自定义排序 bool cmp 2.如何使用find和erase来找到学生类里面的指定姓名的人并将其从动态数组中删除。 3.find要找的是学生类里面的成员变量而非单纯的直接找值,应如何实现 &…

dcat admin 各种问题

样式问题 如何根据条件给表格数据栏添加背景色 use Illuminate\Support\Collection;protected function grid(){return Grid::make(new BookArticle(), function (Grid $grid) {... 其他代码// Collection的完整路径:Illuminate\Support\Collection;$grid->row…

Python 使用tkinter复刻Windows记事本UI和菜单功能(二)

上一篇:Python tkinter实现复刻Windows记事本UI和菜单的文本编辑器(一)-CSDN博客 下一篇:敬请耐心等待,如发现BUG以及建议,请在评论区发表,谢谢! 相对上一篇文章,本篇文…

数字化仪的超声波应用

超声波是频率大于人类听觉范围上限的声学声压(声学)波。超声波设备的工作频率为 20 kHz 至几千 MHz。表 1 总结了一些更常见的超声波应用的特征。每个应用中使用的频率范围都反映了实际情况下的平衡。提高工作频率可以通过提高分辨率来检测较小的伪影&am…

JAVA集合学习

一、结构 List和Set继承了Collection接口,Collection继承了Iterable Object类是所有类的根类,包括集合类,集合类中的元素通常是对象,继承了Object类中的一些基本方法,例如toString()、equals()、hashCode()。 Collect…

时间序列预测实战(九)PyTorch实现LSTM-ARIMA融合移动平均进行长期预测

一、本文介绍 本文带来的是利用传统时间序列预测模型ARIMA(注意:ARIMA模型不属于机器学习)和利用PyTorch实现深度学习模型LSTM进行融合进行预测,主要思想是->先利用ARIMA先和移动平均结合处理数据的线性部分(例如趋势和季节性&#xff09…

【mysql】将逗号分割的字段内容转换为多行并group by

先说需求: 公司想让我通过mysql导出一个报表,内容为公司每个人参加会议的次数,现在有一个会议表fusion_meeting,正常的逻辑是通过人员直接group by就可以得出结果,但是我们的参会人是通过逗号分割这种方式存在一个字段…

【MySQL基本功系列】第二篇 InnoDB事务提交过程深度解析

通过上一篇博文,我们简要了解了MySQL的运行逻辑,从用户请求到最终将数据写入磁盘的整个过程。 当数据写入磁盘时,存储引擎扮演着关键的角色,它负责实际的数据存储和检索。 在MySQL中,有多个存储引擎可供选择&#xf…

vColorPicker——基于 Vue 的颜色选择器插件

文章目录 前言样例特点 一、使用步骤?1. 安装2.引入3.在项目中使用 vcolorpicker 二、选项三、事件 前言 vColorPicker——官网 vColorPicker——GitHub 样例 vColorPicker是基于 Vue 的一款颜色选择器插件,仿照Angular的color-picker插件制作 特点 …

【GIT】git分支命令,使用分支场景介绍git标签介绍,git标签命令,git标签使用的场景git查看提交历史

目录 一,git分支命令,使用分支场景介绍 二,git标签介绍,git标签命令,git标签使用的场景 三,git查看提交历史 前言: 今天我们来聊聊关于Git 分支管理。几乎每一种版本控制系统都以某种形式支持…

第24章_mysql性能分析工具的使用

文章目录 1. 数据库服务器的优化步骤2.查看系统性能参数3. 统计SQL的查询成本:last_query_cost4. 定位执行慢的 SQL:慢查询日志4.1 开启慢查询日志参数4.2 查看慢查询数目4.3 测试慢sql语句,查看慢日志4.4 系统变量 log_output, l…