소스 검색

feat:对接农事方案页面接口

wangsisi 20 시간 전
부모
커밋
b23547a4ea

+ 6 - 1
src/api/modules/monitor.js

@@ -12,5 +12,10 @@ module.exports = {
     farmWorkPlan: {
         url: config.base_dev_url + "container_space_time/farmWorkPlan",
         type: "get",
-    }
+    },
+    //根据农场ID查询农事列表(按物候期分组)
+    listByFarmId: {
+        url: config.base_dev_url + "z_farm_work_lib/listByFarmId",
+        type: "get",
+    },
 }

BIN
src/assets/img/home/farm-bg-4.png


BIN
src/assets/img/home/farm-bg-5.png


+ 27 - 18
src/components/pageComponents/PlanList.vue

@@ -6,16 +6,16 @@
                     <el-sub-menu v-for="(menu, index) in menuData" :key="index" :index="String(menu.id)">
                         <template #title>
                             <img class="menu-icon" :src="require(`@/assets/img/gallery/icon-${index}.png`)" />
-                            <span class="menu-text">{{ menu.name }}</span>
+                            <span class="menu-text">{{ menu.phenologyName }}</span>
                         </template>
                         <el-menu-item
-                            v-for="item in menu.farmWorkArrangeList"
+                            v-for="item in menu.farmWorkList"
                             :key="item.id"
-                            :index="`${menu.id}-${item.id}`"
+                            :index="`${menu.phenologyId}-${item.id}`"
                         >
                             <el-anchor-link
-                                :href="'#' + menu.name + item.farmWorkDetail?.name"
-                                :title="item.farmWorkDetail?.name || '摇花落花'"
+                                :href="'#' + menu.phenologyName + item.name"
+                                :title="item.name"
                             />
                         </el-menu-item>
                     </el-sub-menu>
@@ -27,16 +27,19 @@
                 <div v-for="(section, index) in menuData" :key="index" class="content-section">
                     <div
                         class="section-item"
-                        v-for="(sub, subI) in section.farmWorkArrangeList"
+                        v-for="(sub, subI) in section.farmWorkList"
                         :key="index + '-' + subI"
                     >
-                        <div class="section-id" :id="section.name + sub.farmWorkDetail?.name"></div>
+                        <div class="section-id" :id="section.phenologyName + sub.name"></div>
                         <record-item :record-item-data="sub">
                             <template #title>
                                 <div class="box-title">
                                     <div class="title-l">
-                                        {{ sub.farmWorkDetail?.name }}
-                                        <span class="parent-text">{{ section.name }}</span>
+                                        {{ sub.name }}
+                                        <span class="parent-text">{{ getFarmTypeText(sub.type) }}</span>
+                                    </div>
+                                    <div class="title-r" v-if="curRole == 2 && isEdit">
+                                        <el-icon color="#2199F8" size="16"><Edit /></el-icon>
                                     </div>
                                 </div>
                             </template>
@@ -57,9 +60,9 @@ const props = defineProps({
         type: [Number, String],
         required: true,
     },
-    containerId: {
-        type: [Number, String],
-        default: 2,
+    isEdit: {
+        type: Boolean,
+        default: false,
     },
     defaultActive: {
         type: String,
@@ -67,17 +70,26 @@ const props = defineProps({
     },
 });
 
+const curRole = localStorage.getItem("SET_USER_CUR_ROLE")
 const menuData = ref([]);
 const containerRef = ref(null);
 
 function getPlanWorkList() {
-    VE_API.home
-        .getPhenologyFarmWorkList({ farmId: props.farmId, containerId: props.containerId })
+    VE_API.monitor
+        .listByFarmId({ farmId: props.farmId })
         .then(({ data }) => {
             menuData.value = data;
         });
 }
 
+const getFarmTypeText = (type) => {
+    const value = typeof type === "string" ? type.trim() : type;
+    if (value === 0 || value === "0") return "预警农事";
+    if (value === 1 || value === "1") return "标准农事";
+    if (value === 2 || value === "2") return "建议农事";
+    return "";
+};
+
 onMounted(() => {
     getPlanWorkList();
 });
@@ -174,13 +186,10 @@ const handleClick = (e) => {
         box-sizing: border-box;
         .content-section {
             position: relative;
+            margin: 0 10px;
             .section-item {
                 position: relative;
                 border-radius: 14px;
-                border: 1px solid rgba(228, 228, 228, 0.5);
-                .record-item{
-                    padding: 12px 0;
-                }
             }
             .section-item + .section-item{
                 margin-top: 10px;

+ 4 - 4
src/components/recordItem.vue

@@ -122,15 +122,15 @@
             </div>
             <div class="info-item">
                 触发条件:
-                <span class="info-val">{{ recordItemData?.farmWorkDetail?.condition || '暂无触发条件' }}</span>
+                <span class="info-val">{{ recordItemData?.farmWorkDetail?.condition || recordItemData?.condition || '暂无触发条件' }}</span>
             </div>
             <div class="info-item one-text">
                 农事编号:
-                <span class="info-val">{{ recordItemData?.farmWorkDetail?.code ||recordItemData.farmWorkCode }}</span>
+                <span class="info-val">{{ recordItemData?.farmWorkDetail?.code ||recordItemData.farmWorkCode || recordItemData.code }}</span>
             </div>
-            <div class="info-item" v-if="recordItemData?.attention">
+            <div class="info-item">
                 巡园提醒:
-                <span class="info-val">{{ recordItemData?.attention }}</span>
+                <span class="info-val">{{ recordItemData?.attention || '暂无巡园提醒' }}</span>
             </div>
         </div>
         <slot name="footer"></slot>

+ 10 - 6
src/components/weatherInfo.vue

@@ -9,14 +9,14 @@
                 <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="isDefaultFarm ? 'ellipsis-l1' : ''">{{ farmName }}</span>
+                            <span class="ellipsis-l1">{{ farmName }}</span>
                             <div class="default-text" v-show="isDefaultFarm">默认</div>
                             <el-icon class="el-icon--right"><arrow-down /></el-icon>
                         </div>
                         <template #dropdown>
                             <el-dropdown-menu>
                                 <el-dropdown-item
-                                    @click="handleCommand(item.id, item.name)"
+                                    @click="handleCommand(item)"
                                     v-for="item in farmList"
                                     :key="item.id"
                                     :class="{ 'selected-active-garden': farmId === item.id }"
@@ -67,16 +67,18 @@ const props = defineProps({
 // 定义emit事件
 const emit = defineEmits(['weatherExpanded','changeGarden']);
 const router = useRouter();
-const handleCommand = (id, name) => {
+const containerIdVal = ref(null)
+const handleCommand = ({id, name, containerId}) => {
     farmName.value = name;
     farmId.value = id;
+    containerIdVal.value = containerId;
     // 更新默认农场标识
     const selectedFarm = farmList.value.find(farm => farm.id === id);
     isDefaultFarm.value = selectedFarm ? selectedFarm.defaultOption || false : false;
     // 保存用户选择的农场到 localStorage
     localStorage.setItem('selectedFarmId', id);
     localStorage.setItem('selectedFarmName', name);
-    emit('changeGarden',id);
+    emit('changeGarden',{id, containerId});
 };
 
 const isExpanded = ref(false);
@@ -102,7 +104,6 @@ function getFarmList() {
             // 优先使用 localStorage 中保存的农场选择
             const savedFarmId = localStorage.getItem('selectedFarmId');
             const savedFarmName = localStorage.getItem('selectedFarmName');
-            
             if (savedFarmId && savedFarmName) {
                 // 检查保存的农场是否还在当前列表中
                 const savedFarm = data.find(farm => farm.id == savedFarmId);
@@ -110,6 +111,7 @@ function getFarmList() {
                     farmName.value = savedFarmName;
                     farmId.value = Number(savedFarmId);
                     isDefaultFarm.value = savedFarm.defaultOption || false;
+                    containerIdVal.value = savedFarm.containerId;
                 } else {
                     // 如果保存的农场不在列表中,按优先级选择
                     selectDefaultFarm(data);
@@ -118,7 +120,7 @@ function getFarmList() {
                 // 如果没有保存的选择,按优先级选择
                 selectDefaultFarm(data);
             }
-            emit('changeGarden',farmId.value);
+            emit('changeGarden',{id: farmId.value, containerId: containerIdVal.value});
         }
     })
 }
@@ -133,11 +135,13 @@ function selectDefaultFarm(data) {
         farmName.value = defaultFarm.name;
         farmId.value = defaultFarm.id;
         isDefaultFarm.value = true;
+        containerIdVal.value = defaultFarm.containerId;
     } else {
         // 如果没有默认农场,选择第一个
         farmName.value = data[0].name;
         farmId.value = data[0].id;
         isDefaultFarm.value = data[0].defaultOption || false;
+        containerIdVal.value = data[0].containerId;
     }
     
     // 保存到 localStorage

+ 20 - 16
src/views/old_mini/home/components/problemReminder.vue

@@ -18,7 +18,7 @@
                     <span class="options-label">您可以选择</span>
                     <div class="options-buttons">
                         <div class="option-btn" @click="toUpload">拍照识别</div>
-                        <div class="option-btn" @click="toPage">咨询专家</div>
+                        <div class="option-btn" @click="toPage" v-if="curRole == 0">咨询专家</div>
                     </div>
                 </div>
             </div>
@@ -34,6 +34,7 @@
                     {{ getOptionLabel(opt) }}
                 </div>
             </div>
+            <div class="forward-btn bottom-btn" v-if="curRole == 2">转发给客户</div>
         </div>
     </Popup>
     <Popup v-model:show="noShow" class="no-popup">
@@ -80,6 +81,8 @@ function toPage() {
 }
 const detailDialogRef = ref(null);
 
+const curRole = localStorage.getItem("SET_USER_CUR_ROLE");
+
 onActivated(() => {
     fetchQuestPopup();
 });
@@ -275,22 +278,23 @@ function handleUploadSuccess(params) {
             display: flex;
             gap: 12px;
             margin-top: 10px;
+        }
+        .forward-btn{
+            margin-top: 10px;
+        }
+        .bottom-btn {
+            flex: 1;
+            padding: 8px 0;
+            border-radius: 25px;
+            font-size: 16px;
+            text-align: center;
+            background: #fff;
+            border: 1px solid #e5e5e5;
 
-            .bottom-btn {
-                flex: 1;
-                padding: 8px 0;
-                border-radius: 25px;
-                font-size: 16px;
-                font-weight: 500;
-                text-align: center;
-                background: #fff;
-                border: 1px solid #e5e5e5;
-
-                &.yes-btn {
-                    background-image: linear-gradient(180deg, #76c3ff 0%, #2199f8 100%);
-                    color: #fff;
-                    border: none;
-                }
+            &.yes-btn {
+                background-image: linear-gradient(180deg, #76c3ff 0%, #2199f8 100%);
+                color: #fff;
+                border: none;
             }
         }
     }

+ 72 - 35
src/views/old_mini/home/index.vue

@@ -5,11 +5,14 @@
         <div class="weather-mask" v-show="isExpanded"></div>
         <!-- 天气 -->
         <weather-info class="weather-info" @weatherExpanded="weatherExpanded" :isGarden="false"></weather-info>
-        <div class="farm-monitor-container">
+        <div class="farm-monitor-container" :class="{ 'container-role': curRole == 2 }">
             <div class="farm-monitor-left" @click="handleCardClick(monitorCards.left)">
-                <div class="title">{{ monitorCards.left.title }}</div>
+                <div class="title">
+                    <span>{{ monitorCards.left.title }}</span>
+                    <el-icon v-if="curRole == 2" class="icon"><ArrowRightBold /></el-icon>
+                </div>
                 <div class="content">{{ monitorCards.left.content }}</div>
-                <div class="arrow">
+                <div class="arrow" v-if="curRole != 2">
                     <el-icon class="icon"><ArrowRightBold /></el-icon>
                 </div>
             </div>
@@ -34,17 +37,19 @@
     <!-- 创建农场弹窗 -->
     <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="" />
+            <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="">
+            <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" @click="handleBtn">{{ farmPopupType === 'create' ? '去创建农场' : '我知道了' }}</div>
+        <div class="create-farm-btn" @click="handleBtn">
+            {{ farmPopupType === "create" ? "去创建农场" : "我知道了" }}
+        </div>
     </popup>
     <!-- 问题提醒 -->
     <problem-reminder></problem-reminder>
@@ -59,7 +64,9 @@ import AgriculturalDynamics from "./components/AgriculturalDynamics.vue";
 import { useRouter, useRoute } from "vue-router";
 import wx from "weixin-js-sdk";
 import problemReminder from "./components/problemReminder.vue";
+import { ElMessage } from "element-plus";
 
+const curRole = localStorage.getItem("SET_USER_CUR_ROLE");
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
 const router = useRouter();
@@ -92,46 +99,64 @@ const monitorCards = ref({
 // 卡片点击事件
 const handleCardClick = (card) => {
     // showFarmPopup.value = true;
-    if(card.route === "/pest"){
-        const dropdownGardenItem = ref({
-            organId:766,
-            periodId:1,
-            wktVal:'wktVal',
-            address:'address',
-            district:'district',
-            name:'荔博园',
-        });
-        wx.miniProgram.navigateTo({
-            url: `/pages/subPages/new_recognize/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
-        });
-    }else{
-        if(card.route === "/chat_frame"){
-            router.push(`/chat_frame?userId=91754&name=专家1`);
+    if (card.route === "/pest") {
+        if(curRole == 2){
+            ElMessage.warning("该功能正在升级中,敬请期待");
         }else{
+            const dropdownGardenItem = ref({
+                organId: 766,
+                periodId: 1,
+                wktVal: "wktVal",
+                address: "address",
+                district: "district",
+                name: "荔博园",
+            });
+            wx.miniProgram.navigateTo({
+                url: `/pages/subPages/new_recognize/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
+            });
+        }
+    } else {
+        if (card.route === "/chat_frame") {
+            router.push(`/chat_frame?userId=91754&name=专家1`);
+        } else {
             router.push(card.route);
         }
     }
 };
 
 const handleBtn = () => {
-    if(farmPopupType.value === 'create'){
+    if (farmPopupType.value === "create") {
         router.push("/create_farm?isReload=true&from=home");
     }
     showFarmPopup.value = false;
-}
+};
 
 onActivated(() => {
     // 检测是否从创建农场页面成功返回
-    if (route.query.showSuccess === 'true') {
-        farmPopupType.value = 'success';
+    if (route.query.showSuccess === "true") {
+        farmPopupType.value = "success";
         showFarmPopup.value = true;
-        
+
         // 清除URL参数,避免刷新页面时再次显示弹窗
-        router.replace({ 
-            path: '/home', 
-            query: { reload: route.query.reload } 
+        router.replace({
+            path: "/home",
+            query: { reload: route.query.reload },
         });
     }
+    if (curRole == 2) {
+        monitorCards.value.left = {
+            title: "新增客户",
+            content: "实时监测农场状态",
+            route: "/create_farm?type=client&isReload=true&from=home",
+        };
+        monitorCards.value.right = [
+            {
+                title: "病虫识别",
+                content: "精准识别病虫",
+                route: "/pest",
+            },
+        ];
+    }
 });
 
 const isExpanded = ref(false);
@@ -230,6 +255,18 @@ const weatherExpanded = (isExpandedValue) => {
                 background: url("@/assets/img/home/farm-bg-3.png") no-repeat center center / 100% 100%;
             }
         }
+
+        &.container-role{
+            height: 104px;
+            .farm-monitor-left{
+                background: url("@/assets/img/home/farm-bg-4.png") no-repeat center center / 100% 100%;
+            }
+            .farm-monitor-right {
+                .right-item {
+                    background: url("@/assets/img/home/farm-bg-5.png") no-repeat center center / 100% 100%;
+                }
+            }
+        }
     }
 }
 .create-farm-popup {
@@ -239,33 +276,33 @@ const weatherExpanded = (isExpandedValue) => {
     flex-direction: column;
     align-items: center;
     justify-content: center;
-    .create-farm-icon{
+    .create-farm-icon {
         width: 40px;
         height: 40px;
         margin-bottom: 12px;
     }
-    .farm-check-icon{
+    .farm-check-icon {
         width: 68px;
         height: 68px;
         margin-bottom: 12px;
     }
-    .create-farm-text{
+    .create-farm-text {
         font-size: 18px;
         font-weight: 500;
         margin-bottom: 32px;
         text-align: center;
-        &.success-text{
+        &.success-text {
             font-size: 23px;
             font-weight: 400;
         }
     }
-    .create-farm-btn{
+    .create-farm-btn {
         width: 100%;
         box-sizing: border-box;
         padding: 8px;
         border-radius: 25px;
         font-size: 16px;
-        background: #2199F8;
+        background: #2199f8;
         color: #fff;
         text-align: center;
     }

+ 2 - 3
src/views/old_mini/monitor/index.vue

@@ -194,8 +194,7 @@ const onLoad = () => {
 // 卡片点击事件
 const handleCardClick = (card) => {
     const params = {
-        farmId: gardenId.value,
-        containerId: card.containerId,
+        farmId: gardenId.value
     };
     router.push({
         path: card.route,
@@ -274,7 +273,7 @@ const weatherExpanded = (isExpandedValue) => {
 };
 
 const gardenId = ref(store.state.home.gardenId);
-const changeGarden = (id) => {
+const changeGarden = ({id}) => {
     gardenId.value = id;
     // 更新 store 中的状态
     store.commit('home/SET_GARDEN_ID', id);

+ 2 - 55
src/views/old_mini/plan/index.vue

@@ -2,32 +2,7 @@
     <div class="farm-card-page">
         <custom-header name="农事方案"></custom-header>
         <div class="farm-card-content">
-            <PlanList :farm-id="93301" :container-id="route.query.containerId || 2" :default-active="defaultActive">
-                <template #default="{ menuData }">
-                    <div v-for="(section, index) in menuData" :key="index" class="content-section">
-                        <div
-                            class="section-item"
-                            v-for="(sub, subI) in section.farmWorkArrangeList"
-                            :key="index + '-' + subI"
-                        >
-                            <div class="section-id" :id="section.name + sub.farmWorkDetail?.name"></div>
-                            <record-item :record-item-data="sub" @click="handleClick(sub)">
-                                <template #title>
-                                    <div class="box-title">
-                                        <div class="title-l">
-                                            {{ sub.farmWorkDetail?.name }}
-                                            <span class="parent-text">{{ section.name }}</span>
-                                        </div>
-                                        <div class="title-r" v-if="curRole == 2">
-                                            <el-icon color="#2199F8" size="16"><Edit /></el-icon>
-                                        </div>
-                                    </div>
-                                </template>
-                            </record-item>
-                        </div>
-                    </div>
-                </template>
-            </PlanList>
+            <plan-list :farm-id="route.query.farmId" :default-active="defaultActive" isEdit> </plan-list>
         </div>
     </div>
 </template>
@@ -39,7 +14,7 @@ import { useRoute, useRouter } from "vue-router";
 import recordItem from "@/components/recordItem.vue";
 import PlanList from "@/components/pageComponents/PlanList.vue";
 
-const curRole = ref(localStorage.getItem("SET_USER_CUR_ROLE") || 0);
+const curRole = localStorage.getItem("SET_USER_CUR_ROLE");
 const route = useRoute();
 const router = useRouter();
 // 菜单
@@ -61,34 +36,6 @@ const handleClick = (sub) => {
         width: 100%;
         height: calc(100vh - 40px);
         padding-top: 10px;
-        ::v-deep .expert-prescription {
-            height: 100%;
-            .plan-menu {
-                padding: 10px 0;
-                border-radius: 0 10px 10px 0;
-            }
-            .box-title {
-                display: flex;
-                align-items: center;
-                justify-content: space-between;
-                padding-bottom: 8px;
-                border-bottom: 1px solid #f5f5f5;
-                margin-bottom: 8px;
-                .title-l {
-                    font-size: 16px;
-                    font-weight: 600;
-                    color: #000;
-                    .parent-text {
-                        margin-left: 5px;
-                        font-size: 12px;
-                        font-weight: normal;
-                        padding: 4px 6px;
-                        border-radius: 14px;
-                        background: rgba(119, 119, 119, 0.1);
-                    }
-                }
-            }
-        }
     }
 }
 </style>