diff --git a/start/src/main/java/com/zcloud/personnel/positioning/config/FlywayRecoveryConfiguration.java b/start/src/main/java/com/zcloud/personnel/positioning/config/FlywayRecoveryConfiguration.java
index 6d55cf1..ca9ffbe 100644
--- a/start/src/main/java/com/zcloud/personnel/positioning/config/FlywayRecoveryConfiguration.java
+++ b/start/src/main/java/com/zcloud/personnel/positioning/config/FlywayRecoveryConfiguration.java
@@ -13,10 +13,11 @@ import java.util.List;
import java.util.stream.Collectors;
/**
- * Recovers the known partial MySQL migration left by V20260710_02.
+ * Recovers known partial or removed MySQL migrations.
*
- *
The migration is idempotent and can be safely rerun after Flyway removes
- * its failed history entry. Other failed migrations are never repaired
+ *
V20260710_02 is idempotent and can be safely rerun after Flyway removes
+ * its failed history entry. V20260722_01 was removed and only its failed
+ * history entry needs cleanup. Other failed migrations are never repaired
* automatically so that new database problems still stop application startup.
*/
@Configuration
@@ -24,6 +25,7 @@ public class FlywayRecoveryConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(FlywayRecoveryConfiguration.class);
private static final MigrationVersion RECOVERABLE_VERSION = MigrationVersion.fromVersion("20260710.02");
+ private static final MigrationVersion REMOVED_VERSION = MigrationVersion.fromVersion("20260722.01");
@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {
@@ -34,7 +36,7 @@ public class FlywayRecoveryConfiguration {
if (!failedMigrations.isEmpty()) {
boolean onlyKnownFailure = failedMigrations.size() == 1
- && RECOVERABLE_VERSION.equals(failedMigrations.get(0).getVersion());
+ && isRecoverable(failedMigrations.get(0).getVersion());
if (!onlyKnownFailure) {
String failedVersions = failedMigrations.stream()
.map(migration -> migration.getVersion() == null
@@ -45,11 +47,16 @@ public class FlywayRecoveryConfiguration {
"Flyway contains unsupported failed migrations: " + failedVersions);
}
- LOGGER.warn("Repairing known failed Flyway migration {} before retry", RECOVERABLE_VERSION);
+ LOGGER.warn("Repairing known failed Flyway migration {} before retry",
+ failedMigrations.get(0).getVersion());
flyway.repair();
}
flyway.migrate();
};
}
+
+ private boolean isRecoverable(MigrationVersion version) {
+ return RECOVERABLE_VERSION.equals(version) || REMOVED_VERSION.equals(version);
+ }
}
diff --git a/start/src/main/resources/bootstrap.yml b/start/src/main/resources/bootstrap.yml
index 272b3e7..dfff433 100644
--- a/start/src/main/resources/bootstrap.yml
+++ b/start/src/main/resources/bootstrap.yml
@@ -1,8 +1,8 @@
spring:
config:
import:
- - classpath:nacos-prod.yml
-# - classpath:nacos.yml
+# - classpath:nacos-prod.yml
+ - classpath:nacos.yml
- classpath:kafka.yml
- classpath:sdk.yml
- classpath:swagger.yml
diff --git a/start/src/main/resources/kafka.yml b/start/src/main/resources/kafka.yml
index fc17624..754983e 100644
--- a/start/src/main/resources/kafka.yml
+++ b/start/src/main/resources/kafka.yml
@@ -30,3 +30,8 @@ personnel-positioning:
allowed-origins: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_ALLOWED_ORIGINS:*}
send-time-limit-ms: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_SEND_TIME_LIMIT_MS:10000}
buffer-size-limit-bytes: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_BUFFER_SIZE_LIMIT_BYTES:524288}
+ mock:
+ enabled: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_MOCK_ENABLED:true}
+ initial-delay-ms: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_MOCK_INITIAL_DELAY_MS:1000}
+ interval-ms: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_MOCK_INTERVAL_MS:1000}
+ new-person-delay-ms: ${PERSONNEL_POSITIONING_WEBSOCKET_LOCATION_MOCK_NEW_PERSON_DELAY_MS:8000}
diff --git a/start/src/main/resources/sdk.yml b/start/src/main/resources/sdk.yml
index 74a32b1..8b7abd3 100644
--- a/start/src/main/resources/sdk.yml
+++ b/start/src/main/resources/sdk.yml
@@ -1,5 +1,6 @@
sdk:
server:
+# app-key: 4e11af8a2b224f6fb1c680df53c72457
app-key: 9f32c2300c4444a6a2ab8f48a15802a0
client:
gateway:
diff --git a/web-adapter/src/main/java/com/zcloud/personnel/positioning/websocket/MockPersonLocationPublisher.java b/web-adapter/src/main/java/com/zcloud/personnel/positioning/websocket/MockPersonLocationPublisher.java
new file mode 100644
index 0000000..8a21744
--- /dev/null
+++ b/web-adapter/src/main/java/com/zcloud/personnel/positioning/websocket/MockPersonLocationPublisher.java
@@ -0,0 +1,190 @@
+package com.zcloud.personnel.positioning.websocket;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.zcloud.personnel.positioning.dto.clientobject.BiPersonLocationCO;
+import com.zcloud.personnel.positioning.integration.realtime.RealtimeLocationPublisher;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import javax.annotation.PostConstruct;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+/**
+ * 前端联调用实时点位模拟器,仅在配置明确开启时生效。
+ */
+@Configuration(proxyBeanMethods = false)
+@EnableScheduling
+@ConditionalOnProperty(
+ prefix = "personnel-positioning.websocket.location.mock",
+ name = "enabled",
+ havingValue = "true"
+)
+public class MockPersonLocationPublisher {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MockPersonLocationPublisher.class);
+ private static final BigDecimal STEP = new BigDecimal("0.000030");
+ private static final int TRACK_POINT_COUNT = 40;
+
+ private final ObjectMapper objectMapper;
+ private final ObjectProvider publishers;
+ private final AtomicLong sequence = new AtomicLong();
+ private final AtomicLongArray trackSequences = new AtomicLongArray(3);
+ private final AtomicBoolean thirdPersonActivated = new AtomicBoolean();
+ private final long newPersonDelayMs;
+ private final long startedAtMs;
+
+ public MockPersonLocationPublisher(ObjectMapper objectMapper,
+ ObjectProvider publishers,
+ @Value("${personnel-positioning.websocket.location.mock.new-person-delay-ms:8000}")
+ long newPersonDelayMs) {
+ this.objectMapper = objectMapper;
+ this.publishers = publishers;
+ this.newPersonDelayMs = Math.max(0, newPersonDelayMs);
+ this.startedAtMs = System.currentTimeMillis();
+ }
+
+ @PostConstruct
+ public void logEnabled() {
+ LOGGER.warn("人员实时点位WebSocket模拟数据已开启,仅用于前端联调,新增人员延迟={}ms",
+ newPersonDelayMs);
+ }
+
+ @Scheduled(
+ initialDelayString = "${personnel-positioning.websocket.location.mock.initial-delay-ms:1000}",
+ fixedRateString = "${personnel-positioning.websocket.location.mock.interval-ms:1000}"
+ )
+ public void publishNextLocation() {
+ int personIndex = nextPersonIndex();
+ long trackIndex = trackSequences.getAndIncrement(personIndex) % TRACK_POINT_COUNT;
+ BiPersonLocationCO location = createPerson(personIndex, trackIndex);
+
+ String payload = serialize(location);
+ int deliveries = 0;
+ for (RealtimeLocationPublisher publisher : publishers) {
+ deliveries += publisher.publish(payload);
+ }
+ LOGGER.debug("模拟人员点位已推送,staffNo={}, terminalNo={}, websocketDeliveries={}",
+ location.getStaffNo(), location.getTerminalNo(), deliveries);
+ }
+
+ private int nextPersonIndex() {
+ if (!thirdPersonActivated.get()
+ && System.currentTimeMillis() - startedAtMs >= newPersonDelayMs
+ && thirdPersonActivated.compareAndSet(false, true)) {
+ LOGGER.info("模拟新增人员开始推送,staffNo=CODEX-STAFF-003, terminalNo=CODEX-TERMINAL-003");
+ return 2;
+ }
+ int personCount = thirdPersonActivated.get() ? 3 : 2;
+ return (int) (sequence.getAndIncrement() % personCount);
+ }
+
+ private BiPersonLocationCO createPerson(int personIndex, long trackIndex) {
+ if (personIndex == 0) {
+ return createEastPortPerson(trackIndex);
+ }
+ if (personIndex == 1) {
+ return createWestPortPerson(trackIndex);
+ }
+ return createHarborPerson(trackIndex);
+ }
+
+ private BiPersonLocationCO createEastPortPerson(long trackIndex) {
+ BigDecimal offset = STEP.multiply(BigDecimal.valueOf(trackIndex));
+ BiPersonLocationCO location = baseLocation(
+ "Codex测试人员A", "CODEX-STAFF-001", "CODEX-TERMINAL-001");
+ location.setCompanyName("Codex测试东港公司");
+ location.setCorpinfoId("CODEX-CORP-EAST");
+ location.setCorpinfoName("Codex测试东港公司");
+ location.setOrgCode("CODEX-ORG-EAST");
+ location.setOrgName("Codex测试东港组织");
+ location.setPortArea(2);
+ location.setCurrentLocation("东港区模拟路线");
+ location.setLon(new BigDecimal("119.604000").add(offset));
+ location.setLat(new BigDecimal("39.925000").add(offset.divide(BigDecimal.valueOf(2))));
+ location.setDirection(new BigDecimal("45"));
+ return location;
+ }
+
+ private BiPersonLocationCO createWestPortPerson(long trackIndex) {
+ BigDecimal offset = STEP.multiply(BigDecimal.valueOf(trackIndex));
+ BiPersonLocationCO location = baseLocation(
+ "Codex测试人员B", "CODEX-STAFF-002", "CODEX-TERMINAL-002");
+ location.setCompanyName("Codex测试西港公司");
+ location.setCorpinfoId("CODEX-CORP-WEST");
+ location.setCorpinfoName("Codex测试西港公司");
+ location.setOrgCode("CODEX-ORG-WEST");
+ location.setOrgName("Codex测试西港组织");
+ location.setPortArea(3);
+ location.setCurrentLocation("西港区模拟路线");
+ location.setLon(new BigDecimal("119.552000").subtract(offset));
+ location.setLat(new BigDecimal("39.913000").add(offset.divide(BigDecimal.valueOf(3))));
+ location.setDirection(new BigDecimal("315"));
+ return location;
+ }
+
+ private BiPersonLocationCO createHarborPerson(long trackIndex) {
+ BigDecimal offset = STEP.multiply(BigDecimal.valueOf(trackIndex));
+ BiPersonLocationCO location = baseLocation(
+ "Codex测试新增人员C", "CODEX-STAFF-003", "CODEX-TERMINAL-003");
+ location.setCompanyName("Codex测试港区公司");
+ location.setCorpinfoId("CODEX-CORP-HARBOR");
+ location.setCorpinfoName("Codex测试港区公司");
+ location.setOrgCode("CODEX-ORG-HARBOR");
+ location.setOrgName("Codex测试港区组织");
+ location.setPortArea(1);
+ location.setCurrentLocation("秦皇岛港区模拟路线");
+ location.setLon(new BigDecimal("119.580000").add(offset));
+ location.setLat(new BigDecimal("39.920000").subtract(offset.divide(BigDecimal.valueOf(2))));
+ location.setDirection(new BigDecimal("135"));
+ return location;
+ }
+
+ private BiPersonLocationCO baseLocation(String staffName, String staffNo, String terminalNo) {
+ BiPersonLocationCO location = new BiPersonLocationCO();
+ location.setStaffName(staffName);
+ location.setLocalStaffNo(staffNo);
+ location.setStaffNo(staffNo);
+ location.setTerminalNo(terminalNo);
+ location.setPositionMode("模拟定位卡");
+ location.setLastLocationTime(System.currentTimeMillis());
+ location.setAlt(new BigDecimal("5.0"));
+ location.setSpeed(new BigDecimal("1.2"));
+ location.setOnline(true);
+ location.setAlarmStatus(false);
+ location.setAlarmCount(0);
+ return location;
+ }
+
+ private String serialize(BiPersonLocationCO location) {
+ try {
+ ObjectNode payload = objectMapper.valueToTree(location);
+ List nullFields = new ArrayList<>();
+ Iterator> fields = payload.fields();
+ while (fields.hasNext()) {
+ Map.Entry field = fields.next();
+ if (field.getValue().isNull()) {
+ nullFields.add(field.getKey());
+ }
+ }
+ payload.remove(nullFields);
+ return objectMapper.writeValueAsString(payload);
+ } catch (JsonProcessingException e) {
+ throw new IllegalStateException("模拟人员点位序列化失败", e);
+ }
+ }
+}
diff --git a/web-app/src/main/java/com/zcloud/personnel/positioning/command/query/AlarmRuleQueryExe.java b/web-app/src/main/java/com/zcloud/personnel/positioning/command/query/AlarmRuleQueryExe.java
index 4f48053..c525f02 100644
--- a/web-app/src/main/java/com/zcloud/personnel/positioning/command/query/AlarmRuleQueryExe.java
+++ b/web-app/src/main/java/com/zcloud/personnel/positioning/command/query/AlarmRuleQueryExe.java
@@ -44,6 +44,12 @@ import java.util.stream.Collectors;
@Component
@AllArgsConstructor
public class AlarmRuleQueryExe {
+ private static final String COMPANY_GROUP_UNMAPPED = "UNMAPPED";
+ private static final String COMPANY_GROUP_UNMAPPED_NAME = "未归属企业";
+ private static final String COMPANY_GROUP_ID_PREFIX = "ID:";
+ private static final String COMPANY_GROUP_ORG_PREFIX = "ORG:";
+ private static final String COMPANY_GROUP_NAME_PREFIX = "NAME:";
+
private final AlarmRuleRepository alarmRuleRepository;
private final AlarmRuleFenceRelRepository alarmRuleFenceRelRepository;
private final AlarmRuleItemRepository alarmRuleItemRepository;
@@ -58,6 +64,7 @@ public class AlarmRuleQueryExe {
if (StringUtils.hasText(ruleStatus)) {
params.put("eqRuleStatus", ruleStatus);
}
+ normalizeCompanyGroupParams(params);
PageResponse pageResponse = alarmRuleRepository.listCompanyStats(params);
List data = alarmRuleCoConvertor
.converCompanyStatDOsToCOs(pageResponse.getData());
@@ -83,7 +90,7 @@ public class AlarmRuleQueryExe {
params.put("eqDeleteEnum", "FALSE");
normalizeListParams(params);
fillCorpinfo(params);
- preferCorpinfoId(params);
+ normalizeCompanyGroupParams(params);
PageResponse pageResponse = alarmRuleRepository.listPage(params);
List data = alarmRuleCoConvertor.converDOsToCOs(pageResponse.getData());
fillFenceRelations(data);
@@ -170,14 +177,46 @@ public class AlarmRuleQueryExe {
}
}
- private void preferCorpinfoId(Map params) {
- String corpinfoId = (String) params.get("eqCorpinfoId");
- if (!StringUtils.hasText(corpinfoId)) {
+ private void normalizeCompanyGroupParams(Map params) {
+ String corpinfoId = textValue(params.get("eqCorpinfoId"));
+ String corpinfoName = textValue(params.get("eqCorpinfoName"));
+ String likeCorpinfoName = textValue(params.get("likeCorpinfoName"));
+ if (StringUtils.hasText(likeCorpinfoName)
+ && COMPANY_GROUP_UNMAPPED_NAME.contains(likeCorpinfoName)) {
+ params.put("includeUnmappedCompany", Boolean.TRUE);
+ }
+ if (COMPANY_GROUP_UNMAPPED.equalsIgnoreCase(corpinfoId)
+ || COMPANY_GROUP_UNMAPPED_NAME.equals(corpinfoName)
+ || ("0".equals(corpinfoId) && !StringUtils.hasText(corpinfoName))) {
+ params.remove("eqCorpinfoId");
+ params.remove("eqCorpinfoName");
+ params.put("unmappedCompany", Boolean.TRUE);
return;
}
+ if (StringUtils.hasText(corpinfoId) && corpinfoId.startsWith(COMPANY_GROUP_ID_PREFIX)) {
+ corpinfoId = corpinfoId.substring(COMPANY_GROUP_ID_PREFIX.length());
+ } else if (StringUtils.hasText(corpinfoId) && corpinfoId.startsWith(COMPANY_GROUP_ORG_PREFIX)) {
+ params.remove("eqCorpinfoId");
+ params.remove("eqCorpinfoName");
+ params.put("companyGroupOrgCode", corpinfoId.substring(COMPANY_GROUP_ORG_PREFIX.length()));
+ return;
+ } else if (StringUtils.hasText(corpinfoId) && corpinfoId.startsWith(COMPANY_GROUP_NAME_PREFIX)) {
+ params.remove("eqCorpinfoId");
+ params.put("eqCorpinfoName", corpinfoId.substring(COMPANY_GROUP_NAME_PREFIX.length()));
+ return;
+ }
+ if (!StringUtils.hasText(corpinfoId) || "0".equals(corpinfoId)) {
+ params.remove("eqCorpinfoId");
+ return;
+ }
+ params.put("eqCorpinfoId", corpinfoId);
params.remove("eqCorpinfoName");
}
+ private String textValue(Object value) {
+ return value == null ? null : String.valueOf(value).trim();
+ }
+
private void applyCorpinfo(QueryWrapper queryWrapper) {
SSOUser ssoUser = AuthContext.getCurrentUser();
if (ssoUser != null && ssoUser.getCompanyId() != null) {
diff --git a/web-infrastructure/src/main/java/com/zcloud/personnel/positioning/persistence/repository/impl/AlarmRuleRepositoryImpl.java b/web-infrastructure/src/main/java/com/zcloud/personnel/positioning/persistence/repository/impl/AlarmRuleRepositoryImpl.java
index bc4ea48..9c4727d 100644
--- a/web-infrastructure/src/main/java/com/zcloud/personnel/positioning/persistence/repository/impl/AlarmRuleRepositoryImpl.java
+++ b/web-infrastructure/src/main/java/com/zcloud/personnel/positioning/persistence/repository/impl/AlarmRuleRepositoryImpl.java
@@ -15,8 +15,9 @@ import com.jjb.saas.framework.repository.repo.impl.BaseRepositoryImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
-import java.util.Map;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* web-infrastructure
@@ -32,8 +33,19 @@ public class AlarmRuleRepositoryImpl extends BaseRepositoryImpl listPage(Map params) {
IPage iPage = new Query().getPage(params);
+ Map queryParams = new HashMap<>(params);
+ Object companyGroupOrgCode = queryParams.remove("companyGroupOrgCode");
+ boolean unmappedCompany = Boolean.TRUE.equals(queryParams.remove("unmappedCompany"));
QueryWrapper queryWrapper = new QueryWrapper<>();
- queryWrapper = PageQueryHelper.createPageQueryWrapper(queryWrapper, params);
+ queryWrapper = PageQueryHelper.createPageQueryWrapper(queryWrapper, queryParams);
+ if (companyGroupOrgCode != null) {
+ queryWrapper.eq("org_code", companyGroupOrgCode);
+ }
+ if (unmappedCompany) {
+ queryWrapper.and(wrapper -> wrapper.isNull("corpinfo_name")
+ .or().eq("corpinfo_name", "")
+ .or().apply("TRIM(corpinfo_name) = ''"));
+ }
queryWrapper.orderByDesc("create_time");
IPage result = alarmRuleMapper.selectPage(iPage, queryWrapper);
return PageHelper.pageToResponse(result, result.getRecords());
diff --git a/web-infrastructure/src/main/resources/db/migration/mysql/V20260722_01__corp_info_port_area.sql b/web-infrastructure/src/main/resources/db/migration/mysql/V20260722_01__corp_info_port_area.sql
deleted file mode 100644
index 6f40549..0000000
--- a/web-infrastructure/src/main/resources/db/migration/mysql/V20260722_01__corp_info_port_area.sql
+++ /dev/null
@@ -1,5 +0,0 @@
--- Refresh the proxy view after basic-info.corp_info adds port_area.
-CREATE OR REPLACE VIEW `corp_info` AS
-SELECT *
-FROM `jjb-saas-zcloud-basic-info`.`corp_info`
-WHERE `delete_enum` = 'FALSE';
diff --git a/web-infrastructure/src/main/resources/mapper/AlarmRuleMapper.xml b/web-infrastructure/src/main/resources/mapper/AlarmRuleMapper.xml
index e980ca7..b4b64a7 100644
--- a/web-infrastructure/src/main/resources/mapper/AlarmRuleMapper.xml
+++ b/web-infrastructure/src/main/resources/mapper/AlarmRuleMapper.xml
@@ -5,35 +5,65 @@
- SELECT corpinfo_id,
- corpinfo_name,
+ SELECT company_key AS corpinfo_id,
+ CASE WHEN company_key = 'UNMAPPED' THEN '未归属企业'
+ ELSE MAX(corpinfo_name) END AS corpinfo_name,
COUNT(1) AS config_count,
SUM(CASE WHEN enable = 1 OR rule_status = 'ENABLED' THEN 1 ELSE 0 END) AS enabled_count,
COALESCE(MAX(last_sync_time), MAX(update_time)) AS last_sync_time
- FROM alarm_rule
- WHERE (delete_enum IS NULL OR delete_enum = 'FALSE')
-
- AND corpinfo_id = #{params.eqCorpinfoId}
-
-
- AND corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
-
-
- AND EXISTS (
- SELECT 1
- FROM corp_info ci
- WHERE CAST(ci.corpinfo_id AS CHAR) = CAST(alarm_rule.corpinfo_id AS CHAR)
- AND (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
- AND ci.contacts LIKE CONCAT('%', #{params.likeContactName}, '%')
- )
-
-
- AND rule_status = #{params.eqRuleStatus}
-
-
- AND enable = #{params.eqEnable}
-
- GROUP BY corpinfo_id, corpinfo_name
+ FROM (
+ SELECT ar.*,
+ CASE
+ WHEN ar.corpinfo_name IS NULL OR TRIM(ar.corpinfo_name) = '' THEN 'UNMAPPED'
+ WHEN ar.corpinfo_id IS NOT NULL AND TRIM(ar.corpinfo_id) != ''
+ AND TRIM(ar.corpinfo_id) != '0' THEN TRIM(ar.corpinfo_id)
+ WHEN ar.org_code IS NOT NULL AND TRIM(ar.org_code) != ''
+ THEN CONCAT('ORG:', TRIM(ar.org_code))
+ ELSE CONCAT('NAME:', TRIM(ar.corpinfo_name))
+ END AS company_key
+ FROM alarm_rule ar
+ WHERE (ar.delete_enum IS NULL OR ar.delete_enum = 'FALSE')
+
+ AND ar.corpinfo_id = #{params.eqCorpinfoId}
+
+
+ AND ar.org_code = #{params.companyGroupOrgCode}
+
+
+ AND (ar.corpinfo_name IS NULL OR TRIM(ar.corpinfo_name) = '')
+
+
+
+
+ AND (ar.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
+ OR ar.corpinfo_name IS NULL OR TRIM(ar.corpinfo_name) = '')
+
+
+ AND ar.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
+
+
+
+
+ AND EXISTS (
+ SELECT 1
+ FROM corp_info ci
+ WHERE (ci.delete_enum IS NULL OR ci.delete_enum = 'FALSE')
+ AND (
+ CAST(ci.corpinfo_id AS CHAR) = CAST(ar.corpinfo_id AS CHAR)
+ OR ((ar.corpinfo_id IS NULL OR TRIM(ar.corpinfo_id) = '' OR ar.corpinfo_id = '0')
+ AND ci.corp_name = ar.corpinfo_name)
+ )
+ AND ci.contacts LIKE CONCAT('%', #{params.likeContactName}, '%')
+ )
+
+
+ AND ar.rule_status = #{params.eqRuleStatus}
+
+
+ AND ar.enable = #{params.eqEnable}
+
+ ) grouped_rule
+ GROUP BY company_key
ORDER BY COALESCE(MAX(last_sync_time), MAX(update_time)) DESC