|
@@ -118,7 +118,28 @@
|
|
|
</span> -->
|
|
</span> -->
|
|
|
</div>
|
|
</div>
|
|
|
<div class="report-card__body">
|
|
<div class="report-card__body">
|
|
|
- <div class="report-card__title">{{ item.title }}</div>
|
|
|
|
|
|
|
+ <div class="report-card__head">
|
|
|
|
|
+ <div class="report-card__title">{{ item.title }}</div>
|
|
|
|
|
+ <div v-if="item.date" class="report-card__day">{{ item.date }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="report-card__desc">{{ item.desc }}</div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <!-- 气象报告:weather_report_list -->
|
|
|
|
|
+ <div
|
|
|
|
|
+ v-for="item in weatherReportList"
|
|
|
|
|
+ :key="item.id"
|
|
|
|
|
+ class="report-card"
|
|
|
|
|
+ @click="goReportDetail(item)"
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="report-card__cover">
|
|
|
|
|
+ <img :src="item.cover" alt="" />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="report-card__body">
|
|
|
|
|
+ <div class="report-card__head">
|
|
|
|
|
+ <div class="report-card__title">{{ item.title }}</div>
|
|
|
|
|
+ <div v-if="item.date" class="report-card__day">{{ item.date }}</div>
|
|
|
|
|
+ </div>
|
|
|
<div class="report-card__desc">{{ item.desc }}</div>
|
|
<div class="report-card__desc">{{ item.desc }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -177,6 +198,7 @@ const INSPECT_SUCCESS_EVENT = "inspect-upload-success";
|
|
|
|
|
|
|
|
function onInspectSuccess() {
|
|
function onInspectSuccess() {
|
|
|
fetchReportList();
|
|
fetchReportList();
|
|
|
|
|
+ fetchWeatherReportList();
|
|
|
fetchCropArchiveList();
|
|
fetchCropArchiveList();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -380,6 +402,8 @@ async function fetchTmpAlbumImages() {
|
|
|
const reportCover = require("@/assets/img/common/sd-1.jpg");
|
|
const reportCover = require("@/assets/img/common/sd-1.jpg");
|
|
|
/** 诊断报告列表:风险报告 / 胁迫报告 / 异常农情研判报告 */
|
|
/** 诊断报告列表:风险报告 / 胁迫报告 / 异常农情研判报告 */
|
|
|
const reportList = ref([]);
|
|
const reportList = ref([]);
|
|
|
|
|
+/** 气象报告列表:weather_report_list */
|
|
|
|
|
+const weatherReportList = ref([]);
|
|
|
|
|
|
|
|
function resolveReportCover() {
|
|
function resolveReportCover() {
|
|
|
return readStoredCropQuestionPic() || reportCover;
|
|
return readStoredCropQuestionPic() || reportCover;
|
|
@@ -402,10 +426,47 @@ function unwrapApiData(raw) {
|
|
|
return Array.isArray(res.data) ? res.data[0] : res.data;
|
|
return Array.isArray(res.data) ? res.data[0] : res.data;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * risk_report / stress_report:兼容
|
|
|
|
|
+ * - 新:{ current_time, reports: [...] }
|
|
|
|
|
+ * - 旧:data 为报告对象或数组
|
|
|
|
|
+ */
|
|
|
|
|
+function unwrapRiskStressEnvelope(raw) {
|
|
|
|
|
+ const res = Array.isArray(raw) ? raw[0] : raw;
|
|
|
|
|
+ if (Number(res?.code) !== 200 || !res.data) {
|
|
|
|
|
+ return { report: null, currentTime: "" };
|
|
|
|
|
+ }
|
|
|
|
|
+ const data = res.data;
|
|
|
|
|
+ if (Array.isArray(data)) {
|
|
|
|
|
+ return { report: data[0] || null, currentTime: "" };
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Array.isArray(data.reports)) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ report: data.reports[0] || null,
|
|
|
|
|
+ currentTime: data.current_time || "",
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ return {
|
|
|
|
|
+ report: data,
|
|
|
|
|
+ currentTime: data.current_time || "",
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function pickReportDate(data) {
|
|
function pickReportDate(data) {
|
|
|
return data?.create_time || data?.update_time || data?.date || data?.report_date || "";
|
|
return data?.create_time || data?.update_time || data?.date || data?.report_date || "";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 日期字段 → 仅年月日;兼容 2026-09-11 / Wed, 23 Sep 2026 09:42:00 GMT */
|
|
|
|
|
+function formatReportDay(value) {
|
|
|
|
|
+ if (!value) return "";
|
|
|
|
|
+ const text = String(value).trim();
|
|
|
|
|
+ const matched = text.match(/(\d{4})-(\d{2})-(\d{2})/);
|
|
|
|
|
+ if (matched) return `${matched[1]}-${matched[2]}-${matched[3]}`;
|
|
|
|
|
+ const d = new Date(text);
|
|
|
|
|
+ if (Number.isNaN(d.getTime())) return "";
|
|
|
|
|
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
/** 异常研判报告:取 summary 首段正文作卡片简介 */
|
|
/** 异常研判报告:取 summary 首段正文作卡片简介 */
|
|
|
function pickAbnormalReportDesc(summary) {
|
|
function pickAbnormalReportDesc(summary) {
|
|
|
const text = String(summary || "").trim();
|
|
const text = String(summary || "").trim();
|
|
@@ -436,8 +497,8 @@ async function fetchReportList() {
|
|
|
VE_API.questionnaire.queryAbnormalReport({ tel }).catch(() => null),
|
|
VE_API.questionnaire.queryAbnormalReport({ tel }).catch(() => null),
|
|
|
]);
|
|
]);
|
|
|
|
|
|
|
|
- const riskData = unwrapApiData(riskRaw);
|
|
|
|
|
- const stressData = unwrapApiData(stressRaw);
|
|
|
|
|
|
|
+ const { report: riskData, currentTime: riskTime } = unwrapRiskStressEnvelope(riskRaw);
|
|
|
|
|
+ const { report: stressData, currentTime: stressTime } = unwrapRiskStressEnvelope(stressRaw);
|
|
|
// query_abnormal_report:data.reports / data.report 均为报告数组
|
|
// query_abnormal_report:data.reports / data.report 均为报告数组
|
|
|
const abnormalRes = Array.isArray(abnormalRaw) ? abnormalRaw[0] : abnormalRaw;
|
|
const abnormalRes = Array.isArray(abnormalRaw) ? abnormalRaw[0] : abnormalRaw;
|
|
|
const abnormalRawList =
|
|
const abnormalRawList =
|
|
@@ -457,8 +518,10 @@ async function fetchReportList() {
|
|
|
title: riskData
|
|
title: riskData
|
|
|
? `未来预警: ${entry?.weatherRisk || riskData.risk_name || "预警"}`
|
|
? `未来预警: ${entry?.weatherRisk || riskData.risk_name || "预警"}`
|
|
|
: "",
|
|
: "",
|
|
|
- desc: riskData?.explain_simple || riskData?.interact_explain || "",
|
|
|
|
|
- date: pickReportDate(riskData),
|
|
|
|
|
|
|
+ // 卡片简介:explain_simple
|
|
|
|
|
+ desc: riskData?.explain_simple || "",
|
|
|
|
|
+ // 日期:外层 current_time
|
|
|
|
|
+ date: formatReportDay(riskTime),
|
|
|
cover,
|
|
cover,
|
|
|
},
|
|
},
|
|
|
{
|
|
{
|
|
@@ -467,8 +530,10 @@ async function fetchReportList() {
|
|
|
title: stressData
|
|
title: stressData
|
|
|
? `当下胁迫: ${entry?.weatherStress || stressData.stress_name || "胁迫"}`
|
|
? `当下胁迫: ${entry?.weatherStress || stressData.stress_name || "胁迫"}`
|
|
|
: "",
|
|
: "",
|
|
|
- desc: stressData?.explain_simple || stressData?.interact_explain || "",
|
|
|
|
|
- date: pickReportDate(stressData),
|
|
|
|
|
|
|
+ // 卡片简介:explain_simple
|
|
|
|
|
+ desc: stressData?.explain_simple || "",
|
|
|
|
|
+ // 日期:外层 current_time
|
|
|
|
|
+ date: formatReportDay(stressTime),
|
|
|
cover,
|
|
cover,
|
|
|
},
|
|
},
|
|
|
].filter((item) => item.title || item.desc);
|
|
].filter((item) => item.title || item.desc);
|
|
@@ -481,14 +546,48 @@ async function fetchReportList() {
|
|
|
type: "abnormal_report",
|
|
type: "abnormal_report",
|
|
|
title: item.title || "异常农情诊断报告",
|
|
title: item.title || "异常农情诊断报告",
|
|
|
// 卡片简介:analysis[].desc
|
|
// 卡片简介:analysis[].desc
|
|
|
- desc:item.explain_simple ||"",
|
|
|
|
|
- cover: item.cover_url || cover,
|
|
|
|
|
- date: pickReportDate(item),
|
|
|
|
|
|
|
+ desc: item.explain_simple || "",
|
|
|
|
|
+ // cover_url 相对路径需拼 base_img_url2
|
|
|
|
|
+ cover: resolveCropQuestionImageUrl(item.cover_url) || cover,
|
|
|
|
|
+ // 异常报告日期:calc_date → 年月日
|
|
|
|
|
+ date: formatReportDay(item.calc_date),
|
|
|
}));
|
|
}));
|
|
|
|
|
|
|
|
reportList.value = [...baseList, ...abnormalList];
|
|
reportList.value = [...baseList, ...abnormalList];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 气象报告列表:weather_report_list → 卡片展示在诊断报告下方 */
|
|
|
|
|
+async function fetchWeatherReportList() {
|
|
|
|
|
+ const cover = resolveReportCover();
|
|
|
|
|
+ try {
|
|
|
|
|
+ const raw = await VE_API.questionnaire.weatherReportList({}).catch(() => null);
|
|
|
|
|
+ const res = Array.isArray(raw) ? raw[0] : raw;
|
|
|
|
|
+ if (Number(res?.code) !== 200) {
|
|
|
|
|
+ weatherReportList.value = [];
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const reports = Array.isArray(res?.data?.reports) ? res.data.reports : [];
|
|
|
|
|
+ weatherReportList.value = reports
|
|
|
|
|
+ .filter((item) => item && (item.id != null || item.explain_simple || item.risk_name))
|
|
|
|
|
+ .map((item) => ({
|
|
|
|
|
+ id: `weather-${item.id}`,
|
|
|
|
|
+ reportId: item.id,
|
|
|
|
|
+ type: "weather",
|
|
|
|
|
+ title: item.risk_name
|
|
|
|
|
+ ? `气象报告: ${item.risk_name}`
|
|
|
|
|
+ : item.crop_name
|
|
|
|
|
+ ? `气象报告: ${item.crop_name}`
|
|
|
|
|
+ : "气象报告",
|
|
|
|
|
+ desc: item.explain_simple || item.interact_explain || "",
|
|
|
|
|
+ date: formatReportDay(item.report_date),
|
|
|
|
|
+ // cover_url 相对路径需拼 base_img_url2
|
|
|
|
|
+ cover: resolveCropQuestionImageUrl(item.cover_url) || cover,
|
|
|
|
|
+ }));
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ weatherReportList.value = [];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const showUploadPopup = ref(false);
|
|
const showUploadPopup = ref(false);
|
|
|
const showCompleteFarmPopup = ref(false);
|
|
const showCompleteFarmPopup = ref(false);
|
|
|
// 后续由接口控制是否展示代管授权弹窗
|
|
// 后续由接口控制是否展示代管授权弹窗
|
|
@@ -782,6 +881,7 @@ async function loadPatrolContent() {
|
|
|
await fetchCropQuestionAlbumPic();
|
|
await fetchCropQuestionAlbumPic();
|
|
|
await fetchTmpAlbumImages();
|
|
await fetchTmpAlbumImages();
|
|
|
await fetchReportList();
|
|
await fetchReportList();
|
|
|
|
|
+ await fetchWeatherReportList();
|
|
|
await fetchCropArchiveList();
|
|
await fetchCropArchiveList();
|
|
|
await nextTick();
|
|
await nextTick();
|
|
|
bindZoneOverlays();
|
|
bindZoneOverlays();
|
|
@@ -1305,11 +1405,27 @@ watch(activeNav, (key) => {
|
|
|
margin-top: 4px;
|
|
margin-top: 4px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ &__head {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
&__title {
|
|
&__title {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ min-width: 0;
|
|
|
font-size: 16px;
|
|
font-size: 16px;
|
|
|
font-weight: 500;
|
|
font-weight: 500;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ &__day {
|
|
|
|
|
+ flex: none;
|
|
|
|
|
+ color: #9E9B9B;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
&__desc {
|
|
&__desc {
|
|
|
margin-top: 4px;
|
|
margin-top: 4px;
|
|
|
color: #9E9B9B;
|
|
color: #9E9B9B;
|