dev-2025 #1
@@ -13,6 +13,7 @@ import com.pomelotea.hoperun.sign.config.HoperunUserConfig.userConfigMap
|
||||
import com.pomelotea.hoperun.sign.config.UserConfig
|
||||
import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler
|
||||
import com.pomelotea.hoperun.sign.scheduler.AutoDakaScheduler.Companion.dakaQueue
|
||||
import com.pomelotea.hoperun.sign.scheduler.AutoRenewSessionScheduler
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.Request
|
||||
@@ -35,8 +36,11 @@ import java.util.*
|
||||
@RequestMapping("/api/daka")
|
||||
class HoperunSignController {
|
||||
|
||||
val LOGIN_URL = "http://pom.hoperun.com:8187/attm/login/login"
|
||||
|
||||
init {
|
||||
AutoDakaScheduler()
|
||||
AutoRenewSessionScheduler()
|
||||
val yxl = UserConfig(
|
||||
project_id = "U2103S000112",
|
||||
projectcode = "U2103S000112",
|
||||
@@ -46,14 +50,22 @@ class HoperunSignController {
|
||||
userConfigMap["16638"] = yxl
|
||||
}
|
||||
|
||||
@GetMapping("/username/{employeeNo}/{jsessionId}/{checked}")
|
||||
// @GetMapping("/username/{employeeNo}/{checked}/{jsessionId}")
|
||||
@GetMapping("/username/{employeeNo}/{checked}")
|
||||
fun getUsername(
|
||||
@PathVariable employeeNo: String,
|
||||
@PathVariable jsessionId: String,
|
||||
@PathVariable checked: Boolean
|
||||
): WebResult<LoginResponse?> {
|
||||
getJsessionIdAutoLogin(employeeNo, jsessionId)
|
||||
val userConfig = getUserConfig(employeeNo) ?: return WebResult.getFailed("登陆失败")
|
||||
/*
|
||||
if (jsessionId != null) {
|
||||
getJsessionIdAutoLogin(employeeNo, jsessionId)
|
||||
}*/
|
||||
|
||||
val userConfig = getUserConfig(employeeNo).let {
|
||||
oldLogin(employeeNo)
|
||||
getUserConfig(employeeNo)
|
||||
}
|
||||
userConfig ?: return WebResult.getFailed("登陆失败")
|
||||
userConfig.autoDaka = checked
|
||||
userConfig.device = deviceMap[employeeNo]
|
||||
return WebResult.getSuccess(
|
||||
@@ -138,6 +150,7 @@ class HoperunSignController {
|
||||
if (sessionMap.get(employeeNo) == null) {
|
||||
login(employeeNo, jsessionId)
|
||||
}
|
||||
sessionMap[employeeNo] = jsessionId
|
||||
return sessionMap.get(employeeNo)
|
||||
}
|
||||
|
||||
@@ -186,10 +199,26 @@ class HoperunSignController {
|
||||
// 读取员工姓名
|
||||
if (userConfigMap[employeeNo]?.username == null) {
|
||||
setUserConfig(employeeNo, jsessionId)
|
||||
sessionMap.put(employeeNo, jsessionId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun oldLogin(employeeNo: String) {
|
||||
val jsessionId: String?
|
||||
val loginRequest = Request.Builder()
|
||||
.url(LOGIN_URL)
|
||||
.post(
|
||||
FormBody.Builder()
|
||||
.add("login_id", padEmployeeNumber(employeeNo))
|
||||
.add("password", "123456")
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
val response = client.newCall(loginRequest).execute()
|
||||
jsessionId = response.request.url.pathSegments[2].substring(19)
|
||||
sessionMap.put(employeeNo, jsessionId)
|
||||
setUserConfigOld(employeeNo)
|
||||
}
|
||||
|
||||
private fun setUserConfig(employeeNo: String, jsessionId: String) {
|
||||
val attendancesDetailRequest = Request.Builder()
|
||||
.url("http://pom.hoperun.com:8187/attm/calendar/monthAtt?staff_code=${padEmployeeNumber(employeeNo)}&yearmonth=${getNowDateyyyy_MM()}-01")
|
||||
@@ -252,6 +281,77 @@ class HoperunSignController {
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun setUserConfigOld(employeeNo: String) {
|
||||
// 获取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()
|
||||
|
||||
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) {
|
||||
if (lastDakaInfo.getString("actual_area_end") != null) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ object HoperunUserConfig {
|
||||
|
||||
val deviceMap = mapOf<String, String>(
|
||||
"16638" to "Android 12;Redmi;M2007J3SC;deviceId:OAIDe7fa6084205e9a22d8f6f71bc91893ff;deviceName:Android",
|
||||
"9119" to "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"
|
||||
"9119" to "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"
|
||||
)
|
||||
|
||||
val userConfigMap: MutableMap<String, UserConfig> = HashMap()
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.pomelotea.hoperun.sign.scheduler
|
||||
|
||||
import com.pomelotea.hoperun.sign.common.client
|
||||
import com.pomelotea.hoperun.sign.common.sessionMap
|
||||
import okhttp3.Request
|
||||
import org.jsoup.Jsoup
|
||||
import java.io.BufferedWriter
|
||||
import java.io.File
|
||||
import java.io.OutputStreamWriter
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
/**
|
||||
*
|
||||
* @version 0.0.1
|
||||
* @author jimlee
|
||||
* date 2023-03-23 08:54
|
||||
*
|
||||
**/
|
||||
class AutoRenewSessionScheduler {
|
||||
|
||||
val outFile = File("./renewsession.log")
|
||||
val bw: BufferedWriter = BufferedWriter(OutputStreamWriter(outFile.outputStream()))
|
||||
|
||||
val schedulerThreadPool: ScheduledExecutorService = Executors.newScheduledThreadPool(1)
|
||||
|
||||
init {
|
||||
schedulerThreadPool.schedule({renewSession()}, 2, TimeUnit.MINUTES)
|
||||
}
|
||||
|
||||
private fun renewSession() {
|
||||
val iterator = sessionMap.iterator()
|
||||
while (iterator.hasNext()) {
|
||||
val item = iterator.next()
|
||||
item.value?.let {
|
||||
val result = index(it)
|
||||
if (result != null) {
|
||||
bw.write("[RENEW-SESSION]:SUCCESS:USER:$result")
|
||||
bw.newLine()
|
||||
bw.flush()
|
||||
} else {
|
||||
bw.write("[REMOVE-SESSION]:USER:$result")
|
||||
bw.newLine()
|
||||
bw.flush()
|
||||
iterator.remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
schedulerThreadPool.schedule({renewSession()}, (30 + Random().nextInt(30)).toLong(), TimeUnit.MINUTES)
|
||||
}
|
||||
|
||||
private fun index(jsessionId: String): String? {
|
||||
val indexRequest = Request.Builder()
|
||||
.url("http://pom.hoperun.com:8187/attm/attence/getInfo")
|
||||
.get()
|
||||
.addHeader("Cookie", "JSESSIONID=$jsessionId")
|
||||
.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"
|
||||
)
|
||||
.addHeader("accept", "*/*")
|
||||
.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 username = try {
|
||||
Jsoup.parse(indexHtml!!).select("#attendance-detail-content > div.container.none-padding > div > div:nth-child(1) > div:nth-child(4)")
|
||||
.text()
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
return username
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,9 +37,9 @@
|
||||
<div>
|
||||
<input class="login-input" id="employee-number" type="text" placeholder="输入工号">
|
||||
</div>
|
||||
<div>
|
||||
<!--<div>
|
||||
<input class="login-input" style="width: 280px" id="jsessionId" type="text" placeholder="输入SESSIONID">
|
||||
</div>
|
||||
</div>-->
|
||||
<div>
|
||||
<div id="autodaka">自动打卡开关</div>
|
||||
</div>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>打卡</title><link rel="stylesheet"href="./normalize.min.css"><link rel="stylesheet"href="./style.css"></head><body class="dark-mode"><!--partial:index.partial.html--><div class="job"><div class="header"><div class="logo"><svg xmlns="http://www.w3.org/2000/svg"viewBox="0 0 512 512"><path xmlns="http://www.w3.org/2000/svg"d="M512 503.5H381.7a48 48 0 01-45.3-32.1L265 268.1l-9-25.5 2.7-124.6L338.2 8.5l23.5 67.1L512 503.5z"fill="#0473ff"data-original="#28b446"/><path xmlns="http://www.w3.org/2000/svg"fill="#0473ff"data-original="#219b38"d="M361.7 75.6L265 268.1l-9-25.5 2.7-124.6L338.2 8.5z"/><path xmlns="http://www.w3.org/2000/svg"d="M338.2 8.5l-82.2 234-80.4 228.9a48 48 0 01-45.3 32.1H0l173.8-495h164.4z"fill="#0473ff"data-original="#518ef8"/></svg>打卡</div><div class="user-settings"><div class="dark-light"><svg viewBox="0 0 24 24"stroke="currentColor"stroke-width="1.5"fill="none"stroke-linecap="round"stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path></svg></div><img class="user-profile"id="user-head"src="img/tx.png"alt=""><div id="user-div"><div id="username">未登陆</div><span id="login-span"><div class="alert-inline"><div><input class="login-input"id="employee-number"type="text"placeholder="输入工号"></div><div><input class="login-input"style="width: 280px"id="jsessionId"type="text"placeholder="输入SESSIONID"></div><div><div id="autodaka">自动打卡开关</div></div><div><div class="toggle toggle--switch"><input type="checkbox"id="toggle--switch"class="toggle--checkbox"><label class="toggle--btn"for="toggle--switch"><span class="toggle--feature"data-label-on="on"data-label-off="off"></span></label></div></div><div><button class="random-buttons"id="login">登陆</button></div></div></span><div id="logout-div"style="display: none"><button class="random-buttons"id="logout">登出</button></div></div></div></div><div class="dialog"style="display: none"><div class="alert"><div class="job-card-title"id="sign-date"><span style="font-size: 24px"></span></div><div class="alert-inline"><div><input id="sign-begin-time"type="text"placeholder="输入上班时间"></div><div><button class="random-buttons"id="sign-begin-random">随机</button></div></div><div class="alert-inline"><div><input id="sign-end-time"type="text"placeholder="输入下班时间"></div><div><button class="random-buttons"id="sign-end-random">随机</button></div></div><button class="search-buttons card-buttons begin-buttons"id="save-sign">保存</button></div></div><div class="userinfo_dialog"style="display: none"><div class="alert"><div class="job-card-title"><span style="font-size: 24px">打卡信息</span></div><div class="alert-inline"><div><label for="_user_input">用户名:</label><input id="_user_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_project_id_input">项目I D:</label><input id="_project_id_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_project_name_input">项目名称:</label><input id="_project_name_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_area_input">打卡地区:</label><input id="_area_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_device_input">设备信息:</label><input id="_device_input"readonly="readonly"type="text"></div></div></div></div><div class="wrapper"><div class="main-container"><div class="searched-jobs"><div class="searched-bar"><div class="searched-show">打卡记录</div><!--<button class="search-button">餐补<span class="canbu-span"></span></button>--></div><div class="job-cards"></div></div></div></div><script src="./coco-message.js"></script><script src="./jquery.min.js"></script><script src="./script.js"></script></div></body></html>
|
||||
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>打卡</title><link rel="stylesheet"href="./normalize.min.css"><link rel="stylesheet"href="./style.css"></head><body class="dark-mode"><!--partial:index.partial.html--><div class="job"><div class="header"><div class="logo"><svg xmlns="http://www.w3.org/2000/svg"viewBox="0 0 512 512"><path xmlns="http://www.w3.org/2000/svg"d="M512 503.5H381.7a48 48 0 01-45.3-32.1L265 268.1l-9-25.5 2.7-124.6L338.2 8.5l23.5 67.1L512 503.5z"fill="#0473ff"data-original="#28b446"/><path xmlns="http://www.w3.org/2000/svg"fill="#0473ff"data-original="#219b38"d="M361.7 75.6L265 268.1l-9-25.5 2.7-124.6L338.2 8.5z"/><path xmlns="http://www.w3.org/2000/svg"d="M338.2 8.5l-82.2 234-80.4 228.9a48 48 0 01-45.3 32.1H0l173.8-495h164.4z"fill="#0473ff"data-original="#518ef8"/></svg>打卡</div><div class="user-settings"><div class="dark-light"><svg viewBox="0 0 24 24"stroke="currentColor"stroke-width="1.5"fill="none"stroke-linecap="round"stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path></svg></div><img class="user-profile"id="user-head"src="img/tx.png"alt=""><div id="user-div"><div id="username">未登陆</div><span id="login-span"><div class="alert-inline"><div><input class="login-input"id="employee-number"type="text"placeholder="输入工号"></div><!--<div><input class="login-input"style="width: 280px"id="jsessionId"type="text"placeholder="输入SESSIONID"></div>--><div><div id="autodaka">自动打卡开关</div></div><div><div class="toggle toggle--switch"><input type="checkbox"id="toggle--switch"class="toggle--checkbox"><label class="toggle--btn"for="toggle--switch"><span class="toggle--feature"data-label-on="on"data-label-off="off"></span></label></div></div><div><button class="random-buttons"id="login">登陆</button></div></div></span><div id="logout-div"style="display: none"><button class="random-buttons"id="logout">登出</button></div></div></div></div><div class="dialog"style="display: none"><div class="alert"><div class="job-card-title"id="sign-date"><span style="font-size: 24px"></span></div><div class="alert-inline"><div><input id="sign-begin-time"type="text"placeholder="输入上班时间"></div><div><button class="random-buttons"id="sign-begin-random">随机</button></div></div><div class="alert-inline"><div><input id="sign-end-time"type="text"placeholder="输入下班时间"></div><div><button class="random-buttons"id="sign-end-random">随机</button></div></div><button class="search-buttons card-buttons begin-buttons"id="save-sign">保存</button></div></div><div class="userinfo_dialog"style="display: none"><div class="alert"><div class="job-card-title"><span style="font-size: 24px">打卡信息</span></div><div class="alert-inline"><div><label for="_user_input">用户名:</label><input id="_user_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_project_id_input">项目I D:</label><input id="_project_id_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_project_name_input">项目名称:</label><input id="_project_name_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_area_input">打卡地区:</label><input id="_area_input"readonly="readonly"type="text"></div></div><div class="alert-inline"><div><label for="_device_input">设备信息:</label><input id="_device_input"readonly="readonly"type="text"></div></div></div></div><div class="wrapper"><div class="main-container"><div class="searched-jobs"><div class="searched-bar"><div class="searched-show">打卡记录</div><!--<button class="search-button">餐补<span class="canbu-span"></span></button>--></div><div class="job-cards"></div></div></div></div><script src="./coco-message.js"></script><script src="./jquery.min.js"></script><script src="./script.js"></script></div></body></html>
|
||||
@@ -29,13 +29,13 @@ if ($('#login-span').css('display') !== 'none') {
|
||||
}
|
||||
|
||||
|
||||
let jsessonIdInput = document.querySelector('#jsessionId');
|
||||
//let jsessonIdInput = document.querySelector('#jsessionId');
|
||||
let autoDaka = document.querySelector("#toggle--switch")
|
||||
autoDaka.checked = window.localStorage.getItem("autodaka")
|
||||
|
||||
document.querySelector('#login').addEventListener("click", () => {
|
||||
window.localStorage.setItem("employeeNo", employeeNumberInput.value);
|
||||
window.localStorage.setItem("jsessionId", jsessonIdInput.value);
|
||||
// window.localStorage.setItem("jsessionId", jsessonIdInput.value);
|
||||
window.localStorage.setItem("autodaka", autoDaka.checked);
|
||||
loginAndLoadRecord();
|
||||
})
|
||||
@@ -44,12 +44,12 @@ function loginAndLoadRecord() {
|
||||
|
||||
$.ajax({
|
||||
method: "get",
|
||||
url: "/api/daka/username/" + window.localStorage.getItem("employeeNo") + "/" + window.localStorage.getItem("jsessionId") + "/" + window.localStorage.getItem("autodaka") ,
|
||||
url: "/api/daka/username/" + window.localStorage.getItem("employeeNo") + "/" + window.localStorage.getItem("autodaka"),
|
||||
success: function (result) {
|
||||
if (result.success) {
|
||||
// $("#login-span").css("display", "none");
|
||||
$("#login").css("display", "none");
|
||||
$("#jsessionId").css("display", "none");
|
||||
//$("#jsessionId").css("display", "none");
|
||||
$("#employee-number").css("display", "none");
|
||||
$('#username').text(result.data.username);
|
||||
window.localStorage.setItem("username", result.data.username);
|
||||
|
||||
Reference in New Issue
Block a user