2023-01-10 16:52:33 +08:00
package com.pomelotea.hoperun.sign.api
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject
import com.alibaba.fastjson.TypeReference
2023-03-22 18:10:03 +08:00
import com.pomelotea.hoperun.sign.common.*
import com.pomelotea.hoperun.sign.config.HoperunUserConfig.deviceMap
import com.pomelotea.hoperun.sign.config.HoperunUserConfig.getUserConfig
import com.pomelotea.hoperun.sign.config.HoperunUserConfig.userConfigMap
2023-01-10 16:52:33 +08:00
import com.pomelotea.hoperun.sign.config.UserConfig
2023-03-22 18:10:03 +08:00
import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler
2023-03-22 19:34:53 +08:00
import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler.Companion.dakaQueue
2023-01-10 16:52:33 +08:00
import okhttp3.FormBody
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
2023-03-22 18:10:03 +08:00
import org.springframework.web.bind.annotation.*
2023-01-10 16:52:33 +08:00
import java.text.SimpleDateFormat
import java.util.*
/ * *
*
* @version 0.0 . 1
* @author jimlee
* date 2022 - 07 - 15 11 : 01
2023-03-22 18:10:03 +08:00
* update : 2023 / 3 / 22
2023-01-10 16:52:33 +08:00
* hoperun打卡服务接口
* * /
2023-03-22 18:10:03 +08:00
2023-01-10 16:52:33 +08:00
@RestController
@RequestMapping ( " /api/daka " )
2023-03-22 18:10:03 +08:00
class HoperunSignController {
2023-01-10 16:52:33 +08:00
2023-04-26 13:09:45 +08:00
2023-04-10 23:14:27 +08:00
2023-03-22 18:10:03 +08:00
init {
AutoDakaScheduler ( )
2023-04-11 11:04:00 +08:00
// AutoRenewSessionScheduler()
2023-03-22 23:46:42 +08:00
val yxl = UserConfig (
project _id = " U2103S000112 " ,
projectcode = " U2103S000112 " ,
projectname = " JRKF-浙江网商-技术服务外包 " ,
device = " Android 12;Redmi;M2007J3SC;deviceId:OAIDe7fa6084205e9a22d8f6f71bc91893ff;deviceName:Android "
)
userConfigMap [ " 16638 " ] = yxl
2023-01-10 16:52:33 +08:00
}
2023-04-10 23:14:27 +08:00
// @GetMapping("/username/{employeeNo}/{checked}/{jsessionId}")
@GetMapping ( " /username/{employeeNo}/{checked} " )
2023-03-22 23:46:42 +08:00
fun getUsername (
@PathVariable employeeNo : String ,
@PathVariable checked : Boolean
) : WebResult < LoginResponse ? > {
2023-04-10 23:14:27 +08:00
/ *
if ( jsessionId != null ) {
getJsessionIdAutoLogin ( employeeNo , jsessionId )
} * /
val userConfig = getUserConfig ( employeeNo ) . let {
2023-04-26 13:09:45 +08:00
defaultLogin ( employeeNo )
2023-04-10 23:14:27 +08:00
getUserConfig ( employeeNo )
}
userConfig ?: return WebResult . getFailed ( " 登陆失败 " )
2023-03-22 18:10:03 +08:00
userConfig . autoDaka = checked
userConfig . device = deviceMap [ employeeNo ]
2023-01-10 16:52:33 +08:00
return WebResult . getSuccess (
LoginResponse (
userConfig . username ,
userConfig . device ,
userConfig . project _id ,
userConfig . projectname ,
" 杭州市 "
)
)
}
2023-03-22 18:10:03 +08:00
@GetMapping ( " /auto/{employeeNo}/{checked} " )
fun autoDaka ( @PathVariable employeeNo : String , @PathVariable checked : Boolean ) : WebResult < Any ? > {
val userConfig = getUserConfig ( employeeNo ) ?: return WebResult . getFailed ( " 需要重新登录 " )
userConfig . autoDaka = checked
return WebResult . getSuccess ( checked )
}
2023-01-10 16:52:33 +08:00
@GetMapping ( " /last/{employeeNo} " )
fun getLast5DaysRecord ( @PathVariable employeeNo : String ) : WebResult < Any ? > {
2023-03-22 18:10:03 +08:00
val jsessionId = sessionMap . get ( employeeNo ) ?: return WebResult . getFailed ( " 登陆失败 " )
2023-01-10 16:52:33 +08:00
return WebResult . getSuccess ( monthAtt ( employeeNo , jsessionId ) )
}
@PostMapping ( " /endTime " )
fun endTime ( @RequestBody request : DakaRequest ) : WebResult < Any ? > {
2023-03-22 18:10:03 +08:00
val userConfig = userConfigMap . get ( request . employeeNo )
2023-01-10 16:52:33 +08:00
if ( userConfig ?. device == null ) {
return WebResult . getFailed ( " 用户没有配置的deviceUA " )
}
2023-03-22 18:10:03 +08:00
val jsessionId = sessionMap . get ( request . employeeNo )
2023-01-10 16:52:33 +08:00
if ( jsessionId == null ) {
return WebResult . getFailed ( " 登陆失败 " )
}
val date = if ( request . date == " 今天 " ) SimpleDateFormat ( " yyyy-MM-dd " ) . format ( Date ( ) ) else request . date
val dakaRequest = Request . Builder ( )
. url ( DAKA _URL )
. post (
JSON . toJSONString (
endTimeHoperunDakaRequest (
request . employeeNo ,
date ,
request . time
)
) . toRequestBody ( " application/json;charset=utf-8 " . toMediaTypeOrNull ( ) )
)
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
. build ( )
val result : String ? = client . newCall ( dakaRequest ) . execute ( ) . body ?. string ( )
return WebResult . getSuccess ( JSONObject . parseObject ( result , DakaResponse :: class . java ) )
}
@PostMapping ( " /beginTime " )
fun beginTime ( @RequestBody request : DakaRequest ) : WebResult < Any ? > {
2023-03-22 18:10:03 +08:00
val userConfig = userConfigMap . get ( request . employeeNo )
2023-01-10 16:52:33 +08:00
if ( userConfig ?. device == null ) {
return WebResult . getFailed ( " 用户没有配置的deviceUA " )
}
2023-03-22 18:10:03 +08:00
val jsessionId = sessionMap . get ( request . employeeNo )
2023-01-10 16:52:33 +08:00
val date = if ( request . date == " 今天 " ) SimpleDateFormat ( " yyyy-MM-dd " ) . format ( Date ( ) ) else request . date
val dakaRequest = Request . Builder ( )
. url ( DAKA _URL )
. post (
JSON . toJSONString (
beginTimeHoperunDakaRequest (
request . employeeNo ,
date ,
request . time
)
) . toRequestBody ( " application/json;charset=utf-8 " . toMediaTypeOrNull ( ) )
)
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
. build ( )
val result : String ? = client . newCall ( dakaRequest ) . execute ( ) . body ?. string ( )
return WebResult . getSuccess ( JSONObject . parseObject ( result , DakaResponse :: class . java ) )
}
/ * *
* 查询近两个月的
* /
private fun monthAtt ( employeeNo : String , jsessionId : String ) : List < MonthAttLog > {
val monthAttResult : MutableList < MonthAttLog > = ArrayList ( )
val monthAttList : List < MonthAttLog > = queryMonthAttData ( employeeNo , jsessionId , getNowDateyyyy _MM ( ) + " -01 " )
// 如果dateType = 1的结果小于3条, 查询上月
val monthAttLogs = monthAttList . sortedByDescending { it . yearmonth } . filter { it . dateType == " 1 " }
. filter { it . yearmonth !! . compareTo ( getNowDateyyyy _MM _dd ( ) ) <= 0 }
monthAttResult . addAll ( monthAttLogs )
val lastMonthAttList : List < MonthAttLog > =
queryMonthAttData ( employeeNo , jsessionId , getLastDateyyyy _MM ( ) + " -01 " )
val lastMonthAttLogs = lastMonthAttList . sortedByDescending { it . yearmonth } . filter { it . dateType == " 1 " }
monthAttResult . addAll ( lastMonthAttLogs )
2023-03-22 19:34:53 +08:00
val monthAttLog = monthAttResult . find { it . yearmonth == getNowDateyyyy _MM _dd ( ) }
2023-03-22 23:46:42 +08:00
val autoDaka =
dakaQueue . filter { it . dakaDate == getNowDateyyyy _MM _dd ( ) } . findLast { it . employeeNo == employeeNo }
2023-03-22 19:34:53 +08:00
if ( autoDaka != null && monthAttLog != null ) {
monthAttLog . autoDakaBeginTime = autoDaka . beginTime
monthAttLog . autoDakaEndTime = autoDaka . endTime
}
2023-01-10 16:52:33 +08:00
return monthAttResult
}
private fun queryMonthAttData ( employeeNo : String , jsessionId : String , yearmonth : String ) : List < MonthAttLog > {
val monthAttRequest = Request . Builder ( )
. url ( MONTH _ATT _URL )
. post (
FormBody . Builder ( )
. add ( " staff_code " , padEmployeeNumber ( employeeNo ) )
. add ( " yearmonth " , yearmonth )
. build ( )
)
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
. build ( )
val result : String ? = client . newCall ( monthAttRequest ) . execute ( ) . body ?. string ( )
return JSONObject . parseObject (
JSONObject . parseObject ( result ) . getString ( " data " ) ,
object : TypeReference < List < MonthAttLog > ? > ( ) { } )
}
2023-04-26 13:09:45 +08:00
private fun defaultLogin ( employeeNo : String ) {
resetJSessionId ( employeeNo )
setUserConfig ( employeeNo )
2023-04-10 23:14:27 +08:00
}
2023-04-26 13:09:45 +08:00
/ *
2023-03-22 18:10:03 +08:00
private fun setUserConfig ( employeeNo : String , jsessionId : String ) {
2023-01-10 16:52:33 +08:00
val attendancesDetailRequest = Request . Builder ( )
2023-03-22 18:10:03 +08:00
. url ( " http://pom.hoperun.com:8187/attm/calendar/monthAtt?staff_code= ${padEmployeeNumber(employeeNo)} &yearmonth= ${getNowDateyyyy_MM()} -01 " )
. get ( )
2023-01-10 16:52:33 +08:00
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
2023-03-22 23:46:42 +08:00
. addHeader (
" User-Agent " ,
2023-04-11 11:04:00 +08:00
" Qing/0.9.113;iOS 16.4.1;Apple;iPhone13,2;deviceId:a8baf66f-fdeb-4f4d-b1e5-9fafcd5045b6;deviceName:iOS;clientId:10200;os:iOS 16.3.1;brand:Apple;model:iPhone13,2;lang:zh-CN;fontNum:0;fontScale:1.0;ver:10.7.14;Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 "
2023-03-22 23:46:42 +08:00
)
2023-04-26 13:09:45 +08:00
. addHeader ( " accept " , " * " )
2023-03-22 18:10:03 +08:00
. addHeader ( " Origin " , " http://pom.hoperun.com:8187 " )
. addHeader ( " Referer " , " http://pom.hoperun.com:8187/attm/attence/getInfo " )
. addHeader ( " content-type " , " application/x-www-form-urlencoded; charset=UTF-8 " )
2023-01-10 16:52:33 +08:00
. build ( )
2023-03-22 18:10:03 +08:00
val attendancesDetailResp = client . newCall ( attendancesDetailRequest ) . execute ( )
val bodyString = attendancesDetailResp . body ?. string ( )
val attendancesDetailResponse = JSONObject . parseObject ( bodyString , AttendancesDetailResponse :: class . java )
2023-03-22 23:46:42 +08:00
val dataList : List < AttendancesDetail > =
JSONObject . parseObject ( attendancesDetailResponse . data , object : TypeReference < List < AttendancesDetail > > ( ) { } )
2023-03-22 18:10:03 +08:00
val userConfig : UserConfig = userConfigMap . get ( employeeNo ) ?: UserConfig ( )
2023-03-22 23:46:42 +08:00
if ( dataList . isNotEmpty ( ) ) {
val lastDakaInfo : AttendancesDetail = dataList . sortedByDescending { it . yearmonth }
. filter { it . project _id != " -1 " }
. filter { it . begin _time != null }
. firstOrNull ( ) !!
if ( userConfig . projectcode == null ) {
userConfig . projectcode = lastDakaInfo . projectcode
}
if ( userConfig . projectname == null ) {
userConfig . projectname = lastDakaInfo . projectname
}
if ( userConfig . project _id == null ) {
userConfig . project _id = lastDakaInfo . project _id
}
2023-01-10 16:52:33 +08:00
}
2023-03-22 23:46:42 +08:00
2023-03-22 18:10:03 +08:00
// username 要从主页的html元素中获取
val indexRequest = Request . Builder ( )
. url ( " http://pom.hoperun.com:8187/attm/attence/getInfo " )
. get ( )
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
2023-03-22 23:46:42 +08:00
. addHeader (
" User-Agent " ,
" Qing/0.9.113;iOS 16.3.1;Apple;iPhone13,2;deviceId:a8baf66f-fdeb-4f4d-b1e5-9fafcd5045b6;deviceName:iOS;clientId:10200;os:iOS 16.3.1;brand:Apple;model:iPhone13,2;lang:zh-CN;fontNum:0;fontScale:1.0;ver:10.7.14;Mozilla/5.0 (iPhone; CPU iPhone OS 16_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 "
)
2023-04-26 13:09:45 +08:00
. addHeader ( " accept " , " * " )
2023-03-22 18:10:03 +08:00
. addHeader ( " Origin " , " http://pom.hoperun.com:8187 " )
. addHeader ( " Referer " , " http://pom.hoperun.com:8187/attm/attence/getInfo " )
. addHeader ( " content-type " , " application/x-www-form-urlencoded; charset=UTF-8 " )
. build ( )
val indexResp = client . newCall ( indexRequest ) . execute ( )
val indexHtml = indexResp . body ?. string ( )
val doc = Jsoup . parse ( indexHtml !! )
2023-03-22 23:46:42 +08:00
userConfig . username =
doc . select ( " #attendance-detail-content > div.container.none-padding > div > div:nth-child(1) > div:nth-child(4) " )
. text ( )
2023-03-22 18:10:03 +08:00
userConfig . employeeNo = employeeNo
HoperunUserConfig . addUserConfig (
2023-01-10 16:52:33 +08:00
employeeNo , userConfig
)
2023-04-26 13:09:45 +08:00
} * /
2023-01-10 16:52:33 +08:00
2023-04-10 23:14:27 +08:00
2023-04-26 13:09:45 +08:00
private fun setUserConfig ( employeeNo : String ) {
2025-03-21 15:16:09 +08:00
if ( userConfigMap [ employeeNo ] != null
&& userConfigMap [ employeeNo ] !! . timeout > System . currentTimeMillis ( ) ) return
2023-04-10 23:14:27 +08:00
// 获取deviceua
val loginRequest = Request . Builder ( )
. url ( " http://pom.hoperun.com:8187/attp/login/login.do " )
. post (
JSON . toJSONString (
mapOf (
" login_id " to padEmployeeNumber ( employeeNo ) ,
" password " to " 123456 " ,
" roleType " to " 0 "
)
) . toRequestBody ( " application/json;charset=utf-8 " . toMediaTypeOrNull ( ) )
)
. build ( )
val response = client . newCall ( loginRequest ) . execute ( )
val jsessionId = response . headers ( " Set-Cookie " ) [ 0 ] . substring ( 11 , 43 )
val attendancesDetailRequest = Request . Builder ( )
. url ( " http://pom.hoperun.com:8187/attp/attendances/queryAttendancesDetail " )
. post (
JSON . toJSONString (
mapOf (
" beginDate " to getLastDateyyyy _MM ( ) + " -21 " ,
" endDate " to getNowDateyyyy _MM _dd ( ) ,
" staffCode " to padEmployeeNumber ( employeeNo )
)
) . toRequestBody ( " application/json;charset=utf-8 " . toMediaTypeOrNull ( ) )
)
. addHeader ( " Cookie " , " JSESSIONID= $jsessionId " )
. build ( )
val attendancesDetailResponse = client . newCall ( attendancesDetailRequest ) . execute ( )
val bodyString = attendancesDetailResponse . body ?. string ( )
val dakaJsonArray = JSONObject . parseArray ( bodyString )
val dakaInfo = dakaJsonArray . getJSONObject ( dakaJsonArray . size - 1 )
val dakaList = dakaInfo . getJSONArray ( " list " )
var lastDakaInfo = dakaList . getJSONObject ( dakaList . size - 1 )
val userConfig : UserConfig = userConfigMap . get ( employeeNo ) ?: UserConfig ( )
2023-04-11 11:04:00 +08:00
userConfig . employeeNo = employeeNo
2023-04-10 23:14:27 +08:00
if ( lastDakaInfo . getString ( " begin_time " ) == null ) {
for ( i in dakaList . size - 1 downTo 0 ) {
lastDakaInfo = dakaList . getJSONObject ( i )
if ( lastDakaInfo . getString ( " actual_area_end " ) != null ) {
break
}
}
}
val username : String = lastDakaInfo . getString ( " staff_name " )
userConfig . username = username
if ( userConfig . device == null ) {
2025-03-21 15:16:09 +08:00
if ( lastDakaInfo . getString ( " actual_area_end " ) != null
&& lastDakaInfo . getString ( " actual_area_end " ) != " buqianka " ) {
2023-04-10 23:14:27 +08:00
val area : String = lastDakaInfo . getString ( " actual_area_end " )
userConfig . device = area . substring ( area . lastIndexOf ( " Qing " ) + 13 )
} else if ( lastDakaInfo . getString ( " actual_area_begin " ) != null ) {
val area : String = lastDakaInfo . getString ( " actual_area_begin " )
userConfig . device = area . substring ( area . lastIndexOf ( " Qing " ) + 13 )
} else {
userConfig . device = null
}
}
if ( userConfig . projectcode == null ) {
userConfig . projectcode = dakaInfo . getString ( " pro_id " )
}
if ( userConfig . projectname == null ) {
userConfig . projectname = dakaInfo . getString ( " pro_name " )
}
if ( userConfig . project _id == null ) {
userConfig . project _id = dakaInfo . getString ( " pro_id " )
}
userConfigMap [ employeeNo ] = userConfig
}
2023-01-10 16:52:33 +08:00
}
data class DakaRequest (
val employeeNo : String ,
val date : String ,
val time : String
)
data class DakaResponse (
var result : String ? = null ,
var comment : String ? = null ,
var data : String ? = null
2023-04-23 10:25:54 +08:00
) {
override fun toString ( ) : String {
return " DakaResponse(result= $result , comment= $comment , data= $data ) "
}
}
2023-01-10 16:52:33 +08:00
class WebResult < T > protected constructor ( ) : java . io . Serializable {
var data : T ? = null
var code : Int ? = null
var success = false
var message : String ? = null
@Suppress ( " UNUSED " )
var timestamp = System . currentTimeMillis ( )
companion object {
fun < T > getSuccess ( data : T ) : WebResult < T > {
return getWebResult ( true , data , " success " , 0 )
}
fun < T > getFailed ( message : String = " failed " ) : WebResult < T ? > {
return getWebResult ( false , null , message , - 1 )
}
fun < T > getWebResult ( success : Boolean , data : T , message : String ? , code : Int ? ) : WebResult < T > {
val webResult = WebResult < T > ( )
webResult . success = success
webResult . data = data
webResult . code = code
webResult . message = message
return webResult
}
}
}
data class MonthAttLog (
var area _id : String ? = null ,
var area _id _begin : String ? = null ,
var area _id _end : String ? = null ,
var attState : String ? = null ,
var att _type : String ? = null ,
var begin _time : String ? = null ,
var dateType : String ? = null ,
var departmentcode : String ? = null ,
var end _time : String ? = null ,
var project _id : String ? = null ,
var projectcode : String ? = null ,
var staff _code : String ? = null ,
2023-03-22 19:34:53 +08:00
var yearmonth : String ? = null ,
var autoDakaBeginTime : String ? = null ,
var autoDakaEndTime : String ? = null ,
2023-01-10 16:52:33 +08:00
)
data class HoperunDakaRequest (
val staff _code : String ,
val yearmonth : String ,
var project _id : String = " U2103S000078 " ,
var projectname : String = " JRKF-银河资产对接合作平台贷项目 " ,
var projectcode : String = " U2103S000078 " ,
val area _id : String = " 杭州市 " ,
val actualArea : String ,
var begin _time : String ? = null ,
var end _time : String ? = null
)
data class LoginResponse (
var username : String ? = null ,
var device : String ? = null ,
var project _id : String ? = null ,
var projectname : String ? = null ,
var area : String ? = null
)