|
|
@@ -106,6 +106,17 @@
|
|
|
</div>
|
|
|
|
|
|
<div class="box-wrap stage-card">
|
|
|
+ <div class="method-switch" v-if="methodTabs.length">
|
|
|
+ <div
|
|
|
+ v-for="tab in methodTabs"
|
|
|
+ :key="tab.value"
|
|
|
+ class="method-switch__item"
|
|
|
+ :class="{ active: executeMethod === tab.value }"
|
|
|
+ @click="handleMethodSwitch(tab.value)"
|
|
|
+ >
|
|
|
+ {{ tab.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div class="work-info">
|
|
|
<div class="info-item">
|
|
|
<div class="info-title"><span class="title-block"></span>{{ $t('workDetail.prescription') }}
|
|
|
@@ -295,8 +306,86 @@ function readWorkAgronomyPayload() {
|
|
|
}
|
|
|
|
|
|
/** 列表带入:agronomy_detail 原样 + 列表上的类型/状态标签 */
|
|
|
+const methodTabs = ref([]);
|
|
|
+const executeMethod = ref("");
|
|
|
+/** 切换方式时保留列表标签等元信息 */
|
|
|
+const farmMeta = ref({});
|
|
|
+
|
|
|
+function pickGroupRecord(group) {
|
|
|
+ const records = group?.work_records;
|
|
|
+ if (Array.isArray(records) && records.length > 0) return records[0];
|
|
|
+ return null;
|
|
|
+}
|
|
|
+
|
|
|
+function applyGroupDetail(group, meta = farmMeta.value) {
|
|
|
+ const record = pickGroupRecord(group);
|
|
|
+ const detail = record?.agronomy_detail;
|
|
|
+ if (!detail) return false;
|
|
|
+ const workType = record.work_type ?? meta.work_type;
|
|
|
+ const isWeather = workType === "weather_warning" || workType === "warning";
|
|
|
+ farmData.value = {
|
|
|
+ ...detail,
|
|
|
+ work_id: record.work_id ?? detail.id,
|
|
|
+ work_type: workType,
|
|
|
+ work_status: record.work_status ?? meta.work_status,
|
|
|
+ status: meta.status,
|
|
|
+ isNormal: meta.isNormal ?? (!isWeather && workType === "standard"),
|
|
|
+ isAbnormal: meta.isAbnormal ?? false,
|
|
|
+ isWeather: meta.isWeather ?? isWeather,
|
|
|
+ isHighRisk: meta.isHighRisk ?? isWeather,
|
|
|
+ cornerTip: meta.cornerTip || "",
|
|
|
+ };
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+function buildMethodTabs(groups) {
|
|
|
+ if (!Array.isArray(groups)) return [];
|
|
|
+ return groups
|
|
|
+ .map((group, index) => {
|
|
|
+ const label = group?.fw_type || `方案${index + 1}`;
|
|
|
+ return {
|
|
|
+ label,
|
|
|
+ value: String(index),
|
|
|
+ group,
|
|
|
+ };
|
|
|
+ })
|
|
|
+ .filter((tab) => pickGroupRecord(tab.group)?.agronomy_detail);
|
|
|
+}
|
|
|
+
|
|
|
+function handleMethodSwitch(value) {
|
|
|
+ if (executeMethod.value === value) return;
|
|
|
+ const tab = methodTabs.value.find((item) => item.value === value);
|
|
|
+ if (!tab) return;
|
|
|
+ executeMethod.value = value;
|
|
|
+ applyGroupDetail(tab.group);
|
|
|
+}
|
|
|
+
|
|
|
function applyAgronomyDetailPayload(payload) {
|
|
|
if (!payload || typeof payload !== "object") return false;
|
|
|
+
|
|
|
+ const groups = Array.isArray(payload.fw_type_groups) ? payload.fw_type_groups : [];
|
|
|
+ const tabs = buildMethodTabs(groups);
|
|
|
+ methodTabs.value = tabs;
|
|
|
+
|
|
|
+ const workType = payload.work_type;
|
|
|
+ const isWeather = workType === "weather_warning" || workType === "warning";
|
|
|
+ farmMeta.value = {
|
|
|
+ work_type: workType,
|
|
|
+ work_status: payload.work_status,
|
|
|
+ status: payload.status,
|
|
|
+ isNormal: payload.isNormal ?? (!isWeather && workType === "standard"),
|
|
|
+ isAbnormal: payload.isAbnormal ?? false,
|
|
|
+ isWeather: payload.isWeather ?? isWeather,
|
|
|
+ isHighRisk: payload.isHighRisk ?? isWeather,
|
|
|
+ cornerTip: payload.cornerTip || "",
|
|
|
+ };
|
|
|
+
|
|
|
+ // 有方案分组:默认选第 0 个
|
|
|
+ if (tabs.length > 0) {
|
|
|
+ executeMethod.value = tabs[0].value;
|
|
|
+ return applyGroupDetail(tabs[0].group, farmMeta.value);
|
|
|
+ }
|
|
|
+
|
|
|
const detail =
|
|
|
payload.agronomy_detail && typeof payload.agronomy_detail === "object"
|
|
|
? payload.agronomy_detail
|
|
|
@@ -304,26 +393,26 @@ function applyAgronomyDetailPayload(payload) {
|
|
|
? payload
|
|
|
: null;
|
|
|
if (!detail) return false;
|
|
|
- const workType = payload.work_type;
|
|
|
- const isWeather = workType === "weather_warning" || workType === "warning";
|
|
|
farmData.value = {
|
|
|
...detail,
|
|
|
work_id: payload.work_id ?? detail.id,
|
|
|
work_type: workType,
|
|
|
work_status: payload.work_status,
|
|
|
status: payload.status,
|
|
|
- // 与列表卡片标签一致
|
|
|
- isNormal: payload.isNormal ?? (!isWeather && workType === "standard"),
|
|
|
- isAbnormal: payload.isAbnormal ?? false,
|
|
|
- isWeather: payload.isWeather ?? isWeather,
|
|
|
- isHighRisk: payload.isHighRisk ?? isWeather,
|
|
|
- cornerTip: payload.cornerTip || "",
|
|
|
+ isNormal: farmMeta.value.isNormal,
|
|
|
+ isAbnormal: farmMeta.value.isAbnormal,
|
|
|
+ isWeather: farmMeta.value.isWeather,
|
|
|
+ isHighRisk: farmMeta.value.isHighRisk,
|
|
|
+ cornerTip: farmMeta.value.cornerTip,
|
|
|
};
|
|
|
+ executeMethod.value = "";
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
const wktFmt = new WKT();
|
|
|
const MAP_CENTER_FALLBACK = "POINT(113.1093017627431 22.57454083668)";
|
|
|
+const ENTRY_FARM_DATA_KEY = "ENTRY_FARM_DATA";
|
|
|
+const MAP_POINT_STORAGE_KEY = "GROWTH_REPORT_MAP_POINT";
|
|
|
|
|
|
const farmZones = computed(() => {
|
|
|
const zones = farmData.value?.zones;
|
|
|
@@ -333,6 +422,37 @@ const farmZones = computed(() => {
|
|
|
);
|
|
|
});
|
|
|
|
|
|
+const isPointWkt = (value) => typeof value === "string" && /^POINT\s*\(/i.test(value.trim());
|
|
|
+
|
|
|
+/** 优先用户选中点位(录入 / 长势报告 / 农场) */
|
|
|
+function resolveUserMapPoint() {
|
|
|
+ try {
|
|
|
+ const entry = JSON.parse(localStorage.getItem(ENTRY_FARM_DATA_KEY) || "null");
|
|
|
+ if (isPointWkt(entry?.point)) return entry.point.trim();
|
|
|
+ if (Array.isArray(entry?.coordinate) && entry.coordinate.length === 2) {
|
|
|
+ return `POINT(${entry.coordinate[0]} ${entry.coordinate[1]})`;
|
|
|
+ }
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+
|
|
|
+ const growthPoint = localStorage.getItem(MAP_POINT_STORAGE_KEY);
|
|
|
+ if (isPointWkt(growthPoint)) return growthPoint.trim();
|
|
|
+
|
|
|
+ const selectedPoint = localStorage.getItem("selectedFarmPoint");
|
|
|
+ if (isPointWkt(selectedPoint)) return selectedPoint.trim();
|
|
|
+
|
|
|
+ try {
|
|
|
+ const farm = JSON.parse(localStorage.getItem("selectedFarmData") || "{}");
|
|
|
+ const wkt = farm.wkt || farm.geom_wkt || farm.farm_location;
|
|
|
+ if (isPointWkt(wkt)) return wkt.trim();
|
|
|
+ } catch {
|
|
|
+ // ignore
|
|
|
+ }
|
|
|
+
|
|
|
+ return "";
|
|
|
+}
|
|
|
+
|
|
|
/** 从地块 WKT 取首坐标作为初始中心,initZones 会 fit 到全部地块 */
|
|
|
function wktCenterPointFromZones(zones) {
|
|
|
const list = Array.isArray(zones) ? zones : [];
|
|
|
@@ -357,8 +477,10 @@ function initWorkDetailMap() {
|
|
|
nextTick(() => {
|
|
|
if (!mapContainer.value) return;
|
|
|
const zones = farmZones.value;
|
|
|
+ // 默认定位用户选中点;无点位再用地块 / 兜底
|
|
|
+ const center = resolveUserMapPoint() || wktCenterPointFromZones(zones);
|
|
|
areaMap.destroyMap();
|
|
|
- areaMap.initMap(wktCenterPointFromZones(zones), mapContainer.value);
|
|
|
+ areaMap.initMap(center, mapContainer.value);
|
|
|
areaMap.initZones(zones);
|
|
|
});
|
|
|
}
|
|
|
@@ -1119,6 +1241,32 @@ const areaMap = new AreaMap();
|
|
|
}
|
|
|
|
|
|
.stage-card {
|
|
|
+ .method-switch {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+
|
|
|
+ .method-switch__item {
|
|
|
+ height: 28px;
|
|
|
+ line-height: 28px;
|
|
|
+ padding: 0 12px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: 12px;
|
|
|
+ color: #8E8E8E;
|
|
|
+ background: #fff;
|
|
|
+ border: 1px solid #fff;
|
|
|
+ border-radius: 2px;
|
|
|
+ box-sizing: border-box;
|
|
|
+ white-space: nowrap;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ color: #2199F8;
|
|
|
+ background: rgba(33, 153, 248, 0.1);
|
|
|
+ border-color: #2199f8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
.stage-header {
|
|
|
padding-bottom: 12px;
|
|
|
display: flex;
|