|
@@ -155,10 +155,30 @@ function readEntryFarmData() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 农事列表用手机号:优先录入信息 */
|
|
|
|
|
+function resolveUserTel() {
|
|
|
|
|
+ const entry = readEntryFarmData();
|
|
|
|
|
+ if (entry?.phone) return String(entry.phone).trim();
|
|
|
|
|
+ try {
|
|
|
|
|
+ const userInfo = JSON.parse(localStorage.getItem("localUserInfo") || "{}");
|
|
|
|
|
+ return String(userInfo.tel || userInfo.phone || userInfo.mobile || "").trim();
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function formatExecuteDate(date = new Date()) {
|
|
function formatExecuteDate(date = new Date()) {
|
|
|
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(date.getDate()).padStart(2, "0")}`;
|
|
return `${String(date.getMonth() + 1).padStart(2, "0")}/${String(date.getDate()).padStart(2, "0")}`;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** work_time → MM/DD */
|
|
|
|
|
+function formatWorkTime(workTime) {
|
|
|
|
|
+ if (!workTime) return formatExecuteDate();
|
|
|
|
|
+ const d = new Date(workTime);
|
|
|
|
|
+ if (Number.isNaN(d.getTime())) return formatExecuteDate();
|
|
|
|
|
+ return formatExecuteDate(d);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/** 根据中心点生成附近任务点位(已完成 mock) */
|
|
/** 根据中心点生成附近任务点位(已完成 mock) */
|
|
|
const buildCompletedNearCenter = (centerWkt) => {
|
|
const buildCompletedNearCenter = (centerWkt) => {
|
|
|
const coord = convertPointToArray(centerWkt);
|
|
const coord = convertPointToArray(centerWkt);
|
|
@@ -175,96 +195,69 @@ const buildCompletedNearCenter = (centerWkt) => {
|
|
|
});
|
|
});
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-/**
|
|
|
|
|
- * 接口农事 → 列表卡片
|
|
|
|
|
- * @param {'standard' | 'warning'} type 标准 / 预警
|
|
|
|
|
- */
|
|
|
|
|
-function mapAgronomyToTask(item, index, centerWkt, type = "standard") {
|
|
|
|
|
|
|
+/** user_work 单条 → 列表卡片 */
|
|
|
|
|
+function mapUserWorkToTask(item, index, centerWkt) {
|
|
|
|
|
+ const detail = item?.agronomy_detail || {};
|
|
|
const coord = convertPointToArray(centerWkt);
|
|
const coord = convertPointToArray(centerWkt);
|
|
|
const lng = Number(coord?.[0]);
|
|
const lng = Number(coord?.[0]);
|
|
|
const lat = Number(coord?.[1]);
|
|
const lat = Number(coord?.[1]);
|
|
|
const dx = ((index % 3) - 1) * 0.0012;
|
|
const dx = ((index % 3) - 1) * 0.0012;
|
|
|
const dy = (Math.floor(index / 3) - 0.5) * 0.001;
|
|
const dy = (Math.floor(index / 3) - 0.5) * 0.001;
|
|
|
const hasCoord = Number.isFinite(lng) && Number.isFinite(lat);
|
|
const hasCoord = Number.isFinite(lng) && Number.isFinite(lat);
|
|
|
- const title = item.fw_name || "";
|
|
|
|
|
- const isWarning = type === "warning";
|
|
|
|
|
|
|
+ const title = detail.fw_name || "";
|
|
|
|
|
+ const executeDate = formatWorkTime(item.work_time);
|
|
|
|
|
+ const isWarning = item.work_type === "weather_warning" || item.work_type === "warning";
|
|
|
|
|
+ const isCompleted = Number(item.work_status) === 1;
|
|
|
return {
|
|
return {
|
|
|
- id: item.id ?? `${type}-${index}`,
|
|
|
|
|
- status: "pending",
|
|
|
|
|
|
|
+ id: item.work_id ?? detail.id ?? `work-${index}`,
|
|
|
|
|
+ status: isCompleted ? "completed" : "pending",
|
|
|
title,
|
|
title,
|
|
|
farmName: title,
|
|
farmName: title,
|
|
|
isHighRisk: isWarning,
|
|
isHighRisk: isWarning,
|
|
|
isNormal: !isWarning,
|
|
isNormal: !isWarning,
|
|
|
isAbnormal: false,
|
|
isAbnormal: false,
|
|
|
isWeather: isWarning,
|
|
isWeather: isWarning,
|
|
|
- cornerTip: isWarning ? "建议执行" : "待执行",
|
|
|
|
|
- analysisSummary: item.fw_explain_simple || item.fw_explain || "",
|
|
|
|
|
- areaCode: item.crop_category_name || "分区一",
|
|
|
|
|
- executeDate: formatExecuteDate(),
|
|
|
|
|
- phenophaseCode: item.phenophase_code,
|
|
|
|
|
- phenophaseName: item.phenophase_name,
|
|
|
|
|
- fwExplain: item.fw_explain,
|
|
|
|
|
- fwAtten: item.fw_atten,
|
|
|
|
|
- fwParams: item.fw_params,
|
|
|
|
|
- fwPrecrip: item.fw_precrip,
|
|
|
|
|
- agronomyType: type,
|
|
|
|
|
|
|
+ cornerTip: isCompleted ? "已完成" : isWarning ? "建议执行" : "待执行",
|
|
|
|
|
+ analysisSummary: detail.fw_explain_simple || detail.fw_explain || "",
|
|
|
|
|
+ areaCode: detail.crop_category_name || "分区一",
|
|
|
|
|
+ executeDate,
|
|
|
|
|
+ phenophaseCode: detail.phenophase_code,
|
|
|
|
|
+ phenophaseName: detail.phenophase_name,
|
|
|
|
|
+ fwExplain: detail.fw_explain,
|
|
|
|
|
+ fwAtten: detail.fw_atten,
|
|
|
|
|
+ fwParams: detail.fw_params,
|
|
|
|
|
+ fwPrecrip: detail.fw_precrip,
|
|
|
|
|
+ workType: item.work_type,
|
|
|
|
|
+ workStatus: item.work_status,
|
|
|
|
|
+ agronomyType: isWarning ? "warning" : "standard",
|
|
|
wkt: hasCoord ? `POINT(${lng + dx} ${lat + dy})` : "",
|
|
wkt: hasCoord ? `POINT(${lng + dx} ${lat + dy})` : "",
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-/** 拉取单类农事,失败返回空数组(不阻断另一类) */
|
|
|
|
|
-async function requestAgronomyList(apiFn, params, errorMsg) {
|
|
|
|
|
|
|
+/** 拉取用户农事列表(report/user_work) */
|
|
|
|
|
+async function fetchUserWorkTasks(centerWkt) {
|
|
|
|
|
+ const tel = resolveUserTel();
|
|
|
|
|
+ if (!tel) {
|
|
|
|
|
+ taskList.value = buildCompletedNearCenter(centerWkt);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
try {
|
|
try {
|
|
|
- const res = await apiFn(params);
|
|
|
|
|
- if (res?.code != null && res.code !== 200) {
|
|
|
|
|
- ElMessage.error(res.msg || errorMsg);
|
|
|
|
|
- return [];
|
|
|
|
|
|
|
+ const raw = await VE_API.questionnaire.userWork({ tel });
|
|
|
|
|
+ const res = Array.isArray(raw) ? raw[0] : raw;
|
|
|
|
|
+ const code = Number(res?.code);
|
|
|
|
|
+ if (!(code === 200 || code === 0 || code === 1)) {
|
|
|
|
|
+ ElMessage.error(res?.message || res?.msg || "获取农事列表失败");
|
|
|
|
|
+ taskList.value = buildCompletedNearCenter(centerWkt);
|
|
|
|
|
+ return;
|
|
|
}
|
|
}
|
|
|
- return Array.isArray(res?.data) ? res.data : [];
|
|
|
|
|
|
|
+ const list = Array.isArray(res?.data) ? res.data : [];
|
|
|
|
|
+ const mapped = list.map((item, index) => mapUserWorkToTask(item, index, centerWkt));
|
|
|
|
|
+ const hasCompleted = mapped.some((item) => item.status === "completed");
|
|
|
|
|
+ taskList.value = hasCompleted ? mapped : [...mapped, ...buildCompletedNearCenter(centerWkt)];
|
|
|
} catch {
|
|
} catch {
|
|
|
- ElMessage.error(errorMsg);
|
|
|
|
|
- return [];
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-/** 并行拉取标准农事 + 预警农事 */
|
|
|
|
|
-async function fetchAgronomyTasks(centerWkt) {
|
|
|
|
|
- const entry = readEntryFarmData();
|
|
|
|
|
- const cropType = entry?.crop;
|
|
|
|
|
- const phenophaseCode = entry?.cropCode;
|
|
|
|
|
- const riskName = entry?.weatherRisk;
|
|
|
|
|
- if (!cropType || !phenophaseCode) {
|
|
|
|
|
|
|
+ ElMessage.error("获取农事列表失败,请稍后再试");
|
|
|
taskList.value = buildCompletedNearCenter(centerWkt);
|
|
taskList.value = buildCompletedNearCenter(centerWkt);
|
|
|
- return;
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- const baseParams = {
|
|
|
|
|
- crop_type: cropType,
|
|
|
|
|
- phenophase_code: phenophaseCode,
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- const standardPromise = requestAgronomyList(
|
|
|
|
|
- VE_API.questionnaire.standardAgronomy,
|
|
|
|
|
- baseParams,
|
|
|
|
|
- "获取标准农事失败"
|
|
|
|
|
- );
|
|
|
|
|
-
|
|
|
|
|
- const warningPromise = riskName
|
|
|
|
|
- ? requestAgronomyList(
|
|
|
|
|
- VE_API.questionnaire.warningAgronomy,
|
|
|
|
|
- { ...baseParams, risk_name: riskName },
|
|
|
|
|
- "获取预警农事失败"
|
|
|
|
|
- )
|
|
|
|
|
- : Promise.resolve([]);
|
|
|
|
|
-
|
|
|
|
|
- const [standardList, warningList] = await Promise.all([standardPromise, warningPromise]);
|
|
|
|
|
- const pending = [
|
|
|
|
|
- ...standardList.map((item, index) => mapAgronomyToTask(item, index, centerWkt, "standard")),
|
|
|
|
|
- ...warningList.map((item, index) =>
|
|
|
|
|
- mapAgronomyToTask(item, standardList.length + index, centerWkt, "warning")
|
|
|
|
|
- ),
|
|
|
|
|
- ];
|
|
|
|
|
- taskList.value = [...pending, ...buildCompletedNearCenter(centerWkt)];
|
|
|
|
|
}
|
|
}
|
|
|
const activeTab = ref("pending");
|
|
const activeTab = ref("pending");
|
|
|
const pendingCount = computed(() => taskList.value.filter((item) => item.status === "pending").length);
|
|
const pendingCount = computed(() => taskList.value.filter((item) => item.status === "pending").length);
|
|
@@ -381,7 +374,7 @@ const refreshMapMarkers = () => {
|
|
|
const loadWorkPage = async () => {
|
|
const loadWorkPage = async () => {
|
|
|
if (!mapContainer.value) return;
|
|
if (!mapContainer.value) return;
|
|
|
mapPoint.value = resolveMapPoint();
|
|
mapPoint.value = resolveMapPoint();
|
|
|
- await fetchAgronomyTasks(mapPoint.value);
|
|
|
|
|
|
|
+ await fetchUserWorkTasks(mapPoint.value);
|
|
|
refreshMapMarkers();
|
|
refreshMapMarkers();
|
|
|
if (mapContainer.value && indexMap.kmap?.map) {
|
|
if (mapContainer.value && indexMap.kmap?.map) {
|
|
|
const checkAndUpdateSize = () => {
|
|
const checkAndUpdateSize = () => {
|