Przeglądaj źródła

fix: 对接农情互动

lxf 2 tygodni temu
rodzic
commit
e280b476bb

+ 17 - 0
src/api/modules/farm_v3.js

@@ -0,0 +1,17 @@
+const config = require("../config")
+const url = config.base_dev_url + "v3/farm/"
+
+module.exports = {
+    phenologyInitOrConfirmStatus: {
+        url: url + "phenologyInitOrConfirmStatus",
+        type: "get",
+    },
+    initFarmData: {
+        url: url + "initFarmData",
+        type: "post",
+    },
+    confirmReproductivePhenology: {
+        url: url + "confirmReproductivePhenology",
+        type: "post",
+    },
+}

+ 1 - 1
src/components/popup/qrCodePopup.vue

@@ -24,7 +24,7 @@ const showValue = ref(false);
 const props = defineProps({
     closeOnClickOverlay: {
         type: Boolean,
-        default: true,
+        default: false,
     },
 });
 function showPopup() {

+ 2 - 2
src/views/old_mini/home/index.vue

@@ -225,12 +225,12 @@ const handleTitleTagClick = (farmId) => {
     router.push(`/weather_detail?farmId=${farmId}`);
 };
 
-const handleInviteClick = (farmId) => {
+const handleInviteClick = (subjectId) => {
     const query = {
         askInfo: { title: "农情互动", content: "是否分享该互动给好友" },
         shareText: '邀请您农情互动,精准匹配种植方案',
         targetUrl: `interaction`,
-        paramsPage: JSON.stringify({ farmId: farmId }),
+        paramsPage: JSON.stringify({ subjectId }),
         imageUrl: 'https://birdseye-img.sysuimars.com/birdseye-look-mini/work_cover.png',
     };
     wx.miniProgram.navigateTo({

+ 140 - 72
src/views/old_mini/interaction/index.vue

@@ -7,25 +7,25 @@
                 完善作物品种以及物候信息,精准匹配种植方案,实现精细化管理
             </div>
 
-            <!-- 作物块 -->
-            <div v-for="crop in crops" :key="crop.id" class="crop-section">
+            <!-- 作物块(每个农场一块) -->
+            <div v-for="(crop, cropIndex) in farmData" :key="cropIndex" class="crop-section">
                 <div class="crop-header">
-                    <div class="crop-tag">{{ crop.name }}</div>
+                    <div class="crop-tag">{{ crop.speciesName }}</div>
                     <div class="add-btn" @click="addVariety(crop)">+ 新增品种</div>
                 </div>
 
-                <div v-for="variety in crop.varieties" :key="variety.id" class="variety-card">
+                <div v-for="(region, regionIndex) in crop.regions" :key="regionIndex" class="variety-card">
                     <div class="field-row">
                         <div class="field-value">
                             <el-select 
-                                v-model="variety.variety" 
+                                v-model="region.regionId" 
                                 class="variety-input" 
                                 placeholder="选择品种"
                             >
-                                <el-option v-for="item in varietyOptions" :key="item.value" :label="item.label"
-                                    :value="item.value" />
+                                <el-option v-for="(item, index) in crop.typeIdItems" :key="index" :label="item.name"
+                                    :value="item.id" />
                                     <template #footer>
-                                        <el-button text bg @click="onAddOption(variety)">
+                                        <el-button text bg @click="onAddOption(region)">
                                             + 增加品种
                                         </el-button>
                                     </template>
@@ -36,18 +36,26 @@
                     <div class="field-row">
                         <div class="field-label">当下物候期</div>
                         <div class="field-value">
-                            <el-select v-model="variety.currentStage" class="select-input" placeholder="选择物候期"
-                                >
-                                <el-option v-for="item in stageOptions" :key="item.value" :label="item.label"
-                                    :value="item.value" />
+                            <el-select
+                                v-model="region.phenologyId"
+                                class="select-input"
+                                placeholder="选择物候期"
+                            >
+                                <el-option v-for="(item, index) in crop.phenologyOptions" :key="index" :label="item.phenologyName"
+                                    :value="item.phenologyId" />
                             </el-select>
                         </div>
                     </div>
 
-                    <div class="field-row">
-                        <div class="field-label">第一批花穗时间</div>
+                    <div class="field-row" v-if="region.phenologyId">
+                        <div class="field-label">{{ getPhenologyLabel(crop, region.phenologyId) }}</div>
                         <div class="field-value">
-                            <el-date-picker :editable="false" style="width: 100%" v-model="variety.firstFlowerDate" class="date-picker" type="date"
+                            <el-date-picker
+                                :editable="false"
+                                style="width: 100%"
+                                v-model="region.phenologyStartDate"
+                                class="date-picker"
+                                type="date"
                                 placeholder="选择时间" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
                         </div>
                     </div>
@@ -86,70 +94,132 @@
 </template>
 
 <script setup>
-import { ref, nextTick } from "vue";
+import { ref, nextTick, onActivated } from "vue";
+import { ElMessage } from "element-plus";
 import { Popup } from "vant";
 import customHeader from "@/components/customHeader.vue";
 import qrCodePopup from "@/components/popup/qrCodePopup.vue";
+import { useRoute } from "vue-router";
+
+const route = useRoute();
+
+onActivated(() => {
+    const subjectId = route.query.subjectId;
+    getPhenologyInitOrConfirmStatus(subjectId);
+});
 
-// 简单示例数据,后续可替换为接口返回
-const crops = ref([
-    {
-        id: 1,
-        name: "荔枝",
-        varieties: [
-            {
-                id: 1,
-                variety: "",
-                currentStage: "花穗期",
-                firstFlowerDate: "",
-            },
-        ],
-    },
-    {
-        id: 2,
-        name: "水稻",
-        varieties: [
-            {
-                id: 1,
-                variety: "",
-                currentStage: "花穗期",
-                firstFlowerDate: "",
-            },
-        ],
-    },
-]);
+const farmData = ref([])
+const getPhenologyInitOrConfirmStatus = async (subjectId) => {
+    const {data} = await VE_API.farm_v3.phenologyInitOrConfirmStatus({subjectId});
+    farmData.value = data.farms;
+    farmData.value.forEach(item => {
+        addVariety(item);
+    });
+}
 
 const addVariety = (crop) => {
-    const nextId = crop.varieties.length + 1;
-    crop.varieties.push({
-        id: nextId,
-        variety: "",
-        currentStage: "花穗期",
-        firstFlowerDate: "",
+    if (!Array.isArray(crop.regions)) {
+        crop.regions = [];
+    }
+    crop.regions.push({
+        regionId: null,
+        phenologyId: null,
+        phenologyStartDate: "",
     });
 };
 
-// 品种下拉选项(示例)
-const varietyOptions = ref([
-    { label: "桂味", value: "桂味" },
-    { label: "糯米糍", value: "糯米糍" },
-    { label: "妃子笑", value: "妃子笑" },
-    { label: "井岗红糯", value: "井岗红糯" },
-]);
-
-// 物候期选项(示例)
-const stageOptions = ref([
-    { label: "花穗期", value: "花穗期" },
-    { label: "萌芽期", value: "萌芽期" },
-    { label: "抽梢期", value: "抽梢期" },
-    { label: "坐果期", value: "坐果期" },
-]);
+// 获取物候期对应的时间标签
+const getPhenologyLabel = (farm, phenologyId) => {
+    if (!farm?.phenologyOptions) return "选择时间";
+    const found = farm.phenologyOptions.find(
+        (item) => item.id === phenologyId || item.phenologyId === phenologyId
+    );
+    return found?.startDateLabel || "选择时间";
+};
 
 const qrCodePopupRef = ref(null);
 
-const handleConfirm = () => {
-    qrCodePopupRef.value.showPopup();
-}
+const handleConfirm = async () => {
+    // 组装为 initFarmData 接口所需的 farmDataList 结构
+    const farmDataList = farmData.value
+        .map((farm) => {
+            const typeIdItems = (farm.regions || [])
+                .filter(
+                    (r) => r.regionId && r.phenologyId && r.phenologyStartDate
+                )
+                .map((r) => {
+                    const origin =
+                        (farm.typeIdItems || []).find(
+                            (t) => String(t.id) === String(r.regionId)
+                        ) || {};
+                    return {
+                        id: r.regionId,
+                        name: origin.name || "",
+                        phenologyId: r.phenologyId,
+                        phenologyStartDate: r.phenologyStartDate,
+                    };
+                })
+                .filter((item) => item.id);
+
+            return {
+                farmId: farm.farmId,
+                speciesId: farm.speciesId,
+                typeIdItems,
+            };
+        })
+        .filter((item) => item.typeIdItems.length > 0);
+
+    if (!farmDataList.length) {
+        ElMessage.warning("请先选择品种、物候期和时间");
+        return;
+    }
+
+    const params = {
+        expertMiniUserId: 81881,
+        farmDataList,
+    };
+    console.log("params", params);
+
+    const { code, msg } = await VE_API.farm_v3.initFarmData(params);
+    if (code === 0) {
+        qrCodePopupRef.value.showPopup();
+    } else {
+        ElMessage.error(msg || "提交失败");
+    }
+
+    // 大物候期转换所需参数// 组装为后端所需的 farmDataList 结构
+    // const farmDataList = farmData.value
+    //     .map((farm) => {
+    //         const regionPhenologyItems = (farm.regions || [])
+    //             .filter(
+    //                 (r) => r.regionId && r.phenologyId && r.phenologyStartDate
+    //             )
+    //             .map((r) => ({
+    //                 regionId: r.regionId,
+    //                 phenologyId: r.phenologyId,
+    //                 phenologyStartDate: r.phenologyStartDate,
+    //             }));
+
+    //         return {
+    //             farmId: farm.farmId,
+    //             regionPhenologyItems,
+    //         };
+    //     })
+    //     .filter((item) => item.regionPhenologyItems.length > 0);
+
+    // console.log("farmDataList", farmDataList);
+    
+    // const params = {
+    //     farmDataList,
+    //     expertMiniUserId: 81881,
+    // }
+    // const {code, msg} = await VE_API.farm_v3.confirmReproductivePhenology(params);
+    // if(code === 0) {
+    //     qrCodePopupRef.value.showPopup();
+    // } else {
+    //     ElMessage.error(msg);
+    // }
+};
 
 const showAddPopup = ref(false);
 const newVarietyName = ref("");
@@ -159,8 +229,6 @@ const handleAddVariety = () => {
     if (!newVarietyName.value.trim()) {
         return;
     }
-    const newOption = { label: newVarietyName.value, value: newVarietyName.value };
-    varietyOptions.value.push(newOption);
     
     // 如果当前有正在添加品种的 variety,则自动选中新增的品种
     if (currentVariety.value) {
@@ -172,7 +240,7 @@ const handleAddVariety = () => {
     currentVariety.value = null;
 }
 
-const onAddOption = async (variety) => {
+const onAddOption = async (region) => {
     // 先关闭下拉菜单
     if (document.activeElement) {
         document.activeElement.blur();
@@ -181,8 +249,8 @@ const onAddOption = async (variety) => {
     // 等待下拉菜单关闭后再显示弹窗
     await nextTick();
     
-    // 记录当前 variety
-    currentVariety.value = variety;
+    // 记录当前 region
+    currentVariety.value = region;
     showAddPopup.value = true;
 }
 

+ 1 - 1
src/views/old_mini/work_detail/components/executePopup.vue

@@ -119,7 +119,7 @@ const disabledDate = (time) => {
 };
 
 const showRemindValue = ref(false);
-const remindTime = ref("");
+const remindTime = ref(1);
 
 function showRemindPopup() {
     showRemindValue.value = true;

+ 15 - 103
src/views/old_mini/work_detail/index.vue

@@ -35,8 +35,7 @@
                 </div> -->
 
                 <!-- 每一段农事 -->
-                <div v-for="(prescription, index) in stageList" :key="index" class="box-wrap stage-card"
-                    :class="'status-' + prescription.tagType">
+                <div v-for="(prescription, index) in stageList" :key="index" class="box-wrap stage-card">
                     <div class="stage-header">
                         <div class="stage-title">{{ detail.farmWorkName }}</div>
                         <div class="title-tag" :class="'tag-' + prescription.tagType">{{ prescription.tagType === 0 ?
@@ -130,12 +129,6 @@
                             </photo-provider>
                         </div>
                     </div>
-
-                    <!-- 执行操作 -->
-                    <div class="execute-action" v-if="info?.appType === 1 && prescription.tagType === 0">
-                        <div class="action-item second" @click="handleRemind">稍后执行</div>
-                        <div class="action-item primary" @click="handleExecute">我已完成</div>
-                    </div>
                 </div>
 
                 <!-- 底部按钮 -->
@@ -144,6 +137,11 @@
                         转发农事
                     </div>
                 </div>
+
+                <div class="fixed-btn-wrap execute-action" v-if="info?.appType === 1">
+                    <div class="action-item second" @click="handleRemind">稍后执行</div>
+                    <div class="action-item primary" @click="handleExecute">我已完成</div>
+                </div>
             </div>
         </div>
         <ExecutePopup ref="executePopupRef" />
@@ -245,98 +243,17 @@ const detail = ref({
     "isPublic": null,
     "users": [],
     "groupList": [
-        // {
-        //     "name": "蒂蛀虫防治",
-        //     "tagType": 1,
-        //     "cropAlbum": [
-        //         {
-        //             "filename": "6e707c1f-7095-409e-8b3a-2633e7b36bd5/1e2dc0e7-6f8b-4952-a574-8e8e0713529c/DJI_202601251415_001_1e2dc0e7-6f8b-4952-a574-8e8e0713529c/DJI_20260125141713_0003_V_code-ws0gefwtn5n4.jpeg"
-        //         },
-        //         {
-        //             "filename": "dfb387fa-e7d3-4f49-a40c-fcbb9be2baf9/c727d4e9-f5bb-4e40-be2d-efdec3b91702/DJI_202511270800_001_c727d4e9-f5bb-4e40-be2d-efdec3b91702/DJI_20251127080720_0056_V_code-ws0gefyb37kp.jpeg"
-        //         }
-        //     ],
-        //     "pesticideList": [
-        //         {
-        //             "code": "1009",
-        //             "name": "化学水溶肥",
-        //             "typeName": "氮肥",
-        //             "params": [
-        //                 {
-        //                     "dosage": "50",
-        //                     "executionMethod": 1,
-        //                     "ratio": "30000",
-        //                     "remark": "飞行参数设置为***,飞行速度设置为飞行参数设置为***,飞行速度设置为"
-        //                 },
-        //                 {
-        //                     "dosage": "21",
-        //                     "executionMethod": 2,
-        //                     "ratio": "221",
-        //                     "remark": "rengong"
-        //                 },
-        //                 {
-        //                     "dosage": "11",
-        //                     "executionMethod": 3,
-        //                     "ratio": "111",
-        //                     "remark": "dimian"
-        //                 }
-        //             ]
-        //         },
-        //         {
-        //             "code": "1010",
-        //             "name": "化学水溶肥2",
-        //             "typeName": "营养",
-        //             "params": [
-        //                 {
-        //                     "dosage": "0.5",
-        //                     "executionMethod": 1,
-        //                     "ratio": "30000",
-        //                     "remark": "zhibaoji"
-        //                 },
-        //                 {
-        //                     "dosage": "22",
-        //                     "executionMethod": 2,
-        //                     "ratio": "222",
-        //                     "remark": "rengong"
-        //                 },
-        //                 {
-        //                     "dosage": "12",
-        //                     "executionMethod": 3,
-        //                     "ratio": "112",
-        //                     "remark": "dimian"
-        //                 }
-        //             ]
-        //         },
-        //         {
-        //             "code": "1011",
-        //             "name": "化学水溶肥3",
-        //             "typeName": "营养",
-        //             "params": [
-        //                 {
-        //                     "dosage": "60",
-        //                     "executionMethod": 1,
-        //                     "ratio": "30000",
-        //                     "remark": "zhibaoji"
-        //                 },
-        //                 {
-        //                     "dosage": "23",
-        //                     "executionMethod": 2,
-        //                     "ratio": "223",
-        //                     "remark": "rengong"
-        //                 },
-        //                 {
-        //                     "dosage": "13",
-        //                     "executionMethod": 3,
-        //                     "ratio": "113",
-        //                     "remark": "dimian"
-        //                 }
-        //             ]
-        //         }
-        //     ],
-        // },
         {
             "name": "蒂蛀虫防治",
             "tagType": 0,
+            "cropAlbum": [
+                {
+                    "filename": "6e707c1f-7095-409e-8b3a-2633e7b36bd5/1e2dc0e7-6f8b-4952-a574-8e8e0713529c/DJI_202601251415_001_1e2dc0e7-6f8b-4952-a574-8e8e0713529c/DJI_20260125141713_0003_V_code-ws0gefwtn5n4.jpeg"
+                },
+                {
+                    "filename": "dfb387fa-e7d3-4f49-a40c-fcbb9be2baf9/c727d4e9-f5bb-4e40-be2d-efdec3b91702/DJI_202511270800_001_c727d4e9-f5bb-4e40-be2d-efdec3b91702/DJI_20251127080720_0056_V_code-ws0gefyb37kp.jpeg"
+                }
+            ],
             "pesticideList": [
                 {
                     "code": "1009",
@@ -600,10 +517,6 @@ const changeExecutionMethod = (stageIndex, value) => {
     padding: 14px 10px 10px 10px;
     box-shadow: 0 2px 8px rgba(15, 35, 52, 0.06);
     border: 1px solid transparent;
-
-    &.status-0 {
-        border: 1px solid #FF953D;
-    }
 }
 
 .photo-box {
@@ -835,7 +748,6 @@ const changeExecutionMethod = (stageIndex, value) => {
 }
 
 .execute-action {
-    margin-top: 8px;
     display: flex;
     align-items: center;
     justify-content: center;
@@ -870,7 +782,7 @@ const changeExecutionMethod = (stageIndex, value) => {
     left: 0;
     right: 0;
     background: #fff;
-    padding: 10px 12px;
+    padding: 10px 12px 16px 12px;
     box-sizing: border-box;
     // box-shadow: 0 -2px 8px rgba(15, 35, 52, 0.06);
     box-shadow: 2px 2px 4.5px 0px #00000066;