1、优化
parent
a43e9b0bbf
commit
340626e83b
|
|
@ -5,6 +5,7 @@ import com.zcloud.personnel.positioning.integration.realtime.RealtimeLocationMes
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.socket.CloseStatus;
|
import org.springframework.web.socket.CloseStatus;
|
||||||
import org.springframework.web.socket.TextMessage;
|
import org.springframework.web.socket.TextMessage;
|
||||||
|
|
@ -87,6 +88,15 @@ public class PersonLocationWebSocketHandler extends TextWebSocketHandler impleme
|
||||||
return sessions.size();
|
return sessions.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Scheduled(fixedDelayString = "${personnel-positioning.websocket.location.session-cleanup-ms:30000}")
|
||||||
|
public void cleanupClosedSessions() {
|
||||||
|
for (Map.Entry<String, SubscriptionSession> entry : sessions.entrySet()) {
|
||||||
|
if (!entry.getValue().session.isOpen()) {
|
||||||
|
sessions.remove(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void removeAndClose(String sessionId) {
|
private void removeAndClose(String sessionId) {
|
||||||
SubscriptionSession subscriptionSession = sessions.remove(sessionId);
|
SubscriptionSession subscriptionSession = sessions.remove(sessionId);
|
||||||
WebSocketSession session = subscriptionSession == null ? null : subscriptionSession.session;
|
WebSocketSession session = subscriptionSession == null ? null : subscriptionSession.session;
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ public class BiOverviewCache {
|
||||||
if (local != null && local.expireAt > now) {
|
if (local != null && local.expireAt > now) {
|
||||||
return local.value;
|
return local.value;
|
||||||
}
|
}
|
||||||
|
if (local != null) {
|
||||||
|
localCache.remove(key, local);
|
||||||
|
}
|
||||||
if (stringRedisTemplate == null) {
|
if (stringRedisTemplate == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,23 +229,27 @@ public class PersonnelPositioningBiQueryExe {
|
||||||
|
|
||||||
public PageResponse<BiAreaFenceCO> listCompanyFence(BiCompanyFenceQry qry) {
|
public PageResponse<BiAreaFenceCO> listCompanyFence(BiCompanyFenceQry qry) {
|
||||||
BiCompanyFenceQry query = qry == null ? new BiCompanyFenceQry() : qry;
|
BiCompanyFenceQry query = qry == null ? new BiCompanyFenceQry() : qry;
|
||||||
List<BiAreaFenceCO> matched = new ArrayList<>();
|
|
||||||
for (BiAreaFenceCO fence : listAllAreaFence()) {
|
|
||||||
if (matchesCompanyFence(fence, query)) {
|
|
||||||
matched.add(fence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int pageNo = Math.max(query.getPageIndex(), 1);
|
int pageNo = Math.max(query.getPageIndex(), 1);
|
||||||
int pageSize = Math.max(query.getPageSize(), 1);
|
int pageSize = Math.max(query.getPageSize(), 1);
|
||||||
int fromIndex = Math.min((pageNo - 1) * pageSize, matched.size());
|
QueryWrapper<FenceDO> wrapper = companyFenceQuery(query);
|
||||||
int toIndex = Math.min(fromIndex + pageSize, matched.size());
|
long total = fenceRepository.count(wrapper);
|
||||||
return PageResponse.of(matched.subList(fromIndex, toIndex), matched.size(), pageSize, pageNo);
|
wrapper.orderByDesc("update_time", "id");
|
||||||
|
wrapper.last("LIMIT " + pageSize + " OFFSET " + ((pageNo - 1) * pageSize));
|
||||||
|
return PageResponse.of(mapLocalFences(fenceRepository.list(wrapper)),
|
||||||
|
safeLongToInt(total), pageSize, pageNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PageResponse<BiPersonLocationCO> listPersonLocation(BiPersonLocationQry qry) {
|
public PageResponse<BiPersonLocationCO> listPersonLocation(BiPersonLocationQry qry) {
|
||||||
BiPersonLocationQry query = qry == null ? new BiPersonLocationQry() : qry;
|
BiPersonLocationQry query = qry == null ? new BiPersonLocationQry() : qry;
|
||||||
int pageNo = Math.max(query.getPageIndex(), 1);
|
int pageNo = Math.max(query.getPageIndex(), 1);
|
||||||
int pageSize = Math.max(query.getPageSize(), 1);
|
int pageSize = Math.max(query.getPageSize(), 1);
|
||||||
|
if (query.getCorpinfoId() != null && localLookupService.hasPersonnelMappings()) {
|
||||||
|
PageResponse<PositionPersonLocalLookupService.PersonMapping> mappingPage =
|
||||||
|
localLookupService.findMatchedPersonnelPage(query);
|
||||||
|
List<BiPersonLocationCO> pageRows = loadPersistedPersonLocations(
|
||||||
|
query, mappingPage.getData());
|
||||||
|
return PageResponse.of(pageRows, mappingPage.getTotalCount(), pageSize, pageNo);
|
||||||
|
}
|
||||||
List<BiPersonLocationCO> rows = loadMatchedPersonLocations(query);
|
List<BiPersonLocationCO> rows = loadMatchedPersonLocations(query);
|
||||||
int fromIndex = Math.min((pageNo - 1) * pageSize, rows.size());
|
int fromIndex = Math.min((pageNo - 1) * pageSize, rows.size());
|
||||||
int toIndex = Math.min(fromIndex + pageSize, rows.size());
|
int toIndex = Math.min(fromIndex + pageSize, rows.size());
|
||||||
|
|
@ -526,11 +530,19 @@ public class PersonnelPositioningBiQueryExe {
|
||||||
localQuery.setCorpinfoName(query.getCompanyName());
|
localQuery.setCorpinfoName(query.getCompanyName());
|
||||||
localQuery.setStaffName(query.getStaffName());
|
localQuery.setStaffName(query.getStaffName());
|
||||||
|
|
||||||
|
return loadPersistedPersonLocations(query, localLookupService.findMatchedPersonnel(localQuery));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<BiPersonLocationCO> loadPersistedPersonLocations(
|
||||||
|
BiPersonLocationQry query,
|
||||||
|
List<PositionPersonLocalLookupService.PersonMapping> mappings) {
|
||||||
|
if (mappings == null || mappings.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
List<MatchedStaffSnapshot> matchedStaff = new ArrayList<>();
|
List<MatchedStaffSnapshot> matchedStaff = new ArrayList<>();
|
||||||
Set<Long> matchedUserIds = new HashSet<>();
|
Set<Long> matchedUserIds = new HashSet<>();
|
||||||
Set<String> terminalNos = new LinkedHashSet<>();
|
Set<String> terminalNos = new LinkedHashSet<>();
|
||||||
for (PositionPersonLocalLookupService.PersonMapping mapping
|
for (PositionPersonLocalLookupService.PersonMapping mapping : mappings) {
|
||||||
: localLookupService.findMatchedPersonnel(localQuery)) {
|
|
||||||
PositionPersonLocalLookupService.LocalPerson local = mapping.getLocal();
|
PositionPersonLocalLookupService.LocalPerson local = mapping.getLocal();
|
||||||
if (local == null || (local.getUserId() != null && !matchedUserIds.add(local.getUserId()))) {
|
if (local == null || (local.getUserId() != null && !matchedUserIds.add(local.getUserId()))) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -654,6 +666,29 @@ public class PersonnelPositioningBiQueryExe {
|
||||||
return wrapper;
|
return wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QueryWrapper<FenceDO> companyFenceQuery(BiCompanyFenceQry query) {
|
||||||
|
QueryWrapper<FenceDO> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.and(value -> value.isNull("delete_enum").or().eq("delete_enum", "FALSE"));
|
||||||
|
if (query.getId() != null) {
|
||||||
|
wrapper.and(value -> value.eq("id", query.getId()).or().eq("finds_fence_id", query.getId()));
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(query.getNameLike())) {
|
||||||
|
wrapper.like("fence_name", query.getNameLike());
|
||||||
|
}
|
||||||
|
if (query.getCorpinfoId() != null) {
|
||||||
|
wrapper.eq("corpinfo_id", query.getCorpinfoId());
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(query.getCompanyName())) {
|
||||||
|
String companyName = query.getCompanyName();
|
||||||
|
wrapper.and(value -> value.eq("corpinfo_name", companyName).or().eq("org_name", companyName));
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(query.getOrgName())) {
|
||||||
|
String orgName = query.getOrgName();
|
||||||
|
wrapper.and(value -> value.eq("corpinfo_name", orgName).or().eq("org_name", orgName));
|
||||||
|
}
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
private List<BiAreaFenceCO> mapLocalFences(List<FenceDO> fences) {
|
private List<BiAreaFenceCO> mapLocalFences(List<FenceDO> fences) {
|
||||||
List<BiAreaFenceCO> result = new ArrayList<>();
|
List<BiAreaFenceCO> result = new ArrayList<>();
|
||||||
if (fences == null || fences.isEmpty()) {
|
if (fences == null || fences.isEmpty()) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.zcloud.personnel.positioning.command.query;
|
package com.zcloud.personnel.positioning.command.query;
|
||||||
|
|
||||||
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
import com.zcloud.personnel.positioning.dto.PositionPersonPageQry;
|
import com.zcloud.personnel.positioning.dto.PositionPersonPageQry;
|
||||||
|
import com.zcloud.personnel.positioning.dto.BiPersonLocationQry;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
||||||
|
|
@ -42,6 +44,36 @@ class PositionPersonLocalLookupService {
|
||||||
return findMatchedPersonnel(query, null);
|
return findMatchedPersonnel(query, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PageResponse<PersonMapping> findMatchedPersonnelPage(PositionPersonPageQry query) {
|
||||||
|
Map<String, Object> params = matchedPersonnelParams(query, null);
|
||||||
|
return findMatchedPersonnelPage(params, query.getPageIndex(), query.getPageSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
PageResponse<PersonMapping> findMatchedPersonnelPage(BiPersonLocationQry query) {
|
||||||
|
Map<String, Object> params = new HashMap<>();
|
||||||
|
params.put("staffName", normalize(query.getStaffName()));
|
||||||
|
params.put("corpinfoId", query.getCorpinfoId());
|
||||||
|
params.put("biCompanyName", normalize(query.getCompanyName()));
|
||||||
|
params.put("staffNo", normalize(query.getStaffNo()));
|
||||||
|
params.put("idCardNo", normalize(query.getIdCardNo()));
|
||||||
|
params.put("mobileNo", normalize(query.getMobileNo()));
|
||||||
|
params.put("terminalNo", normalize(query.getTerminalNo()));
|
||||||
|
params.put("sourceOrgName", normalize(query.getOrgName()));
|
||||||
|
params.put("orgCode", normalize(query.getOrgCode()));
|
||||||
|
params.put("creditCode", normalize(query.getCreditCode()));
|
||||||
|
return findMatchedPersonnelPage(params, query.getPageIndex(), query.getPageSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
private PageResponse<PersonMapping> findMatchedPersonnelPage(Map<String, Object> params,
|
||||||
|
int pageIndex,
|
||||||
|
int pageSize) {
|
||||||
|
params.put("pageIndex", Math.max(pageIndex, 1));
|
||||||
|
params.put("pageSize", Math.max(pageSize, 1));
|
||||||
|
PageResponse<PersonnelMappingSnapshotDO> page = personnelMatchRepository.listMatchedPage(params);
|
||||||
|
return PageResponse.of(toPersonMappings(page.getData()), page.getTotalCount(),
|
||||||
|
page.getPageSize(), page.getPageIndex());
|
||||||
|
}
|
||||||
|
|
||||||
List<PersonMapping> findMatchedPersonnelByCorpinfoIds(Set<Long> corpinfoIds) {
|
List<PersonMapping> findMatchedPersonnelByCorpinfoIds(Set<Long> corpinfoIds) {
|
||||||
List<PersonMapping> result = new ArrayList<>();
|
List<PersonMapping> result = new ArrayList<>();
|
||||||
for (Set<Long> batch : idBatches(corpinfoIds)) {
|
for (Set<Long> batch : idBatches(corpinfoIds)) {
|
||||||
|
|
@ -52,6 +84,12 @@ class PositionPersonLocalLookupService {
|
||||||
|
|
||||||
private List<PersonMapping> findMatchedPersonnel(PositionPersonPageQry query,
|
private List<PersonMapping> findMatchedPersonnel(PositionPersonPageQry query,
|
||||||
Set<Long> corpinfoIds) {
|
Set<Long> corpinfoIds) {
|
||||||
|
return toPersonMappings(personnelMatchRepository.listMatched(
|
||||||
|
matchedPersonnelParams(query, corpinfoIds)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> matchedPersonnelParams(PositionPersonPageQry query,
|
||||||
|
Set<Long> corpinfoIds) {
|
||||||
Map<String, Object> params = new HashMap<>();
|
Map<String, Object> params = new HashMap<>();
|
||||||
if (query != null) {
|
if (query != null) {
|
||||||
params.put("userId", query.getUserId());
|
params.put("userId", query.getUserId());
|
||||||
|
|
@ -60,12 +98,18 @@ class PositionPersonLocalLookupService {
|
||||||
params.put("corpinfoName", normalize(query.getCorpinfoName()));
|
params.put("corpinfoName", normalize(query.getCorpinfoName()));
|
||||||
params.put("departmentId", query.getDepartmentId());
|
params.put("departmentId", query.getDepartmentId());
|
||||||
params.put("departmentName", normalize(query.getDepartmentName()));
|
params.put("departmentName", normalize(query.getDepartmentName()));
|
||||||
|
params.put("locationStatus", upper(query.getLocationStatus()));
|
||||||
|
params.put("positionSource", upper(query.getPositionSource()));
|
||||||
}
|
}
|
||||||
if (corpinfoIds != null && !corpinfoIds.isEmpty()) {
|
if (corpinfoIds != null && !corpinfoIds.isEmpty()) {
|
||||||
params.put("corpinfoIds", corpinfoIds);
|
params.put("corpinfoIds", corpinfoIds);
|
||||||
}
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PersonMapping> toPersonMappings(List<PersonnelMappingSnapshotDO> rows) {
|
||||||
List<PersonMapping> result = new ArrayList<>();
|
List<PersonMapping> result = new ArrayList<>();
|
||||||
for (PersonnelMappingSnapshotDO row : personnelMatchRepository.listMatched(params)) {
|
for (PersonnelMappingSnapshotDO row : rows) {
|
||||||
PersonMapping mapping = new PersonMapping();
|
PersonMapping mapping = new PersonMapping();
|
||||||
mapping.setFindsStaffNo(normalize(row.getFindsStaffNo()));
|
mapping.setFindsStaffNo(normalize(row.getFindsStaffNo()));
|
||||||
mapping.setFindsStaffNoType(normalize(row.getFindsStaffNoType()));
|
mapping.setFindsStaffNoType(normalize(row.getFindsStaffNoType()));
|
||||||
|
|
@ -86,6 +130,11 @@ class PositionPersonLocalLookupService {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String upper(String value) {
|
||||||
|
String normalized = normalize(value);
|
||||||
|
return normalized == null ? null : normalized.toUpperCase(java.util.Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量保存实时定位点匹配出的当前区域。
|
* 批量保存实时定位点匹配出的当前区域。
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,14 @@ public class PositionPersonQueryExe {
|
||||||
|
|
||||||
public PageResponse<PositionPersonCO> list(PositionPersonPageQry qry) {
|
public PageResponse<PositionPersonCO> list(PositionPersonPageQry qry) {
|
||||||
PositionPersonPageQry query = qry == null ? new PositionPersonPageQry() : qry;
|
PositionPersonPageQry query = qry == null ? new PositionPersonPageQry() : qry;
|
||||||
|
if (localLookupService.hasPersonnelMappings()) {
|
||||||
|
PageResponse<PositionPersonLocalLookupService.PersonMapping> mappingPage =
|
||||||
|
localLookupService.findMatchedPersonnelPage(query);
|
||||||
|
List<PositionPersonCO> pageRows = buildRows(
|
||||||
|
query, true, loadPersistedMatches(mappingPage.getData()), true);
|
||||||
|
return PageResponse.of(pageRows, mappingPage.getTotalCount(),
|
||||||
|
mappingPage.getPageSize(), mappingPage.getPageIndex());
|
||||||
|
}
|
||||||
List<PositionPersonCO> rows = listRows(query);
|
List<PositionPersonCO> rows = listRows(query);
|
||||||
int pageIndex = Math.max(query.getPageIndex(), 1);
|
int pageIndex = Math.max(query.getPageIndex(), 1);
|
||||||
int pageSize = Math.max(query.getPageSize(), 1);
|
int pageSize = Math.max(query.getPageSize(), 1);
|
||||||
|
|
@ -260,12 +268,11 @@ public class PositionPersonQueryExe {
|
||||||
for (int pageNo = 2; pageNo <= pageCount; pageNo++) {
|
for (int pageNo = 2; pageNo <= pageCount; pageNo++) {
|
||||||
requests.add(staffPageRequest(pageNo));
|
requests.add(staffPageRequest(pageNo));
|
||||||
}
|
}
|
||||||
List<JsonNode> roots = findsOpenApiClient.postFailFastBatch(
|
findsOpenApiClient.consumeFailFastBatch(
|
||||||
STAFF_LIST_API, requests, FINDS_BATCH_CONCURRENCY);
|
STAFF_LIST_API, requests, FINDS_BATCH_CONCURRENCY, (index, root) -> {
|
||||||
for (JsonNode root : roots) {
|
JsonNode data = assertSuccess(root, STAFF_LIST_API).path("data");
|
||||||
JsonNode data = assertSuccess(root, STAFF_LIST_API).path("data");
|
appendFindsStaff(result, extractRows(data));
|
||||||
appendFindsStaff(result, extractRows(data));
|
});
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -330,12 +337,10 @@ public class PositionPersonQueryExe {
|
||||||
for (List<String> terminalBatch : batches) {
|
for (List<String> terminalBatch : batches) {
|
||||||
requests.add(Collections.singletonMap("terminalNoList", terminalBatch));
|
requests.add(Collections.singletonMap("terminalNoList", terminalBatch));
|
||||||
}
|
}
|
||||||
List<JsonNode> roots = findsOpenApiClient.postFailFastBatch(
|
|
||||||
POINT_LOCATE_API, requests, FINDS_BATCH_CONCURRENCY);
|
|
||||||
Map<String, JsonNode> result = new LinkedHashMap<>();
|
Map<String, JsonNode> result = new LinkedHashMap<>();
|
||||||
for (int index = 0; index < roots.size(); index++) {
|
findsOpenApiClient.consumeFailFastBatch(
|
||||||
appendLocatedTerminals(batches.get(index), roots.get(index), result);
|
POINT_LOCATE_API, requests, FINDS_BATCH_CONCURRENCY,
|
||||||
}
|
(index, root) -> appendLocatedTerminals(batches.get(index), root, result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -195,8 +195,6 @@ public class RealtimePersonLocationMatcher {
|
||||||
co.setOnline(online == null ? Boolean.FALSE : online);
|
co.setOnline(online == null ? Boolean.FALSE : online);
|
||||||
co.setAlarmStatus(booleanValue(firstValue(location, row, "alarmStatus", "isAlarm")));
|
co.setAlarmStatus(booleanValue(firstValue(location, row, "alarmStatus", "isAlarm")));
|
||||||
co.setAlarmCount(integerValue(firstValue(location, row, "alarmCount", "unclosedAlarmCount")));
|
co.setAlarmCount(integerValue(firstValue(location, row, "alarmCount", "unclosedAlarmCount")));
|
||||||
co.setStaffRawJson(row.toString());
|
|
||||||
co.setLocationRawJson(location.toString());
|
|
||||||
return co;
|
return co;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,12 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FindS OpenAPI signed client.
|
* FindS OpenAPI signed client.
|
||||||
|
|
@ -43,6 +45,7 @@ import java.util.concurrent.Future;
|
||||||
public class FindsOpenApiClient {
|
public class FindsOpenApiClient {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(FindsOpenApiClient.class);
|
private static final Logger LOGGER = LoggerFactory.getLogger(FindsOpenApiClient.class);
|
||||||
private static final String SIK_PATH_SEGMENT = "sik";
|
private static final String SIK_PATH_SEGMENT = "sik";
|
||||||
|
private static final int MAX_RESPONSE_BYTES = 16 * 1024 * 1024;
|
||||||
|
|
||||||
@Value("${finds.openapi.connect-timeout-ms:10000}")
|
@Value("${finds.openapi.connect-timeout-ms:10000}")
|
||||||
private int connectTimeoutMs = 10000;
|
private int connectTimeoutMs = 10000;
|
||||||
|
|
@ -73,34 +76,38 @@ public class FindsOpenApiClient {
|
||||||
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1);
|
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<JsonNode> postFailFastBatch(String apiName, List<Map<String, Object>> requests,
|
public void consumeFailFastBatch(String apiName, List<Map<String, Object>> requests,
|
||||||
int maxConcurrency) {
|
int maxConcurrency,
|
||||||
|
BiConsumer<Integer, JsonNode> responseConsumer) {
|
||||||
if (requests == null || requests.isEmpty()) {
|
if (requests == null || requests.isEmpty()) {
|
||||||
return Collections.emptyList();
|
return;
|
||||||
}
|
}
|
||||||
|
Objects.requireNonNull(responseConsumer, "responseConsumer");
|
||||||
OpenapiConfigDO config = loadEnabledConfig();
|
OpenapiConfigDO config = loadEnabledConfig();
|
||||||
int concurrency = Math.max(1, Math.min(Math.min(maxConcurrency, 8), requests.size()));
|
int concurrency = Math.max(1, Math.min(Math.min(maxConcurrency, 8), requests.size()));
|
||||||
if (concurrency == 1) {
|
if (concurrency == 1) {
|
||||||
List<JsonNode> result = new ArrayList<>(requests.size());
|
for (int index = 0; index < requests.size(); index++) {
|
||||||
for (Map<String, Object> request : requests) {
|
responseConsumer.accept(index, post(config, apiName, requests.get(index),
|
||||||
result.add(post(config, apiName, request,
|
|
||||||
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1));
|
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1));
|
||||||
}
|
}
|
||||||
return result;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(concurrency);
|
ExecutorService executor = Executors.newFixedThreadPool(concurrency);
|
||||||
try {
|
try {
|
||||||
List<Future<JsonNode>> futures = new ArrayList<>(requests.size());
|
// 每个窗口完成后立即交给调用方处理,避免所有分页响应同时滞留在 Future 中。
|
||||||
for (Map<String, Object> request : requests) {
|
for (int from = 0; from < requests.size(); from += concurrency) {
|
||||||
futures.add(executor.submit(() -> post(config, apiName, request,
|
int to = Math.min(from + concurrency, requests.size());
|
||||||
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1)));
|
List<Future<JsonNode>> futures = new ArrayList<>(to - from);
|
||||||
|
for (int index = from; index < to; index++) {
|
||||||
|
Map<String, Object> request = requests.get(index);
|
||||||
|
futures.add(executor.submit(() -> post(config, apiName, request,
|
||||||
|
failFastConnectTimeoutMs, failFastReadTimeoutMs, 1)));
|
||||||
|
}
|
||||||
|
for (int offset = 0; offset < futures.size(); offset++) {
|
||||||
|
responseConsumer.accept(from + offset, futures.get(offset).get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
List<JsonNode> result = new ArrayList<>(requests.size());
|
|
||||||
for (Future<JsonNode> future : futures) {
|
|
||||||
result.add(future.get());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
throw new BizException("FindS OpenAPI批量请求被中断");
|
throw new BizException("FindS OpenAPI批量请求被中断");
|
||||||
|
|
@ -247,13 +254,18 @@ public class FindsOpenApiClient {
|
||||||
if (inputStream == null) {
|
if (inputStream == null) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(8192);
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
|
int total = 0;
|
||||||
int len;
|
int len;
|
||||||
while ((len = inputStream.read(buffer)) != -1) {
|
while ((len = inputStream.read(buffer)) != -1) {
|
||||||
|
if (len > MAX_RESPONSE_BYTES - total) {
|
||||||
|
throw new IOException("FindS OpenAPI response exceeds 16 MiB safety limit");
|
||||||
|
}
|
||||||
outputStream.write(buffer, 0, len);
|
outputStream.write(buffer, 0, len);
|
||||||
|
total += len;
|
||||||
}
|
}
|
||||||
return new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
|
return outputStream.toString(StandardCharsets.UTF_8.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String writeJson(Object value) {
|
private String writeJson(Object value) {
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,9 @@ public class OpenapiConfigCache {
|
||||||
if (local != null && local.expireAt > now) {
|
if (local != null && local.expireAt > now) {
|
||||||
return local.config;
|
return local.config;
|
||||||
}
|
}
|
||||||
|
if (local != null) {
|
||||||
|
localCache.remove(key, local);
|
||||||
|
}
|
||||||
OpenapiConfigDO redisConfig = readRedis(key);
|
OpenapiConfigDO redisConfig = readRedis(key);
|
||||||
if (redisConfig != null) {
|
if (redisConfig != null) {
|
||||||
putLocal(key, redisConfig);
|
putLocal(key, redisConfig);
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,8 @@ import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
@ -83,8 +82,7 @@ public class RealtimePersonRoutingCache {
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Map<String, PersonRoute> routes = buildRoutes(
|
Map<String, PersonRoute> routes = buildRoutes();
|
||||||
personnelMatchRepository.listRealtimePersonRoutes(SOURCE_CONFIG_CODE));
|
|
||||||
snapshot = new CacheSnapshot(Collections.unmodifiableMap(routes), now + ttlMillis);
|
snapshot = new CacheSnapshot(Collections.unmodifiableMap(routes), now + ttlMillis);
|
||||||
LOGGER.info("Realtime WebSocket person-routing cache refreshed, size={}", routes.size());
|
LOGGER.info("Realtime WebSocket person-routing cache refreshed, size={}", routes.size());
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
|
|
@ -97,49 +95,10 @@ public class RealtimePersonRoutingCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, PersonRoute> buildRoutes(List<RealtimePersonRoutingDO> rows) {
|
private Map<String, PersonRoute> buildRoutes() {
|
||||||
Map<String, PersonRoute> persistedRoutes = new LinkedHashMap<>();
|
RouteAccumulator accumulator = new RouteAccumulator();
|
||||||
UniqueRouteIndex usernames = new UniqueRouteIndex();
|
personnelMatchRepository.scanRealtimePersonRoutes(SOURCE_CONFIG_CODE, accumulator::add);
|
||||||
UniqueRouteIndex phones = new UniqueRouteIndex();
|
return accumulator.toRoutes();
|
||||||
if (rows != null) {
|
|
||||||
for (RealtimePersonRoutingDO row : rows) {
|
|
||||||
if (row == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PersonRoute route = toRoute(row);
|
|
||||||
if (row.isPersistedMatch()) {
|
|
||||||
String staffNo = normalize(row.getFindsStaffNo());
|
|
||||||
if (staffNo != null) {
|
|
||||||
persistedRoutes.put(staffNo, route);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
usernames.add(row.getLocalStaffNo(), route);
|
|
||||||
phones.add(row.getMobileNo(), route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, PersonRoute> routes = new LinkedHashMap<>(persistedRoutes);
|
|
||||||
Set<String> fallbackKeys = new LinkedHashSet<>();
|
|
||||||
fallbackKeys.addAll(usernames.keys());
|
|
||||||
fallbackKeys.addAll(phones.keys());
|
|
||||||
for (String key : fallbackKeys) {
|
|
||||||
if (routes.containsKey(key)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
IndexResult username = usernames.resolve(key);
|
|
||||||
if (username.present) {
|
|
||||||
if (!username.ambiguous) {
|
|
||||||
routes.put(key, username.route);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
IndexResult phone = phones.resolve(key);
|
|
||||||
if (phone.present && !phone.ambiguous) {
|
|
||||||
routes.put(key, phone.route);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return routes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PersonRoute toRoute(RealtimePersonRoutingDO row) {
|
private PersonRoute toRoute(RealtimePersonRoutingDO row) {
|
||||||
|
|
@ -179,8 +138,8 @@ public class RealtimePersonRoutingCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class UniqueRouteIndex {
|
private static final class UniqueRouteIndex {
|
||||||
private final Map<String, PersonRoute> unique = new LinkedHashMap<>();
|
private final Map<String, PersonRoute> unique = new HashMap<>();
|
||||||
private final Set<String> ambiguous = new LinkedHashSet<>();
|
private final Set<String> ambiguous = new HashSet<>();
|
||||||
|
|
||||||
private void add(String rawKey, PersonRoute route) {
|
private void add(String rawKey, PersonRoute route) {
|
||||||
String key = normalize(rawKey);
|
String key = normalize(rawKey);
|
||||||
|
|
@ -194,18 +153,18 @@ public class RealtimePersonRoutingCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> keys() {
|
private boolean contains(String key) {
|
||||||
Set<String> keys = new LinkedHashSet<>(unique.keySet());
|
return unique.containsKey(key) || ambiguous.contains(key);
|
||||||
keys.addAll(ambiguous);
|
|
||||||
return keys;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndexResult resolve(String key) {
|
private void appendUniqueRoutes(Map<String, PersonRoute> routes,
|
||||||
if (ambiguous.contains(key)) {
|
UniqueRouteIndex preferredIndex) {
|
||||||
return IndexResult.ambiguous();
|
for (Map.Entry<String, PersonRoute> entry : unique.entrySet()) {
|
||||||
|
if (preferredIndex != null && preferredIndex.contains(entry.getKey())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
routes.putIfAbsent(entry.getKey(), entry.getValue());
|
||||||
}
|
}
|
||||||
PersonRoute route = unique.get(key);
|
|
||||||
return route == null ? IndexResult.absent() : IndexResult.unique(route);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean sameUser(PersonRoute first, PersonRoute second) {
|
private boolean sameUser(PersonRoute first, PersonRoute second) {
|
||||||
|
|
@ -213,20 +172,33 @@ public class RealtimePersonRoutingCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class IndexResult {
|
private final class RouteAccumulator {
|
||||||
private final boolean present;
|
private final Map<String, PersonRoute> routes = new HashMap<>();
|
||||||
private final boolean ambiguous;
|
private final UniqueRouteIndex usernames = new UniqueRouteIndex();
|
||||||
private final PersonRoute route;
|
private final UniqueRouteIndex phones = new UniqueRouteIndex();
|
||||||
|
|
||||||
private IndexResult(boolean present, boolean ambiguous, PersonRoute route) {
|
private void add(RealtimePersonRoutingDO row) {
|
||||||
this.present = present;
|
if (row == null) {
|
||||||
this.ambiguous = ambiguous;
|
return;
|
||||||
this.route = route;
|
}
|
||||||
|
PersonRoute route = toRoute(row);
|
||||||
|
if (row.isPersistedMatch()) {
|
||||||
|
String staffNo = normalize(row.getFindsStaffNo());
|
||||||
|
if (staffNo != null) {
|
||||||
|
routes.put(staffNo, route);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
usernames.add(row.getLocalStaffNo(), route);
|
||||||
|
phones.add(row.getMobileNo(), route);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IndexResult absent() { return new IndexResult(false, false, null); }
|
private Map<String, PersonRoute> toRoutes() {
|
||||||
private static IndexResult ambiguous() { return new IndexResult(true, true, null); }
|
usernames.appendUniqueRoutes(routes, null);
|
||||||
private static IndexResult unique(PersonRoute route) { return new IndexResult(true, false, route); }
|
// 用户名存在但有歧义时也不能回退到同值手机号,保持原有匹配优先级。
|
||||||
|
phones.appendUniqueRoutes(routes, usernames);
|
||||||
|
return routes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class CacheSnapshot {
|
private static final class CacheSnapshot {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,10 @@ import com.zcloud.personnel.positioning.persistence.dataobject.RealtimePersonRou
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.TerminalBindingSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.TerminalBindingSnapshotDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.TerminalLocationSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.TerminalLocationSnapshotDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.session.ResultHandler;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -51,11 +53,16 @@ public interface PersonnelMatchMapper {
|
||||||
@Param("updates") List<PersonnelLocationAreaUpdateDO> updates,
|
@Param("updates") List<PersonnelLocationAreaUpdateDO> updates,
|
||||||
@Param("syncTime") LocalDateTime syncTime);
|
@Param("syncTime") LocalDateTime syncTime);
|
||||||
|
|
||||||
List<RealtimePersonRoutingDO> listRealtimePersonRoutes(
|
void scanRealtimePersonRoutes(
|
||||||
@Param("sourceConfigCode") String sourceConfigCode);
|
@Param("sourceConfigCode") String sourceConfigCode,
|
||||||
|
ResultHandler<RealtimePersonRoutingDO> resultHandler);
|
||||||
|
|
||||||
List<PersonnelMappingSnapshotDO> listMatched(@Param("params") Map<String, Object> params);
|
List<PersonnelMappingSnapshotDO> listMatched(@Param("params") Map<String, Object> params);
|
||||||
|
|
||||||
|
IPage<PersonnelMappingSnapshotDO> listMatchedPage(
|
||||||
|
IPage<PersonnelMappingSnapshotDO> page,
|
||||||
|
@Param("params") Map<String, Object> params);
|
||||||
|
|
||||||
List<PersonnelLocalPersonDO> listPeopleByPhones(@Param("values") List<String> values);
|
List<PersonnelLocalPersonDO> listPeopleByPhones(@Param("values") List<String> values);
|
||||||
|
|
||||||
List<PersonnelLocalPersonDO> listAllPeople();
|
List<PersonnelLocalPersonDO> listAllPeople();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.zcloud.personnel.positioning.persistence.repository;
|
package com.zcloud.personnel.positioning.persistence.repository;
|
||||||
|
|
||||||
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
||||||
|
|
@ -11,6 +12,7 @@ import com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotD
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public interface PersonnelMatchRepository {
|
public interface PersonnelMatchRepository {
|
||||||
long countActive(String sourceConfigCode);
|
long countActive(String sourceConfigCode);
|
||||||
|
|
@ -36,10 +38,12 @@ public interface PersonnelMatchRepository {
|
||||||
List<PersonnelLocationAreaUpdateDO> updates,
|
List<PersonnelLocationAreaUpdateDO> updates,
|
||||||
LocalDateTime syncTime);
|
LocalDateTime syncTime);
|
||||||
|
|
||||||
List<RealtimePersonRoutingDO> listRealtimePersonRoutes(String sourceConfigCode);
|
void scanRealtimePersonRoutes(String sourceConfigCode, Consumer<RealtimePersonRoutingDO> consumer);
|
||||||
|
|
||||||
List<PersonnelMappingSnapshotDO> listMatched(Map<String, Object> params);
|
List<PersonnelMappingSnapshotDO> listMatched(Map<String, Object> params);
|
||||||
|
|
||||||
|
PageResponse<PersonnelMappingSnapshotDO> listMatchedPage(Map<String, Object> params);
|
||||||
|
|
||||||
List<PersonnelLocalPersonDO> listPeopleByPhones(List<String> values);
|
List<PersonnelLocalPersonDO> listPeopleByPhones(List<String> values);
|
||||||
|
|
||||||
List<PersonnelLocalPersonDO> listAllPeople();
|
List<PersonnelLocalPersonDO> listAllPeople();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
package com.zcloud.personnel.positioning.persistence.repository.impl;
|
package com.zcloud.personnel.positioning.persistence.repository.impl;
|
||||||
|
|
||||||
|
import com.alibaba.cola.dto.PageResponse;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.jjb.saas.framework.repository.common.PageHelper;
|
||||||
|
import com.zcloud.gbscommon.utils.Query;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocalPersonDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelLocationAreaUpdateDO;
|
||||||
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
import com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO;
|
||||||
|
|
@ -18,6 +22,8 @@ import java.time.LocalDateTime;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
|
@ -63,12 +69,21 @@ public class PersonnelMatchRepositoryImpl implements PersonnelMatchRepository {
|
||||||
}
|
}
|
||||||
return affected;
|
return affected;
|
||||||
}
|
}
|
||||||
@Override public List<RealtimePersonRoutingDO> listRealtimePersonRoutes(String code) {
|
@Override
|
||||||
return personnelMatchMapper.listRealtimePersonRoutes(code);
|
public void scanRealtimePersonRoutes(String code, Consumer<RealtimePersonRoutingDO> consumer) {
|
||||||
|
Objects.requireNonNull(consumer, "consumer");
|
||||||
|
// ResultHandler 在 Mapper 调用期间逐行消费,避免先将全量人员结果装入 List。
|
||||||
|
personnelMatchMapper.scanRealtimePersonRoutes(
|
||||||
|
code, context -> consumer.accept(context.getResultObject()));
|
||||||
}
|
}
|
||||||
@Override public List<PersonnelMappingSnapshotDO> listMatched(Map<String, Object> params) {
|
@Override public List<PersonnelMappingSnapshotDO> listMatched(Map<String, Object> params) {
|
||||||
return personnelMatchMapper.listMatched(params);
|
return personnelMatchMapper.listMatched(params);
|
||||||
}
|
}
|
||||||
|
@Override public PageResponse<PersonnelMappingSnapshotDO> listMatchedPage(Map<String, Object> params) {
|
||||||
|
IPage<PersonnelMappingSnapshotDO> page = new Query<PersonnelMappingSnapshotDO>().getPage(params);
|
||||||
|
IPage<PersonnelMappingSnapshotDO> result = personnelMatchMapper.listMatchedPage(page, params);
|
||||||
|
return PageHelper.pageToResponse(result, result.getRecords());
|
||||||
|
}
|
||||||
@Override public List<PersonnelLocalPersonDO> listPeopleByPhones(List<String> values) {
|
@Override public List<PersonnelLocalPersonDO> listPeopleByPhones(List<String> values) {
|
||||||
return personnelMatchMapper.listPeopleByPhones(values);
|
return personnelMatchMapper.listPeopleByPhones(values);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,19 +113,18 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<select id="listRealtimePersonRoutes"
|
<select id="scanRealtimePersonRoutes"
|
||||||
|
fetchSize="-2147483648"
|
||||||
|
resultSetType="FORWARD_ONLY"
|
||||||
resultType="com.zcloud.personnel.positioning.persistence.dataobject.RealtimePersonRoutingDO">
|
resultType="com.zcloud.personnel.positioning.persistence.dataobject.RealtimePersonRoutingDO">
|
||||||
SELECT pm.finds_staff_no, u.id AS user_id, u.username AS local_staff_no,
|
SELECT pm.finds_staff_no, u.id AS user_id, u.username AS local_staff_no,
|
||||||
u.name AS staff_name, TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no,
|
u.name AS staff_name, TRIM(u.phone) AS mobile_no,
|
||||||
ci.id AS corpinfo_id, ci.corp_name AS corpinfo_name, ci.code AS credit_code,
|
ci.id AS corpinfo_id, ci.corp_name AS corpinfo_name, ci.port_area AS port_area,
|
||||||
ci.port_area AS port_area, u.department_id, d.dept_name AS department_name,
|
|
||||||
1 AS persisted_match
|
1 AS persisted_match
|
||||||
FROM personnel_match pm
|
FROM personnel_match pm
|
||||||
INNER JOIN user_scope_v u ON u.id = pm.local_user_id
|
INNER JOIN user_scope_v u ON u.id = pm.local_user_id
|
||||||
LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
|
LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
|
||||||
AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
|
AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
|
||||||
LEFT JOIN department d ON d.id = u.department_id
|
|
||||||
AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
|
|
||||||
WHERE pm.source_config_code = #{sourceConfigCode}
|
WHERE pm.source_config_code = #{sourceConfigCode}
|
||||||
AND pm.match_status = 'MATCHED'
|
AND pm.match_status = 'MATCHED'
|
||||||
AND (pm.delete_enum IS NULL OR pm.delete_enum = 'FALSE')
|
AND (pm.delete_enum IS NULL OR pm.delete_enum = 'FALSE')
|
||||||
|
|
@ -133,15 +132,12 @@
|
||||||
AND pm.finds_staff_no IS NOT NULL AND TRIM(pm.finds_staff_no) <> ''
|
AND pm.finds_staff_no IS NOT NULL AND TRIM(pm.finds_staff_no) <> ''
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT NULL AS finds_staff_no, u.id AS user_id, u.username AS local_staff_no,
|
SELECT NULL AS finds_staff_no, u.id AS user_id, u.username AS local_staff_no,
|
||||||
u.name AS staff_name, TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no,
|
u.name AS staff_name, TRIM(u.phone) AS mobile_no,
|
||||||
ci.id AS corpinfo_id, ci.corp_name AS corpinfo_name, ci.code AS credit_code,
|
ci.id AS corpinfo_id, ci.corp_name AS corpinfo_name, ci.port_area AS port_area,
|
||||||
ci.port_area AS port_area, u.department_id, d.dept_name AS department_name,
|
|
||||||
0 AS persisted_match
|
0 AS persisted_match
|
||||||
FROM user_scope_v u
|
FROM user_scope_v u
|
||||||
LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
|
LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
|
||||||
AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
|
AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
|
||||||
LEFT JOIN department d ON d.id = u.department_id
|
|
||||||
AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
|
|
||||||
WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
|
WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
@ -255,6 +251,102 @@
|
||||||
ORDER BY u.id DESC, pm.finds_staff_no
|
ORDER BY u.id DESC, pm.finds_staff_no
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="listMatchedPage"
|
||||||
|
resultType="com.zcloud.personnel.positioning.persistence.dataobject.PersonnelMappingSnapshotDO">
|
||||||
|
SELECT pm.finds_staff_no, pm.finds_staff_no_type, pm.finds_id_card_no,
|
||||||
|
pm.finds_staff_name, pm.finds_corpinfo_id, pm.finds_corpinfo_name,
|
||||||
|
pm.finds_department_name, pm.finds_terminal_no, pm.location_status,
|
||||||
|
pm.finds_device_status, pm.location_area_id, pm.location_area_name,
|
||||||
|
pm.location_area_time, u.id AS user_id, u.username AS local_staff_no,
|
||||||
|
u.name AS staff_name, TRIM(u.phone) AS mobile_no, u.user_id_card AS id_card_no,
|
||||||
|
ci.id AS corpinfo_id, ci.corp_name AS corpinfo_name, ci.code AS credit_code,
|
||||||
|
u.department_id, d.dept_name AS department_name
|
||||||
|
FROM personnel_match pm
|
||||||
|
JOIN user_scope_v u ON u.id = pm.local_user_id
|
||||||
|
LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
|
||||||
|
LEFT JOIN department d ON d.id = u.department_id
|
||||||
|
AND (d.delete_enum IS NULL OR d.delete_enum = 'FALSE')
|
||||||
|
<if test="(params.locationStatus != null and params.locationStatus != '')
|
||||||
|
or (params.positionSource != null and params.positionSource != '')">
|
||||||
|
LEFT JOIN terminal t ON t.id = (
|
||||||
|
SELECT t_pick.id
|
||||||
|
FROM terminal t_pick
|
||||||
|
WHERE t_pick.terminal_no = pm.finds_terminal_no
|
||||||
|
AND (t_pick.delete_enum IS NULL OR t_pick.delete_enum = 'FALSE')
|
||||||
|
ORDER BY t_pick.update_time DESC, t_pick.id DESC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
WHERE pm.match_status = 'MATCHED'
|
||||||
|
AND (pm.delete_enum IS NULL OR pm.delete_enum = 'FALSE')
|
||||||
|
AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
|
||||||
|
AND pm.id = (
|
||||||
|
SELECT pm_pick.id
|
||||||
|
FROM personnel_match pm_pick
|
||||||
|
WHERE pm_pick.local_user_id = pm.local_user_id
|
||||||
|
AND pm_pick.match_status = 'MATCHED'
|
||||||
|
AND (pm_pick.delete_enum IS NULL OR pm_pick.delete_enum = 'FALSE')
|
||||||
|
ORDER BY pm_pick.finds_staff_no, pm_pick.id
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
<if test="params.userId != null">AND u.id = #{params.userId}</if>
|
||||||
|
<if test="params.staffName != null and params.staffName != ''">AND u.name LIKE CONCAT('%', #{params.staffName}, '%')</if>
|
||||||
|
<if test="params.corpinfoId != null">AND ci.id = #{params.corpinfoId}</if>
|
||||||
|
<if test="params.corpinfoName != null and params.corpinfoName != ''">AND ci.corp_name LIKE CONCAT('%', #{params.corpinfoName}, '%')</if>
|
||||||
|
<if test="params.biCompanyName != null and params.biCompanyName != ''">
|
||||||
|
AND COALESCE(NULLIF(ci.corp_name, ''), NULLIF(pm.finds_department_name, ''),
|
||||||
|
pm.finds_corpinfo_name, '') LIKE CONCAT('%', #{params.biCompanyName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="params.departmentId != null">AND u.department_id = #{params.departmentId}</if>
|
||||||
|
<if test="params.departmentName != null and params.departmentName != ''">AND d.dept_name LIKE CONCAT('%', #{params.departmentName}, '%')</if>
|
||||||
|
<if test="params.staffNo != null and params.staffNo != ''">AND pm.finds_staff_no = #{params.staffNo}</if>
|
||||||
|
<if test="params.idCardNo != null and params.idCardNo != ''">AND u.user_id_card = #{params.idCardNo}</if>
|
||||||
|
<if test="params.mobileNo != null and params.mobileNo != ''">AND TRIM(u.phone) = #{params.mobileNo}</if>
|
||||||
|
<if test="params.sourceOrgName != null and params.sourceOrgName != ''">
|
||||||
|
AND COALESCE(NULLIF(pm.finds_department_name, ''), pm.finds_corpinfo_name, '')
|
||||||
|
LIKE CONCAT('%', #{params.sourceOrgName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="params.creditCode != null and params.creditCode != ''">AND ci.code = #{params.creditCode}</if>
|
||||||
|
<if test="params.orgCode != null and params.orgCode != ''">AND 1 = 0</if>
|
||||||
|
<if test="params.terminalNo != null and params.terminalNo != ''">
|
||||||
|
AND (
|
||||||
|
pm.finds_terminal_no = #{params.terminalNo}
|
||||||
|
OR ((pm.finds_terminal_no IS NULL OR pm.finds_terminal_no = '') AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM terminal t_filter
|
||||||
|
LEFT JOIN terminal_bind tb_filter ON tb_filter.id = (
|
||||||
|
SELECT tb_pick.id
|
||||||
|
FROM terminal_bind tb_pick
|
||||||
|
WHERE tb_pick.terminal_no = t_filter.terminal_no
|
||||||
|
AND tb_pick.bind_status = 'BOUND'
|
||||||
|
AND (tb_pick.delete_enum IS NULL OR tb_pick.delete_enum = 'FALSE')
|
||||||
|
ORDER BY tb_pick.bind_time DESC, tb_pick.id DESC
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
WHERE t_filter.terminal_no = #{params.terminalNo}
|
||||||
|
AND (t_filter.delete_enum IS NULL OR t_filter.delete_enum = 'FALSE')
|
||||||
|
AND COALESCE(NULLIF(tb_filter.id_card_no, ''), NULLIF(t_filter.bind_id_card_no, ''))
|
||||||
|
= u.user_id_card
|
||||||
|
))
|
||||||
|
)
|
||||||
|
</if>
|
||||||
|
<if test="params.locationStatus != null and params.locationStatus != ''">
|
||||||
|
AND (CASE
|
||||||
|
WHEN UPPER(COALESCE(NULLIF(pm.location_status, ''), NULLIF(pm.finds_device_status, ''), t.device_status, ''))
|
||||||
|
IN ('ONLINE', 'STATIC', 'MOVING') THEN 'ONLINE'
|
||||||
|
ELSE 'OFFLINE'
|
||||||
|
END) = #{params.locationStatus}
|
||||||
|
</if>
|
||||||
|
<if test="params.positionSource != null and params.positionSource != ''">
|
||||||
|
AND (CASE
|
||||||
|
WHEN UPPER(COALESCE(t.device_type, '')) = 'CARD' THEN 'CARD'
|
||||||
|
WHEN UPPER(COALESCE(t.device_type, '')) = 'APP' THEN 'APP'
|
||||||
|
ELSE 'FINDS'
|
||||||
|
END) = #{params.positionSource}
|
||||||
|
</if>
|
||||||
|
ORDER BY u.id DESC, pm.finds_staff_no
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="listMatchedPersonCompanies"
|
<select id="listMatchedPersonCompanies"
|
||||||
resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
|
resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
|
||||||
SELECT DISTINCT ci.id AS corpinfo_id, ci.corp_name
|
SELECT DISTINCT ci.id AS corpinfo_id, ci.corp_name
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue