package com.zy.asrs.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.annotations.ManagerAuth; import com.core.common.R; import com.zy.asrs.domain.path.StationPathResolvedPolicy; import com.zy.asrs.entity.BasMap; import com.zy.asrs.entity.BasStation; import com.zy.asrs.entity.BasStationPathProfile; import com.zy.asrs.entity.BasStationPathRule; import com.zy.asrs.service.BasMapService; import com.zy.asrs.service.BasStationService; import com.zy.asrs.service.BasStationPathProfileService; import com.zy.asrs.service.BasStationPathRuleService; import com.zy.asrs.service.StationPathPolicyService; import com.zy.common.model.NavigateNode; import com.zy.common.utils.NavigateUtils; import com.zy.common.utils.RedisUtil; import com.zy.common.web.BaseController; import com.zy.core.enums.RedisKeyType; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @RestController @RequestMapping("/basStationPathPolicy") public class BasStationPathPolicyController extends BaseController { @Autowired private BasStationPathProfileService basStationPathProfileService; @Autowired private BasStationPathRuleService basStationPathRuleService; @Autowired private ConfigService configService; @Autowired private RedisUtil redisUtil; @Autowired private StationPathPolicyService stationPathPolicyService; @Autowired private BasStationService basStationService; @Autowired private BasMapService basMapService; @Autowired private NavigateUtils navigateUtils; @RequestMapping("/data/auth") @ManagerAuth public R data() { Map data = new HashMap<>(); data.put("profiles", basStationPathProfileService.list(new QueryWrapper().orderByAsc("priority", "id"))); data.put("rules", basStationPathRuleService.list(new QueryWrapper().orderByAsc("priority", "id"))); data.put("scoreMode", getSystemConfig("stationPathScoreMode", "legacy")); data.put("defaultProfileCode", getSystemConfig("stationPathDefaultProfileCode", "default")); data.put("stations", buildStationSummaryList()); data.put("levList", basMapService.getLevList()); return R.ok(data); } @RequestMapping("/save/auth") @ManagerAuth public R save(@RequestBody JSONObject payload) { JSONArray profiles = payload.getJSONArray("profiles"); JSONArray rules = payload.getJSONArray("rules"); upsertSystemConfig("站点路径评分模式", "stationPathScoreMode", defaultIfBlank(payload.getString("scoreMode"), "legacy"), "String"); upsertSystemConfig("站点路径默认模板编码", "stationPathDefaultProfileCode", defaultIfBlank(payload.getString("defaultProfileCode"), "default"), "String"); basStationPathProfileService.remove(new QueryWrapper<>()); basStationPathRuleService.remove(new QueryWrapper<>()); List profileList = new ArrayList<>(); if (profiles != null) { for (int i = 0; i < profiles.size(); i++) { JSONObject item = profiles.getJSONObject(i); if (item == null) { continue; } if (isBlank(item.getString("profileCode"))) { continue; } BasStationPathProfile profile = new BasStationPathProfile(); profile.setProfileCode(item.getString("profileCode")); profile.setProfileName(defaultIfBlank(item.getString("profileName"), item.getString("profileCode"))); profile.setPriority(item.getInteger("priority") == null ? 100 : item.getInteger("priority")); profile.setStatus(item.getShort("status") == null ? (short) 1 : item.getShort("status")); profile.setMemo(item.getString("memo")); Object configObj = item.get("config"); if (configObj != null) { profile.setConfigJson(JSON.toJSONString(configObj)); } else { profile.setConfigJson(item.getString("configJson")); } profileList.add(profile); } } if (!profileList.isEmpty()) { basStationPathProfileService.saveBatch(profileList); } List ruleList = new ArrayList<>(); if (rules != null) { for (int i = 0; i < rules.size(); i++) { JSONObject item = rules.getJSONObject(i); if (item == null) { continue; } if (isBlank(item.getString("ruleCode"))) { continue; } BasStationPathRule rule = new BasStationPathRule(); rule.setRuleCode(item.getString("ruleCode")); rule.setRuleName(defaultIfBlank(item.getString("ruleName"), item.getString("ruleCode"))); rule.setPriority(item.getInteger("priority") == null ? 100 : item.getInteger("priority")); rule.setStatus(item.getShort("status") == null ? (short) 1 : item.getShort("status")); rule.setSceneType(item.getString("sceneType")); rule.setStartStationId(item.getInteger("startStationId")); rule.setEndStationId(item.getInteger("endStationId")); rule.setProfileCode(item.getString("profileCode")); rule.setMemo(item.getString("memo")); rule.setHardJson(toJson(item.get("hard"), item.getString("hardJson"))); rule.setWaypointJson(toJson(item.get("waypoint"), item.getString("waypointJson"))); rule.setSoftJson(toJson(item.get("soft"), item.getString("softJson"))); rule.setFallbackJson(toJson(item.get("fallback"), item.getString("fallbackJson"))); ruleList.add(rule); } } if (!ruleList.isEmpty()) { basStationPathRuleService.saveBatch(ruleList); } refreshSystemConfigCache(); stationPathPolicyService.evictCache(); return R.ok(); } @RequestMapping("/resolve/auth") @ManagerAuth public R resolve(@RequestParam Integer startStationId, @RequestParam Integer endStationId) { StationPathResolvedPolicy resolved = stationPathPolicyService.resolvePolicy(startStationId, endStationId); return R.ok(resolved); } @RequestMapping("/preview/auth") @ManagerAuth public R preview(@RequestParam Integer startStationId, @RequestParam Integer endStationId, @RequestParam(required = false, defaultValue = "false") Boolean includeMapData) { StationPathResolvedPolicy resolved = stationPathPolicyService.resolvePolicy(startStationId, endStationId); List nodes = navigateUtils.calcByStationId(startStationId, endStationId); List stationIdList = new ArrayList<>(); List> nodeList = new ArrayList<>(); Set seen = new HashSet<>(); for (NavigateNode node : nodes) { JSONObject value = parseNodeValue(node == null ? null : node.getNodeValue()); Integer stationId = value == null ? null : value.getInteger("stationId"); if (stationId != null && seen.add(stationId)) { stationIdList.add(stationId); } Map item = new HashMap<>(); item.put("stationId", stationId); item.put("x", node == null ? null : node.getX()); item.put("y", node == null ? null : node.getY()); item.put("direction", node == null ? null : node.getDirection()); item.put("isInflectionPoint", node != null && Boolean.TRUE.equals(node.getIsInflectionPoint())); item.put("isLiftTransferPoint", node != null && Boolean.TRUE.equals(node.getIsLiftTransferPoint())); nodeList.add(item); } BasStation startStation = basStationService.getById(startStationId); Integer lev = startStation == null ? null : startStation.getStationLev(); BasMap basMap = Boolean.TRUE.equals(includeMapData) && lev != null ? basMapService.getOne(new QueryWrapper().eq("lev", lev)) : null; Map result = new HashMap<>(); result.put("resolvedPolicy", resolved); result.put("pathStationIds", stationIdList); result.put("pathNodes", nodeList); result.put("pathLength", stationIdList.size()); result.put("turnCount", countTurnCount(nodeList)); result.put("liftTransferCount", countLiftTransferCount(nodeList)); result.put("lev", lev); result.put("mapData", basMap == null ? null : basMap.getData()); result.put("previewTime", new Date()); return R.ok(result); } @RequestMapping("/expandSoftPath/auth") @ManagerAuth public R expandSoftPath(@RequestBody JSONObject payload) { Integer startStationId = payload.getInteger("startStationId"); Integer endStationId = payload.getInteger("endStationId"); if (startStationId == null || endStationId == null) { return R.error("起点和终点不能为空"); } List routePoints = new ArrayList<>(); routePoints.add(startStationId); routePoints.addAll(parseStationIdArray(payload.getJSONArray("keyStations"))); routePoints.add(endStationId); List fullPathStationIds = new ArrayList<>(); for (int i = 0; i < routePoints.size() - 1; i++) { Integer segmentStart = routePoints.get(i); Integer segmentEnd = routePoints.get(i + 1); if (segmentStart == null || segmentEnd == null) { continue; } if (segmentStart.equals(segmentEnd)) { if (fullPathStationIds.isEmpty()) { fullPathStationIds.add(segmentStart); } continue; } List segmentNodes = navigateUtils.calcByStationId(segmentStart, segmentEnd); List segmentStationIds = extractStationIds(segmentNodes); if (segmentStationIds.isEmpty()) { return R.error("未找到 " + segmentStart + " 到 " + segmentEnd + " 的可行路径"); } appendSegmentPath(fullPathStationIds, segmentStationIds); } Map result = new HashMap<>(); result.put("startStationId", startStationId); result.put("endStationId", endStationId); result.put("keyStations", routePoints.size() <= 2 ? new ArrayList<>() : routePoints.subList(1, routePoints.size() - 1)); result.put("pathStationIds", fullPathStationIds); result.put("pathLength", fullPathStationIds.size()); result.put("segmentCount", Math.max(routePoints.size() - 1, 0)); result.put("previewTime", new Date()); return R.ok(result); } private List> buildStationSummaryList() { List> result = new ArrayList<>(); List stationList = basStationService.list(new QueryWrapper() .eq("status", 1) .orderByAsc("station_lev", "station_id")); for (BasStation station : stationList) { if (station == null || station.getStationId() == null) { continue; } Map item = new HashMap<>(); item.put("stationId", station.getStationId()); item.put("stationLev", station.getStationLev()); item.put("stationAlias", station.getStationAlias()); result.add(item); } return result; } private void upsertSystemConfig(String name, String code, String value, String selectType) { String finalValue = value == null ? "" : value.trim(); Config config = configService.getOne(new QueryWrapper().eq("code", code)); if (config == null) { config = new Config(name, code, finalValue, (short) 1, (short) 1); config.setSelectType(selectType); configService.save(config); } else { config.setName(name); config.setValue(finalValue); config.setType((short) 1); config.setStatus((short) 1); config.setSelectType(selectType); configService.updateById(config); } } private void refreshSystemConfigCache() { HashMap systemConfigMap = new HashMap<>(); List configList = configService.list(new QueryWrapper<>()); for (Config config : configList) { systemConfigMap.put(config.getCode(), config.getValue()); } redisUtil.set(RedisKeyType.SYSTEM_CONFIG_MAP.key, systemConfigMap); } private String getSystemConfig(String code, String defaultValue) { Object mapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key); if (mapObj instanceof Map) { Object value = ((Map) mapObj).get(code); if (value != null) { String text = String.valueOf(value).trim(); if (!text.isEmpty()) { return text; } } } return defaultValue; } private List parseStationIdArray(JSONArray array) { List result = new ArrayList<>(); if (array == null || array.isEmpty()) { return result; } Set seen = new HashSet<>(); for (int i = 0; i < array.size(); i++) { Integer stationId = toInteger(array.get(i)); if (stationId != null && seen.add(stationId)) { result.add(stationId); } } return result; } private List extractStationIds(List nodes) { List stationIdList = new ArrayList<>(); Set seen = new HashSet<>(); for (NavigateNode node : nodes) { JSONObject value = parseNodeValue(node == null ? null : node.getNodeValue()); Integer stationId = value == null ? null : value.getInteger("stationId"); if (stationId != null && seen.add(stationId)) { stationIdList.add(stationId); } } return stationIdList; } private void appendSegmentPath(List fullPathStationIds, List segmentStationIds) { if (segmentStationIds == null || segmentStationIds.isEmpty()) { return; } for (Integer stationId : segmentStationIds) { if (stationId == null) { continue; } if (fullPathStationIds.isEmpty() || !stationId.equals(fullPathStationIds.get(fullPathStationIds.size() - 1))) { fullPathStationIds.add(stationId); } } } private String toJson(Object obj, String fallbackText) { if (obj != null) { return JSON.toJSONString(obj); } return fallbackText; } private JSONObject parseNodeValue(String text) { if (isBlank(text)) { return null; } try { return JSON.parseObject(text); } catch (Exception ignore) { return null; } } private int countTurnCount(List> nodeList) { if (nodeList == null || nodeList.size() < 3) { return 0; } int count = 0; for (int i = 1; i < nodeList.size() - 1; i++) { Map prev = nodeList.get(i - 1); Map next = nodeList.get(i + 1); Integer prevX = toInteger(prev.get("x")); Integer prevY = toInteger(prev.get("y")); Integer nextX = toInteger(next.get("x")); Integer nextY = toInteger(next.get("y")); if (prevX == null || prevY == null || nextX == null || nextY == null) { continue; } if (!prevX.equals(nextX) && !prevY.equals(nextY)) { count++; } } return count; } private int countLiftTransferCount(List> nodeList) { int count = 0; for (Map item : nodeList) { if (Boolean.TRUE.equals(item.get("isLiftTransferPoint"))) { count++; } } return count; } private Integer toInteger(Object value) { if (value == null) { return null; } if (value instanceof Integer) { return (Integer) value; } try { return Integer.parseInt(String.valueOf(value)); } catch (Exception ignore) { return null; } } private String defaultIfBlank(String text, String defaultValue) { return isBlank(text) ? defaultValue : text.trim(); } private boolean isBlank(String text) { return text == null || text.trim().isEmpty(); } }