Переглянути джерело

feat:对接农情互动和修改农事规划样式兼容

wangsisi 2 тижнів тому
батько
коміт
7b258f68ac

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

@@ -57,5 +57,10 @@ module.exports = {
     selectSchemes:{
         url: config.base_dev_url + "container_farm_work_scheme/selectSchemes",
         type: "get",
-    }
+    },
+    //农资弹出问卷接口
+    popupByAgriculturalUserFarms: {
+        url: config.base_dev_url + "work_code/phenology/quest/popupByAgriculturalUserFarms",
+        type: "get",
+    },
 }

BIN
src/assets/img/home/sd.png


+ 2 - 2
src/components/chatWindow.vue

@@ -136,9 +136,9 @@
                     :value="item.id"
                 />
             </el-select>
-            <div v-for="(btn, index) in functionButtons" :key="index" class="function-btn" @click="btn.handler">
+            <!-- <div v-for="(btn, index) in functionButtons" :key="index" class="function-btn" @click="btn.handler">
                 <span class="btn-text">{{ btn.text }}</span>
-            </div>
+            </div> -->
         </div>
 
         <!-- 输入框区域 -->

+ 2 - 7
src/components/detailDialog.vue

@@ -89,7 +89,7 @@
         </div>
         <div class="no-popup-title">
             <span>{{ curRole == 0 ? "好的,感谢您的配合" : "农事下发成功" }}</span>
-            <div class="no-popup-title-sub" v-if="curRole == 0">请您耐心等待 专家确认农事</div>
+            <div class="no-popup-title-sub" v-if="curRole == 0">请您耐心等待 农事确认</div>
         </div>
         <div class="no-popup-btn" @click="noShow = false">{{ curRole == 0 ? "我知道了" : "转发给客户" }}</div>
     </Popup>
@@ -114,19 +114,14 @@ const noShow = ref(false);
 const btnText = ref('');
 const route = useRoute();
 const router = useRouter();
-const sampleId = route.query.sampleId;
-const farmId = route.query.farmId;
 
 const triggerClick = () => {
     winDialogVisible.value = false;
-
     // 如果只显示成功弹窗(来自 album_recognize 页面)
     if (props.showSuccessOnly) {
         noShow.value = true;
-        // eventBus.emit("activeUpload:success");
-    } else {
-        emit("triggerFarmWork");
     }
+    emit("triggerFarmWork");
 };
 
 const emit = defineEmits(["triggerFarmWork"]);

+ 22 - 18
src/components/popup/activeUploadPopup.vue

@@ -92,31 +92,35 @@ const emit = defineEmits(["handleUploadSuccess"]);
 
 const handleUpload = () => {
     if (images.value.length === 0) return ElMessage.warning("请上传图片");
-    const params = {
-        gardenId: gardenId.value,
-        images: images.value,
+    const paramsObj = {
+        farmId: gardenId.value,
+        arrangeId: arrangeId.value,
         executeDate: uploadDate.value,
+        imagePaths: images.value,
     };
-    // 提交成功后的反馈弹窗(示例直接展示)
-    if (type.value === "question") {
+    if(type.value === "question"){
         show.value = false;
-        emit("handleUploadSuccess", params);
-    } else {
-        const paramsObj = {
-            farmId: gardenId.value,
-            arrangeId: arrangeId.value,
-            executeDate: uploadDate.value,
-            imagePaths: images.value,
-        };
-        VE_API.monitor.triggerFarmWork(paramsObj).then((res) => {
-            if (res.code === 0) {
+        emit("handleUploadSuccess", paramsObj);
+        return
+    }
+    triggerFarmWork(paramsObj,true)
+};
+
+function triggerFarmWork(paramsObj,showSuccess) {
+    VE_API.monitor.triggerFarmWork(paramsObj).then((res) => {
+        if (res.code === 0) {
+            if(showSuccess){
                 show.value = false;
                 successShow.value = true;
                 emit("handleUploadSuccess", paramsObj);
             }
-        });
-    }
-};
+        }
+    });
+}
+
+defineExpose({
+    triggerFarmWork
+})
 
 function handleClosed() {
     eventBus.emit("upload:reset");

+ 6 - 2
src/views/old_mini/create_farm/index.vue

@@ -545,6 +545,12 @@ const submitForm = (formEl) => {
                     store.commit("home/SET_EDIT_FARM_DATA", null); // 清除编辑数据
                     polygonArr.value = null;
                     isFromEditMap.value = false;
+                    localStorage.setItem('isGarden', true);
+
+                    if(route.query.type !== 'edit' && curRole == 0){
+                        localStorage.setItem('selectedFarmId', res.data.id);
+                        localStorage.setItem('selectedFarmName', res.data.name);
+                    }
                     
                     // 根据来源页面决定跳转目标
                     const fromPage = route.query.from;
@@ -560,12 +566,10 @@ const submitForm = (formEl) => {
                         }
                         
                     } else if (fromPage === "details") {
-                        console.log('details', res.data);
                         router.go(-1)
                     } else {
                         router.replace(`/home`);
                     }
-                    localStorage.setItem('isGarden', true);
                 }else{
                     ElMessage.error(res.msg);
                 }

+ 5 - 0
src/views/old_mini/dev_login.vue

@@ -48,9 +48,14 @@ onMounted(async () => {
 })
 
 const getFarmList = async () => {
+    localStorage.removeItem('selectedFarmId');
+    localStorage.removeItem('selectedFarmName');
     const { data } = await VE_API.farm.userFarmSelectOption();
     if(data && data.length > 0) {
         localStorage.setItem('isGarden', true);
+        const defalutFarm = data[0]
+        localStorage.setItem('selectedFarmId', defalutFarm.id);
+        localStorage.setItem('selectedFarmName', defalutFarm.name);
     }
 }
 

+ 1 - 1
src/views/old_mini/home/components/farmInfoPopup.vue

@@ -111,7 +111,7 @@ const handleEditMap = () => {
 const handleEdit = () => {
     setTimeout(() => {
         show.value = false;
-    }, 50);
+    }, 150);
 
     // 在跳转前,将当前农场的地块数据存储到store中
     if (farmInfo.value.geomWkt) {

+ 55 - 35
src/views/old_mini/home/components/problemReminder.vue

@@ -10,11 +10,9 @@
                 <img class="header-icon" src="@/assets/img/home/file-icon.png" alt="" />
             </div>
             <div class="question-section-wrapper">
-                <!-- <span class="question-text">{{ questPopupData.quest }}</span> -->
-                <span class="question-text">请问 <span style="color: #2199f8;">水稻园</span> 的水稻是否进入分蘖期?</span>
+                <div class="question-text">请问 <span style="color: #2199f8;">{{ farmName }}</span> {{ questPopupData.quest }}</div>
                 <div class="img">
-                    <!-- <img :src="questPopupData.backgroundImage" alt="" /> -->
-                    <img src="@/assets/img/home/sd.png" alt="" />
+                    <img :src="questPopupData.backgroundImage" alt="" />
                 </div>
                 <div class="options-section">
                     <span class="options-label">您可以选择</span>
@@ -47,27 +45,21 @@
         <div class="no-popup-btn" @click="noShow = false">我知道了</div>
     </Popup>
     <!-- 农事信息弹窗 -->
-    <detail-dialog ref="detailDialogRef" :show-success-only="true"></detail-dialog>
+    <detail-dialog ref="detailDialogRef" showSuccessOnly @triggerFarmWork="triggerFarmWork"></detail-dialog>
     <!-- 新增:激活上传弹窗 -->
-    <active-upload-popup @handleUploadSuccess="handleUploadSuccess"></active-upload-popup>
+    <active-upload-popup ref="activeUploadPopupRef" @handleUploadSuccess="handleUploadSuccess"></active-upload-popup>
 </template>
 <script setup>
 import { Popup } from "vant";
-import { ref,watch } from "vue";
+import { ref,onActivated } from "vue";
 import wx from "weixin-js-sdk";
 import activeUploadPopup from "@/components/popup/activeUploadPopup.vue";
 import detailDialog from "@/components/detailDialog.vue";
 import eventBus from "@/api/eventBus";
 import { useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
 const router = useRouter();
 
-const props = defineProps({
-    farmId: {
-        type: [Number, String],
-        default: null,
-    }
-}); 
-
 const show = ref(false);
 const noShow = ref(false);
 const dropdownGardenItem = ref({
@@ -79,37 +71,57 @@ const dropdownGardenItem = ref({
     name: "荔博园",
 });
 const toUpload = () => {
-    wx.miniProgram.navigateTo({
-        url: `/pages/subPages/carmera/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
-    });
+    if(curRole == 0){
+        wx.miniProgram.navigateTo({
+            url: `/pages/subPages/carmera/index?gardenData=${JSON.stringify(dropdownGardenItem.value)}`,
+        });
+    }else{
+        ElMessage.warning("该功能正在升级中,敬请期待");
+    }
 };
 
 function toPage() {
-    router.push("/expert_list");
+    const expertId = sessionStorage.getItem('expertId');
+    if(expertId){
+        router.push(`/chat_frame?userId=${expertId}`);
+    }else{
+        ElMessage.warning("专家信息不存在,请联系管理员");
+    }
 }
 const detailDialogRef = ref(null);
 
 const curRole = localStorage.getItem("SET_USER_CUR_ROLE");
 
-watch(() => props.farmId, (newVal) => {
-    if (newVal) {
+const farmName = ref('');
+const farmIdVal = ref(null);
+
+onActivated(() => {
+    if(curRole == 0){
+        if(localStorage.getItem('selectedFarmId')){
+            farmIdVal.value = localStorage.getItem('selectedFarmId');
+            fetchQuestPopup();
+        }
+    }else{
         fetchQuestPopup();
     }
 });
 
+
 const questPopupData = ref({});
 const bottomAnswerOptions = ref([]);
+//弹出问卷接口
 const fetchQuestPopup = () => {
-    VE_API.home
-        .fetchQuestPopup({ farmId: props.farmId })
-        .then(({ data }) => {
-            if (Array.isArray(data) && data.length > 0) {
-                show.value = true;
-                questPopupData.value = data[0];
-                bottomAnswerOptions.value = transformAnswerOptions(questPopupData.value?.answerOptions);
-            }
-        })
-        .catch(() => {});
+    const api = curRole == 0 ? VE_API.home.fetchQuestPopup({ farmId: farmIdVal.value }) : VE_API.home.popupByAgriculturalUserFarms();
+    api.then(({ data }) => {
+        if (Array.isArray(data) && data.length > 0) {
+            show.value = true;
+            farmName.value = data[0].farm?.name;
+            farmIdVal.value = data[0].farm?.id;
+            questPopupData.value = data[0];
+            bottomAnswerOptions.value = transformAnswerOptions(questPopupData.value?.answerOptions);
+        }
+    })
+    .catch(() => {});
 };
 
 function transformAnswerOptions(raw) {
@@ -157,8 +169,9 @@ function onBottomOptionClick(opt) {
     optValue.value = opt.value;
     if (opt.value == 1) {
         eventBus.emit("activeUpload:show", {
-            gardenIdVal: props.farmId,
-            problemTitleVal: "请选择您出现白点的时间",
+            gardenIdVal: farmIdVal.value,
+            arrangeIdVal: questPopupData.value.arrangeId,
+            problemTitleVal: `请选择您出现${questPopupData.value.phenologyName}的时间`,
             typeVal: "question",
         });
     } else {
@@ -169,7 +182,7 @@ function onBottomOptionClick(opt) {
 function saveQuestPopup() {
     const agriDate = getTodayStr();
     const params = {
-        farmId: props.farmId,
+        farmId: farmIdVal.value,
         phenologyId: questPopupData.value.phenologyId,
         indicatorId: questPopupData.value.indicatorId,
         answerValue: optValue.value,
@@ -194,10 +207,17 @@ function getTodayStr() {
     return `${y}-${m}-${day}`;
 }
 const images = ref([]);
+const currentParams = ref({});
 function handleUploadSuccess(params) {
-    images.value = params.images;
+    currentParams.value = params;
+    images.value = params.imagePaths;
+    detailDialogRef.value.showDialog(questPopupData.value.farmWorkLibId, "转发");
+}
+
+const activeUploadPopupRef = ref(null);
+function triggerFarmWork() {
+    activeUploadPopupRef.value.triggerFarmWork(currentParams.value);
     saveQuestPopup();
-    detailDialogRef.value.showDialog("2220003", curRole == 0 ? "咨询专家" : "转发");
 }
 </script>
 <style lang="scss" scoped>

+ 3 - 5
src/views/old_mini/home/index.vue

@@ -42,7 +42,7 @@
         @confirm="handleBtn"
     />
     <!-- 问题提醒 -->
-    <problem-reminder :farmId="gardenId1"></problem-reminder>
+    <problem-reminder></problem-reminder>
 </template>
 
 <script setup>
@@ -66,21 +66,18 @@ const showFarmPopup = ref(false);
 const farmPopupType = ref("create");
 
 const gardenId = ref(null);
-const gardenId1 = ref(null);
 
 const isGarden = ref(false);
 const changeGarden = ({id}) => {
     gardenId.value = id;
-    gardenId1.value = 766;
     getExpertByFarmId();
-    isGarden.value = true;
-    localStorage.setItem('isGarden', true);
 }
 
 const expertInfo = ref({});
 const getExpertByFarmId = () => {
     VE_API.home.getExpertByFarmId({ farmId: gardenId.value }).then(({ data }) => {
         expertInfo.value = data || {};
+        sessionStorage.setItem('expertId',data.appUserId);
     });
 }
 
@@ -145,6 +142,7 @@ const handleBtn = () => {
 };
 
 onActivated(() => {
+    isGarden.value = Boolean(localStorage.getItem('isGarden'));
     // 检测是否从创建农场页面成功返回
     if (route.query.showSuccess === "true") {
         farmPopupType.value = "success";

+ 84 - 4
src/views/old_mini/monitor/subPages/plan.vue

@@ -36,16 +36,29 @@
                                 v-for="(r, rIdx) in Array.isArray(p.reproductiveList) ? p.reproductiveList : []"
                                 :key="r.id ?? rIdx"
                                 class="reproductive-item"
+                                :class="{
+                                    'horizontal-text': getReproductiveItemHeight(p) < 30,
+                                    'vertical-lr-text': getReproductiveItemHeight(p) >= 30
+                                }"
+                                :style="getReproductiveItemHeight(p) < 30 ? { '--item-height': `${getReproductiveItemHeight(p)}px` } : {}"
                             >
                                 {{ r.name }}
-                                <div class="arranges">
+                                <div class="arranges" :class="{ 'no-wrap': getReproductiveItemHeight(p) <= 35 }">
                                     <div
                                         v-for="(fw, aIdx) in Array.isArray(r.farmWorkArrangeList)
                                             ? r.farmWorkArrangeList
                                             : []"
                                         :key="fw.id ?? aIdx"
                                         class="arrange-box"
-                                        :class="getArrangeStatusClass(fw)"
+                                        :class="[
+                                            getArrangeStatusClass(fw),
+                                            {
+                                                'small-height': getReproductiveItemHeight(p) <= 35,
+                                                'two-chars': fw.farmWorkName && fw.farmWorkName.trim().length === 2,
+                                                'text-4-6': fw.farmWorkName && getTextLengthClass(fw.farmWorkName) === 'text-4-6',
+                                                'text-7-8': fw.farmWorkName && getTextLengthClass(fw.farmWorkName) === 'text-7-8'
+                                            }
+                                        ]"
                                         @click="handleRowClick(fw)"
                                     >
                                         <span class="arrange-text">{{ fw.farmWorkName }}</span>
@@ -133,8 +146,8 @@ const getCurrentSeason = () => {
         return "spring"; // 春季:3-5月
     } else if (month >= 6 && month <= 8) {
         return "summer"; // 夏季:6-8月
-    } else if (month >= 9 && month <= 11) {
-        return "autumn"; // 秋季:9-11
+    } else if (month >= 9 && month <= 10) {
+        return "autumn"; // 秋季:9-10
     } else {
         return "winter"; // 冬季:12-2月
     }
@@ -358,6 +371,36 @@ const getArrangeStatusClass = (fw) => {
     if (t === 6) return "status-warning";
     return "status-default";
 };
+
+// 计算 phenology-bar 的高度(px)
+const getPhenologyBarHeight = (item) => {
+    const p1 = Math.max(0, Math.min(100, Number(item?.progress) || 0));
+    const p2 = Math.max(0, Math.min(100, Number(item?.progress2) || 0));
+    const start = Math.min(p1, p2);
+    const end = Math.max(p1, p2);
+    const total = (solarTerms.value?.length || 0) * 100;
+    const heightPx = Math.max(2, ((end - start) / 100) * total);
+    return heightPx;
+};
+
+// 计算 reproductive-item 的高度(px)
+// 由于 reproductive-list 使用 grid-auto-rows: 1fr,每个 item 会等分 phenology-bar 的高度
+const getReproductiveItemHeight = (phenologyItem) => {
+    const barHeight = getPhenologyBarHeight(phenologyItem);
+    const listLength = Array.isArray(phenologyItem?.reproductiveList) ? phenologyItem.reproductiveList.length : 1;
+    // 如果列表为空,返回 barHeight;否则等分
+    return listLength > 0 ? barHeight / listLength : barHeight;
+};
+
+// 根据文字长度返回对应的 class
+const getTextLengthClass = (text) => {
+    if (!text || typeof text !== "string") return "";
+    const len = text.trim().length;
+    if (len > 4 && len <= 6) return "text-4-6";
+    if (len > 6 && len <= 8) return "text-7-8";
+    return "";
+};
+
 </script>
 
 <style scoped lang="scss">
@@ -494,6 +537,18 @@ const getArrangeStatusClass = (fw) => {
                     line-height: 23px;
                     color: inherit;
                     position: relative;
+                    &.horizontal-text {
+                        writing-mode: horizontal-tb;
+                        text-orientation: mixed;
+                        letter-spacing: normal;
+                        line-height: calc(var(--item-height, 15px) - 3px);
+                    }
+                    &.vertical-lr-text {
+                        writing-mode: vertical-lr;
+                        text-orientation: upright;
+                        letter-spacing: 3px;
+                        line-height: 26px;
+                    }
                     .arranges {
                         position: absolute;
                         left: 48px; /* 列与中线右侧一段距离 */
@@ -506,6 +561,9 @@ const getArrangeStatusClass = (fw) => {
                         align-items: center;
                         max-width: calc(100vw - 100px);
                         gap: 16px;
+                        &.no-wrap {
+                            flex-wrap: nowrap;
+                        }
                         .arrange-box {
                             width: 36px;
                             height: 36px;
@@ -520,6 +578,28 @@ const getArrangeStatusClass = (fw) => {
                             position: relative;
                             font-size: 12px;
                             flex-shrink: 0;
+                            &.small-height {
+                                height: 20px;
+                                width: 70px;
+                                &.two-chars {
+                                    width: 35px;
+                                }
+                                &.text-4-6 {
+                                    width: 64px;
+                                }
+                                &.text-7-8 {
+                                    width: 66px;
+                                }
+                                .arrange-text {
+                                    writing-mode: vertical-lr;
+                                }
+                            }
+                            &.text-4-6 {
+                                width: 64px;
+                            }
+                            &.text-7-8 {
+                                width: 66px;
+                            }
                             .arrange-text {
                                 writing-mode: horizontal-tb;
                                 line-height: 14px;

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

@@ -43,7 +43,7 @@
                 @change="handleTabChange"
                 class="tabs-list"
             />
-            <plan-list :schemeId="active" :farmId="route.query.farmId" :containerId="containerId" :isEdit="isEditVal"> </plan-list>
+            <plan-list :schemeId="active" :farmId="route.query.farmId" :containerId="containerId" :isEdit="true"> </plan-list>
         </div>
         <div v-else class="system-generated">
             <div class="tip-box">
@@ -58,7 +58,7 @@
                 @change="handleTabChange"
                 class="tabs-list"
             />
-            <plan-list :schemeId="active" :containerId="containerId" :isEdit="isEditVal"> </plan-list>
+            <plan-list :schemeId="active" :containerId="containerId" :isEdit="false"> </plan-list>
         </div>
     </div>
     <div v-if="route.query.containerId" class="custom-bottom-fixed-btns">
@@ -99,9 +99,6 @@ const containerId = ref(null);
 const handleTabChange = (id, item) => {
     containerId.value = item.containerId;
     active.value = id;
-    if(!route.query.containerId){
-        isEditVal.value = id ? true : false;
-    }
 };
 
 onActivated(() => {
@@ -115,8 +112,6 @@ onDeactivated(() => {
     containerId.value = null;
 });
 
-const isEditVal = ref(false);
-
 const getListMySchemes = () => {
     VE_API.home.listMySchemes().then(({ data }) => {
         if (data.length) {