Quellcode durchsuchen

feat:修改农事档案页面样式UI和添加长势和异常页面

wangsisi vor 1 Woche
Ursprung
Commit
33b63f3f5b

BIN
src/assets/img/agricultural/interact-ref.png


BIN
src/assets/img/agricultural/patrol-guide.png


BIN
src/assets/img/agricultural/start.png


BIN
src/assets/img/agricultural/title-bg.png


+ 13 - 0
src/components/pageComponents/PhenologyTrackTimelineItem.vue

@@ -1,4 +1,5 @@
 <template>
+    <div v-if="yearText" class="track-year">{{ yearText }}</div>
     <template v-if="groupedList.length">
         <div class="phenology-track-item" v-for="group in groupedList" :key="group.date">
             <div class="track-axis">
@@ -41,6 +42,13 @@ const dataLoaded = ref(false);
 
 const sourceList = computed(() => (Array.isArray(props.list) ? props.list : imageList.value));
 
+const yearText = computed(() => {
+    if (!Array.isArray(props.list)) return "";
+    const item = props.list.find((entry) => entry?.date || entry?.latest_time);
+    const match = String(item?.date || item?.latest_time || "").match(/(\d{4})/);
+    return match ? t("agriFile.yearLabel", { year: match[1] }) : "";
+});
+
 function formatDate(value) {
     if (!value) return "";
     const text = String(value);
@@ -124,6 +132,11 @@ defineExpose({
 </script>
 
 <style scoped lang="scss">
+.track-year {
+    margin-bottom: 12px;
+    color: rgba(0, 0, 0, 0.4);
+}
+
 .track-empty {
     padding: 24px 0;
     text-align: center;

+ 18 - 4
src/i18n/messages.js

@@ -145,8 +145,8 @@ export default {
             farmLocation: "位置位置位置位置",
             moreFarms: "更多农场",
             patrolRecord: "巡园记录",
-            patrolGrowthTitle: "长势跟踪巡园要点 ({zone})",
-            patrolAbnormalTitle: "异常态势巡园要点 ({zone})",
+            patrolGrowthTitle: "长势跟踪巡园要点",
+            patrolAbnormalTitle: "异常态势巡园要点",
             patrolSubject: "某某主题",
             patrolIssue: "互动问题互动问题互动问题互动问题互",
             forward: "转发",
@@ -155,6 +155,13 @@ export default {
             interactReason: "互动原因互动原因",
             agriAssessment: "农情研判",
             agriAssessmentDesc: "互动原因互动原因互动原因互动原因互气象风险等互动原因互动原因互动原因互动原因互气象风险等",
+            interactQuestion: "互动问题",
+            interactQuestionText: "具体问题具体问题具体问题具体问题具体?",
+            ratioPlaceholder: "请输入比例",
+            submit: "提交",
+            referenceImage: "参考图片",
+            patrolGuide: "巡园向导",
+            growthAbnormal: "长势异常",
             uploadPhoto: "上传照片",
             agriAlbum: "农情相册",
             diagnosisReport: "诊断报告",
@@ -518,8 +525,8 @@ export default {
             farmLocation: "Location",
             moreFarms: "More farms",
             patrolRecord: "Patrol records",
-            patrolGrowthTitle: "Growth tracking patrol ({zone})",
-            patrolAbnormalTitle: "Abnormality patrol ({zone})",
+            patrolGrowthTitle: "Growth tracking patrol",
+            patrolAbnormalTitle: "Abnormality patrol",
             patrolSubject: "Subject",
             patrolIssue: "Interaction questions interaction questions",
             forward: "Forward",
@@ -528,6 +535,13 @@ export default {
             interactReason: "Interaction reason",
             agriAssessment: "Agri assessment",
             agriAssessmentDesc: "Interaction reason interaction reason meteorological risk, etc.",
+            interactQuestion: "Interactive question",
+            interactQuestionText: "Specific question specific question specific question?",
+            ratioPlaceholder: "Enter ratio",
+            submit: "Submit",
+            referenceImage: "Reference image",
+            patrolGuide: "Patrol guide",
+            growthAbnormal: "Growth abnormality",
             uploadPhoto: "Upload photo",
             agriAlbum: "Agri album",
             diagnosisReport: "Diagnosis report",

+ 349 - 377
src/views/old_mini/agri_file/index.vue

@@ -9,108 +9,106 @@
             </div>
         </div>
         <div class="content-panel">
-        <div v-show="activeNav === 'patrol'">
-            <div
-                v-for="item in patrolList"
-                :key="item.id"
-                class="tracking-item"
-                :class="`tracking-item--${item.theme}`"
-                @click="goGrowthTrack(item)"
-            >
-                <div class="tracking-item__header">
-                    <div class="tracking-item__header-row">
-                        <div class="tracking-item__header-left">
-                            <span class="tracking-item__level">
-                                <el-icon class="tracking-item__level-icon"><Bell /></el-icon>
-                                {{ item.level }}
-                            </span>
-                            <span class="tracking-item__title van-ellipsis">{{ item.title }}</span>
-                        </div>
-                        <div class="tracking-item__share" @click.stop>
-                            <el-icon><Right /></el-icon>
-                            <span>{{ t("agriFile.forward") }}</span>
+            <div v-show="activeNav === 'patrol'">
+                <div v-for="item in patrolList" :key="item.id" class="tracking-item"
+                    :class="`tracking-item--${item.theme}`" @click="goGrowthTrack(item)">
+                    <div class="tracking-item__header">
+                        <div class="tracking-item__header-row">
+                            <div class="tracking-item__header-left">
+                                <span class="tracking-item__level">
+                                    <el-icon><BellFilled /></el-icon>
+                                    {{ item.level }}
+                                </span>
+                                <span class="tracking-item__title van-ellipsis">
+                                    {{ item.title }}<span v-if="item.zone" class="tracking-item__zone"> ({{ item.zone }})</span>
+                                </span>
+                            </div>
+                            <div class="tracking-item__share" @click.stop>
+                                <Icon size="14" color="#2199F8" name="share" />
+                                <span>{{ t("agriFile.forward") }}</span>
+                            </div>
                         </div>
                     </div>
-                </div>
-                <div class="tracking-item__body">
-                    <div class="tracking-item__action">
-                        <div class="tracking-item__action-main">
-                            <div class="tracking-item__icon">
-                                <img :src="item.icon" alt="" />
-                                <span class="tracking-item__reason">{{ item.subject }}</span>
+                    <div class="tracking-item__body">
+                        <div class="tracking-item__action">
+                            <div class="tracking-item__action-main">
+                                <div class="tracking-item__icon">
+                                    <img :src="item.icon" alt="" />
+                                    <span class="tracking-item__reason">{{ item.subject }}</span>
+                                </div>
+                                <div class="tracking-item__issue">{{ item.issue }}</div>
+                            </div>
+                            <div class="tracking-item__btn" @click.stop="openUploadPopup">
+                                <el-icon>
+                                    <Plus />
+                                </el-icon>
+                                <span>{{ t("agriFile.uploadPhoto") }}</span>
                             </div>
-                            <div class="tracking-item__issue">{{ item.issue }}</div>
-                        </div>
-                        <div class="tracking-item__btn" @click.stop="openUploadPopup">
-                            <el-icon><Plus /></el-icon>
-                            <span>{{ t("agriFile.uploadPhoto") }}</span>
                         </div>
                     </div>
                 </div>
-            </div>
-            <div class="crop-archive">
-                <div class="crop-archive__title">{{ t("agriFile.cropArchive") }}</div>
-                <div class="crop-archive__year">{{ t("agriFile.yearLabel", { year: 2025 }) }}</div>
-                <PhenologyTrackTimelineItem :list="cropArchiveList" />
-            </div>
-        </div>
-        <div v-show="activeNav === 'album'">
-            <div class="map-card" @click="goAlbumMap">
-                <div ref="mapContainer" class="map-container"></div>
-                <div class="add-zone-btn" @click.stop="goAddZone">
-                    <el-icon>
-                        <Plus />
-                    </el-icon>
-                    <span>{{ t("agriFile.addZone") }}</span>
-                </div>
-                <div v-for="item in zoneList" :key="item.id" :ref="(el) => setMarkerEl(item.id, el)"
-                    class="zone-marker">
-                    <div class="zone-marker__label">{{ item.name }}</div>
-                    <div class="zone-marker__thumb">
-                        <img :src="item.cover" alt="" />
-                        <span class="zone-marker__badge">{{ item.count }}</span>
-                    </div>
-                    <div class="zone-marker__arrow"></div>
+                <div class="crop-archive">
+                    <div class="crop-archive__title">{{ t("agriFile.cropArchive") }}</div>
+                    <PhenologyTrackTimelineItem :list="cropArchiveList" />
                 </div>
             </div>
-            <div class="album-grid">
-                <div class="album-add">
-                    <el-icon class="album-add__icon">
-                        <Plus />
-                    </el-icon>
-                    <span>{{ t("agriFile.addAlbum") }}</span>
+            <div v-show="activeNav === 'album'">
+                <div class="map-card" @click="goAlbumMap">
+                    <div ref="mapContainer" class="map-container"></div>
+                    <div class="add-zone-btn" @click.stop="goAddZone">
+                        <el-icon>
+                            <Plus />
+                        </el-icon>
+                        <span>{{ t("agriFile.addZone") }}</span>
+                    </div>
+                    <div v-for="item in zoneList" :key="item.id" :ref="(el) => setMarkerEl(item.id, el)"
+                        class="zone-marker">
+                        <div class="zone-marker__label">{{ item.name }}</div>
+                        <div class="zone-marker__thumb">
+                            <img :src="item.cover" alt="" />
+                            <span class="zone-marker__badge">{{ item.count }}</span>
+                        </div>
+                        <div class="zone-marker__arrow"></div>
+                    </div>
                 </div>
-                <div v-for="item in albumList" :key="item.id" class="album-card">
-                    <div class="album-card__cover">
-                        <img :src="item.cover" alt="" />
-                        <span class="album-card__count">{{ t("agriFile.photoCount", { count: item.count }) }}</span>
-                        <div class="album-card__add">
-                            <el-icon>
-                                <Plus />
-                            </el-icon>
+                <div class="album-grid">
+                    <div class="album-add">
+                        <el-icon class="album-add__icon">
+                            <Plus />
+                        </el-icon>
+                        <span>{{ t("agriFile.addAlbum") }}</span>
+                    </div>
+                    <div v-for="item in albumList" :key="item.id" class="album-card">
+                        <div class="album-card__cover">
+                            <img :src="item.cover" alt="" />
+                            <span class="album-card__count">{{ t("agriFile.photoCount", { count: item.count }) }}</span>
+                            <div class="album-card__add">
+                                <el-icon>
+                                    <Plus />
+                                </el-icon>
+                            </div>
                         </div>
+                        <div class="album-card__name">{{ item.name }}</div>
                     </div>
-                    <div class="album-card__name">{{ item.name }}</div>
                 </div>
             </div>
-        </div>
-        <div v-show="activeNav === 'report'">
-            <div v-for="item in reportList" :key="item.id" class="report-card">
-                <div class="report-card__cover">
-                    <img :src="item.cover" alt="" />
-                    <span class="report-card__date">{{ item.date }}</span>
-                    <span class="report-card__status">
-                        <i class="report-card__dot"></i>
-                        {{ t("agriFile.reportUpdate") }}
-                    </span>
-                </div>
-                <div class="report-card__body">
-                    <div class="report-card__title">{{ item.title }}</div>
-                    <div class="report-card__desc">{{ item.desc }}</div>
+            <div v-show="activeNav === 'report'">
+                <div v-for="item in reportList" :key="item.id" class="report-card">
+                    <div class="report-card__cover">
+                        <img :src="item.cover" alt="" />
+                        <span class="report-card__date">{{ item.date }}</span>
+                        <span class="report-card__status">
+                            <i class="report-card__dot"></i>
+                            {{ t("agriFile.reportUpdate") }}
+                        </span>
+                    </div>
+                    <div class="report-card__body">
+                        <div class="report-card__title">{{ item.title }}</div>
+                        <div class="report-card__desc">{{ item.desc }}</div>
+                    </div>
                 </div>
             </div>
         </div>
-        </div>
         <album-upload-popup v-model:show="showUploadPopup" />
     </div>
 </template>
@@ -119,9 +117,9 @@
 import { computed, nextTick, onActivated, onBeforeUnmount, onMounted, ref, watch } from "vue";
 import { useStore } from "vuex";
 import { useRouter } from "vue-router";
-import { Switch, Plus, Bell, Right } from "@element-plus/icons-vue";
 import Overlay from "ol/Overlay";
 import { useI18n } from "@/i18n";
+import { Icon } from 'vant';
 import FileMap from "./fileMap";
 import * as util from "@/common/ol_common.js";
 import farmHeader from "@/components/farmHeader.vue";
@@ -184,21 +182,23 @@ const showUploadPopup = ref(false);
 const patrolList = ref([
     {
         id: 1,
+        type: "growth",
         theme: "blue",
         level: "",
         title: "",
         subject: "",
         issue: "",
-        icon: require("@/assets/img/report/yc-icon.png"),
+        icon: require("@/assets/img/report/wh-icon.png"),
     },
     {
         id: 2,
+        type: "abnormal",
         theme: "blue",
         level: "",
         title: "",
         subject: "",
         issue: "",
-        icon: require("@/assets/img/report/bh-icon.png"),
+        icon: require("@/assets/img/report/wh-icon.png"),
     },
 ]);
 
@@ -276,7 +276,8 @@ const fillMockLabels = () => {
     patrolList.value = patrolList.value.map((item, index) => ({
         ...item,
         level: t("agriFile.riskLevel2"),
-        title: t(index === 0 ? "agriFile.patrolGrowthTitle" : "agriFile.patrolAbnormalTitle", { zone: albumName }),
+        title: t(index === 0 ? "agriFile.patrolGrowthTitle" : "agriFile.patrolAbnormalTitle"),
+        zone: albumName,
         subject: t("agriFile.patrolSubject"),
         issue: t("agriFile.patrolIssue"),
     }));
@@ -298,7 +299,7 @@ const goAlbumMap = () => {
 const goGrowthTrack = (item) => {
     router.push({
         path: "/growth_track",
-        query: { id: item?.id },
+        query: { id: item?.id, type: item?.type || "growth" },
     });
 };
 
@@ -339,7 +340,7 @@ watch(activeNav, (key) => {
         display: flex;
         justify-content: space-around;
         padding: 10px 10px;
-        margin-bottom: 0;
+        margin-bottom: 10px;
 
         .nav-card {
             position: relative;
@@ -461,352 +462,323 @@ watch(activeNav, (key) => {
                 border-top: 6px solid #fff;
             }
         }
-    }
-
-    .add-zone-btn {
-        position: absolute;
-        right: 5px;
-        bottom: 10px;
-        z-index: 5;
-        display: flex;
-        align-items: center;
-        gap: 2px;
-        padding: 5px 10px;
-        border-radius: 4px;
-        background: #fff;
-        color: #2199F8;
-        font-weight: 500;
-    }
-
-    .album-grid {
-        display: grid;
-        grid-template-columns: 1fr 1fr;
-        gap: 16px;
-        margin-top: 16px;
-        box-sizing: border-box;
 
-        .album-add {
-            align-self: start;
+        .add-zone-btn {
+            position: absolute;
+            right: 5px;
+            bottom: 10px;
+            z-index: 5;
             display: flex;
-            flex-direction: column;
             align-items: center;
-            justify-content: center;
-            width: 100%;
-            aspect-ratio: 1;
-            border-radius: 5px;
-            background: #F5F5F7;
-            color: #969494;
-            font-size: 16px;
+            gap: 2px;
+            padding: 5px 10px;
+            border-radius: 4px;
+            background: #fff;
+            color: #2199F8;
+            font-weight: 500;
+        }
 
-            &__icon {
-                margin-bottom: 6px;
-                font-size: 20px;
+        .album-grid {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 16px;
+            margin-top: 16px;
+            box-sizing: border-box;
+
+            .album-add {
+                align-self: start;
+                display: flex;
+                flex-direction: column;
+                align-items: center;
+                justify-content: center;
+                width: 100%;
+                aspect-ratio: 1;
+                border-radius: 5px;
+                background: #F5F5F7;
+                color: #969494;
+                font-size: 16px;
+
+                &__icon {
+                    margin-bottom: 6px;
+                    font-size: 20px;
+                }
+            }
+
+            .album-card {
+                width: 100%;
+
+                &__cover {
+                    position: relative;
+                    width: 100%;
+                    aspect-ratio: 1;
+
+                    img {
+                        width: 100%;
+                        height: 100%;
+                        object-fit: cover;
+                        border-radius: 6px;
+                    }
+                }
+
+                &__count {
+                    position: absolute;
+                    top: 1px;
+                    right: 0;
+                    padding: 1px 5px;
+                    border-radius: 0 5px 0 5px;
+                    background: rgba(0, 0, 0, 0.4);
+                    backdrop-filter: blur(4px);
+                    color: #fff;
+                }
+
+                &__add {
+                    position: absolute;
+                    right: 8px;
+                    bottom: 8px;
+                    z-index: 1;
+                    display: flex;
+                    align-items: center;
+                    justify-content: center;
+                    width: 44px;
+                    height: 44px;
+                    border-radius: 50%;
+                    background: #2199F8;
+                    color: #fff;
+                    font-size: 20px;
+                    box-shadow: 0 2px 8px rgba(33, 153, 248, 0.35);
+                }
+
+                &__name {
+                    margin-top: 10px;
+                    color: #1F1F1F;
+                }
             }
         }
 
-        .album-card {
-            width: 100%;
+        .report-card {
+            margin-bottom: 10px;
+            border-radius: 8px;
+            background: #fff;
+
+            &:last-child {
+                margin-bottom: 0;
+            }
 
             &__cover {
                 position: relative;
                 width: 100%;
-                aspect-ratio: 1;
+                height: 158px;
+
                 img {
+                    display: block;
                     width: 100%;
                     height: 100%;
                     object-fit: cover;
-                    border-radius: 6px;
+                    border-radius: 5px;
                 }
             }
 
-            &__count {
+            &__date {
                 position: absolute;
-                top: 1px;
-                right: 0;
-                padding: 1px 5px;
-                border-radius: 0 5px 0 5px;
-                background: rgba(0, 0, 0, 0.4);
+                top: 0;
+                padding: 5px 12px;
+                border-radius: 4px;
+                background: rgba(0, 0, 0, 0.45);
                 backdrop-filter: blur(4px);
                 color: #fff;
+                font-size: 16px;
+                border-radius: 5px 0 5px 0;
             }
 
-            &__add {
+            &__status {
                 position: absolute;
-                right: 8px;
-                bottom: 8px;
-                z-index: 1;
+                top: 10px;
+                right: 0;
                 display: flex;
                 align-items: center;
-                justify-content: center;
-                width: 44px;
-                height: 44px;
-                border-radius: 50%;
-                background: #2199F8;
+                gap: 4px;
+                padding: 2px 13px;
+                border-radius: 20px 0 0 20px;
+                background: #FF5454;
                 color: #fff;
-                font-size: 20px;
-                box-shadow: 0 2px 8px rgba(33, 153, 248, 0.35);
+                font-size: 12px;
             }
 
-            &__name {
-                margin-top: 10px;
-                color: #1F1F1F;
+            &__dot {
+                width: 6px;
+                height: 6px;
+                border-radius: 50%;
+                background: #fff;
             }
-        }
-    }
-
-    .report-card {
-        overflow: hidden;
-        margin-bottom: 12px;
-        border-radius: 12px;
-        background: #fff;
-
-        &:last-child {
-            margin-bottom: 0;
-        }
-
-        &__cover {
-            position: relative;
-            width: 100%;
-            height: 148px;
 
-            img {
-                display: block;
-                width: 100%;
-                height: 100%;
-                object-fit: cover;
+            &__body {
+                padding: 10px;
+                margin-top: 4px;
             }
-        }
 
-        &__date {
-            position: absolute;
-            top: 8px;
-            left: 8px;
-            padding: 2px 8px;
-            border-radius: 4px;
-            background: rgba(0, 0, 0, 0.45);
-            color: #fff;
-            font-size: 12px;
-            line-height: 18px;
-        }
-
-        &__status {
-            position: absolute;
-            top: 8px;
-            right: 8px;
-            display: flex;
-            align-items: center;
-            gap: 4px;
-            padding: 2px 8px 2px 6px;
-            border-radius: 20px;
-            background: #FF4D4F;
-            color: #fff;
-            font-size: 12px;
-            line-height: 18px;
-        }
-
-        &__dot {
-            width: 6px;
-            height: 6px;
-            border-radius: 50%;
-            background: #fff;
-        }
-
-        &__body {
-            padding: 10px 12px 12px;
-        }
-
-        &__title {
-            color: #1F1F1F;
-            font-size: 16px;
-            font-weight: 600;
-            line-height: 22px;
-        }
+            &__title {
+                font-size: 16px;
+                font-weight: 500;
+            }
 
-        &__desc {
-            margin-top: 6px;
-            color: rgba(0, 0, 0, 0.45);
-            font-size: 13px;
-            line-height: 20px;
+            &__desc {
+                margin-top: 4px;
+                color: #9E9B9B;
+            }
         }
-    }
 
-    .tracking-item {
-        width: 100%;
-        margin-bottom: 12px;
-        border: 1px solid #fff;
-        border-radius: 10px;
-        box-shadow: 0 4px 4px 0 var(--tracking-shadow);
-        cursor: pointer;
+        .tracking-item {
+            width: 100%;
+            margin-bottom: 16px;
+            box-shadow: 0px 4px 4px 0px rgba(33, 153, 248, 0.1);
 
-        &:last-of-type {
-            margin-bottom: 0;
-        }
 
-        &--blue {
-            --tracking-header-bg: linear-gradient(90deg, #5BB8FF 0%, #2199F8 100%);
-            --tracking-primary: #2199f8;
-            --tracking-action-border: rgba(33, 153, 248, 0.2);
-            --tracking-shadow: #2199f81a;
-        }
+            &:last-of-type {
+                margin-bottom: 0;
+            }
 
-        &__header {
-            position: relative;
-            padding: 10px 10px 18px;
-            border-radius: 10px 10px 0 0;
-            background: var(--tracking-header-bg);
-        }
+            &__header {
+                position: relative;
+                padding: 10px 10px 20px;
+                border-radius: 10px 10px 0 0;
+                background: linear-gradient(180deg, #86CAFF 0%, #2199F8 48.5%);
+            }
 
-        &__header-row {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            gap: 8px;
-        }
+            &__header-row {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+            }
 
-        &__header-left {
-            display: flex;
-            align-items: center;
-            min-width: 0;
-            gap: 6px;
-        }
+            &__header-left {
+                display: flex;
+                align-items: center;
+                gap: 5px;
+            }
 
-        &__level {
-            display: flex;
-            align-items: center;
-            flex-shrink: 0;
-            gap: 2px;
-            padding: 1px 8px;
-            border-radius: 20px;
-            background: #fff;
-            color: #FF6A6A;
-            font-size: 12px;
-        }
+            &__level {
+                display: flex;
+                align-items: center;
+                gap: 4px;
+                padding: 1px 4px;
+                border-radius: 2px;
+                background: #fff;
+                color: #FF6A6A;
+                font-size: 12px;
+            }
 
-        &__level-icon {
-            font-size: 12px;
-        }
+            &__title {
+                color: #fff;
+                font-size: 16px;
+                font-weight: 500;
+            }
 
-        &__title {
-            min-width: 0;
-            color: #fff;
-            font-size: 15px;
-            font-weight: 500;
-        }
+            &__zone {
+                font-size: 12px;
+            }
 
-        &__share {
-            display: flex;
-            align-items: center;
-            flex-shrink: 0;
-            gap: 2px;
-            padding: 3px 10px;
-            border-radius: 16px;
-            background: #fff;
-            color: #2199F8;
-            font-size: 12px;
-        }
+            &__share {
+                display: flex;
+                align-items: center;
+                gap: 4px;
+                padding: 2px 10px;
+                border-radius: 25px;
+                background: #fff;
+                color: #2199F8;
+                font-size: 12px;
+            }
 
-        &__body {
-            position: relative;
-            padding: 14px 10px 10px;
-            margin-top: -8px;
-            border-radius: 10px;
-            background: #fff;
+            &__body {
+                position: relative;
+                padding: 10px;
+                margin-top: -8px;
+                border-radius: 10px;
+                background: #fff;
 
-            &::before {
-                content: "";
-                position: absolute;
-                top: -7px;
-                left: 50%;
-                width: 0;
-                height: 0;
-                border-left: 7px solid transparent;
-                border-right: 7px solid transparent;
-                border-bottom: 7px solid #fff;
-                transform: translateX(-50%);
+                &::before {
+                    content: "";
+                    position: absolute;
+                    top: -7px;
+                    left: 21%;
+                    width: 0;
+                    height: 0;
+                    border-left: 7px solid transparent;
+                    border-right: 7px solid transparent;
+                    border-bottom: 7px solid #fff;
+                    transform: translateX(-50%);
+                }
             }
-        }
 
-        &__action {
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            gap: 8px;
-        }
+            &__action {
+                display: flex;
+                align-items: center;
+                justify-content: space-between;
+                border: 1px solid rgba(33, 153, 248, 0.2);
+                border-radius: 6px;
+                padding: 8px;
+            }
 
-        &__action-main {
-            min-width: 0;
-            flex: 1;
-        }
+            &__icon {
+                display: flex;
+                align-items: center;
+                gap: 5px;
 
-        &__icon {
-            display: flex;
-            align-items: center;
-            gap: 4px;
+                img {
+                    width: 18px;
+                    height: 16px;
+                }
+            }
 
-            img {
-                width: 18px;
-                height: 16px;
+            &__reason {
+                color: #2199f8;
+                font-weight: 500;
             }
-        }
 
-        &__reason {
-            color: var(--tracking-primary);
-            font-weight: 500;
-        }
+            &__issue {
+                margin-top: 2px;
+                color: #2199f8;
+                font-size: 12px;
+            }
 
-        &__issue {
-            margin-top: 4px;
-            color: var(--tracking-primary);
-            font-size: 12px;
-            line-height: 17px;
+            &__btn {
+                display: flex;
+                align-items: center;
+                gap: 2px;
+                padding: 7px 10px;
+                border-radius: 5px;
+                background: #2199f8;
+                color: #fff;
+                font-size: 12px;
+            }
         }
 
-        &__btn {
-            display: flex;
-            align-items: center;
-            flex-shrink: 0;
-            gap: 2px;
-            padding: 8px 10px;
-            border-radius: 6px;
-            background: var(--tracking-primary);
-            color: #fff;
-            font-size: 13px;
-        }
-    }
+        .crop-archive {
+            padding: 10px;
+            border-radius: 10px;
+            background: #fff;
 
-    .crop-archive {
-        margin-top: 16px;
-        padding: 16px 12px;
-        border-radius: 12px;
-        background: #fff;
+            &__title {
+                position: relative;
+                display: inline-block;
+                z-index: 1;
+                font-size: 16px;
+                font-weight: 500;
+                margin-bottom: 5px;
 
-        &__title {
-            position: relative;
-            display: inline-block;
-            z-index: 1;
-            color: #1F1F1F;
-            font-size: 16px;
-            font-weight: 600;
-            line-height: 22px;
-
-            &::after {
-                content: "";
-                position: absolute;
-                left: 0;
-                bottom: 2px;
-                z-index: -1;
-                width: 2em;
-                height: 6px;
-                border-radius: 2px;
-                background: rgba(91, 184, 255, 0.55);
+                &::after {
+                    content: "";
+                    position: absolute;
+                    left: 0;
+                    bottom: 2px;
+                    z-index: -1;
+                    width: 90px;
+                    height: 6px;
+                    border-radius: 25px;
+                    background: linear-gradient(90deg, #2199f8 0%, rgba(255, 255, 255, 0.37) 100%);
+                    opacity: 0.4; 
+                }
             }
         }
-
-        &__year {
-            margin: 4px 0 12px;
-            color: rgba(0, 0, 0, 0.45);
-            font-size: 12px;
-        }
     }
 }
 </style>

+ 394 - 23
src/views/old_mini/agri_file/pages/growthTrack.vue

@@ -1,6 +1,7 @@
 <template>
     <div class="growth-track-page">
         <custom-header :name="t('agriFile.workName')" />
+        <div class="growth-track-body">
         <div class="growth-hero">
             <div class="growth-hero__top">
                 <div class="growth-hero__main">
@@ -24,37 +25,126 @@
                 </div>
             </div>
         </div>
+        <template v-if="!isAbnormal">
         <div class="growth-content">
             <div class="growth-content__title">{{ t("agriFile.agriAssessment") }}</div>
             <div class="growth-content__desc">{{ t("agriFile.agriAssessmentDesc") }}</div>
         </div>
+        <div class="interact-card">
+            <div class="interact-card__head">
+                <div class="interact-card__tab">
+                    <img class="interact-card__star" src="@/assets/img/agricultural/start.png" alt="" />
+                    <span>{{ t("agriFile.interactQuestion") }}</span>
+                </div>
+            </div>
+            <div class="interact-card__qa">
+                <div class="interact-card__question">{{ t("agriFile.interactQuestionText") }}</div>
+                <div class="interact-card__row">
+                    <div class="interact-card__input">
+                        <input
+                            v-model="ratio"
+                            type="number"
+                            inputmode="decimal"
+                            :placeholder="t('agriFile.ratioPlaceholder')"
+                        />
+                        <span>%</span>
+                    </div>
+                    <div class="interact-card__submit" @click="handleSubmit">{{ t("agriFile.submit") }}</div>
+                </div>
+            </div>
+            <div class="interact-card__ref">
+                <span class="interact-card__ref-label">{{ t("agriFile.referenceImage") }}</span>
+                <img class="interact-card__ref-img" src="@/assets/img/agricultural/interact-ref.png" alt="" />
+            </div>
+        </div>
+        <div class="guide-card">
+            <div class="guide-card__title">{{ t("agriFile.patrolGuide") }}</div>
+            <div class="guide-card__upload" @click="showUploadPopup = true">
+                <el-icon class="guide-card__upload-icon"><Plus /></el-icon>
+                <span>{{ t("agriFile.uploadPhoto") }}</span>
+            </div>
+            <img class="guide-card__img" src="@/assets/img/agricultural/patrol-guide.png" alt="" />
+        </div>
+        </template>
+        <div v-else class="situation-card">
+            <div class="situation-card__head">
+                <span class="situation-card__icon">
+                    <svg viewBox="0 0 32 32" aria-hidden="true">
+                        <circle cx="16" cy="16" r="16" fill="#2199F8" />
+                        <path
+                            fill="#fff"
+                            d="M16 6.5c-1.1 0-2 .8-2 1.9v1.1c-2.6.7-4.5 3-4.5 5.7V18h13v-2.8c0-2.7-1.9-5-4.5-5.7V8.4c0-1.1-.9-1.9-2-1.9zm-7 13.2h14c.4 1.4.7 2.3.7 2.3H8.3s.3-.9.7-2.3zM11 23.5h10c0 .8-.9 1.5-2.1 1.5h-5.8c-1.2 0-2.1-.7-2.1-1.5z"
+                        />
+                    </svg>
+                </span>
+                <span class="situation-card__name">{{ t("agriFile.growthAbnormal") }}</span>
+            </div>
+            <div class="situation-card__assess">
+                <div class="situation-card__assess-title">{{ t("agriFile.agriAssessment") }}</div>
+                <div class="situation-card__assess-desc">{{ t("agriFile.agriAssessmentDesc") }}</div>
+            </div>
+            <div class="situation-card__guide">
+                <div class="situation-card__guide-title">{{ t("agriFile.patrolGuide") }}</div>
+                <div class="situation-card__guide-box">
+                    <img src="@/assets/img/agricultural/patrol-guide.png" alt="" />
+                </div>
+            </div>
+        </div>
+        </div>
+        <album-upload-popup v-model:show="showUploadPopup" />
     </div>
 </template>
 
 <script setup>
-import { computed } from "vue";
-import { Bell, Right } from "@element-plus/icons-vue";
+import { computed, ref } from "vue";
+import { useRoute } from "vue-router";
+import { Bell, Right, Plus } from "@element-plus/icons-vue";
+import { ElMessage } from "element-plus";
 import customHeader from "@/components/customHeader.vue";
+import albumUploadPopup from "../components/albumUploadPopup.vue";
 import { useI18n } from "@/i18n";
 
 const { t } = useI18n();
+const route = useRoute();
 
+const isAbnormal = computed(() => route.query.type === "abnormal");
 const theme = computed(() => t("agriFile.interactTheme"));
 const level = computed(() => t("agriFile.riskLevel2"));
 const reason = computed(() => t("agriFile.interactReason"));
 const zoneName = computed(() => t("agriFile.zoneOne"));
+const ratio = ref("");
+const showUploadPopup = ref(false);
+
+const handleSubmit = () => {
+    if (ratio.value === "" || ratio.value == null) {
+        ElMessage.warning(t("agriFile.ratioPlaceholder"));
+        return;
+    }
+    ElMessage.success(t("agriFile.submit"));
+};
 </script>
 
 <style lang="scss" scoped>
 .growth-track-page {
+    display: flex;
+    flex-direction: column;
     width: 100%;
-    min-height: 100vh;
+    height: 100vh;
+    overflow: hidden;
     background: #f5f5f5;
 
+    .growth-track-body {
+        flex: 1;
+        min-height: 0;
+        overflow-y: auto;
+        -webkit-overflow-scrolling: touch;
+        padding-bottom: 16px;
+    }
+
     .growth-hero {
-        flex-shrink: 0;
-        padding: 14px 12px 28px;
+        padding: 18px 0 28px 10px;
         background: #2199f8;
+        color: #fff;
 
         &__top {
             display: flex;
@@ -63,30 +153,22 @@ const zoneName = computed(() => t("agriFile.zoneOne"));
             gap: 10px;
         }
 
-        &__main {
-            min-width: 0;
-            flex: 1;
-        }
-
         &__title-row {
             display: flex;
-            flex-wrap: wrap;
             align-items: center;
-            gap: 6px;
+            gap: 10px;
         }
 
         &__title {
-            color: #fff;
-            font-size: 20px;
-            font-weight: 600;
-            line-height: 28px;
+            font-size: 28px;
+            font-family: "PangMenZhengDao";
+            margin-top: -5px;
         }
 
         &__tag {
             display: inline-flex;
             align-items: center;
-            flex-shrink: 0;
-            gap: 2px;
+            gap: 8px;
             height: 20px;
             padding: 0 8px;
             border-radius: 20px;
@@ -109,12 +191,9 @@ const zoneName = computed(() => t("agriFile.zoneOne"));
 
         &__reason {
             margin-top: 10px;
-            padding: 6px 8px;
+            padding: 4px 10px;
             border-radius: 4px;
-            background: rgba(255, 255, 255, 0.16);
-            color: #fff;
-            font-size: 13px;
-            line-height: 20px;
+            background: linear-gradient(90deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0) 100%);
         }
 
         &__share {
@@ -153,5 +232,297 @@ const zoneName = computed(() => t("agriFile.zoneOne"));
             line-height: 20px;
         }
     }
+
+    .interact-card {
+        margin: 0 10px 16px;
+        overflow: hidden;
+        border: 1px solid rgba(33, 153, 248, 0.5);
+        border-radius: 12px;
+        background: #fff;
+
+        &__head {
+            position: relative;
+            min-height: 36px;
+            background: linear-gradient(180deg, #e5f4ff 0%, #ffffff 72%);
+        }
+
+        &__tab {
+            display: inline-flex;
+            align-items: center;
+            isolation: isolate;
+            gap: 6px;
+            height: 36px;
+            padding: 0 28px 4px 12px;
+            color: #fff;
+            font-size: 15px;
+            font-weight: 600;
+            line-height: 1;
+            background: url("@/assets/img/agricultural/title-bg.png") no-repeat center / 100% 100%;
+        }
+
+        &__star {
+            width: 16px;
+            height: 14px;
+            object-fit: contain;
+            mix-blend-mode: screen;
+        }
+
+        &__qa {
+            margin: 10px 10px 0;
+            padding: 12px 10px;
+            border-radius: 8px;
+            background: #e8f5ff;
+        }
+
+        &__question {
+            color: #1f1f1f;
+            font-size: 14px;
+            font-weight: 600;
+            line-height: 20px;
+        }
+
+        &__row {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+            margin-top: 10px;
+        }
+
+        &__input {
+            display: flex;
+            align-items: center;
+            flex: 1;
+            min-width: 0;
+            height: 36px;
+            padding: 0 10px;
+            border: 1px solid #dcdfe6;
+            border-radius: 6px;
+            background: #fff;
+
+            input {
+                flex: 1;
+                min-width: 0;
+                border: none;
+                outline: none;
+                color: #333;
+                font-size: 13px;
+                background: transparent;
+
+                &::placeholder {
+                    color: #c0c4cc;
+                }
+
+                &::-webkit-outer-spin-button,
+                &::-webkit-inner-spin-button {
+                    appearance: none;
+                    margin: 0;
+                }
+            }
+
+            span {
+                flex-shrink: 0;
+                color: #999;
+                font-size: 13px;
+            }
+        }
+
+        &__submit {
+            flex-shrink: 0;
+            height: 36px;
+            padding: 0 16px;
+            border-radius: 6px;
+            background: #2199f8;
+            color: #fff;
+            font-size: 14px;
+            line-height: 36px;
+            text-align: center;
+        }
+
+        &__ref {
+            position: relative;
+            margin: 12px 10px 10px;
+            overflow: hidden;
+            border-radius: 8px;
+        }
+
+        &__ref-label {
+            position: absolute;
+            top: 8px;
+            left: 8px;
+            z-index: 1;
+            padding: 2px 8px;
+            border-radius: 10px;
+            background: rgba(60, 60, 60, 0.72);
+            color: #fff;
+            font-size: 11px;
+            line-height: 16px;
+        }
+
+        &__ref-img {
+            display: block;
+            width: 100%;
+        }
+    }
+
+    .guide-card {
+        position: relative;
+        margin: 0 10px 16px;
+        padding: 14px 12px 12px;
+        overflow: visible;
+        border-radius: 12px;
+        background: #fff;
+
+        &__title {
+            position: relative;
+            z-index: 1;
+            display: inline-block;
+            color: #1f1f1f;
+            font-size: 16px;
+            font-weight: 600;
+            line-height: 22px;
+
+            &::after {
+                content: "";
+                position: absolute;
+                left: 0;
+                bottom: 1px;
+                z-index: -1;
+                width: 64px;
+                height: 6px;
+                border-radius: 2px;
+                background: linear-gradient(90deg, #7cc5ff 0%, rgba(124, 197, 255, 0) 100%);
+            }
+        }
+
+        &__upload {
+            position: absolute;
+            top: 8px;
+            right: 12px;
+            z-index: 2;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            width: 72px;
+            height: 72px;
+            border-radius: 50%;
+            background: #2199f8;
+            color: #fff;
+            box-shadow: 0 4px 12px rgba(33, 153, 248, 0.35);
+        }
+
+        &__upload-icon {
+            font-size: 22px;
+            font-weight: 600;
+        }
+
+        &__upload span {
+            margin-top: 2px;
+            font-size: 11px;
+            line-height: 14px;
+        }
+
+        &__img {
+            display: block;
+            width: 100%;
+            margin-top: 8px;
+        }
+    }
+
+    .situation-card {
+        position: relative;
+        z-index: 1;
+        margin: -16px 0 0;
+        padding: 16px 12px 20px;
+        min-height: calc(100% + 16px);
+        border-radius: 16px 16px 0 0;
+        background: #fff;
+
+        &__head {
+            display: flex;
+            align-items: center;
+            gap: 8px;
+            padding-bottom: 12px;
+            border-bottom: 1px solid #eee;
+        }
+
+        &__icon {
+            display: flex;
+            width: 22px;
+            height: 22px;
+
+            svg {
+                display: block;
+                width: 100%;
+                height: 100%;
+            }
+        }
+
+        &__name {
+            color: #2199f8;
+            font-size: 16px;
+            font-weight: 600;
+            line-height: 22px;
+        }
+
+        &__assess {
+            margin-top: 12px;
+            padding: 12px;
+            border-radius: 8px;
+            background: #f7f7f7;
+        }
+
+        &__assess-title {
+            color: #1f1f1f;
+            font-size: 15px;
+            font-weight: 600;
+            line-height: 22px;
+        }
+
+        &__assess-desc {
+            margin-top: 8px;
+            color: rgba(0, 0, 0, 0.45);
+            font-size: 13px;
+            line-height: 20px;
+        }
+
+        &__guide {
+            margin-top: 16px;
+        }
+
+        &__guide-title {
+            position: relative;
+            z-index: 1;
+            display: inline-block;
+            color: #1f1f1f;
+            font-size: 16px;
+            font-weight: 600;
+            line-height: 22px;
+
+            &::after {
+                content: "";
+                position: absolute;
+                left: 0;
+                bottom: 1px;
+                z-index: -1;
+                width: 64px;
+                height: 6px;
+                border-radius: 2px;
+                background: linear-gradient(90deg, #7cc5ff 0%, rgba(124, 197, 255, 0) 100%);
+            }
+        }
+
+        &__guide-box {
+            margin-top: 10px;
+            overflow: hidden;
+            border: 1px solid #ddecff;
+            border-radius: 8px;
+
+            img {
+                display: block;
+                width: 100%;
+            }
+        }
+    }
 }
 </style>