增加字符串兼容性;去除国外开源地图软件代码;批次发布后仍可编辑;

This commit is contained in:
BBIT-Kai
2026-04-15 15:20:51 +08:00
parent 55a2490e14
commit a23355ac5b
9 changed files with 493 additions and 395 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ plugins {
}
group = "com.bbitcn"
version = "0.0.4"
version = "0.0.5"
application {
mainClass = "io.ktor.server.netty.EngineMain"
+13 -3
View File
@@ -110,7 +110,17 @@ class TraceabilityService(
value.entries.joinToString("") { "${it.key}: ${formatJsonValue(it.value)}" }
}
}
else -> value.toString().trim('"').ifBlank { "未填写" }
else -> normalizeDisplayText(value.toString().trim('"'))
}
private fun normalizeDisplayText(text: String): String {
if (text.isBlank()) {
return "未填写"
}
return text
.replace("\\r\\n", "\n")
.replace("\\n", "\n")
.replace("\\t", "\t")
}
private fun formatDateOnly(value: String): String {
@@ -126,7 +136,7 @@ class TraceabilityService(
val lng = coordinate["lng"]?.jsonPrimitive?.doubleOrNull
val lat = coordinate["lat"]?.jsonPrimitive?.doubleOrNull
return when {
lng != null && lat != null -> "https://www.openstreetmap.org/?mlat=$lat&mlon=$lng#map=15/$lat/$lng"
lng != null && lat != null -> "https://uri.amap.com/marker?position=$lng,$lat&name=坐标位置&src=traceability"
else -> ""
}
}
@@ -135,7 +145,7 @@ class TraceabilityService(
val coordinate = value as? JsonObject ?: return ""
val lng = coordinate["lng"]?.jsonPrimitive?.doubleOrNull ?: return ""
val lat = coordinate["lat"]?.jsonPrimitive?.doubleOrNull ?: return ""
return "https://www.openstreetmap.org/export/embed.html?bbox=${lng - 0.01}%2C${lat - 0.01}%2C${lng + 0.01}%2C${lat + 0.01}&layer=mapnik&marker=$lat%2C$lng"
return "https://uri.amap.com/marker?position=$lng,$lat&name=坐标位置&src=traceability&callnative=0"
}
private fun buildPageViewModel(
+2 -2
View File
@@ -7,5 +7,5 @@ ktor:
traceability:
# 访问主服务的地址
# core-base-url: "http://127.0.0.1:8089" # 开发
core-base-url: "https://ai.ronsunny.cn:8090/api" # 生产
core-base-url: "http://127.0.0.1:8089" # 开发
# core-base-url: "https://ai.ronsunny.cn:8090/api" # 生产
@@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${page.batchName} - 溯源信息</title>
<link rel="stylesheet" href="/static/traceability.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@10.6.1/ol.css" />
</head>
<body style="--traceability-primary:${page.themeColor};">
<div class="page-shell">
@@ -78,9 +79,11 @@
<img class="kv-image" src="${entry.value}" alt="${entry.label}" />
</button>
<#elseif entry.type == "coordinate" && entry.value?has_content && entry.value != "未填写">
<#if entry.mapEmbedUrl?has_content>
<iframe class="kv-map" src="${entry.mapEmbedUrl}" loading="lazy" referrerpolicy="no-referrer-when-downgrade" title="${entry.label}"></iframe>
</#if>
<div
class="kv-map"
data-coordinate="${entry.value?html}"
data-label="${entry.label?html}"
></div>
<strong<#if entry.bold || entry.color?has_content> style="<#if entry.bold>font-weight:700;</#if><#if entry.color?has_content>color:${entry.color};</#if>"</#if>>${entry.value}</strong>
<#else>
<strong<#if entry.bold || entry.color?has_content> style="<#if entry.bold>font-weight:700;</#if><#if entry.color?has_content>color:${entry.color};</#if>"</#if>>${entry.value}</strong>
@@ -115,9 +118,11 @@
<img class="kv-image" src="${entry.value}" alt="${entry.label}" />
</button>
<#elseif entry.type == "coordinate" && entry.value?has_content && entry.value != "未填写">
<#if entry.mapEmbedUrl?has_content>
<iframe class="kv-map" src="${entry.mapEmbedUrl}" loading="lazy" referrerpolicy="no-referrer-when-downgrade" title="${entry.label}"></iframe>
</#if>
<div
class="kv-map"
data-coordinate="${entry.value?html}"
data-label="${entry.label?html}"
></div>
<strong<#if entry.bold || entry.color?has_content> style="<#if entry.bold>font-weight:700;</#if><#if entry.color?has_content>color:${entry.color};</#if>"</#if>>${entry.value}</strong>
<#else>
<strong<#if entry.bold || entry.color?has_content> style="<#if entry.bold>font-weight:700;</#if><#if entry.color?has_content>color:${entry.color};</#if>"</#if>>${entry.value}</strong>
@@ -190,6 +195,12 @@
</div>
<script>
const openLayersScript = document.createElement('script');
openLayersScript.src = 'https://cdn.jsdelivr.net/npm/ol@10.6.1/dist/ol.js';
openLayersScript.defer = true;
openLayersScript.onload = initCoordinateMaps;
document.head.appendChild(openLayersScript);
const themeColor = '${page.themeColor}';
function hexToRgb(hex) {
const normalized = (hex || '').replace('#', '').trim();
@@ -287,6 +298,73 @@
});
});
function parseCoordinateValue(raw) {
if (!raw) return null;
try {
const parsed = JSON.parse(raw);
const lng = Number(parsed.lng);
const lat = Number(parsed.lat);
if (Number.isFinite(lng) && Number.isFinite(lat)) {
return { lng, lat };
}
} catch (error) {
const parts = String(raw).split(',').map((item) => item.trim());
if (parts.length >= 2) {
const lng = Number(parts[0]);
const lat = Number(parts[1]);
if (Number.isFinite(lng) && Number.isFinite(lat)) {
return { lng, lat };
}
}
}
return null;
}
function initCoordinateMaps() {
if (!window.ol) return;
const mapNodes = document.querySelectorAll('.kv-map[data-coordinate]');
mapNodes.forEach((node) => {
if (node.dataset.initialized === 'true') return;
const parsed = parseCoordinateValue(node.dataset.coordinate);
if (!parsed) return;
node.dataset.initialized = 'true';
const map = new ol.Map({
target: node,
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
crossOrigin: 'anonymous',
}),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([parsed.lng, parsed.lat]),
zoom: 13,
}),
controls: [],
});
const marker = new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([parsed.lng, parsed.lat])),
});
const vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
features: [marker],
}),
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({ color: primary }),
stroke: new ol.style.Stroke({ color: '#ffffff', width: 2 }),
}),
}),
});
map.addLayer(vectorLayer);
});
}
if (window.location.search.includes('result=')) {
const nextUrl = window.location.pathname + window.location.hash;
window.history.replaceState({}, '', nextUrl);