dingtalk.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "math"
  8. "net/http"
  9. "strconv"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. OnDutyCheckTime = 120048879
  15. OnDutyCheckResult = 120048880
  16. OffDutyCheckTime = 120048881
  17. OffDutyCheckResult = 120048882
  18. AttendanceApprove = 120048891
  19. )
  20. type DingTalk struct {
  21. token string
  22. agentId string
  23. }
  24. func (dt *DingTalk) refreshToken() {
  25. resp, err := http.Get("https://oapi.dingtalk.com/gettoken?appkey=dinglvrfy5p9zq79ojaj&appsecret=7Tcy-xRj8m3jVM9cNZo62XlbFaxfONgRE0LKImUrka4DgEOt16RN9TJh9cZR63Vl")
  26. if err == nil {
  27. result := make(map[string]any)
  28. err := json.Unmarshal(readBody(resp), &result)
  29. if err == nil {
  30. if int((result["errcode"]).(float64)) == 0 {
  31. dt.token = result["access_token"].(string)
  32. dt.agentId = "1485668405"
  33. }
  34. } else {
  35. panic(any(err))
  36. }
  37. }
  38. }
  39. func (dt *DingTalk) getEmployeeIdByUnionId(unionId string) string {
  40. var param io.Reader = nil
  41. args := make(map[string]any)
  42. args["unionid"] = unionId
  43. data, dataErr := json.Marshal(args)
  44. if dataErr == nil {
  45. param = bytes.NewReader(data)
  46. } else {
  47. panic(any(dataErr))
  48. }
  49. resp, err := http.Post("https://oapi.dingtalk.com/topapi/user/getbyunionid?access_token="+dt.token, "application/json;charset=utf-8", param)
  50. if err == nil {
  51. result := make(map[string]any)
  52. err = json.Unmarshal(readBody(resp), &result)
  53. if err == nil {
  54. if int((result["errcode"]).(float64)) == 0 {
  55. userResult := result["result"].(map[string]any)
  56. userId := userResult["userid"].(string)
  57. return userId
  58. }
  59. panic(any("获取员工[" + unionId + "]信息失败"))
  60. } else {
  61. panic(any(err))
  62. }
  63. } else {
  64. panic(any(err))
  65. }
  66. }
  67. func (dt *DingTalk) getEmployeeIdByAuthCode(authCode string) string {
  68. var param io.Reader = nil
  69. args := make(map[string]any)
  70. args["clientId"] = "dinglvrfy5p9zq79ojaj"
  71. args["clientSecret"] = "7Tcy-xRj8m3jVM9cNZo62XlbFaxfONgRE0LKImUrka4DgEOt16RN9TJh9cZR63Vl"
  72. args["code"] = authCode
  73. args["refreshToken"] = authCode
  74. args["grantType"] = "authorization_code"
  75. data, dataErr := json.Marshal(args)
  76. if dataErr == nil {
  77. param = bytes.NewReader(data)
  78. } else {
  79. panic(any(dataErr))
  80. }
  81. var token = ""
  82. resp, err := http.Post("https://api.dingtalk.com/v1.0/oauth2/userAccessToken", "application/json;charset=utf-8", param)
  83. if err == nil {
  84. result := make(map[string]any)
  85. err = json.Unmarshal(readBody(resp), &result)
  86. if err == nil {
  87. if result["accessToken"] != nil {
  88. token = result["accessToken"].(string)
  89. req, _ := http.NewRequest("GET", "https://api.dingtalk.com/v1.0/contact/users/me", nil)
  90. req.Header.Set("x-acs-dingtalk-access-token", token)
  91. resp, err := (&http.Client{}).Do(req)
  92. if err != nil {
  93. panic(any("无法获取员工信息。"))
  94. } else {
  95. err = json.Unmarshal(readBody(resp), &result)
  96. if err == nil {
  97. if result["unionId"] != nil {
  98. unionId := result["unionId"].(string)
  99. id := dt.getEmployeeIdByUnionId(unionId)
  100. return id
  101. } else {
  102. panic(any("无法获取员工信息。"))
  103. }
  104. } else {
  105. panic(any("无法获取员工信息。"))
  106. }
  107. }
  108. } else {
  109. panic(any("无法获取员工Token。"))
  110. }
  111. } else {
  112. panic(any(err))
  113. }
  114. } else {
  115. panic(any(err))
  116. }
  117. }
  118. func (dt *DingTalk) getIsLeaderById(id string) bool {
  119. var param io.Reader = nil
  120. args := make(map[string]any)
  121. args["userid"] = id
  122. data, dataErr := json.Marshal(args)
  123. if dataErr == nil {
  124. param = bytes.NewReader(data)
  125. } else {
  126. panic(any(dataErr))
  127. }
  128. resp, err := http.Post("https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+dt.token, "application/json;charset=utf-8", param)
  129. if err == nil {
  130. result := make(map[string]any)
  131. err = json.Unmarshal(readBody(resp), &result)
  132. if err == nil {
  133. if int((result["errcode"]).(float64)) == 0 {
  134. userResult := result["result"].(map[string]any)
  135. leaderInDeps := userResult["leader_in_dept"].([]any)
  136. for i := 0; i < len(leaderInDeps); i++ {
  137. leaderInDep := leaderInDeps[i].(map[string]any)
  138. isLeader := leaderInDep["leader"].(bool)
  139. if isLeader {
  140. return true
  141. }
  142. }
  143. return false
  144. }
  145. panic(any("获取员工[" + id + "]信息失败"))
  146. } else {
  147. panic(any(err))
  148. }
  149. } else {
  150. panic(any(err))
  151. }
  152. }
  153. func (dt *DingTalk) getEmployeeNameById(id string) string {
  154. var param io.Reader = nil
  155. args := make(map[string]any)
  156. args["userid"] = id
  157. data, dataErr := json.Marshal(args)
  158. if dataErr == nil {
  159. param = bytes.NewReader(data)
  160. } else {
  161. panic(any(dataErr))
  162. }
  163. resp, err := http.Post("https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+dt.token, "application/json;charset=utf-8", param)
  164. if err == nil {
  165. result := make(map[string]any)
  166. err = json.Unmarshal(readBody(resp), &result)
  167. if err == nil {
  168. if int((result["errcode"]).(float64)) == 0 {
  169. userResult := result["result"].(map[string]any)
  170. userName := userResult["name"].(string)
  171. return userName
  172. }
  173. panic(any("获取员工[" + id + "]信息失败"))
  174. } else {
  175. panic(any(err))
  176. }
  177. } else {
  178. panic(any(err))
  179. }
  180. }
  181. func (dt *DingTalk) getEmployeeNameByAuthCode(authCode string) string {
  182. var param io.Reader = nil
  183. args := make(map[string]any)
  184. args["clientId"] = "dinglvrfy5p9zq79ojaj"
  185. args["clientSecret"] = "7Tcy-xRj8m3jVM9cNZo62XlbFaxfONgRE0LKImUrka4DgEOt16RN9TJh9cZR63Vl"
  186. args["code"] = authCode
  187. args["refreshToken"] = authCode
  188. args["grantType"] = "authorization_code"
  189. data, dataErr := json.Marshal(args)
  190. if dataErr == nil {
  191. param = bytes.NewReader(data)
  192. } else {
  193. panic(any(dataErr))
  194. }
  195. var token = ""
  196. resp, err := http.Post("https://api.dingtalk.com/v1.0/oauth2/userAccessToken", "application/json;charset=utf-8", param)
  197. if err == nil {
  198. result := make(map[string]any)
  199. err = json.Unmarshal(readBody(resp), &result)
  200. if err == nil {
  201. if result["accessToken"] != nil {
  202. token = result["accessToken"].(string)
  203. req, _ := http.NewRequest("GET", "https://api.dingtalk.com/v1.0/contact/users/me", nil)
  204. req.Header.Set("x-acs-dingtalk-access-token", token)
  205. resp, err := (&http.Client{}).Do(req)
  206. if err != nil {
  207. panic(any("无法获取员工信息。"))
  208. } else {
  209. err = json.Unmarshal(readBody(resp), &result)
  210. if err == nil {
  211. if result["unionId"] != nil {
  212. unionId := result["unionId"].(string)
  213. id := dt.getEmployeeIdByUnionId(unionId)
  214. name := dt.getEmployeeNameById(id)
  215. return name
  216. } else {
  217. panic(any("无法获取员工信息。"))
  218. }
  219. } else {
  220. panic(any("无法获取员工信息。"))
  221. }
  222. }
  223. } else {
  224. panic(any("无法获取员工Token。"))
  225. }
  226. } else {
  227. panic(any(err))
  228. }
  229. } else {
  230. panic(any(err))
  231. }
  232. }
  233. func (dt *DingTalk) getDepartments(parentId int) []Department {
  234. departments := make([]Department, 0)
  235. var param io.Reader = nil
  236. if parentId != 0 {
  237. args := make(map[string]any)
  238. args["dept_id"] = parentId
  239. json, err := json.Marshal(args)
  240. if err == nil {
  241. param = bytes.NewReader(json)
  242. } else {
  243. panic(any(err))
  244. }
  245. }
  246. resp, err := http.Post("https://oapi.dingtalk.com/topapi/v2/department/listsub?access_token="+dt.token, "application/json;charset=utf-8", param)
  247. if err == nil {
  248. result := make(map[string]any)
  249. resultData := readBody(resp)
  250. err := json.Unmarshal(resultData, &result)
  251. if err == nil {
  252. if int((result["errcode"]).(float64)) == 0 {
  253. depList := result["result"].([]any)
  254. if depList != nil {
  255. for i := 0; i < len(depList); i++ {
  256. dep := depList[i].(map[string]any)
  257. depId := int(dep["dept_id"].(float64))
  258. depName := dep["name"].(string)
  259. parentDepId := int(dep["parent_id"].(float64))
  260. departments = append(departments, Department{depId, depName, parentDepId})
  261. }
  262. }
  263. } else {
  264. fmt.Println(string(resultData))
  265. }
  266. } else {
  267. fmt.Println(err.Error())
  268. }
  269. }
  270. return departments
  271. }
  272. func (dt *DingTalk) getAttendanceRules(userId string, userName string) AttendanceRules {
  273. var param io.Reader = nil
  274. args := make(map[string]any)
  275. args["userid"] = userId
  276. data, err := json.Marshal(args)
  277. if err == nil {
  278. param = bytes.NewReader(data)
  279. } else {
  280. panic(any(err))
  281. }
  282. resp, err := http.Post("https://oapi.dingtalk.com/topapi/attendance/getusergroup?access_token="+dt.token, "application/json;charset=utf-8", param)
  283. if err == nil {
  284. result := make(map[string]any)
  285. err := json.Unmarshal(readBody(resp), &result)
  286. if err == nil {
  287. if int((result["errcode"]).(float64)) == 0 {
  288. groupResult := result["result"].(map[string]any)
  289. if groupResult != nil {
  290. if groupResult["name"] == nil {
  291. return AttendanceRules{"", time.Unix(0, 0), time.Unix(0, 0)}
  292. }
  293. groupName := groupResult["name"].(string)
  294. classes := groupResult["classes"].([]any)
  295. if len(classes) > 0 {
  296. sections := classes[0].(map[string]any)["sections"].([]any)
  297. if len(sections) > 0 {
  298. times := sections[0].(map[string]any)["times"].([]any)
  299. start := dateTimeToTime(strToDateTime(times[0].(map[string]any)["check_time"].(string)))
  300. end := dateTimeToTime(strToDateTime(times[1].(map[string]any)["check_time"].(string)))
  301. return AttendanceRules{groupName, start, end}
  302. }
  303. } else {
  304. return AttendanceRules{groupName, time.Unix(0, 0), time.Unix(0, 0)}
  305. }
  306. }
  307. }
  308. }
  309. panic(any("无法获取员工[" + userName + "]的考勤班次信息。"))
  310. } else {
  311. panic(any(err))
  312. }
  313. }
  314. func (dt *DingTalk) getEmployeeCount() int {
  315. var param io.Reader = nil
  316. args := make(map[string]any)
  317. args["only_active"] = true
  318. data, dataErr := json.Marshal(args)
  319. if dataErr == nil {
  320. param = bytes.NewReader(data)
  321. } else {
  322. panic(any(dataErr))
  323. }
  324. resp, err := http.Post("https://oapi.dingtalk.com/topapi/user/count?access_token="+dt.token, "application/json;charset=utf-8", param)
  325. if err == nil {
  326. result := make(map[string]any)
  327. err = json.Unmarshal(readBody(resp), &result)
  328. if err == nil {
  329. if int((result["errcode"]).(float64)) == 0 {
  330. countResult := result["result"].(map[string]any)
  331. count := int(math.Floor(countResult["count"].(float64)))
  332. return count
  333. }
  334. panic(any("获取员工数量失败。"))
  335. } else {
  336. panic(any(err))
  337. }
  338. } else {
  339. panic(any(err))
  340. }
  341. }
  342. func (dt *DingTalk) getEmployee(userId string, depId int) Employee {
  343. var param io.Reader = nil
  344. args := make(map[string]any)
  345. args["userid"] = userId
  346. data, dataErr := json.Marshal(args)
  347. if dataErr == nil {
  348. param = bytes.NewReader(data)
  349. } else {
  350. panic(any(dataErr))
  351. }
  352. resp, err := http.Post("https://oapi.dingtalk.com/topapi/v2/user/get?access_token="+dt.token, "application/json;charset=utf-8", param)
  353. if err == nil {
  354. result := make(map[string]any)
  355. err = json.Unmarshal(readBody(resp), &result)
  356. if err == nil {
  357. if int((result["errcode"]).(float64)) == 0 {
  358. userResult := result["result"].(map[string]any)
  359. userName := userResult["name"].(string)
  360. title := ""
  361. if userResult["title"] != nil {
  362. title = userResult["title"].(string)
  363. }
  364. email := ""
  365. if userResult["email"] != nil {
  366. email = userResult["email"].(string)
  367. }
  368. attendanceRules := dt.getAttendanceRules(userId, userName)
  369. isStruggle := false
  370. return Employee{userId, userName, title, depId, email, attendanceRules, false, isStruggle}
  371. }
  372. panic(any("获取员工[" + userId + "]信息失败"))
  373. } else {
  374. panic(any(err))
  375. }
  376. } else {
  377. panic(any(err))
  378. }
  379. }
  380. // 获取部门员工列表
  381. func (dt *DingTalk) getEmployees(depId int) []Employee {
  382. employees := make([]Employee, 0)
  383. var param io.Reader = nil
  384. if depId != 0 {
  385. args := make(map[string]any)
  386. args["dept_id"] = depId
  387. json, err := json.Marshal(args)
  388. if err == nil {
  389. param = bytes.NewReader(json)
  390. } else {
  391. panic(any(err))
  392. }
  393. }
  394. resp, err := http.Post("https://oapi.dingtalk.com/topapi/user/listid?access_token="+dt.token, "application/json;charset=utf-8", param)
  395. if err == nil {
  396. result := make(map[string]any)
  397. err := json.Unmarshal(readBody(resp), &result)
  398. if err == nil {
  399. if int((result["errcode"]).(float64)) == 0 {
  400. resultData := result["result"].(map[string]any)
  401. if resultData != nil {
  402. userIdList := resultData["userid_list"].([]any)
  403. for i := 0; i < len(userIdList); i++ {
  404. employees = append(employees, dt.getEmployee(userIdList[i].(string), depId))
  405. }
  406. return employees
  407. }
  408. }
  409. panic(any("无法获取部门[" + strconv.Itoa(depId) + "]员工列表"))
  410. } else {
  411. panic(any(err))
  412. }
  413. } else {
  414. panic(any(err))
  415. }
  416. }
  417. func (dt *DingTalk) sendTextMessage(userIds []string, content string) {
  418. var param io.Reader = nil
  419. args := make(map[string]any)
  420. args["agent_id"] = dt.agentId
  421. args["userid_list"] = strings.Join(userIds, ",")
  422. msg := make(map[string]any)
  423. msg["msgtype"] = "text"
  424. text := make(map[string]any)
  425. text["content"] = content
  426. msg["text"] = text
  427. args["msg"] = msg
  428. data, dataErr := json.Marshal(args)
  429. if dataErr == nil {
  430. param = bytes.NewReader(data)
  431. } else {
  432. panic(any(dataErr))
  433. }
  434. resp, err := http.Post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+dt.token, "application/json;charset=utf-8", param)
  435. if err == nil {
  436. result := make(map[string]any)
  437. err = json.Unmarshal(readBody(resp), &result)
  438. if err == nil {
  439. if int((result["errcode"]).(float64)) != 0 {
  440. panic(any("发送消息失败"))
  441. }
  442. } else {
  443. panic(any(err))
  444. }
  445. }
  446. }
  447. func (dt *DingTalk) sendUrlMessage(userIds []string, title string, text string, imageUrl string, contentUrl string) {
  448. var param io.Reader = nil
  449. args := make(map[string]any)
  450. args["agent_id"] = dt.agentId
  451. args["userid_list"] = strings.Join(userIds, ",")
  452. msg := make(map[string]any)
  453. msg["msgtype"] = "link"
  454. link := make(map[string]any)
  455. link["messageUrl"] = contentUrl
  456. link["picUrl"] = imageUrl
  457. link["title"] = title
  458. link["text"] = text
  459. msg["link"] = link
  460. args["msg"] = msg
  461. data, dataErr := json.Marshal(args)
  462. if dataErr == nil {
  463. param = bytes.NewReader(data)
  464. } else {
  465. panic(any(dataErr))
  466. }
  467. resp, err := http.Post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+dt.token, "application/json;charset=utf-8", param)
  468. if err == nil {
  469. result := make(map[string]any)
  470. err = json.Unmarshal(readBody(resp), &result)
  471. if err == nil {
  472. if int((result["errcode"]).(float64)) != 0 {
  473. panic(any("发送消息失败"))
  474. }
  475. } else {
  476. panic(any(err))
  477. }
  478. }
  479. }
  480. func (dt *DingTalk) sendActionCard(userIds []string, title string, markdown string, singleTitle string, singleUrl string) {
  481. var param io.Reader = nil
  482. args := make(map[string]any)
  483. args["agent_id"] = dt.agentId
  484. args["userid_list"] = strings.Join(userIds, ",")
  485. msg := make(map[string]any)
  486. msg["msgtype"] = "action_card"
  487. actionCard := make(map[string]any)
  488. actionCard["title"] = title
  489. actionCard["markdown"] = markdown
  490. actionCard["single_title"] = singleTitle
  491. actionCard["single_url"] = singleUrl
  492. msg["action_card"] = actionCard
  493. args["msg"] = msg
  494. data, dataErr := json.Marshal(args)
  495. if dataErr == nil {
  496. param = bytes.NewReader(data)
  497. } else {
  498. panic(any(dataErr))
  499. }
  500. resp, err := http.Post("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+dt.token, "application/json;charset=utf-8", param)
  501. if err == nil {
  502. result := make(map[string]any)
  503. err = json.Unmarshal(readBody(resp), &result)
  504. if err == nil {
  505. if int((result["errcode"]).(float64)) != 0 {
  506. panic(any("发送消息失败"))
  507. }
  508. } else {
  509. panic(any(err))
  510. }
  511. }
  512. }
  513. func getOrCreateAttendanceData(list []*AttendanceData, index int, employeeId string, day time.Time) *AttendanceData {
  514. if list[index] == nil {
  515. list[index] = new(AttendanceData)
  516. list[index].EmployeeId = employeeId
  517. list[index].Day = day
  518. }
  519. return list[index]
  520. }
  521. func (dt *DingTalk) getEmployeeAttendanceDataList(employeeId string, start time.Time, end time.Time) []AttendanceData {
  522. var list []*AttendanceData
  523. var param io.Reader = nil
  524. args := make(map[string]any)
  525. args["column_id_list"] = strconv.Itoa(OnDutyCheckTime) + "," + strconv.Itoa(OnDutyCheckResult) + "," + strconv.Itoa(OffDutyCheckTime) + "," + strconv.Itoa(OffDutyCheckResult) + "," + strconv.Itoa(AttendanceApprove)
  526. args["from_date"] = start.Format("2006-01-02 15:04:05")
  527. args["to_date"] = end.Format("2006-01-02 15:04:05")
  528. args["userid"] = employeeId
  529. data, dataErr := json.Marshal(args)
  530. if dataErr == nil {
  531. param = bytes.NewReader(data)
  532. } else {
  533. panic(any(dataErr))
  534. }
  535. resp, err := http.Post("https://oapi.dingtalk.com/topapi/attendance/getcolumnval?access_token="+dt.token, "application/json;charset=utf-8", param)
  536. if err == nil {
  537. result := make(map[string]any)
  538. err = json.Unmarshal(readBody(resp), &result)
  539. if err == nil {
  540. if int((result["errcode"]).(float64)) == 0 {
  541. resultData := result["result"].(map[string]any)
  542. if resultData != nil {
  543. columns := resultData["column_vals"].([]any)
  544. for i := 0; i < len(columns); i++ {
  545. column := columns[i].(map[string]any)
  546. columnId := int(column["column_vo"].(map[string]any)["id"].(float64))
  547. columnsValues := column["column_vals"].([]any)
  548. if list == nil {
  549. list = make([]*AttendanceData, len(columnsValues))
  550. }
  551. var attendanceData *AttendanceData
  552. for i := 0; i < len(columnsValues); i++ {
  553. dayValues := columnsValues[i].(map[string]any)
  554. switch columnId {
  555. case OnDutyCheckTime:
  556. day := dateTimeToDate(strToDateTime(dayValues["date"].(string)))
  557. attendanceData = getOrCreateAttendanceData(list, i, employeeId, day)
  558. attendanceData.Start = dayValues["value"].(string)
  559. case OnDutyCheckResult:
  560. day := dateTimeToDate(strToDateTime(dayValues["date"].(string)))
  561. attendanceData = getOrCreateAttendanceData(list, i, employeeId, day)
  562. attendanceData.StartResult = dayValues["value"].(string)
  563. case OffDutyCheckTime:
  564. day := dateTimeToDate(strToDateTime(dayValues["date"].(string)))
  565. attendanceData = getOrCreateAttendanceData(list, i, employeeId, day)
  566. attendanceData.End = dayValues["value"].(string)
  567. case OffDutyCheckResult:
  568. day := dateTimeToDate(strToDateTime(dayValues["date"].(string)))
  569. attendanceData = getOrCreateAttendanceData(list, i, employeeId, day)
  570. attendanceData.EndResult = dayValues["value"].(string)
  571. case AttendanceApprove:
  572. day := dateTimeToDate(strToDateTime(dayValues["date"].(string)))
  573. attendanceData = getOrCreateAttendanceData(list, i, employeeId, day)
  574. attendanceData.Approve = dayValues["value"].(string)
  575. }
  576. }
  577. }
  578. for i := 0; i < len(list); i++ {
  579. attendanceData := list[i]
  580. attendanceData.State = 出勤
  581. if attendanceData.Start == "" || attendanceData.End == "" {
  582. if attendanceData.StartResult == "出差" || attendanceData.EndResult == "出差" {
  583. attendanceData.State = 出差
  584. }
  585. if attendanceData.StartResult == "外出" || attendanceData.EndResult == "外出" {
  586. attendanceData.State = 外出
  587. }
  588. if attendanceData.StartResult == "缺卡" || attendanceData.EndResult == "缺卡" {
  589. attendanceData.State = 缺卡
  590. }
  591. //不管外出还是缺卡,出差还是外出,只要有请假就是请假
  592. if attendanceData.StartResult == "请假" || attendanceData.EndResult == "请假" {
  593. attendanceData.State = 请假
  594. }
  595. if attendanceData.StartResult == "加班" || attendanceData.EndResult == "加班" {
  596. attendanceData.State = 加班
  597. }
  598. if attendanceData.StartResult == "" && attendanceData.EndResult == "" && attendanceData.Approve == "" {
  599. attendanceData.State = 休息
  600. }
  601. }
  602. //Check approve
  603. if strings.Contains(attendanceData.Approve, "出差") {
  604. attendanceData.State = 出差
  605. }
  606. if strings.Contains(attendanceData.Approve, "外出") {
  607. attendanceData.State = 外出
  608. }
  609. if strings.Contains(attendanceData.Approve, "缺卡") {
  610. attendanceData.State = 缺卡
  611. }
  612. if strings.Contains(attendanceData.Approve, "请假") {
  613. attendanceData.State = 请假
  614. }
  615. if strings.Contains(attendanceData.Approve, "加班") {
  616. attendanceData.State = 加班
  617. }
  618. if strings.Contains(attendanceData.Start, "昨日") {
  619. startTime := dateTimeToTime(strToTime("00:01"))
  620. attendanceData.StartTime = startTime
  621. } else {
  622. startTime := dateTimeToTime(strToTime(attendanceData.Start))
  623. attendanceData.StartTime = startTime
  624. }
  625. if strings.Contains(attendanceData.End, "次日") {
  626. endTime := dateTimeToTime(strToTime("23:59"))
  627. attendanceData.EndTime = endTime
  628. } else {
  629. endTime := dateTimeToTime(strToTime(attendanceData.End))
  630. attendanceData.EndTime = endTime
  631. }
  632. }
  633. result := make([]AttendanceData, 0)
  634. for i := 0; i < len(list); i++ {
  635. result = append(result, *list[i])
  636. }
  637. return result
  638. }
  639. }
  640. panic(any("无法获取员工[" + employeeId + "]的考勤信息。"))
  641. } else {
  642. panic(any(err))
  643. }
  644. } else {
  645. panic(any(err))
  646. }
  647. }
  648. func (dt *DingTalk) getLeaveQuota(lq map[string]any) LeaveQuota {
  649. leaveQuota := LeaveQuota{}
  650. leaveQuota.Id = lq["userid"].(string)
  651. leaveCode := lq["leave_code"].(string)
  652. if leaveCode == "6a6c631c-65cf-434c-97fa-335c9df7cb81" {
  653. leaveQuota.Quota = int(lq["quota_num_per_day"].(float64))
  654. leaveQuota.Used = int(lq["used_num_per_day"].(float64))
  655. leaveQuota.LeaveType = "年假"
  656. leaveQuota.Unit = 天
  657. } else {
  658. leaveQuota.Quota = int(lq["quota_num_per_hour"].(float64))
  659. leaveQuota.Used = int(lq["used_num_per_hour"].(float64))
  660. leaveQuota.LeaveType = "调休"
  661. leaveQuota.Unit = 小时
  662. }
  663. return leaveQuota
  664. }
  665. func (dt *DingTalk) getLeaveQuotas(employeeId string, leaveType int) []LeaveQuota {
  666. leaveQuotas := make([]LeaveQuota, 0)
  667. args := make(map[string]any)
  668. args["offset"] = 0
  669. args["size"] = 100
  670. args["userids"] = employeeId
  671. if leaveType == 年假 {
  672. args["leave_code"] = "6a6c631c-65cf-434c-97fa-335c9df7cb81"
  673. } else {
  674. args["leave_code"] = "12d81490-04e3-4848-920e-7f87e5955451"
  675. }
  676. args["op_userid"] = "14033025461181119"
  677. var param io.Reader = nil
  678. data, dataErr := json.Marshal(args)
  679. if dataErr == nil {
  680. param = bytes.NewReader(data)
  681. } else {
  682. panic(any(dataErr))
  683. }
  684. resp, err := http.Post("https://oapi.dingtalk.com/topapi/attendance/vacation/quota/list?access_token="+dt.token, "application/json;charset=utf-8", param)
  685. if err == nil {
  686. result := make(map[string]any)
  687. err := json.Unmarshal(readBody(resp), &result)
  688. if err == nil {
  689. if int((result["errcode"]).(float64)) == 0 {
  690. resultData := result["result"].(map[string]any)
  691. if resultData != nil {
  692. if resultData["leave_quotas"] != nil {
  693. lqs := resultData["leave_quotas"].([]any)
  694. for i := 0; i < len(lqs); i++ {
  695. lq := lqs[i].(map[string]any)
  696. leaveQuotas = append(leaveQuotas, dt.getLeaveQuota(lq))
  697. }
  698. }
  699. return leaveQuotas
  700. } else {
  701. panic(any("无法获得假期信息"))
  702. }
  703. } else {
  704. panic(any("无法获得假期信息"))
  705. }
  706. } else {
  707. panic(any(err))
  708. }
  709. } else {
  710. panic(any(err))
  711. }
  712. }