Browse Source

修改金蝶对照HR行政组织

v2_dev
超级管理员 2 years ago
parent
commit
cac7321819
  1. 114
      api/version1/administrativeorganization/govcont.go
  2. 8
      api/version1/administrativeorganization/type.go
  3. 470
      api/version1/personnelapi/peoplestatistics.go
  4. 2
      api/version1/personnelapi/staffarchives.go
  5. 48
      api/version1/personnelapi/type.go
  6. 13
      api/version1/shiyan/shiyan.go
  7. 2
      apirouter/organization/organization_group.go
  8. 6
      apirouter/personnel/people.go
  9. 59
      models/hrmodels/educational_structure.go
  10. 73
      models/hrmodels/emp_onb_arc.go
  11. 65
      models/hrmodels/user_emp.go
  12. 206
      overall/overallhandle/overall_handle.go
  13. 5
      overall/overallhandle/type.go

114
api/version1/administrativeorganization/govcont.go

@ -1093,10 +1093,10 @@ func (o *OrganizationApi) BasisOrgObtainSonOrgAndMan(c *gin.Context) {
idInt, _ := strconv.ParseInt(requestData.Id, 10, 64) idInt, _ := strconv.ParseInt(requestData.Id, 10, 64)
idList = []int64{idInt} idList = []int64{idInt}
if idInt != 309 { if idInt != 313 {
err = orgCont.GetCont(map[string]interface{}{"id": idInt}) err = orgCont.GetCont(map[string]interface{}{"id": idInt})
parenAry.SunList = append(parenAry.SunList, idInt) parenAry.SunList = append(parenAry.SunList, idInt)
parenAry.GetAllParentOrg(idInt, 3) parenAry.GetAllParentOrg(idInt, 2)
} else { } else {
} }
@ -1132,7 +1132,7 @@ func (o *OrganizationApi) BasisOrgObtainSonOrgAndMan(c *gin.Context) {
var orgAndPeopleListCont empowerSyncDepartMan //启用协程结构体 var orgAndPeopleListCont empowerSyncDepartMan //启用协程结构体
synPro.Add(1) synPro.Add(1)
go orgAndPeopleListCont.BasisOrgDirectOrg(isNotIn, idList, 3) //获取行政组织 go orgAndPeopleListCont.BasisOrgDirectOrg(isNotIn, idList, 2) //获取行政组织
synPro.Add(1) synPro.Add(1)
go orgAndPeopleListCont.GetPeopleListIng(isNotIn, idList) //获取人员 go orgAndPeopleListCont.GetPeopleListIng(isNotIn, idList) //获取人员
synPro.Wait() synPro.Wait()
@ -1776,3 +1776,111 @@ func (o *OrganizationApi) NewEiteGovStateOrDel(c *gin.Context) {
overallhandle.Result(0, err, c) overallhandle.Result(0, err, c)
} }
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 09:13:10
@ 功能: 获取行政组织直接下属
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (o *OrganizationApi) GetOrgChiled(c *gin.Context) {
var requestData overallhandle.PublicId[int64]
err := c.ShouldBindJSON(&requestData)
if err != nil {
overallhandle.Result(100, err, c)
return
}
if requestData.Id == 0 {
overallhandle.Result(1, err, c, "请提交行政组织ID")
return
}
var orgList []models.AdministrativeOrganization
err = overall.CONSTANT_DB_HR.Where("`state` = 1 AND `superior` = ?", requestData.Id).Find(&orgList).Error
if err != nil {
overallhandle.Result(107, err, c)
return
}
var sendList []AdminOrgSend
for _, v := range orgList {
var sendCont AdminOrgSend
sendCont.Id = v.Id //
sendCont.Number = v.Number //行政编码"`
sendCont.Name = v.Name //组织名称"`
sendCont.Superior = v.Superior //上级ID"`
sendCont.OrganizationType = v.OrganizationType //行政组织类型"`
sendCont.Abbreviation = v.Abbreviation //行政组织简称"`
sendCont.Time = v.Time //创建时间"`
sendCont.State = v.State //状态(1:启用;2:禁用;3:删除)"`
sendCont.WechatOrganizationId = v.WechatOrganizationId //20微信组织架构对照码"`
sendCont.SuperiorSun = v.SuperiorSun //级联ID"`
sendCont.Schoole = v.Schoole //原知行学院对照码"`
sendCont.KingdeeId = v.KingdeeId //金蝶对照ID"`
sendCont.IsPower = v.IsPower // 是否为实权部门"`
sendCont.Sort = v.Sort //是否为实权部门"`
sendCont.IsChild = judgeIsChild(v.Id)
sendList = append(sendList, sendCont)
}
sendOrgList := overallhandle.MapOut()
sendOrgList["list"] = sendList
userKey := c.Request.Header.Get("user-key")
myCont, myErr := overallhandle.GetCreetUserCont(userKey)
if myErr == nil {
sendOrgList["current"] = myCont.Company
} else {
sendOrgList["current"] = 309
}
var parenAry overallhandle.AllSunList[int64]
parenAry.SunList = append(parenAry.SunList, requestData.Id)
parenAry.GetAllParentOrg(requestData.Id, 2)
fmt.Printf("父级--->%v\n", parenAry.SunList)
var orgAndPeopleListTitleCont empowerSynces //启用协程结构体
synProes.Add(1)
go orgAndPeopleListTitleCont.BasisOrgDirectOrgIng(parenAry.SunList) //获取行政组织
synProes.Wait()
orgTitleList := orgAndPeopleListTitleCont.readDataLock()
sort.SliceStable(orgTitleList, func(i, j int) bool {
return orgTitleList[i].Sort < orgTitleList[j].Sort
})
var tabval []TitleDepartmentsCont
if len(parenAry.SunList) > 0 && requestData.Id != 313 {
for _, ov := range orgTitleList {
var titleDepartCont TitleDepartmentsCont
titleDepartCont.DepartmentId = ov.Id //行政组织ID
titleDepartCont.Id = ov.Id //行政组织ID
titleDepartCont.DepartmentKey = ov.Number //行政组织编码
titleDepartCont.DepartmentName = ov.Name //行政组织名称
titleDepartCont.ParentId = ov.Superior //上级ID
titleDepartCont.DepartmentNames = ov.Name //行政组织别名
tabval = append(tabval, titleDepartCont)
}
}
sendOrgList["tabval"] = tabval
overallhandle.Result(0, sendOrgList, c)
}
// 判断是否有子集
func judgeIsChild(orgId int64) (isTrue bool) {
isTrue = false
var countid int64
err := overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Where("`state` = 1 AND `superior` = ?", orgId).Count(&countid).Error
if err != nil {
return
}
if countid > 0 {
isTrue = true
}
return
}

8
api/version1/administrativeorganization/type.go

@ -528,3 +528,11 @@ type PublicAddPostCont struct {
Superior int64 `json:"superior"` //上级岗位 Superior int64 `json:"superior"` //上级岗位
Incharge string `json:"incharge"` // 1:责任岗;2:非责任岗 Incharge string `json:"incharge"` // 1:责任岗;2:非责任岗
} }
/*
行政组织
*/
type AdminOrgSend struct {
models.AdministrativeOrganization
IsChild bool `json:"ischild"`
}

470
api/version1/personnelapi/peoplestatistics.go

@ -0,0 +1,470 @@
package personnelapi
import (
"fmt"
"hr_server/models"
"hr_server/models/hrmodels"
"hr_server/overall"
"hr_server/overall/overallhandle"
"time"
"github.com/gin-gonic/gin"
)
/*
*
@ 作者: 秦东
@ 时间: 2023-06-29 15:10:35
@ 功能: 离职率
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (s *StaffApi) DimissionRate(c *gin.Context) {
var requestData TurnoverRate
err := c.ShouldBindJSON(&requestData)
if err != nil {
requestData.Id = 313
}
if requestData.Id == 0 {
requestData.Id = 313
}
currentTime := time.Now().Unix()
statisticalTime := currentTime
if requestData.Time != "" {
var timeCont overallhandle.DateTimeTotimes
timeCont.BaisStrToTime(requestData.Time)
statisticalTime = timeCont.AllTime
}
//行政组织
var orgList []models.AdministrativeOrganization
err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error
if err != nil {
overallhandle.Result(107, err, c)
return
}
currentYear := overallhandle.ComputingTime(statisticalTime, 1)
currentMonths := overallhandle.ComputingTime(statisticalTime, 3)
// var i int64
if currentYear != overallhandle.ComputingTime(currentTime, 1) {
currentMonths = 12
}
var calRateCont CalTurRateContBlack
calRateCont.CurrentOrgId = requestData.Id
for _, v := range orgList { //行政组织
calRateCont.Dfg(currentYear, currentMonths, v)
}
fmt.Printf("行政组织总数----->%v----->%v\n", len(orgList), len(calRateCont.List))
overallhandle.Result(0, calRateCont, c)
}
func (c *CalTurRateContBlack) Dfg(years, months int64, orgCont models.AdministrativeOrganization) {
// defer synPro.Done()
var contData SendCalTurRateCont
contData.OrgId = orgCont.Id
contData.OrgName = orgCont.Name
var sunAry overallhandle.AllSunList[int64]
sunAry.GetAllSunOrg(orgCont.Id)
var sumPeople int64
overall.CONSTANT_DB_HR.Model(&models.PersonArchives{}).Select("`id`").Where("admin_org IN ? AND emp_type BETWEEN ? AND ?", sunAry.SunList, 1, 10).Count(&sumPeople)
var i int64
for i = 1; i <= months; i++ {
var timeCont overallhandle.DateTimeTotimes
timeCont.BaisStrToTime(fmt.Sprintf("%v-%v-01 00:00:00", years, i))
// fmt.Printf("时间--->%v\n", timeCont.Time)
hjsdk := overallhandle.UnixTimeToDay(timeCont.AllTime, 14)
startTime, endTime := overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdk)
var reatCount int64
overall.CONSTANT_DB_HR.Model(&hrmodels.UserEmp{}).Select("`id`").Where("admin_org IN ? AND leave_date BETWEEN ? AND ?", sunAry.SunList, startTime, endTime).Count(&reatCount)
beiChuShu := sumPeople + reatCount
if beiChuShu == 0 {
contData.Odds = append(contData.Odds, 0)
} else {
reatVal := overallhandle.DecimalEs((float64(reatCount)/float64(beiChuShu))*100, 3)
contData.Odds = append(contData.Odds, reatVal)
}
}
c.List = append(c.List, contData)
}
/*
*
@ 作者: 秦东
@ 时间: 2023-06-29 16:10:50
@ 功能: 根据行政组织计算时间内的离职率
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (c *CalTurRateCont) CalculateTurnoverRate(years, months int64, orgCont models.AdministrativeOrganization) {
// defer synPro.Done()
var calCont CalculateTurnoverRateCont
calCont.OrgId = orgCont.Id
calCont.OrgName = orgCont.Name
calCont.Months = months
calCont.Odds = months
c.List = append(c.List, calCont)
}
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 09:36:07
@ 功能: 获取单一行政组织离职率
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (s *StaffApi) GetOenOrgDimRate(c *gin.Context) {
userKey := c.Request.Header.Get("user-key")
myCont, myErr := overallhandle.GetCreetUserCont(userKey)
var requestData TurnoverRate
err := c.ShouldBindJSON(&requestData)
if err != nil {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
if requestData.Id == 0 {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
fmt.Printf("获得行政组织--->%v\n--->%v\n--->%v\n", userKey, myCont, requestData)
currentTime := time.Now().Unix()
statisticalTime := currentTime
if requestData.Time != "" {
var timeCont overallhandle.DateTimeTotimes
timeCont.BaisStrToTime(requestData.Time)
statisticalTime = timeCont.AllTime
}
//行政组织
var orgList []models.AdministrativeOrganization
err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error
if err != nil {
overallhandle.Result(107, err, c)
return
}
currentYear := overallhandle.ComputingTime(statisticalTime, 1)
currentMonths := overallhandle.ComputingTime(statisticalTime, 3)
// var i int64
if currentYear != overallhandle.ComputingTime(currentTime, 1) {
currentMonths = 12
}
var calRateCont CalTurRateContBlack
calRateCont.CurrentOrgId = requestData.Id
for _, v := range orgList { //行政组织
calRateCont.Dfg(currentYear, currentMonths, v)
}
fmt.Printf("行政组织总数----->%v----->%v\n", len(orgList), len(calRateCont.List))
overallhandle.Result(0, calRateCont, c)
}
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 14:08:40
@ 功能: 获取公司指定年月的离职率
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (s *StaffApi) GetOrgTimeRate(c *gin.Context) {
userKey := c.Request.Header.Get("user-key")
myCont, myErr := overallhandle.GetCreetUserCont(userKey)
var requestData TurnoverRate
err := c.ShouldBindJSON(&requestData)
if err != nil {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
if requestData.Id == 0 {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
//行政组织
var orgList []models.AdministrativeOrganization
err = overall.CONSTANT_DB_HR.Model(&models.AdministrativeOrganization{}).Select("`id`,`name`").Where("`state` = 1 AND `superior` = ?", requestData.Id).Order("`sort` ASC").Find(&orgList).Error
if err != nil {
overallhandle.Result(107, err, c)
return
}
currentTime := time.Now().Unix()
hjsdk := overallhandle.UnixTimeToDay(currentTime, 14)
startTime, endTime := overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdk)
if requestData.Time != "" {
var timeCont overallhandle.DateTimeTotimes
timeCont.BaisStrToTime(requestData.Time)
fmt.Printf("时间--->%v\n--->%v\n", requestData.Time, timeCont.Time)
hjsdks := overallhandle.UnixTimeToDay(timeCont.AllTime, 14)
fmt.Printf("时间--222->%v\n", hjsdks)
startTime, endTime = overallhandle.GetAppointMonthStarAndEndTimeEs(hjsdks)
}
var calRateCont SendPicRateInfo
calRateCont.CurrentOrgId = requestData.Id
for _, v := range orgList { //行政组织
calRateCont.MonthsRate(startTime, endTime, v)
}
overallhandle.Result(0, calRateCont, c)
}
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 14:17:14
@ 功能: 计算指定月份离职率
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (c *SendPicRateInfo) MonthsRate(startTime, endTime int64, orgCont models.AdministrativeOrganization) {
var contData SendPicRateCont
contData.OrgId = orgCont.Id
contData.OrgName = orgCont.Name
var sunAry overallhandle.AllSunList[int64]
sunAry.GetAllSunOrg(orgCont.Id)
var sumPeople int64
overall.CONSTANT_DB_HR.Model(&models.PersonArchives{}).Select("`id`").Where("admin_org IN ? AND emp_type BETWEEN ? AND ?", sunAry.SunList, 1, 10).Count(&sumPeople)
var reatCount int64
overall.CONSTANT_DB_HR.Model(&hrmodels.UserEmp{}).Select("`id`").Where("admin_org IN ? AND leave_date BETWEEN ? AND ?", sunAry.SunList, startTime, endTime).Count(&reatCount)
beiChuShu := sumPeople + reatCount
if beiChuShu == 0 {
contData.Odds = 0
} else {
reatVal := overallhandle.DecimalEs((float64(reatCount)/float64(beiChuShu))*100, 3)
contData.Odds = reatVal
}
c.List = append(c.List, contData)
}
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 15:49:31
@ 功能: 获取学历结构
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func (s *StaffApi) GetEducationalStructure(c *gin.Context) {
userKey := c.Request.Header.Get("user-key")
myCont, myErr := overallhandle.GetCreetUserCont(userKey)
var requestData overallhandle.PublicId[int64]
err := c.ShouldBindJSON(&requestData)
if err != nil {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
if requestData.Id == 0 {
if myErr != nil {
requestData.Id = 309
} else {
requestData.Id = myCont.Company
}
}
var sunAry overallhandle.AllSunList[int64]
sunAry.GetAllSunOrg(requestData.Id)
//学历列表
var eduStruListCont []hrmodels.EducationalStructure
err = overall.CONSTANT_DB_HR.Distinct("`number`,MAX(`education`) as educationmax ").Where("admin_org IN ?", sunAry.SunList).Group("`number`").Find(&eduStruListCont).Error
if err != nil {
overallhandle.Result(0, err, c)
}
a1 := 0
a2 := 0
a3 := 0
a4 := 0
a5 := 0
a6 := 0
a7 := 0
a8 := 0
a9 := 0
a10 := 0
a11 := 0
a12 := 0
for _, v := range eduStruListCont {
switch v.EducationMax {
case 1:
a1++
case 2:
a2++
case 3:
a3++
case 4:
a4++
case 5:
a5++
case 6:
a6++
case 7:
a7++
case 8:
a8++
case 9:
a9++
case 10:
a10++
case 11:
a11++
case 12:
a12++
default:
}
}
var sendEducStruCont []EducStruCont
sumPie := a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12
if a1 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a1)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "初中及以下", Percentage: proportion})
}
if a2 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a2)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "中专", Percentage: proportion})
}
if a3 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a3)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "高中", Percentage: proportion})
}
if a4 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a4)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "中技", Percentage: proportion})
}
if a5 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a5)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "高技", Percentage: proportion})
}
if a6 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a6)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "函数专科", Percentage: proportion})
}
if a7 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a7)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "大学专科", Percentage: proportion})
}
if a8 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a8)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "函数本科", Percentage: proportion})
}
if a9 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a9)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "大学本科", Percentage: proportion})
}
if a10 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a10)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "硕士研究生", Percentage: proportion})
}
if a11 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a11)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "博士研究生", Percentage: proportion})
}
if a12 != 0 {
var proportion float64
if sumPie != 0 {
proportion = overallhandle.DecimalEs((float64(a12)/float64(sumPie))*100, 3)
}
sendEducStruCont = append(sendEducStruCont, EducStruCont{Education: "专家、教授", Percentage: proportion})
}
overallhandle.Result(0, sendEducStruCont, c)
}

2
api/version1/personnelapi/staffarchives.go

@ -1873,7 +1873,7 @@ func (s *StaffApi) WeChatGiveUsCont(c *gin.Context) {
myCont["planformaldate"] = userCont.Planformaldate //预计转正日期 myCont["planformaldate"] = userCont.Planformaldate //预计转正日期
myCont["political_outlook"] = userCont.PoliticalOutlook //政治面貌(1:群众;2:无党派;3:台盟会员;4:九三社员;5:致公党员;6:农工党员;7:民进会员;8:民建会员;9:民盟盟员;10:民革会员,11:共青团员;12:预备党员;13:中共党员) myCont["political_outlook"] = userCont.PoliticalOutlook //政治面貌(1:群众;2:无党派;3:台盟会员;4:九三社员;5:致公党员;6:农工党员;7:民进会员;8:民建会员;9:民盟盟员;10:民革会员,11:共青团员;12:预备党员;13:中共党员)
redisClient.HashMsetAdd(redisMyContKey, myCont) redisClient.HashMsetAdd(redisMyContKey, myCont)
saveData["userinfo"] = myCont
var sendKpiCont WriteIderCont var sendKpiCont WriteIderCont
sendKpiCont.Openid = requestData.OpenId sendKpiCont.Openid = requestData.OpenId
sendKpiCont.Key = userKeyCode sendKpiCont.Key = userKeyCode

48
api/version1/personnelapi/type.go

@ -581,3 +581,51 @@ type editUSerIcons struct {
Id int64 `json:"id"` // Id int64 `json:"id"` //
IconPath string `json:"iconpath"` // IconPath string `json:"iconpath"` //
} }
// 获取离职率
type TurnoverRate struct {
overallhandle.PublicId[int64]
Time string `json:"time"`
}
// 离职率计算
type CalculateTurnoverRateCont struct {
OrgId int64 `json:"orgid"`
OrgName string `json:"orgname"`
Months int64 `json:"months"`
Odds int64 `json:"odds"`
}
type CalTurRateCont struct {
List []CalculateTurnoverRateCont `json:"list"`
}
// 输出离职率
type SendCalTurRateCont struct {
OrgId int64 `json:"orgid"`
OrgName string `json:"orgname"`
Odds []float64 `json:"odds"`
}
type CalTurRateContBlack struct {
CurrentOrgId int64 `json:"currentorgid"`
List []SendCalTurRateCont `json:"list"`
}
/*
输出饼型离职率
*/
type SendPicRateCont struct {
OrgId int64 `json:"orgid"`
OrgName string `json:"orgname"`
Odds float64 `json:"odds"`
}
type SendPicRateInfo struct {
CurrentOrgId int64 `json:"currentorgid"`
List []SendPicRateCont `json:"list"`
}
// 学历结构
type EducStruCont struct {
Education string `json:"education"`
Percentage float64 `json:"percentage"`
}

13
api/version1/shiyan/shiyan.go

@ -298,19 +298,20 @@ func (s *ShiYan) Shitu(c *gin.Context) {
c.ShouldBindJSON(&req) c.ShouldBindJSON(&req)
out := overallhandle.MapOut() out := overallhandle.MapOut()
// groupId := overallhandle.RecursionOrgLevees(103, req.Id, 4)
groupId, companyId, departmentId, sunDepartId, workShopId := overallhandle.GetOrgStructure(req.Id) groupId, companyId, departmentId, sunDepartId, workShopId := overallhandle.GetOrgStructure(req.Id)
sdee := overallhandle.RecursionOrgLeve(req.Id, 3) // sdee := overallhandle.RecursionOrgLeve(req.Id, 3)
// node, err := snowflake.NewWorker(1) // // node, err := snowflake.NewWorker(1)
// fmt.Printf("node--------->%v\n", err) // // fmt.Printf("node--------->%v\n", err)_, companyId, departmentId, sunDepartId, _ := overallhandle.GetOrgStructure(orgMainDepart.Id)
// out["node"] = node.GetId() // // out["node"] = node.GetId()
// out["err "] = err // // out["err "] = err
out["groupId "] = groupId out["groupId "] = groupId
out["companyId "] = companyId out["companyId "] = companyId
out["departmentId "] = departmentId out["departmentId "] = departmentId
out["sunDepartId "] = sunDepartId out["sunDepartId "] = sunDepartId
out["workShopId "] = workShopId out["workShopId "] = workShopId
out["sdee "] = sdee // out["sdee "] = sdee
overallhandle.Result(0, out, c) overallhandle.Result(0, out, c)
} }

2
apirouter/organization/organization_group.go

@ -53,6 +53,8 @@ func (o *OrganizationRoute) InitRouterGroup(route *gin.RouterGroup) {
apiRouter.POST("govnewthreeing", apiHandle.GovNewThreeIng) //行政组织树(新副本) apiRouter.POST("govnewthreeing", apiHandle.GovNewThreeIng) //行政组织树(新副本)
apiRouter.POST("getorgchiled", apiHandle.GetOrgChiled) //获取行政组织直接下属
apiRouter.POST("govthreeaboutman", apiHandle.GovThreeAboutMan) //行政组织树及相关人员 apiRouter.POST("govthreeaboutman", apiHandle.GovThreeAboutMan) //行政组织树及相关人员
apiRouter.POST("search_org_people", apiHandle.SearchOrgAndPeople) //角色组织与人员搜索列表 apiRouter.POST("search_org_people", apiHandle.SearchOrgAndPeople) //角色组织与人员搜索列表

6
apirouter/personnel/people.go

@ -74,6 +74,12 @@ func (p *PersonnelRoute) InitRouterGroup(route *gin.RouterGroup) {
apiRouter.POST("addinsidehistorynew", apiHandle.AddInsideHistoryNew) //添加集团工作履历(新版) apiRouter.POST("addinsidehistorynew", apiHandle.AddInsideHistoryNew) //添加集团工作履历(新版)
apiRouter.POST("dimission_rate", apiHandle.DimissionRate) //离职率
apiRouter.POST("oneorg_dimission_rate", apiHandle.GetOenOrgDimRate) //获取单一行政组织离职率
apiRouter.POST("getorgtimerate", apiHandle.GetOrgTimeRate) //获取公司指定年月的离职率
apiRouter.POST("get_edu_stru", apiHandle.GetEducationalStructure) //获取学历结构
} }
} }

59
models/hrmodels/educational_structure.go

@ -0,0 +1,59 @@
package hrmodels
import (
"hr_server/overall"
"strings"
)
// 学历结构
type EducationalStructure struct {
Number string `json:"number" gorm:"column:number;type:varchar(30) unsigned;comment:员工工号"`
Education int `json:"education" gorm:"column:education;type:int(5) unsigned;default:1;comment:学历(1:初中及以下;2:中专;3:高中;4:中技;5:高技;6:函数专科;7:大学专科;8:函数本科;9:大学本科;10:硕士研究生;11:博士研究生;12:专家、教授)"`
AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:所属行政组织"`
EducationMax int `json:"educationmax" gorm:"column:educationmax;type:int(5) unsigned;default:1;comment:学历(1:初中及以下;2:中专;3:高中;4:中技;5:高技;6:函数专科;7:大学专科;8:函数本科;9:大学本科;10:硕士研究生;11:博士研究生;12:专家、教授)"`
}
func (EducationalStructure *EducationalStructure) TableName() string {
return "educational_structure"
}
// 编辑内容
func (cont *EducationalStructure) EiteCont(whereMap interface{}, saveData interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error
return
}
// 获取内容
func (cont *EducationalStructure) GetCont(whereMap interface{}, field ...string) (err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
gormDb = gormDb.Where(whereMap)
err = gormDb.First(&cont).Error
return
}
// 根据条件获取总数
func (cont *EducationalStructure) CountCont(whereMap interface{}) (countId int64) {
overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId)
return
}
// 读取全部信息
func (cont *EducationalStructure) ContMap(whereMap interface{}, field ...string) (countAry []EducationalStructure, err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
err = gormDb.Where(whereMap).Find(&countAry).Error
return
}
// 删除内容
func (cont *EducationalStructure) DelCont(whereMap interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error
return
}

73
models/hrmodels/emp_onb_arc.go

@ -0,0 +1,73 @@
package hrmodels
import (
"hr_server/overall"
"strings"
)
/**
@ 作者: 秦东
@ 时间: 2023-06-29 15:21:07
@ 功能: 人员变动时间
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
// 金蝶人员状态关键字
type EmpOnbArc struct {
Id int64 `json:"id" gorm:"primaryKey;column:id;type:bigint(20) unsigned;not null;comment:Id;index"`
UserId int64 `json:"userid" gorm:"column:userid;type:bigint(20) unsigned;default:0;not null;comment:员工ID"`
EntryTime int64 `json:"entrytime" gorm:"column:entry_time;type:bigint(20) unsigned;default:0;not null;comment:入职时间"`
LeaveDate int64 `json:"leavedate" gorm:"column:leave_date;type:bigint(20) unsigned;default:0;not null;comment:离职日期"`
ZhuanZheng int64 `json:"zhuanzheng" gorm:"column:zhuan_zheng;type:bigint(20) unsigned;default:0;not null;comment:转正"`
Time int64 `json:"time" gorm:"column:time;type:bigint(20) unsigned;default:0;not null;comment:时间"`
AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:行政组织"`
}
func (EmpOnbArc *EmpOnbArc) TableName() string {
return "emp_onb_arc"
}
// 编辑内容
func (cont *EmpOnbArc) EiteCont(whereMap interface{}, saveData interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error
return
}
// 获取内容
func (cont *EmpOnbArc) GetCont(whereMap interface{}, field ...string) (err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
gormDb = gormDb.Where(whereMap)
err = gormDb.First(&cont).Error
return
}
// 根据条件获取总数
func (cont *EmpOnbArc) CountCont(whereMap interface{}) (countId int64) {
overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId)
return
}
// 读取全部信息
func (cont *EmpOnbArc) ContMap(whereMap interface{}, field ...string) (countAry []EmpOnbArc, err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
err = gormDb.Where(whereMap).Find(&countAry).Error
return
}
// 删除内容
func (cont *EmpOnbArc) DelCont(whereMap interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error
return
}

65
models/hrmodels/user_emp.go

@ -0,0 +1,65 @@
package hrmodels
import (
"hr_server/overall"
"strings"
)
// 金蝶人员状态关键字
type UserEmp struct {
Id int64 `json:"id" gorm:"primaryKey;column:id;type:bigint(20) unsigned;not null;comment:Id;index"`
UserId int64 `json:"userid" gorm:"column:userid;type:bigint(20) unsigned;default:0;not null;comment:员工ID"`
EntryTime int64 `json:"entrytime" gorm:"column:entry_time;type:bigint(20) unsigned;default:0;not null;comment:入职时间"`
LeaveDate int64 `json:"leavedate" gorm:"column:leave_date;type:bigint(20) unsigned;default:0;not null;comment:离职日期"`
ZhuanZheng int64 `json:"zhuanzheng" gorm:"column:zhuan_zheng;type:bigint(20) unsigned;default:0;not null;comment:转正"`
RetireTime int64 `json:"retiretime" gorm:"column:retire_time;type:bigint(20) unsigned;default:0;not null;comment:退休"`
Time int64 `json:"time" gorm:"column:time;type:bigint(20) unsigned;default:0;not null;comment:时间"`
Number string `json:"number" gorm:"column:number;type:varchar(30) unsigned;not null;comment:员工工号"`
Name string `json:"name" gorm:"column:name;type:varchar(255) unsigned;default:'';not null;comment:姓名"`
AdminOrg int64 `json:"adminorg" gorm:"column:admin_org;type:bigint(20) unsigned;default:0;not null;comment:所属行政组织"`
}
func (UserEmp *UserEmp) TableName() string {
return "user_emp"
}
// 编辑内容
func (cont *UserEmp) EiteCont(whereMap interface{}, saveData interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Updates(saveData).Error
return
}
// 获取内容
func (cont *UserEmp) GetCont(whereMap interface{}, field ...string) (err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
gormDb = gormDb.Where(whereMap)
err = gormDb.First(&cont).Error
return
}
// 根据条件获取总数
func (cont *UserEmp) CountCont(whereMap interface{}) (countId int64) {
overall.CONSTANT_DB_HR.Model(&cont).Where(whereMap).Count(&countId)
return
}
// 读取全部信息
func (cont *UserEmp) ContMap(whereMap interface{}, field ...string) (countAry []UserEmp, err error) {
gormDb := overall.CONSTANT_DB_HR.Model(&cont)
if len(field) > 0 {
fieldStr := strings.Join(field, ",")
gormDb = gormDb.Select(fieldStr)
}
err = gormDb.Where(whereMap).Find(&countAry).Error
return
}
// 删除内容
func (cont *UserEmp) DelCont(whereMap interface{}) (err error) {
err = overall.CONSTANT_DB_HR.Where(whereMap).Delete(&cont).Error
return
}

206
overall/overallhandle/overall_handle.go

@ -6,7 +6,9 @@ import (
"crypto/rand" "crypto/rand"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"errors"
"fmt" "fmt"
"hr_server/grocerystore"
"hr_server/middleware/snowflake" "hr_server/middleware/snowflake"
"hr_server/models" "hr_server/models"
"hr_server/overall" "hr_server/overall"
@ -14,6 +16,7 @@ import (
"math" "math"
"math/big" "math/big"
"net/http" "net/http"
"reflect"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -22,6 +25,27 @@ import (
) )
// 全局函数处理 // 全局函数处理
var (
timeLayoutMap = map[string]string{
"y": "2006",
"m": "2006-01",
"d": "2006-01-02",
"h": "2006-01-02 15",
"i": "2006-01-02 15:04",
"s": "2006-01-02 15:04:05",
}
weekDay = map[string]int{
"Monday": 1,
"Tuesday": 2,
"Wednesday": 3,
"Thursday": 4,
"Friday": 5,
"Saturday": 6,
"Sunday": 7,
}
)
// 编号,纯数字 // 编号,纯数字
func TableNumber(class ...string) (number int64) { func TableNumber(class ...string) (number int64) {
result, _ := rand.Int(rand.Reader, big.NewInt(8999)) result, _ := rand.Int(rand.Reader, big.NewInt(8999))
@ -723,6 +747,31 @@ func PolitiToString(emp int) string {
return "群众" return "群众"
} }
} }
func RecursionOrgLevees(oldId, superior int64, leve int64) (groupId int64) {
if leve == 0 {
leve = 1
}
if superior == 0 {
return
}
var orgMap models.OrgContType
err := orgMap.GetCont(map[string]interface{}{"`id`": superior, "`state`": 1}, "`id`", "`superior`", "`level`")
if err != nil {
return
}
if orgMap.Level <= leve {
if orgMap.Level == leve {
groupId = oldId
} else {
groupId = orgMap.Id
}
return
} else {
groupId = RecursionOrgLevees(orgMap.Superior, orgMap.Superior, leve)
}
return
}
// 递归查找 // 递归查找
func RecursionOrgLeve(superior int64, leve int64) (groupId int64) { func RecursionOrgLeve(superior int64, leve int64) (groupId int64) {
@ -779,6 +828,9 @@ func RecursionOrgLeveEs(oldId, superior, leve int64) (groupId int64) {
// 获取集团、公司、部门、二级部门、工段 // 获取集团、公司、部门、二级部门、工段
func GetOrgStructure(orgId int64) (groupId, companyId, departmentId, sunDepartId, workShopId int64) { func GetOrgStructure(orgId int64) (groupId, companyId, departmentId, sunDepartId, workShopId int64) {
if orgId == 0 {
return
}
var orgContTypeInfo models.OrgContType var orgContTypeInfo models.OrgContType
err := orgContTypeInfo.GetCont(map[string]interface{}{"`id`": orgId}) err := orgContTypeInfo.GetCont(map[string]interface{}{"`id`": orgId})
if err != nil { if err != nil {
@ -789,25 +841,26 @@ func GetOrgStructure(orgId int64) (groupId, companyId, departmentId, sunDepartId
case 1: case 1:
groupId = orgContTypeInfo.Id groupId = orgContTypeInfo.Id
case 2: case 2:
groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 1) groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 1)
workShopId = orgContTypeInfo.Id workShopId = orgContTypeInfo.Id
case 3: case 3:
groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2)
companyId = orgContTypeInfo.Id companyId = orgContTypeInfo.Id
case 4: case 4:
groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2)
companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3)
departmentId = orgContTypeInfo.Id departmentId = orgContTypeInfo.Id
case 5: case 5:
groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 2) groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2)
companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3)
departmentId = RecursionOrgLeve(orgContTypeInfo.Superior, 4) departmentId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 4)
fmt.Printf("departmentId--->%v\norgId--->%v\n", departmentId, orgId)
sunDepartId = orgContTypeInfo.Id sunDepartId = orgContTypeInfo.Id
case 6: case 6:
groupId = RecursionOrgLeve(orgContTypeInfo.Superior, 1) groupId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 2)
companyId = RecursionOrgLeve(orgContTypeInfo.Superior, 3) companyId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 3)
departmentId = RecursionOrgLeve(orgContTypeInfo.Superior, 4) departmentId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 4)
sunDepartId = RecursionOrgLeve(orgContTypeInfo.Superior, 5) sunDepartId = RecursionOrgLevees(orgContTypeInfo.Superior, orgContTypeInfo.Superior, 5)
workShopId = orgContTypeInfo.Id workShopId = orgContTypeInfo.Id
default: default:
groupId = orgContTypeInfo.Id groupId = orgContTypeInfo.Id
@ -1137,8 +1190,9 @@ func (d *DateTimeTotimes) BaisStrToTime(dateTime string) {
default: default:
} }
fmt.Printf("dateTime:%v---1--->%v\n", dateTime, len(dateTime)) // fmt.Printf("dateTime:%v---1--->%v\n", dateTime, len(dateTime))
orgTime, orgTimeErr := DateToTimeStamp(fmt.Sprintf("%v-01-01 12:00:00", dateTime)) orgTime, orgTimeErr := DateToTimeStamp(fmt.Sprintf("%v-01-01 12:00:00", dateTime))
d.Time = dateTime
if orgTimeErr { if orgTimeErr {
d.AllTime = orgTime d.AllTime = orgTime
d.Years = strconv.FormatInt(ComputingTime(orgTime, 1), 10) d.Years = strconv.FormatInt(ComputingTime(orgTime, 1), 10)
@ -1284,3 +1338,131 @@ func ComputingTime(timeStamp int64, timeType int) (timeDataInt int64) {
} }
return return
} }
// 获取指定月的起止时间副本
func GetAppointMonthStarAndEndTimeEs(dayTime string) (startTime, endTime int64) {
dataTypeAll := "2006-01-02"
firstToTime := StringToTimeIng("d", dayTime)
startTimeStr := fmt.Sprintf("%v 00:00:00", firstToTime.AddDate(0, 0, 0).Format(dataTypeAll))
endTimeStr := fmt.Sprintf("%v 23:59:59", firstToTime.AddDate(0, 1, -1).Format(dataTypeAll))
// startTime = dayTime
// fmt.Printf("获取指定月的起止时间副本--->%v--->%v\n", startTimeStr, endTimeStr)
startTime, _ = DateToTimeStamp(startTimeStr)
endTime, _ = DateToTimeStamp(endTimeStr)
return
}
// 日期字符串转换成time格式
func StringToTimeIng(unit, str string) (res time.Time) {
loc, _ := time.LoadLocation("Local")
// str := t.ToString()
layout, ok := timeLayoutMap[unit]
if !ok {
layout = timeLayoutMap["s"]
}
res, _ = time.ParseInLocation(layout, str, loc)
return
}
/*
*
@ 作者: 秦东
@ 时间: 2023-07-01 13:04:00
@ 功能: 获取当前登陆人信息
@ 参数
#
@ 返回值
#
@ 方法原型
#
*/
func GetCreetUserCont(userKey string) (manCont models.ManCont, err error) {
redisFileKey := fmt.Sprintf("ScanCode:Authentication:LoginApi_%v_%v", overall.CONSTANT_CONFIG.RedisPrefixStr.Alias, userKey)
redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS5)
userRedisToken, isTrue := redisClient.HashGetAll(redisFileKey)
if !isTrue {
return
}
manCont, err = GetUserRedisCont(userRedisToken["usernumber"])
return
}
// 获取人员Redis信息
func GetUserRedisCont(number string) (manCont models.ManCont, err error) {
redisMyContKey := fmt.Sprintf("ScanCode:Authentication:UserCont_%v_%v", overall.CONSTANT_CONFIG.RedisPrefixStr.Alias, number)
redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS5)
useMap, isTrue := redisClient.HashGetAll(redisMyContKey)
if !isTrue {
errors.New("没有相关信息")
return
}
err = MapToStruct(useMap, &manCont, "json")
return
}
/*
map[string]string struct
*/
func MapToStruct(mapString map[string]string, structInterface interface{}, tag string) (err error) {
strType := reflect.TypeOf(structInterface)
strValue := reflect.ValueOf(structInterface)
switch strType.Kind() {
case reflect.Ptr:
if strType.Elem().Kind() != reflect.Struct {
// fmt.Printf("1-->%v\n", strType.Elem().Kind().String())
return errors.New("需要*struct类型,却传入*" + strType.Elem().Kind().String() + "类型")
}
default:
// fmt.Printf("2-->%v\n", strType.Kind().String())
return errors.New("需要*struct类型,却传入" + strType.Kind().String() + "类型")
}
// fmt.Printf("strType--->%v---strValue---->%v\n", strType, strValue)
strTypeElem := strType.Elem()
strValueElem := strValue.Elem()
strTypeNum := strTypeElem.NumField()
// fmt.Printf("strTypeElem--->%v---strValueElem---->%v---------strTypeNum--------->%v\n", strTypeElem, strValueElem, strTypeNum)
for i := 0; i < strTypeNum; i++ {
fieldName := strTypeElem.Field(i).Name
if tag != "" {
fieldName = strTypeElem.Field(i).Tag.Get(tag)
}
value, ok := mapString[fieldName]
if !ok {
continue
}
// fmt.Printf("name--->%v---tag---->%v----value---->%v----ok---->%v\n", fieldName, tag, value, ok)
if strValueElem.Field(i).CanSet() {
// fmt.Printf("Type--->%v---value---->%v\n", strValueElem.Field(i).Type(), reflect.TypeOf(value))
valType := fmt.Sprintf("%v", strValueElem.Field(i).Type())
switch valType {
case "int":
valueInt, _ := strconv.Atoi(value)
strValueElem.Field(i).Set(reflect.ValueOf(valueInt))
case "int32":
valueInt32, _ := strconv.ParseInt(value, 10, 32)
strValueElem.Field(i).Set(reflect.ValueOf(int32(valueInt32)))
case "int64":
valueInt64, _ := strconv.ParseInt(value, 10, 64)
strValueElem.Field(i).Set(reflect.ValueOf(valueInt64))
case "float32":
valuefloat32, _ := strconv.ParseFloat(value, 32)
strValueElem.Field(i).Set(reflect.ValueOf(float32(valuefloat32)))
case "float64":
valuefloat64, _ := strconv.ParseFloat(value, 64)
strValueElem.Field(i).Set(reflect.ValueOf(valuefloat64))
case "string":
strValueElem.Field(i).Set(reflect.ValueOf(value))
default:
}
} else {
continue
}
}
return
}

5
overall/overallhandle/type.go

@ -18,6 +18,10 @@ type ConstId struct {
Id string `json:"id"` Id string `json:"id"`
} }
type PublicId[T GenericityVariable] struct {
Id T `json:"id"`
}
//翻页格式化 //翻页格式化
type PageTurning struct { type PageTurning struct {
Page int `json:"page" form:"page"` // 页码 Page int `json:"page" form:"page"` // 页码
@ -99,4 +103,5 @@ type DateTimeTotimes struct {
Minutes string `json:"minutes"` Minutes string `json:"minutes"`
Second string `json:"second"` Second string `json:"second"`
AllTime int64 `json:"alltime"` AllTime int64 `json:"alltime"`
Time string `json:"time"`
} }

Loading…
Cancel
Save