李红攀:小程序新增农事记录

This commit is contained in:
2026-06-10 14:02:34 +08:00
parent 273772d68a
commit 5ec4b2d818
7 changed files with 511 additions and 5 deletions

156
src/utils/geo.js Normal file
View File

@@ -0,0 +1,156 @@
export function isPointInGeoJson(point, geoJson) {
if (!point || !isFiniteNumber(point.longitude) || !isFiniteNumber(point.latitude) || !geoJson) {
return false
}
const geometries = collectGeometries(geoJson)
if (!geometries.length) {
return false
}
return geometries.some((geometry) => {
if (!geometry || !geometry.type || !geometry.coordinates) {
return false
}
if (geometry.type === 'Polygon') {
return isPointInPolygonCoordinates(point, geometry.coordinates)
}
if (geometry.type === 'MultiPolygon') {
return geometry.coordinates.some(polygon => isPointInPolygonCoordinates(point, polygon))
}
return false
})
}
export function getGeoJsonPolygonPaths(geoJson) {
const geometries = collectGeometries(geoJson)
if (!geometries.length) {
return []
}
return geometries.flatMap((geometry) => {
if (!geometry || !geometry.type || !geometry.coordinates) {
return []
}
if (geometry.type === 'Polygon') {
return buildPolygonPaths(geometry.coordinates)
}
if (geometry.type === 'MultiPolygon') {
return geometry.coordinates.flatMap(polygon => buildPolygonPaths(polygon))
}
return []
})
}
function collectGeometries(geoJson) {
if (!geoJson || typeof geoJson !== 'object') {
return []
}
if (geoJson.type === 'Feature') {
return geoJson.geometry ? [geoJson.geometry] : []
}
if (geoJson.type === 'FeatureCollection') {
return (geoJson.features || []).flatMap(feature => collectGeometries(feature))
}
if (geoJson.type === 'Polygon' || geoJson.type === 'MultiPolygon') {
return [geoJson]
}
return []
}
function isPointInPolygonCoordinates(point, polygonCoordinates) {
if (!Array.isArray(polygonCoordinates) || polygonCoordinates.length === 0) {
return false
}
const [outerRing, ...holes] = polygonCoordinates
if (!isPointInRing(point, outerRing)) {
return false
}
return !holes.some(hole => isPointInRing(point, hole))
}
function buildPolygonPaths(polygonCoordinates) {
if (!Array.isArray(polygonCoordinates) || polygonCoordinates.length === 0) {
return []
}
const [outerRing] = polygonCoordinates
const points = normalizeRingPoints(outerRing)
return points.length >= 3 ? [points] : []
}
function normalizeRingPoints(ring) {
if (!Array.isArray(ring)) {
return []
}
return ring
.filter(isValidCoordinate)
.map(coordinate => ({
longitude: Number(coordinate[0]),
latitude: Number(coordinate[1]),
}))
}
function isPointInRing(point, ring) {
if (!Array.isArray(ring) || ring.length < 3) {
return false
}
const x = Number(point.longitude)
const y = Number(point.latitude)
let inside = false
for (let i = 0, j = ring.length - 1; i < ring.length; j = i, i += 1) {
const current = ring[i]
const previous = ring[j]
if (!isValidCoordinate(current) || !isValidCoordinate(previous)) {
continue
}
const xi = Number(current[0])
const yi = Number(current[1])
const xj = Number(previous[0])
const yj = Number(previous[1])
if (isPointOnSegment(x, y, xi, yi, xj, yj)) {
return true
}
const intersects = ((yi > y) !== (yj > y))
&& (x <= ((xj - xi) * (y - yi)) / (yj - yi) + xi)
if (intersects) {
inside = !inside
}
}
return inside
}
function isPointOnSegment(px, py, x1, y1, x2, y2) {
const cross = (px - x1) * (y2 - y1) - (py - y1) * (x2 - x1)
if (Math.abs(cross) > 1e-10) {
return false
}
const dot = (px - x1) * (px - x2) + (py - y1) * (py - y2)
return dot <= 1e-10
}
function isValidCoordinate(coordinate) {
return Array.isArray(coordinate)
&& coordinate.length >= 2
&& isFiniteNumber(coordinate[0])
&& isFiniteNumber(coordinate[1])
}
function isFiniteNumber(value) {
return Number.isFinite(Number(value))
}

View File

@@ -123,7 +123,7 @@ export function getEnvBaseUrl() {
// # 有些同学可能需要在微信小程序里面根据 develop、trial、release 分别设置上传地址,参考代码如下。
// TODO @芋艿:这个后续也要调整。
const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'http://localhost:48080/admin-api'
const VITE_SERVER_BASEURL__WEIXIN_DEVELOP = 'http://192.168.1.107:48080/admin-api'
const VITE_SERVER_BASEURL__WEIXIN_TRIAL = 'http://119.96.62.56:7004/admin-api'
const VITE_SERVER_BASEURL__WEIXIN_RELEASE = 'http://localhost:48080/admin-api'