Procházet zdrojové kódy

feat:修改首页和农场监测页面

wangsisi před 3 dny
rodič
revize
b0eb5b1d16

+ 4 - 4
src/App.vue

@@ -22,7 +22,7 @@
 
     <Tabbar class="tabbar" route fixed v-show="showTab" active-color="#2199F8" inactive-color="#898989">
         <tabbar-item replace to="/home" v-if="curRole == 0">
-            <span>农场监测</span>
+            <span>首页</span>
             <template #icon="props">
                 <img
                     :src="
@@ -58,8 +58,8 @@
                 />
             </template>
         </tabbar-item>
-        <tabbar-item replace to="/plan" v-if="curRole == 0">
-            <span>农事方案</span>
+        <tabbar-item replace to="/monitor" v-if="curRole == 0">
+            <span>农场监测</span>
             <template #icon="props">
                 <img
                     :src="
@@ -83,7 +83,7 @@
             </template>
         </tabbar-item>
         <tabbar-item replace to="/agri_services" v-if="curRole == 0">
-            <span>农事管理</span>
+            <span>农事服务</span>
             <template #icon="props">
                 <img
                     :src="

binární
src/assets/img/home/banner.png


binární
src/assets/img/home/create-farm-icon.png


binární
src/assets/img/home/farm-bg-1.png


binární
src/assets/img/home/farm-bg-2.png


binární
src/assets/img/home/farm-bg-3.png


binární
src/assets/img/monitor/bell.png


binární
src/assets/img/monitor/grid-1.png


binární
src/assets/img/monitor/grid-2.png


binární
src/assets/img/monitor/grid-3.png


binární
src/assets/img/monitor/grid-4.png


binární
src/assets/img/monitor/notice.png


binární
src/assets/img/monitor/speaker.png


binární
src/assets/img/tab_bar/farm-active.png


binární
src/assets/img/tab_bar/farm.png


binární
src/assets/img/tab_bar/home-active.png


binární
src/assets/img/tab_bar/home.png


+ 38 - 33
src/components/weatherInfo.vue

@@ -1,15 +1,15 @@
 <template>
-    <div class="weather-info" :class="{ expanded: isExpanded }">
+    <div class="weather-info" :class="{ expanded: isExpanded, 'is-garden': isGarden ,'bg-white': isWhite}">
         <div class="header flex-center">
             <div class="header-left">
-                <!-- <div class="address flex-center">
+                <div class="address flex-center" v-if="!isGarden">
                     <el-icon class="address-icon"><Location /></el-icon>
                     <span class="address-text">广州市番禺区</span>
-                </div> -->
-                <div class="address-select flex-center">
+                </div>
+                <div class="address-select flex-center" v-else>
                     <el-dropdown class="select-garden" trigger="click" popper-class="select-garden-popper">
                         <div class="el-dropdown-link flex-center">
-                            <span :class="farmName === '从化荔博园' ? 'ellipsis-l1' : ''">{{ farmName }}</span>
+                            <span :class="farmName === '从化荔博园' ? 'ellipsis-l1' : ''">广州市番禺区</span>
                             <div class="default-text" v-show="farmName === '从化荔博园'">默认</div>
                             <el-icon class="el-icon--right"><arrow-down /></el-icon>
                         </div>
@@ -26,9 +26,7 @@
                             </el-dropdown-menu>
                         </template>
                     </el-dropdown>
-                    <el-select class="select-plan" v-model="planValue" size="small">
-                        <el-option v-for="item in planList" :key="item.id" :label="item.name" :value="item.id" />
-                    </el-select>
+                    <div class="add-garden">新增农场</div>
                 </div>
                 <div class="temperature flex-center">
                     <div class="temperature-number">26</div>
@@ -60,6 +58,12 @@ import { onMounted, ref } from "vue";
 import weatherChart from "./weatherChart.vue";
 import { useStore } from "vuex";
 const store = useStore();
+const props = defineProps({
+    isGarden: {
+        type: Boolean,
+        default: false
+    }
+});
 // 定义emit事件
 const emit = defineEmits(['weatherExpanded']);
 
@@ -68,8 +72,11 @@ const handleCommand = (command) => {
 };
 
 const isExpanded = ref(false);
-
+const isWhite = ref(false);
 const toggleExpand = () => {
+    if(props.isGarden){
+        isWhite.value = !isWhite.value;
+    }
     isExpanded.value = !isExpanded.value;
     emit('weatherExpanded',isExpanded.value);
 };
@@ -77,7 +84,7 @@ const toggleExpand = () => {
 const miniUserId = store.state.home.miniUserId;
 
 onMounted(() => {
-    getFarmList()
+    // getFarmList()
 });
 
 const farmId = ref(null);
@@ -91,16 +98,6 @@ function getFarmList() {
         farmName.value = data[0].name
         farmId.value = data[0].organId
         containerId.value = data[0].containerId
-        getPlanList()
-    })
-}
-
-// 获取方案列表
-const planValue = ref("");
-const planList = ref([]);
-function getPlanList() {
-    VE_API.home.listByFarmIdAndContainerId({farmId: farmId.value, containerId: containerId.value}).then(({data}) => {
-        planList.value = data || []
     })
 }
 </script>
@@ -120,6 +117,16 @@ function getPlanList() {
         height: 312px;
     }
 
+    &.is-garden {
+        border-radius: 0;
+        background-image: none;
+    }
+
+    &.bg-white{
+        border-radius: 14px;
+        background-image: linear-gradient(90deg, #e2f1fe 0%, #ffffff 80%);
+    }
+
     .flex-center {
         display: flex;
         align-items: center;
@@ -153,25 +160,23 @@ function getPlanList() {
                         }
                     }
                 }
-                .select-plan {
-                    width: 94px;
-                    ::v-deep {
-                        .el-select__wrapper {
-                            border-radius: 25px;
-                            padding: 3px 10px;
-                            text-align: center;
-                        }
-                        .el-select__placeholder,
-                        .el-select__caret {
-                            color: #828282;
-                        }
-                    }
+                .add-garden {
+                    font-size: 12px;
+                    color: #2199f8;
+                    padding: 3px 10px;
+                    border: 1px solid rgba(33, 153, 248, 0.5);
+                    border-radius: 25px;
                 }
             }
             .address-icon {
                 margin-right: 4px;
                 font-size: 16px;
             }
+            .address-text {
+                font-size: 16px;
+                font-weight: 500;
+                color: #000000;
+            }
             .temperature {
                 margin-top: 8px;
                 .temperature-number {

+ 3 - 3
src/router/globalRoutes.js

@@ -19,10 +19,10 @@ export default [
         component: () => import("@/views/old_mini/home/index.vue"),
     },
     {
-        path: "/plan",
-        name: "Plan",
+        path: "/monitor",
+        name: "Monitor",
         meta: { showTabbar: true, keepAlive: true },
-        component: () => import("@/views/old_mini/plan/index.vue"),
+        component: () => import("@/views/old_mini/monitor/index.vue"),
     },
     //个人中心
     {

+ 149 - 0
src/views/old_mini/home/components/AgriculturalDynamics.vue

@@ -0,0 +1,149 @@
+<template>
+    <div class="agricultural-dynamics">
+        <!-- 标题 -->
+        <div class="title">农情动态</div>
+
+        <!-- 标签页导航 -->
+        <div class="tab-nav">
+            <div 
+                v-for="tab in tabs" 
+                :key="tab.value" 
+                class="tab-item" 
+                :class="{ active: activeTab === tab.value }" 
+                @click="activeTab = tab.value"
+            >
+                {{ tab.label }}
+            </div>
+        </div>
+
+        <!-- 内容区域 -->
+        <div class="content-area">
+            <!-- 气象预警内容 -->
+            <div v-if="activeTab === 'weather'" class="content-list">
+                <div class="content-item">
+                    <div class="item-image">
+                        <img src="@/assets/img/home/banner.png" alt="气象预警" />
+                    </div>
+                    <div class="item-content">
+                        <div class="item-text">周边5km出现了高温灼烧气象预警, 请注意某某防范!</div>
+                        <div class="item-date">2022-11-12</div>
+                    </div>
+                </div>
+                <div class="content-item">
+                    <div class="item-image">
+                        <img src="@/assets/img/home/banner.png" alt="气象预警" />
+                    </div>
+                    <div class="item-content">
+                        <div class="item-text">周边3km出现了暴雨预警, 请注意防范!</div>
+                        <div class="item-date">2022-11-10</div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 农事预警内容 -->
+            <div v-if="activeTab === 'agricultural'" class="content-list">
+                <div class="content-item">
+                    <div class="item-image">
+                        <img src="@/assets/img/home/banner.png" alt="农事预警" />
+                    </div>
+                    <div class="item-content">
+                        <div class="item-text">建议进行病虫害防治, 注意观察作物生长情况</div>
+                        <div class="item-date">2022-11-11</div>
+                    </div>
+                </div>
+            </div>
+
+            <!-- 专家问答内容 -->
+            <div v-if="activeTab === 'expert'" class="content-list">
+                <div class="content-item">
+                    <div class="item-image">
+                        <img src="@/assets/img/home/banner.png" alt="专家问答" />
+                    </div>
+                    <div class="item-content">
+                        <div class="item-text">专家解答: 如何提高作物产量? 建议合理施肥...</div>
+                        <div class="item-date">2022-11-09</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { ref } from "vue";
+
+const activeTab = ref("weather");
+
+const tabs = [
+    { label: "气象预警", value: "weather" },
+    { label: "农事预警", value: "agricultural" },
+    { label: "专家问答", value: "expert" }
+];
+</script>
+
+<style scoped lang="scss">
+.agricultural-dynamics {
+    padding: 0 10px;
+
+    .title {
+        font-size: 16px;
+        font-weight: bold;
+        color: #1D2129;
+        margin-bottom: 16px;
+    }
+
+    .tab-nav {
+        display: flex;
+        margin-bottom: 16px;
+
+        .tab-item {
+            margin-right: 20px;
+            font-size: 14px;
+            &.active {
+                color: #2199F8;
+                border-bottom: 2px solid #2199F8;
+
+            }
+        }
+    }
+
+    .content-area {
+        .content-list {
+            .content-item {
+                display: flex;
+                align-items: center;
+                .item-image {
+                    width: 114px;
+                    height: 74px;
+                    margin-right: 12px;
+                    flex-shrink: 0;
+
+                    img {
+                        width: 100%;
+                        height: 100%;
+                        object-fit: cover;
+                        border-radius: 8px;
+                    }
+                }
+
+                .item-content {
+                    flex: 1;
+
+                    .item-text {
+                        color: #1D2129;
+                        margin-bottom: 10px;
+                    }
+
+                    .item-date {
+                        color: #86909C;
+                        font-size: 13px;
+                    }
+                }
+            }
+            .content-item + .content-item{
+                margin-top: 12px;
+            }
+        }
+    }
+}
+</style>

+ 209 - 0
src/views/old_mini/home/index copy.vue

@@ -0,0 +1,209 @@
+<template>
+    <custom-header v-if="isExpert" name="飞鸟管家"></custom-header>
+    <div class="home-index" :style="{ height: isExpert ? `calc(100vh - 40px)` : `calc(100vh - ${tabBarHeight}px - 50px)` }">
+        <!-- 地图 -->
+        <div class="map-container" ref="mapContainer"></div>
+        <!-- 新建按钮 -->
+        <div class="add-button" v-show="showAddButton && !isExpert" @click="toSubPage">
+            <el-icon class="add-button-icon"><CircleCloseFilled /></el-icon>
+            <span>创建我的农场</span>
+        </div>
+        <!-- 天气遮罩 -->
+        <div class="weather-mask" v-show="isExpanded"></div>
+        <!-- 天气 -->
+        <weather-info class="weather-info" @weatherExpanded="weatherExpanded"></weather-info>
+        <!-- 操作按钮 -->
+        <div class="operation-button">
+            <div class="button-group">
+                <div class="button-item" @click="toFarmInfo">
+                    <img class="button-icon" src="@/assets/img/tab_bar/home-active.png" alt="">
+                    <span>基本信息</span>
+                </div>
+                <div class="button-item" @click="toFarmPhoto">
+                    <img class="button-icon" src="@/assets/img/home/photo-icon.png" alt="">
+                    <span>农场相册</span>
+                </div>
+            </div>
+            <div class="add-farm-button" v-show="!isExpert">
+                <el-icon class="icon"><CircleCloseFilled /></el-icon>
+                <span>新增农场</span>
+            </div>
+        </div>
+        <!-- 浮动面板 -->
+        <home-floating-panel
+            :isExpert="isExpert"
+            class="home-floating-panel"
+            :style="{ zIndex: zIndex }"
+            @heightChange="heightChange"
+        ></home-floating-panel>
+        <!-- 问题提醒 -->
+        <problem-reminder></problem-reminder>
+        <!-- 农场信息 -->
+        <farm-info-popup ref="farmInfoRef"></farm-info-popup>
+    </div>
+</template>
+
+<script setup>
+import IndexMap from "./map/index.js";
+import { onMounted, computed, ref } from "vue";
+import { useStore } from "vuex";
+import { useRouter,useRoute } from "vue-router";
+import customHeader from "@/components/customHeader.vue";
+import weatherInfo from "@/components/weatherInfo.vue";
+import homeFloatingPanel from "./components/homeFloatingPanel.vue";
+import problemReminder from "./components/problemReminder.vue";
+import farmInfoPopup from "./components/farmInfoPopup.vue";
+const router = useRouter();
+const route = useRoute();
+const store = useStore();
+const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+const farmInfoRef = ref(null);
+const indexMap = new IndexMap();
+const mapContainer = ref(null);
+
+const isExpert = ref(false);
+if (route.query.type) {
+    isExpert.value = true;
+}
+onMounted(() => {
+    const point = store.state.home.miniUserLocationPoint
+    indexMap.initMap(point, mapContainer.value);
+});
+
+const isExpanded = ref(false);
+const weatherExpanded = (isExpandedValue) => {
+    isExpanded.value = isExpandedValue;
+};
+
+const zIndex = ref(1);
+const showAddButton = ref(true);
+const heightChange = (height) => {
+    zIndex.value = 1;
+    showAddButton.value = true;
+    if (height === 0) {
+        showAddButton.value = false;
+    } else if (height > 310 + tabBarHeight.value) {
+        zIndex.value = 3;
+    }
+};
+
+function toSubPage() {
+    router.push("/create_farm?isFromHome=true");
+}
+
+function toFarmPhoto() {
+    router.push({
+        path: "/farm_photo",
+    });
+}
+
+function toFarmInfo() {
+    farmInfoRef.value.handleShow();
+}
+</script>
+
+<style lang="scss" scoped>
+.home-index {
+    position: relative;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    .map-container {
+        width: 100%;
+        height: 100%;
+    }
+    .add-button {
+        position: absolute;
+        bottom: 20px;
+        left: 50%;
+        transform: translateX(-50%);
+        z-index: 2;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        color: #fff;
+        background-image: linear-gradient(180deg, #70bffe 0%, #2199f8 100%);
+        border-radius: 25px;
+        padding: 12px 0;
+        width: 187px;
+        .add-button-icon {
+            font-size: 20px;
+            margin-right: 5px;
+            transform: rotate(45deg);
+        }
+    }
+    .weather-mask {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: rgba(0, 0, 0, 0.52);
+        z-index: 2;
+    }
+    .weather-info {
+        position: absolute;
+        top: 12px;
+        left: 12px;
+        width: calc(100% - 24px);
+        z-index: 2;
+    }
+    .operation-button{
+        position: absolute;
+        top: 117px;
+        left: 12px;
+        width: calc(100% - 24px);
+        z-index: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 12px;
+        font-weight: 500;
+        .button-group{
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .button-item{
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                gap: 4px;
+                color: rgba(0, 0, 0, 0.8);
+                background-color: #fff;
+                .button-icon{
+                    width: 13px;
+                    height: 13px;
+                }
+            }
+            .button-item:first-child{
+                margin-right: 10px;
+            }
+        }
+        .add-farm-button{
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 4px;
+            background: rgba(0, 0, 0, 0.5);
+            border: 1px solid rgba(255, 255, 255, 0.5);
+            color: #fff;
+            .icon{
+                font-size: 16px;
+                transform: rotate(45deg);
+            }
+        }
+        .button-item,
+        .add-farm-button{
+            border-radius: 25px;
+            padding: 8px 12px;
+        }
+    }
+    .home-floating-panel {
+        position: fixed;
+        bottom: 0;
+        left: 0;
+        width: 100%;
+        z-index: 1;
+    }
+}
+</style>

+ 171 - 152
src/views/old_mini/home/index.vue

@@ -1,139 +1,114 @@
 <template>
-    <custom-header v-if="isExpert" name="飞鸟管家"></custom-header>
-    <div class="home-index" :style="{ height: isExpert ? `calc(100vh - 40px)` : `calc(100vh - ${tabBarHeight}px - 50px)` }">
-        <!-- 地图 -->
-        <div class="map-container" ref="mapContainer"></div>
-        <!-- 新建按钮 -->
-        <div class="add-button" v-show="showAddButton && !isExpert" @click="toSubPage">
-            <el-icon class="add-button-icon"><CircleCloseFilled /></el-icon>
-            <span>创建我的农场</span>
-        </div>
+    <div class="home-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
+        <img class="banner" src="@/assets/img/home/banner.png" alt="" />
         <!-- 天气遮罩 -->
         <div class="weather-mask" v-show="isExpanded"></div>
         <!-- 天气 -->
-        <weather-info class="weather-info" @weatherExpanded="weatherExpanded"></weather-info>
-        <!-- 操作按钮 -->
-        <div class="operation-button">
-            <div class="button-group">
-                <div class="button-item" @click="toFarmInfo">
-                    <img class="button-icon" src="@/assets/img/tab_bar/home-active.png" alt="">
-                    <span>基本信息</span>
-                </div>
-                <div class="button-item" @click="toFarmPhoto">
-                    <img class="button-icon" src="@/assets/img/home/photo-icon.png" alt="">
-                    <span>农场相册</span>
+        <weather-info class="weather-info" @weatherExpanded="weatherExpanded" :isGarden="false"></weather-info>
+        <div class="farm-monitor-container">
+            <div class="farm-monitor-left" @click="handleCardClick(monitorCards.left)">
+                <div class="title">{{ monitorCards.left.title }}</div>
+                <div class="content">{{ monitorCards.left.content }}</div>
+                <div class="arrow">
+                    <el-icon class="icon"><ArrowRightBold /></el-icon>
                 </div>
             </div>
-            <div class="add-farm-button" v-show="!isExpert">
-                <el-icon class="icon"><CircleCloseFilled /></el-icon>
-                <span>新增农场</span>
+            <div class="farm-monitor-right">
+                <div
+                    v-for="(item, index) in monitorCards.right"
+                    :key="index"
+                    class="right-item"
+                    :class="{ expert: index === 1 }"
+                    @click="handleCardClick(item)"
+                >
+                    <div class="title">
+                        <span>{{ item.title }}</span>
+                        <el-icon class="icon"><ArrowRightBold /></el-icon>
+                    </div>
+                    <div class="content">{{ item.content }}</div>
+                </div>
             </div>
         </div>
-        <!-- 浮动面板 -->
-        <home-floating-panel
-            :isExpert="isExpert"
-            class="home-floating-panel"
-            :style="{ zIndex: zIndex }"
-            @heightChange="heightChange"
-        ></home-floating-panel>
-        <!-- 问题提醒 -->
-        <problem-reminder></problem-reminder>
-        <!-- 农场信息 -->
-        <farm-info-popup ref="farmInfoRef"></farm-info-popup>
+        <AgriculturalDynamics />
     </div>
+    <!-- 创建农场弹窗 -->
+    <popup v-model:show="showFarmPopup" round class="create-farm-popup">
+        <template v-if="farmPopupType === 'create'">
+            <img  class="create-farm-icon" src="@/assets/img/home/create-farm-icon.png" alt="" />
+            <div class="create-farm-text">
+                <div>您当前还没有农场</div>
+                <div>请先创建农场</div>
+            </div>
+        </template>
+        <template v-else>
+            <img class="farm-check-icon" src="@/assets/img/home/right.png" alt="">
+            <div class="create-farm-text success-text">农场创建成功</div>
+        </template>
+        <div class="create-farm-btn">{{ farmPopupType === 'create' ? '去创建农场' : '我知道了' }}</div>
+    </popup>
 </template>
 
 <script setup>
-import IndexMap from "./map/index.js";
-import { onMounted, computed, ref } from "vue";
+import { ref, computed, onMounted } from "vue";
 import { useStore } from "vuex";
-import { useRouter,useRoute } from "vue-router";
-import customHeader from "@/components/customHeader.vue";
+import { Popup } from "vant";
 import weatherInfo from "@/components/weatherInfo.vue";
-import homeFloatingPanel from "./components/homeFloatingPanel.vue";
-import problemReminder from "./components/problemReminder.vue";
-import farmInfoPopup from "./components/farmInfoPopup.vue";
-const router = useRouter();
-const route = useRoute();
+import AgriculturalDynamics from "./components/AgriculturalDynamics.vue";
+import { useRouter } from "vue-router";
+
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
-const farmInfoRef = ref(null);
-const indexMap = new IndexMap();
-const mapContainer = ref(null);
+const router = useRouter();
 
-const isExpert = ref(false);
-if (route.query.type) {
-    isExpert.value = true;
-}
-onMounted(() => {
-    const point = store.state.home.miniUserLocationPoint
-    indexMap.initMap(point, mapContainer.value);
+const showFarmPopup = ref(false);
+const farmPopupType = ref("create");
+
+// 监测卡片数据
+const monitorCards = ref({
+    left: {
+        title: "农场监测",
+        content: "实时监测农场环境和作物生长情况",
+        route: "/monitor",
+    },
+    right: [
+        {
+            title: "病虫识别",
+            content: "智能识别病虫害,提供防治建议",
+            route: "/pest-recognition",
+        },
+        {
+            title: "专家咨询",
+            content: "专业农技专家在线解答疑问",
+            route: "/expert-consultation",
+        },
+    ],
 });
 
+// 卡片点击事件
+const handleCardClick = (card) => {
+    router.push(card.route);
+};
+
+onMounted(() => {});
+
 const isExpanded = ref(false);
 const weatherExpanded = (isExpandedValue) => {
     isExpanded.value = isExpandedValue;
 };
-
-const zIndex = ref(1);
-const showAddButton = ref(true);
-const heightChange = (height) => {
-    zIndex.value = 1;
-    showAddButton.value = true;
-    if (height === 0) {
-        showAddButton.value = false;
-    } else if (height > 310 + tabBarHeight.value) {
-        zIndex.value = 3;
-    }
-};
-
-function toSubPage() {
-    router.push("/create_farm?isFromHome=true");
-}
-
-function toFarmPhoto() {
-    router.push({
-        path: "/farm_photo",
-    });
-}
-
-function toFarmInfo() {
-    farmInfoRef.value.handleShow();
-}
 </script>
 
-<style lang="scss" scoped>
+<style scoped lang="scss">
 .home-index {
-    position: relative;
     width: 100%;
     height: 100%;
-    overflow: hidden;
-    .map-container {
+    .banner {
         width: 100%;
-        height: 100%;
-    }
-    .add-button {
-        position: absolute;
-        bottom: 20px;
-        left: 50%;
-        transform: translateX(-50%);
-        z-index: 2;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        color: #fff;
-        background-image: linear-gradient(180deg, #70bffe 0%, #2199f8 100%);
-        border-radius: 25px;
-        padding: 12px 0;
-        width: 187px;
-        .add-button-icon {
-            font-size: 20px;
-            margin-right: 5px;
-            transform: rotate(45deg);
-        }
+        height: 200px;
+        position: relative;
+        z-index: 1;
     }
     .weather-mask {
-        position: absolute;
+        position: fixed;
         top: 0;
         left: 0;
         width: 100%;
@@ -142,68 +117,112 @@ function toFarmInfo() {
         z-index: 2;
     }
     .weather-info {
+        width: calc(100% - 20px);
         position: absolute;
-        top: 12px;
-        left: 12px;
-        width: calc(100% - 24px);
-        z-index: 2;
+        top: calc(200px - 28px);
+        left: 10px;
+        z-index: 3;
     }
-    .operation-button{
-        position: absolute;
-        top: 117px;
-        left: 12px;
-        width: calc(100% - 24px);
-        z-index: 1;
+    .farm-monitor-container {
+        padding-top: 60px;
         display: flex;
         align-items: center;
-        justify-content: space-between;
-        font-size: 12px;
-        font-weight: 500;
-        .button-group{
-            display: flex;
-            align-items: center;
-            justify-content: space-between;
-            .button-item{
+        gap: 7px;
+        margin: 10px;
+        height: 170px;
+        .farm-monitor-left,
+        .farm-monitor-right {
+            .title {
+                font-size: 16px;
+                color: #1d2129;
+                font-weight: 500;
+                .icon {
+                    font-size: 12px;
+                    margin-left: 2px;
+                }
+            }
+            .content {
+                margin-top: 6px;
+                font-size: 12px;
+                color: rgba(29, 33, 41, 0.5);
+                line-height: 1.5;
+            }
+            .arrow {
+                border-radius: 5px;
+                background: #fff;
                 display: flex;
                 align-items: center;
                 justify-content: center;
-                gap: 4px;
-                color: rgba(0, 0, 0, 0.8);
-                background-color: #fff;
-                .button-icon{
-                    width: 13px;
-                    height: 13px;
-                }
-            }
-            .button-item:first-child{
-                margin-right: 10px;
+                width: 34px;
+                height: 25px;
+                margin-top: 10px;
+                font-size: 11px;
             }
         }
-        .add-farm-button{
+        .farm-monitor-left {
+            flex: 1;
+            height: 100%;
+            padding: 25px 10px;
+            box-sizing: border-box;
+            background: url("@/assets/img/home/farm-bg-1.png") no-repeat center center / 100% 100%;
+        }
+        .farm-monitor-right {
+            flex: 1;
+            height: 100%;
             display: flex;
-            align-items: center;
-            justify-content: center;
-            gap: 4px;
-            background: rgba(0, 0, 0, 0.5);
-            border: 1px solid rgba(255, 255, 255, 0.5);
-            color: #fff;
-            .icon{
-                font-size: 16px;
-                transform: rotate(45deg);
+            flex-direction: column;
+            gap: 7px;
+            .right-item {
+                padding: 10px;
+                box-sizing: border-box;
+                display: flex;
+                flex-direction: column;
+                justify-content: center;
+                flex: 1;
+                background: url("@/assets/img/home/farm-bg-2.png") no-repeat center center / 100% 100%;
+            }
+            .expert {
+                background: url("@/assets/img/home/farm-bg-3.png") no-repeat center center / 100% 100%;
             }
         }
-        .button-item,
-        .add-farm-button{
-            border-radius: 25px;
-            padding: 8px 12px;
+    }
+}
+.create-farm-popup {
+    width: 75%;
+    padding: 28px 28px 20px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    justify-content: center;
+    .create-farm-icon{
+        width: 40px;
+        height: 40px;
+        margin-bottom: 12px;
+    }
+    .farm-check-icon{
+        width: 68px;
+        height: 68px;
+        margin-bottom: 12px;
+    }
+    .create-farm-text{
+        font-size: 18px;
+        font-weight: 500;
+        margin-bottom: 32px;
+        text-align: center;
+        &.success-text{
+            font-size: 23px;
+            font-weight: 400;
         }
     }
-    .home-floating-panel {
-        position: fixed;
-        bottom: 0;
-        left: 0;
+    .create-farm-btn{
         width: 100%;
-        z-index: 1;
+        box-sizing: border-box;
+        padding: 8px;
+        border-radius: 25px;
+        font-size: 16px;
+        background: #2199F8;
+        color: #fff;
+        text-align: center;
     }
 }
 </style>

+ 404 - 0
src/views/old_mini/monitor/index.vue

@@ -0,0 +1,404 @@
+<template>
+    <div class="monitor-index" :style="{ height: `calc(100vh - ${tabBarHeight}px)` }">
+        <!-- 天气遮罩 -->
+        <div class="weather-mask" v-show="isExpanded"></div>
+        <!-- 天气 -->
+        <weather-info class="weather-info" @weatherExpanded="weatherExpanded" :isGarden="true"></weather-info>
+        <!-- 操作按钮 -->
+        <div class="operation-button">
+            <div class="button-group">
+                <div class="button-item" @click="toFarmInfo">
+                    <img class="button-icon" src="@/assets/img/tab_bar/home-active.png" alt="" />
+                    <span>基本信息</span>
+                </div>
+                <div class="button-item" @click="toFarmPhoto">
+                    <img class="button-icon" src="@/assets/img/home/photo-icon.png" alt="" />
+                    <span>农场相册</span>
+                </div>
+            </div>
+            <badge dot :offset="[-4, 5]">
+                <div class="add-farm-button">
+                    <img class="icon" src="@/assets/img/monitor/notice.png" alt="" />
+                    <span>农场消息</span>
+                </div>
+            </badge>
+        </div>
+        <!-- 功能卡片网格 -->
+        <div class="function-cards">
+            <div
+                v-for="(card, index) in functionCards"
+                :key="index"
+                class="function-card"
+                @click="handleCardClick(card)"
+            >
+                <img :src="require(`@/assets/img/monitor/grid-${index + 1}.png`)" :alt="card.title" />
+                <div class="card-title">{{ card.title }}</div>
+                <div class="card-status">
+                    {{ card.status }}
+                </div>
+            </div>
+        </div>
+        
+        <!-- 实时播报 -->
+        <div class="realtime-broadcast">
+            <div class="broadcast-header">
+                <div class="header-left">
+                    <span class="broadcast-title">实时播报</span>
+                    <div class="broadcast-action" @click="handleBroadcast">
+                        <img class="speaker-icon" src="@/assets/img/monitor/speaker.png" alt="播报" />
+                        <span class="broadcast-text">点击播报</span>
+                    </div>
+                </div>
+                <div class="more-link" @click="handleMoreBroadcast">更多></div>
+            </div>
+            
+            <div class="broadcast-list">
+                <div 
+                    v-for="(item, index) in broadcastList" 
+                    :key="index"
+                    class="broadcast-item"
+                    @click="handleBroadcastItem(item)"
+                >
+                    <div class="item-icon">
+                        <img src="@/assets/img/monitor/bell.png" alt="通知" />
+                    </div>
+                    <div class="item-content">
+                        <div class="item-title">{{ item.title }}</div>
+                        <div class="item-status">
+                            距离执行还差<span class="countdown">{{ item.daysLeft }}</span>天
+                        </div>
+                    </div>
+                    <div class="item-zone">{{ item.zone }}</div>
+                </div>
+            </div>
+        </div>
+        
+    </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from "vue";
+import { useStore } from "vuex";
+import { Badge } from "vant";
+import weatherInfo from "@/components/weatherInfo.vue";
+import { useRouter } from "vue-router";
+
+const store = useStore();
+const tabBarHeight = computed(() => store.state.home.tabBarHeight);
+const router = useRouter();
+
+// 功能卡片数据
+const functionCards = ref([
+    {
+        title: "农事规划",
+        status: "2 待执行",
+        route: "/agricultural-planning",
+    },
+    {
+        title: "农场报告",
+        status: "最新",
+        route: "/farm-report",
+    },
+    {
+        title: "农事方案",
+        status: "2 待执行",
+        route: "/agricultural-scheme",
+    },
+    {
+        title: "复核成效",
+        status: "最新",
+        route: "/review-results",
+    },
+]);
+
+// 实时播报数据
+const broadcastList = ref([
+    {
+        title: "某莫普农事未执行未执行",
+        daysLeft: 3,
+        zone: "2区"
+    },
+    {
+        title: "某莫普农事未执行未执行",
+        daysLeft: 3,
+        zone: "2区"
+    },
+    {
+        title: "某莫普农事未执行未执行",
+        daysLeft: 3,
+        zone: "2区"
+    },
+    {
+        title: "某莫普农事未执行未执行",
+        daysLeft: 3,
+        zone: "2区"
+    }
+]);
+
+// 卡片点击事件
+const handleCardClick = (card) => {
+    console.log("卡片点击:", card);
+    // router.push(card.route);
+};
+
+// 播报相关事件
+const handleBroadcast = () => {
+    console.log("点击播报");
+    // TODO: 实现播报功能
+};
+
+const handleMoreBroadcast = () => {
+    console.log("查看更多播报");
+    // TODO: 跳转到播报列表页面
+};
+
+const handleBroadcastItem = (item) => {
+    console.log("播报项点击:", item);
+    // TODO: 处理播报项点击事件
+};
+
+onMounted(() => {});
+
+const isExpanded = ref(false);
+const weatherExpanded = (isExpandedValue) => {
+    isExpanded.value = isExpandedValue;
+};
+
+function toSubPage() {
+    router.push("/create_farm?isFromHome=true");
+}
+
+function toFarmPhoto() {
+    router.push({
+        path: "/farm_photo",
+    });
+}
+
+function toFarmInfo() {
+    // farmInfoRef.value.handleShow();
+}
+</script>
+
+<style scoped lang="scss">
+.monitor-index {
+    width: 100%;
+    height: 100%;
+    padding: 13px 10px;
+    box-sizing: border-box;
+    background-image: linear-gradient(250deg, #cbebff 0%, #ffffff 80%);
+    .weather-mask {
+        position: fixed;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        background-color: rgba(0, 0, 0, 0.52);
+        z-index: 2;
+    }
+    .weather-info {
+        width: calc(100% - 20px);
+        position: absolute;
+        z-index: 3;
+    }
+    .operation-button {
+        position: absolute;
+        top: 117px;
+        left: 12px;
+        width: calc(100% - 24px);
+        z-index: 1;
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        font-size: 12px;
+        font-weight: 500;
+        .button-group {
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+            .button-item {
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                gap: 4px;
+                color: rgba(0, 0, 0, 0.8);
+                background-color: #fff;
+                border: 1px solid #f2f2f2;
+                .button-icon {
+                    width: 13px;
+                    height: 13px;
+                }
+            }
+            .button-item:first-child {
+                margin-right: 10px;
+            }
+        }
+        .add-farm-button {
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 4px;
+            background: rgba(33, 153, 248, 0.1);
+            border: 1px solid #fff;
+            .icon {
+                width: 14px;
+                height: 14px;
+            }
+        }
+        .button-item,
+        .add-farm-button {
+            border-radius: 25px;
+            padding: 8px 12px;
+        }
+    }
+
+    .function-cards {
+        display: grid;
+        grid-template-columns: 1fr 1fr;
+        gap: 10px;
+        margin-top: 155px;
+
+        .function-card {
+            background: #fff;
+            border-radius: 12px;
+            padding: 15px;
+            box-shadow: 0 1px 6px rgba(0, 0, 0, 0.05);
+            position: relative;
+            display: flex;
+            align-items: center;
+            justify-content: center;
+            gap: 10px;
+            img {
+                width: 30px;
+                height: 30px;
+            }
+            .card-title {
+                font-size: 14px;
+                font-weight: 500;
+                color: #1d2129;
+            }
+            .card-status {
+                position: absolute;
+                top: 0;
+                right: 0;
+                padding: 1px 4px;
+                border-radius: 6px 8px 8px 2px;
+                font-size: 10px;
+                background: #2199f8;
+                color: #fff;
+            }
+         }
+     }
+     
+     .realtime-broadcast {
+         margin-top: 20px;
+         padding: 0 10px;
+         
+         .broadcast-header {
+             display: flex;
+             align-items: center;
+             justify-content: space-between;
+             margin-bottom: 12px;
+             
+             .header-left {
+                 display: flex;
+                 align-items: center;
+                 gap: 12px;
+                 
+                 .broadcast-title {
+                     font-size: 16px;
+                     font-weight: 600;
+                     color: #1D2129;
+                 }
+                 
+                 .broadcast-action {
+                     display: flex;
+                     align-items: center;
+                     gap: 4px;
+                     cursor: pointer;
+                     
+                     .speaker-icon {
+                         width: 16px;
+                         height: 16px;
+                     }
+                     
+                     .broadcast-text {
+                         font-size: 14px;
+                         color: #2199F8;
+                     }
+                 }
+             }
+             
+             .more-link {
+                 font-size: 14px;
+                 color: #1D2129;
+                 cursor: pointer;
+             }
+         }
+         
+         .broadcast-list {
+             background: #fff;
+             border-radius: 8px;
+             overflow: hidden;
+             
+             .broadcast-item {
+                 display: flex;
+                 align-items: center;
+                 padding: 12px 16px;
+                 border-bottom: 1px solid #F2F2F2;
+                 cursor: pointer;
+                 transition: background-color 0.2s ease;
+                 
+                 &:last-child {
+                     border-bottom: none;
+                 }
+                 
+                 &:active {
+                     background-color: #F8F9FA;
+                 }
+                 
+                 .item-icon {
+                     width: 17px;
+                     height: 11px;
+                     margin-right: 12px;
+                     flex-shrink: 0;
+                     
+                     img {
+                         width: 100%;
+                         height: 100%;
+                     }
+                 }
+                 
+                 .item-content {
+                     flex: 1;
+                     
+                     .item-title {
+                         font-size: 14px;
+                         color: #1D2129;
+                         margin-bottom: 4px;
+                         line-height: 1.4;
+                     }
+                     
+                     .item-status {
+                         font-size: 12px;
+                         color: #86909C;
+                         
+                         .countdown {
+                             color: #F53F3F;
+                             font-weight: 500;
+                         }
+                     }
+                 }
+                 
+                 .item-zone {
+                     background: #F2F3F5;
+                     color: #4E5969;
+                     font-size: 12px;
+                     padding: 2px 8px;
+                     border-radius: 10px;
+                     flex-shrink: 0;
+                 }
+             }
+         }
+     }
+}
+</style>