| | |
| | | if (!isStationFormMode.value) return ""; |
| | | if (!stationForm.value.stationName.trim()) return "请输入场站名称"; |
| | | if (stationDraftPoints.value.length < 3) return "请先在运营区内绘制场站"; |
| | | const geometryError = getStationGeometryInvalidReason(stationDraftPoints.value); |
| | | const geometryError = getStationGeometryInvalidReason(stationDraftPoints.value, { |
| | | allowOutsideOperationArea: isStationEditWorkflow.value, |
| | | }); |
| | | if (geometryError) return geometryError; |
| | | if ( |
| | | isStationEditWorkflow.value && |
| | | !resolveStationOperationAreaByPolygon(stationDraftPoints.value) && |
| | | Number(stationForm.value.areaStatus || 1) === 1 |
| | | ) { |
| | | return "当前场站不在围栏区域内,不允许启用"; |
| | | } |
| | | if (!stationForm.value.parkingTimeLimit) return "请输入限停时长"; |
| | | return getStationCustomTimeErrorMessage(); |
| | | }); |
| | |
| | | .filter((item) => item.points.length >= 3); |
| | | } |
| | | |
| | | function getStationGeometryInvalidReason(points: LngLatTuple[]) { |
| | | function resolveStationOperationAreaByPolygon(points: LngLatTuple[]) { |
| | | if (points.length < 3) return null; |
| | | return ( |
| | | getStationOperationAreas().find((area) => isRingInRing(points, area.points)) |
| | | || null |
| | | ); |
| | | } |
| | | |
| | | function getStationGeometryInvalidReason( |
| | | points: LngLatTuple[], |
| | | options: { |
| | | allowOutsideOperationArea?: boolean; |
| | | } = {} |
| | | ) { |
| | | if (points.length < 3) return "请绘制至少3个点的场站"; |
| | | if (isFencePolygonSelfIntersect(points)) return "场站区域不允许自相交"; |
| | | const operationAreas = getStationOperationAreas(); |
| | | const isInsideOperationArea = operationAreas.some((area) => |
| | | isRingInRing(points, area.points) |
| | | ); |
| | | if (!isInsideOperationArea) return "场站需完全处于运营区内"; |
| | | const matchedOperationArea = resolveStationOperationAreaByPolygon(points); |
| | | if (!matchedOperationArea && !options.allowOutsideOperationArea) |
| | | return "场站需完全处于运营区内"; |
| | | const otherStations = getOtherStations(); |
| | | const geometryUtil = (window as any).AMap?.GeometryUtil; |
| | | if (geometryUtil) { |
| | |
| | | } |
| | | |
| | | function validateStationGeometry(points: LngLatTuple[]) { |
| | | const errorMessage = getStationGeometryInvalidReason(points); |
| | | const errorMessage = getStationGeometryInvalidReason(points, { |
| | | allowOutsideOperationArea: isStationEditWorkflow.value, |
| | | }); |
| | | if (errorMessage) { |
| | | window.$message?.warning(errorMessage); |
| | | return false; |
| | |
| | | function resolveStationOperationArea() { |
| | | if (!fenceAreaData.value.length) return null; |
| | | const draftPolygonPath = clonePolygonPath(stationDraftPoints.value); |
| | | const draftCenter = getPolygonCenter(draftPolygonPath); |
| | | const centerLon = Number.isFinite(Number(draftCenter?.[0])) |
| | | ? Number(draftCenter?.[0]) |
| | | : selectedItem.value?.type === "station" |
| | | ? Number(selectedItem.value.lng) |
| | | : NaN; |
| | | const centerLat = Number.isFinite(Number(draftCenter?.[1])) |
| | | ? Number(draftCenter?.[1]) |
| | | : selectedItem.value?.type === "station" |
| | | ? Number(selectedItem.value.lat) |
| | | : NaN; |
| | | if (!Number.isFinite(centerLon) || !Number.isFinite(centerLat)) return null; |
| | | return resolveOperationArea( |
| | | fenceAreaData.value, |
| | | centerLon, |
| | | centerLat |
| | | if (draftPolygonPath.length >= 3) |
| | | return resolveStationOperationAreaByPolygon(draftPolygonPath); |
| | | const detailPolygonPath = clonePolygonPath( |
| | | stationDetailData.value?.polygonPath || stationForm.value.polygonPath |
| | | ); |
| | | if (detailPolygonPath.length >= 3) |
| | | return resolveStationOperationAreaByPolygon(detailPolygonPath); |
| | | return null; |
| | | } |
| | | |
| | | const stationLifecycleCache = ref<Record<string, Record<string, any> | null>>({}); |
| | |
| | | } |
| | | |
| | | const stationOperationLifecycle = computed(() => { |
| | | if (!stationOperationArea.value) return null; |
| | | const detailLifecycle = normalizeStationLifecycleSource(stationDetailData.value); |
| | | if (detailLifecycle) return detailLifecycle; |
| | | return stationOperationLifecycleFallback.value; |
| | |
| | | ? Number(polygonCenter?.[1]) |
| | | : undefined; |
| | | const currentSelectedStation = selectedItem.value; |
| | | const operationArea = |
| | | polygonCenter && fenceAreaData.value.length |
| | | ? resolveOperationArea( |
| | | fenceAreaData.value, |
| | | Number(polygonCenter[0]), |
| | | Number(polygonCenter[1]) |
| | | ) |
| | | : null; |
| | | const operationArea = resolveStationOperationAreaByPolygon(polygonPath); |
| | | const stationArea = Number(calcFenceArea(polygonPath).toFixed(2)); |
| | | const detail = { |
| | | id: |
| | |
| | | } |
| | | } |
| | | |
| | | watch( |
| | | [isStationEditWorkflow, stationOperationArea, () => stationForm.value.areaStatus], |
| | | ([editing, operationArea, areaStatus]) => { |
| | | if (!editing || operationArea || Number(areaStatus) !== 1) return; |
| | | stationForm.value.areaStatus = 2; |
| | | } |
| | | ); |
| | | |
| | | // tab 切换时重置左侧筛选与选中态,并按目标 tab 刷新对应资源。 |
| | | watch(activeTab, async (value) => { |
| | | keyword.value = ""; |