添加数据贯通代码未调试
This commit is contained in:
@@ -0,0 +1,411 @@
|
||||
package com.klp.framework.client;
|
||||
|
||||
import com.klp.framework.config.SqlServerApiProperties;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* sql-server-api 统一调用客户端。
|
||||
* <p>
|
||||
* 对齐 {@code sql-server-api/app.py} 的接口规范:
|
||||
* <ul>
|
||||
* <li>GET /health</li>
|
||||
* <li>GET /heartbeat</li>
|
||||
* <li>POST /table-schema</li>
|
||||
* <li>POST /execute-sql</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Component
|
||||
public class SqlServerApiClient {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
private final SqlServerApiProperties properties;
|
||||
|
||||
public SqlServerApiClient(RestTemplate sqlServerApiRestTemplate, SqlServerApiProperties properties) {
|
||||
this.restTemplate = sqlServerApiRestTemplate;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return normalizeBaseUrl();
|
||||
}
|
||||
|
||||
public Map<String, Object> health() {
|
||||
return getForMap("/health");
|
||||
}
|
||||
|
||||
public Map<String, Object> heartbeat() {
|
||||
return getForMap("/heartbeat");
|
||||
}
|
||||
|
||||
public TableSchemaResponse tableSchema(String tableType, String tableName) {
|
||||
return postForObject("/table-schema", new TableSchemaRequest(tableType, tableName), TableSchemaResponse.class);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse executeSql(String tableType, String sql, Map<String, Object> params) {
|
||||
return postForObject("/execute-sql", new ExecuteSqlRequest(tableType, sql, params), ExecuteSqlResponse.class);
|
||||
}
|
||||
|
||||
public <T> T get(String path, Class<T> responseType) {
|
||||
return restTemplate.getForObject(buildUri(path), responseType);
|
||||
}
|
||||
|
||||
public <T> T get(String path, Map<String, ?> queryParams, Class<T> responseType) {
|
||||
URI uri = UriComponentsBuilder.fromHttpUrl(normalizeBaseUrl())
|
||||
.path(normalizePath(path))
|
||||
.queryParams(convertToQueryParams(queryParams))
|
||||
.build(true)
|
||||
.toUri();
|
||||
return restTemplate.getForObject(uri, responseType);
|
||||
}
|
||||
|
||||
public <T, R> T post(String path, R requestBody, Class<T> responseType) {
|
||||
return restTemplate.postForObject(buildUri(path), requestBody, responseType);
|
||||
}
|
||||
|
||||
public static class TableSchemaRequest {
|
||||
private String tableType;
|
||||
private String tableName;
|
||||
|
||||
public TableSchemaRequest() {
|
||||
}
|
||||
|
||||
public TableSchemaRequest(String tableType, String tableName) {
|
||||
this.tableType = tableType;
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public String getTableType() {
|
||||
return tableType;
|
||||
}
|
||||
|
||||
public void setTableType(String tableType) {
|
||||
this.tableType = tableType;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExecuteSqlRequest {
|
||||
private String tableType;
|
||||
private String sql;
|
||||
private Map<String, Object> params;
|
||||
|
||||
public ExecuteSqlRequest() {
|
||||
}
|
||||
|
||||
public ExecuteSqlRequest(String tableType, String sql, Map<String, Object> params) {
|
||||
this.tableType = tableType;
|
||||
this.sql = sql;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public String getTableType() {
|
||||
return tableType;
|
||||
}
|
||||
|
||||
public void setTableType(String tableType) {
|
||||
this.tableType = tableType;
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public void setParams(Map<String, Object> params) {
|
||||
this.params = params;
|
||||
}
|
||||
}
|
||||
|
||||
public static class TableSchemaResponse {
|
||||
private String tableType;
|
||||
private String tableName;
|
||||
private Schema schema;
|
||||
|
||||
public String getTableType() {
|
||||
return tableType;
|
||||
}
|
||||
|
||||
public void setTableType(String tableType) {
|
||||
this.tableType = tableType;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public Schema getSchema() {
|
||||
return schema;
|
||||
}
|
||||
|
||||
public void setSchema(Schema schema) {
|
||||
this.schema = schema;
|
||||
}
|
||||
|
||||
public static class Schema {
|
||||
private List<Column> columns = Collections.emptyList();
|
||||
|
||||
public List<Column> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void setColumns(List<Column> columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Column {
|
||||
private String name;
|
||||
private String type;
|
||||
private boolean nullable;
|
||||
private Object defaultValue;
|
||||
private boolean primaryKey;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public void setNullable(boolean nullable) {
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public Object getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void setDefaultValue(Object defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public boolean isPrimaryKey() {
|
||||
return primaryKey;
|
||||
}
|
||||
|
||||
public void setPrimaryKey(boolean primaryKey) {
|
||||
this.primaryKey = primaryKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExecuteSqlResponse {
|
||||
private String tableType;
|
||||
private String resultType;
|
||||
private Integer rowCount;
|
||||
private Object result;
|
||||
|
||||
public String getTableType() {
|
||||
return tableType;
|
||||
}
|
||||
|
||||
public void setTableType(String tableType) {
|
||||
this.tableType = tableType;
|
||||
}
|
||||
|
||||
public String getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
public void setResultType(String resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
public Integer getRowCount() {
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
public void setRowCount(Integer rowCount) {
|
||||
this.rowCount = rowCount;
|
||||
}
|
||||
|
||||
public Object getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(Object result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> getForMap(String path) {
|
||||
ResponseEntity<Map> responseEntity = restTemplate.exchange(buildUri(path), HttpMethod.GET, HttpEntity.EMPTY, Map.class);
|
||||
Map<String, Object> body = responseEntity.getBody();
|
||||
return body == null ? Collections.emptyMap() : body;
|
||||
}
|
||||
|
||||
private <T> T postForObject(String path, Object requestBody, Class<T> responseType) {
|
||||
return restTemplate.postForObject(buildUri(path), requestBody, responseType);
|
||||
}
|
||||
|
||||
private URI buildUri(String path) {
|
||||
return UriComponentsBuilder.fromHttpUrl(normalizeBaseUrl())
|
||||
.path(normalizePath(path))
|
||||
.build(true)
|
||||
.toUri();
|
||||
}
|
||||
|
||||
private String normalizeBaseUrl() {
|
||||
if (properties.getBaseUrl() != null && properties.getBaseUrl().trim().length() > 0) {
|
||||
return properties.getBaseUrl();
|
||||
}
|
||||
if (properties.getHost() == null || properties.getHost().trim().length() == 0 || properties.getPort() == null) {
|
||||
throw new IllegalStateException("sql-server-api 配置缺失,请检查 host/port/base-url");
|
||||
}
|
||||
return "http://" + properties.getHost() + ":" + properties.getPort();
|
||||
}
|
||||
|
||||
private String normalizePath(String path) {
|
||||
if (path == null || path.trim().length() == 0) {
|
||||
return "";
|
||||
}
|
||||
return path.startsWith("/") ? path : "/" + path;
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryPlanByCoilId(String coilId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PDI_PLAN where COILID = :coilId",
|
||||
singletonParam("coilId", coilId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryPlanList() {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PDI_PLAN order by INSDATE desc",
|
||||
emptyParams()
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryPlanListByProcessCode(String processCode) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PDI_PLAN where PROCESS_CODE = :processCode order by INSDATE desc",
|
||||
singletonParam("processCode", processCode)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryPlanListByStatus(String status) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PDI_PLAN where STATUS = :status order by INSDATE desc",
|
||||
singletonParam("status", status)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryPlanByHotCoilId(String hotCoilId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PDI_PLAN where HOT_COILID = :hotCoilId",
|
||||
singletonParam("hotCoilId", hotCoilId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryProSegByEncoilId(String encoilId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PRO_SEG where ENCOILID = :encoilId order by SEGNO",
|
||||
singletonParam("encoilId", encoilId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryProSegByExcoilId(String excoilId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.PLTCM_PRO_SEG where EXCOILID = :excoilId order by SEGNO",
|
||||
singletonParam("excoilId", excoilId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryQualityByExcoilId(String excoilId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.V_PLTCM_PDO_QUALITY where EXCOILID = :excoilId order by END_DATE desc",
|
||||
singletonParam("excoilId", excoilId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryGaugeByMatId(String matId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.V_VBDA_GAUGE where MATID = :matId order by XTIME asc",
|
||||
singletonParam("matId", matId)
|
||||
);
|
||||
}
|
||||
|
||||
public ExecuteSqlResponse queryShapeByMatId(String matId) {
|
||||
return executeSql(
|
||||
"oracle",
|
||||
"select * from JXPLTCM.V_VBDA_SHAPE where MATID = :matId order by XTIME asc",
|
||||
singletonParam("matId", matId)
|
||||
);
|
||||
}
|
||||
|
||||
private org.springframework.util.MultiValueMap<String, String> convertToQueryParams(Map<String, ?> queryParams) {
|
||||
org.springframework.util.LinkedMultiValueMap<String, String> multiValueMap = new org.springframework.util.LinkedMultiValueMap<>();
|
||||
if (queryParams == null || queryParams.isEmpty()) {
|
||||
return multiValueMap;
|
||||
}
|
||||
for (Map.Entry<String, ?> entry : queryParams.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value != null) {
|
||||
multiValueMap.add(entry.getKey(), String.valueOf(value));
|
||||
}
|
||||
}
|
||||
return multiValueMap;
|
||||
}
|
||||
|
||||
private Map<String, Object> singletonParam(String key, Object value) {
|
||||
java.util.HashMap<String, Object> params = new java.util.HashMap<String, Object>();
|
||||
if (value != null) {
|
||||
params.put(key, value);
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
private Map<String, Object> emptyParams() {
|
||||
return new java.util.HashMap<String, Object>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.klp.framework.config;
|
||||
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* sql-server-api HTTP 客户端配置
|
||||
*/
|
||||
@Configuration
|
||||
public class SqlServerApiClientConfig {
|
||||
|
||||
@Bean
|
||||
public RestTemplate sqlServerApiRestTemplate(RestTemplateBuilder builder) {
|
||||
return builder
|
||||
.setConnectTimeout(Duration.ofSeconds(5))
|
||||
.setReadTimeout(Duration.ofSeconds(30))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.klp.framework.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* sql-server-api 中间件配置
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "sql-server-api")
|
||||
public class SqlServerApiProperties {
|
||||
|
||||
/**
|
||||
* 请求地址
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* 请求端口
|
||||
*/
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 基础访问地址
|
||||
*/
|
||||
private String baseUrl;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
package com.klp.framework.service;
|
||||
|
||||
import com.klp.framework.client.SqlServerApiClient;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 面向业务场景的 sql-server-api 查询服务。
|
||||
* <p>
|
||||
* 当前抽象为三个功能:
|
||||
* <ol>
|
||||
* <li>计划查询</li>
|
||||
* <li>钢卷实际 / SEG 查询</li>
|
||||
* <li>实时数据(Gauge / Shape)查询</li>
|
||||
* </ol>
|
||||
*/
|
||||
@Service
|
||||
public class SqlServerApiBusinessService {
|
||||
|
||||
private final SqlServerApiClient client;
|
||||
|
||||
public SqlServerApiBusinessService(SqlServerApiClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划列表:查询所有计划,按时间倒序。
|
||||
* <p>
|
||||
* 这是后续按 coilId 关联 SEG、实时数据的入口。
|
||||
*/
|
||||
public PlanListView getPlanList() {
|
||||
return PlanListView.fromExecuteSqlResponse(client.queryPlanList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划列表:按工艺流程编码筛选。
|
||||
*/
|
||||
public PlanListView getPlanListByProcessCode(String processCode) {
|
||||
return PlanListView.fromExecuteSqlResponse(client.queryPlanListByProcessCode(processCode));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划列表:按状态筛选。
|
||||
*/
|
||||
public PlanListView getPlanListByStatus(String status) {
|
||||
return PlanListView.fromExecuteSqlResponse(client.queryPlanListByStatus(status));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划详情:按成品卷号查询单条计划。
|
||||
*/
|
||||
public PlanDetailView getPlanByCoilId(String coilId) {
|
||||
return PlanDetailView.fromExecuteSqlResponse(coilId, client.queryPlanByCoilId(coilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划详情:按热卷号查询。
|
||||
*/
|
||||
public PlanDetailView getPlanByHotCoilId(String hotCoilId) {
|
||||
return PlanDetailView.fromExecuteSqlResponse(hotCoilId, client.queryPlanByHotCoilId(hotCoilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 钢卷实际 SEG 查询:按入口卷号查询。
|
||||
* <p>
|
||||
* 返回的是按 SEGNO 排序后的原始行数据。
|
||||
*/
|
||||
public SegSeriesView getSegByEncoilId(String encoilId) {
|
||||
return SegSeriesView.fromExecuteSqlResponse(encoilId, client.queryProSegByEncoilId(encoilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 钢卷实际 SEG 查询:按出口卷号查询。
|
||||
*/
|
||||
public SegSeriesView getSegByExcoilId(String excoilId) {
|
||||
return SegSeriesView.fromExecuteSqlResponse(excoilId, client.queryProSegByExcoilId(excoilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 钢卷 SEG 视图数据:把同一钢卷下按 SEGNO 排序的多行数据,整理成“一个钢卷 id + 一个属性对应一个列表”的结构。
|
||||
* <p>
|
||||
* 例如:厚度、张力、速度都会被整理成数组,方便前端直接画表或曲线。
|
||||
*/
|
||||
public SegSeriesView getSegSeriesViewByEncoilId(String encoilId) {
|
||||
return getSegByEncoilId(encoilId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时数据:厚度/仪表数据。
|
||||
*/
|
||||
public SqlServerApiClient.ExecuteSqlResponse getRealtimeGaugeByMatId(String matId) {
|
||||
return client.queryGaugeByMatId(matId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时数据:板形/形状数据。
|
||||
*/
|
||||
public SqlServerApiClient.ExecuteSqlResponse getRealtimeShapeByMatId(String matId) {
|
||||
return client.queryShapeByMatId(matId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时数据总入口:一次性返回厚度与板形两类数据。
|
||||
*/
|
||||
public RealtimeDataBundle getRealtimeData(String matId) {
|
||||
return new RealtimeDataBundle(
|
||||
getRealtimeGaugeByMatId(matId),
|
||||
getRealtimeShapeByMatId(matId)
|
||||
);
|
||||
}
|
||||
|
||||
private static PlanListView toPlanListView(SqlServerApiClient.ExecuteSqlResponse response) {
|
||||
return PlanListView.fromExecuteSqlResponse(response);
|
||||
}
|
||||
|
||||
private static List<Map<String, Object>> asRowList(SqlServerApiClient.ExecuteSqlResponse response) {
|
||||
if (response == null || response.getResult() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Object result = response.getResult();
|
||||
if (result instanceof List) {
|
||||
List<?> list = (List<?>) result;
|
||||
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();
|
||||
for (Object item : list) {
|
||||
if (item instanceof Map) {
|
||||
rows.add((Map<String, Object>) item);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static Number asNumber(Object value) {
|
||||
if (value instanceof Number) {
|
||||
return (Number) value;
|
||||
}
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return new BigDecimal(String.valueOf(value));
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String asString(Object value) {
|
||||
return value == null ? null : String.valueOf(value);
|
||||
}
|
||||
|
||||
public static class PlanListView {
|
||||
private final List<String> coilIds;
|
||||
private final List<Map<String, Object>> rows;
|
||||
|
||||
public PlanListView(List<String> coilIds, List<Map<String, Object>> rows) {
|
||||
this.coilIds = coilIds;
|
||||
this.rows = rows;
|
||||
}
|
||||
|
||||
public List<String> getCoilIds() {
|
||||
return coilIds;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public static PlanListView fromExecuteSqlResponse(SqlServerApiClient.ExecuteSqlResponse response) {
|
||||
List<Map<String, Object>> rows = asRowList(response);
|
||||
List<String> coilIds = rows.stream()
|
||||
.map(row -> asString(row.get("COILID")))
|
||||
.filter(value -> value != null && value.trim().length() > 0)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
return new PlanListView(coilIds, rows);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PlanDetailView {
|
||||
private final String coilId;
|
||||
private final List<Map<String, Object>> rows;
|
||||
private final Map<String, Object> firstRow;
|
||||
|
||||
public PlanDetailView(String coilId, List<Map<String, Object>> rows, Map<String, Object> firstRow) {
|
||||
this.coilId = coilId;
|
||||
this.rows = rows;
|
||||
this.firstRow = firstRow;
|
||||
}
|
||||
|
||||
public String getCoilId() {
|
||||
return coilId;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
public Map<String, Object> getFirstRow() {
|
||||
return firstRow;
|
||||
}
|
||||
|
||||
public static PlanDetailView fromExecuteSqlResponse(String coilId, SqlServerApiClient.ExecuteSqlResponse response) {
|
||||
List<Map<String, Object>> rows = asRowList(response);
|
||||
Map<String, Object> firstRow = rows.isEmpty() ? Collections.<String, Object>emptyMap() : rows.get(0);
|
||||
return new PlanDetailView(coilId, rows, firstRow);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SegSeriesView {
|
||||
private final String coilId;
|
||||
private final List<Integer> segNo;
|
||||
private final Map<String, List<Object>> series;
|
||||
private final List<Map<String, Object>> rows;
|
||||
|
||||
public SegSeriesView(String coilId, List<Integer> segNo, Map<String, List<Object>> series, List<Map<String, Object>> rows) {
|
||||
this.coilId = coilId;
|
||||
this.segNo = segNo;
|
||||
this.series = series;
|
||||
this.rows = rows;
|
||||
}
|
||||
|
||||
public String getCoilId() {
|
||||
return coilId;
|
||||
}
|
||||
|
||||
public List<Integer> getSegNo() {
|
||||
return segNo;
|
||||
}
|
||||
|
||||
public Map<String, List<Object>> getSeries() {
|
||||
return series;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getRows() {
|
||||
return rows;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static SegSeriesView fromExecuteSqlResponse(String coilId, SqlServerApiClient.ExecuteSqlResponse response) {
|
||||
List<Map<String, Object>> rows = asRowList(response);
|
||||
Collections.sort(rows, new Comparator<Map<String, Object>>() {
|
||||
@Override
|
||||
public int compare(Map<String, Object> left, Map<String, Object> right) {
|
||||
Number leftSeg = asNumber(left.get("SEGNO"));
|
||||
Number rightSeg = asNumber(right.get("SEGNO"));
|
||||
int leftValue = leftSeg == null ? Integer.MAX_VALUE : leftSeg.intValue();
|
||||
int rightValue = rightSeg == null ? Integer.MAX_VALUE : rightSeg.intValue();
|
||||
if (leftValue > rightValue) {
|
||||
return 1;
|
||||
}
|
||||
if (leftValue < rightValue) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
List<Integer> segNo = new ArrayList<Integer>();
|
||||
for (Map<String, Object> row : rows) {
|
||||
Number seg = asNumber(row.get("SEGNO"));
|
||||
segNo.add(seg == null ? null : seg.intValue());
|
||||
}
|
||||
|
||||
Map<String, List<Object>> series = new LinkedHashMap<String, List<Object>>();
|
||||
for (Map<String, Object> row : rows) {
|
||||
for (Map.Entry<String, Object> entry : row.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if ("SEGNO".equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
series.computeIfAbsent(key, ignored -> new ArrayList<>()).add(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return new SegSeriesView(coilId, segNo, series, rows);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RealtimeDataBundle {
|
||||
private final SqlServerApiClient.ExecuteSqlResponse gauge;
|
||||
private final SqlServerApiClient.ExecuteSqlResponse shape;
|
||||
|
||||
public RealtimeDataBundle(SqlServerApiClient.ExecuteSqlResponse gauge,
|
||||
SqlServerApiClient.ExecuteSqlResponse shape) {
|
||||
this.gauge = gauge;
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public SqlServerApiClient.ExecuteSqlResponse getGauge() {
|
||||
return gauge;
|
||||
}
|
||||
|
||||
public SqlServerApiClient.ExecuteSqlResponse getShape() {
|
||||
return shape;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.klp.web.controller.sqlserver;
|
||||
|
||||
import com.klp.common.core.domain.R;
|
||||
import com.klp.framework.service.SqlServerApiBusinessService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* sql-server-api 业务查询接口。
|
||||
* <p>
|
||||
* 提供计划、SEG、实时数据三个入口,方便前端联动展示。
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/sql-server-api")
|
||||
public class SqlServerApiController {
|
||||
|
||||
private final SqlServerApiBusinessService businessService;
|
||||
|
||||
/**
|
||||
* 计划列表。
|
||||
*/
|
||||
@GetMapping("/plans")
|
||||
public R<SqlServerApiBusinessService.PlanListView> planList() {
|
||||
return R.ok(businessService.getPlanList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 计划详情。
|
||||
*/
|
||||
@GetMapping("/plans/{coilId}")
|
||||
public R<SqlServerApiBusinessService.PlanDetailView> planDetail(@PathVariable String coilId) {
|
||||
return R.ok(businessService.getPlanByCoilId(coilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 钢卷实际 SEG,按入口卷号查询。
|
||||
*/
|
||||
@GetMapping("/seg/{encoilId}")
|
||||
public R<SqlServerApiBusinessService.SegSeriesView> segByEncoilId(@PathVariable String encoilId) {
|
||||
return R.ok(businessService.getSegSeriesViewByEncoilId(encoilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 钢卷实际 SEG,按出口卷号查询。
|
||||
*/
|
||||
@GetMapping("/seg-by-excoil/{excoilId}")
|
||||
public R<SqlServerApiBusinessService.SegSeriesView> segByExcoilId(@PathVariable String excoilId) {
|
||||
return R.ok(businessService.getSegByExcoilId(excoilId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 实时数据:厚度、板形。
|
||||
*/
|
||||
@GetMapping("/realtime/{matId}")
|
||||
public R<SqlServerApiBusinessService.RealtimeDataBundle> realtime(@PathVariable String matId) {
|
||||
return R.ok(businessService.getRealtimeData(matId));
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,15 @@ user:
|
||||
# 密码锁定时间(默认10分钟)
|
||||
lockTime: 10
|
||||
|
||||
# sql-server-api 中间件配置
|
||||
sql-server-api:
|
||||
# 请求地址,请替换为实际 IP
|
||||
host: 127.0.0.1
|
||||
# 请求端口,请替换为实际端口
|
||||
port: 8080
|
||||
# 基础访问地址(可直接注入使用)
|
||||
base-url: http://${sql-server-api.host}:${sql-server-api.port}
|
||||
|
||||
# Spring配置
|
||||
spring:
|
||||
application:
|
||||
|
||||
Reference in New Issue
Block a user