Prechádzať zdrojové kódy

Merge branch 'master' of http://www.sysuimars.cn:3000/feiniao/feiniao-farm-h5

wangsisi 2 dní pred
rodič
commit
ea427534b2

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

@@ -45,7 +45,7 @@ module.exports = {
     },
     //更新农事编排信息
     updateFarmWorkArrange: {
-        url: config.base_dev_url + "container_farm_work_arrange/update",
+        url: config.base_dev_url + "container_farm_work_arrange/save",
         type: "post",
     },
     //批量保存多个物候期的农场自定义时间

+ 4 - 6
src/views/old_mini/agri_work/components/priceTable.vue

@@ -11,18 +11,16 @@
             </div>
             <div
                 class="new-table-wrap"
-                v-for="(prescriptionItem, prescriptionI) in prescriptionData"
-                :key="prescriptionI"
             >
                 <div
                     class="new-prescription"
-                    v-for="(subP, subI) in prescriptionItem.pesticideFertilizerList"
+                    v-for="(subP, subI) in prescriptionData.pesticideFertilizerList"
                     :key="subI"
                 >
                     <div class="new-table">
                         <div class="line-l">
                             <div class="line-1 title-1">{{ subP.typeName }}</div>
-                            <div class="line-2">{{ subP.defaultName || subP.pesticideFertilizerName }}</div>
+                            <div class="line-2">{{ subP.name || subP.defaultName || subP.pesticideFertilizerName }}</div>
                             <div class="title-3">{{ subP.brand }}</div>
                             <div class="title-4">{{ subP.price }}</div>
                             <div class="title-5">{{ subP.dosage }}</div>
@@ -40,10 +38,10 @@
 <script setup>
 const props = defineProps({
     prescriptionData: {
-        type: Array,
-        default: () => []
+        default: () => {}
     }
 });
+
 </script>
 
 <style lang="scss" scoped>

+ 388 - 53
src/views/old_mini/modify_work/modify.vue

@@ -11,24 +11,16 @@
                 class="demo-dynamic"
             >
                 <div class="farm-card">
-                    <div class="card-title between">
+                    <div class="card-title between common-inputs">
                         <div>{{ detailData?.name }}<span class="type-tag">标准农事</span></div>
-                        <el-popover
-                            title=""
-                            v-if="isEdit"
-                            :popper-style="'min-width: 110px;'"
-                            :width="110"
-                            placement="left-start"
-                            trigger="click"
-                        >
-                            <div class="tag-list">
-                                <div class="tag-item">托管农事</div>
-                                <div class="tag-item active">特别关注</div>
-                            </div>
-                            <template #reference>
-                                <div class="title-tag add-tag">标记为</div>
-                            </template>
-                        </el-popover>
+                        <el-select v-if="isEdit" size="small" v-model="tagName" placeholder="标记为" style="width: 94px">
+                            <el-option
+                            v-for="item in tagList"
+                            :key="item.value"
+                            :label="item.label"
+                            :value="item.value"
+                            />
+                        </el-select>
                         <div class="edit-tag tag-text" v-else>托管农事</div>
                         <!-- <el-tooltip
                             effect="dark"
@@ -90,9 +82,53 @@
                         <div>农情互动</div>
                         <!-- <span class="del-tag">删除互动</span> -->
                     </div>
-                    <div class="interact-content">
+                    <div v-if="isEdit" class="interact-form">
+                        <div class="interact-form-item" data-interact-field="phenologyId">
+                            <div class="form-label">
+                                互动时间
+                            </div>
+                            <div class="form-input-wrapper">
+                                <el-select style="width: 100%" v-model="interactFormData.phenologyId" placeholder="请选择物候期" :editable="false">
+                                    <el-option
+                                        v-for="item in phenologyList"
+                                        :key="item.id"
+                                        :label="item.name"
+                                        :value="item.id"
+                                    ></el-option>
+                                </el-select>
+                            </div>
+                        </div>
+                        <div class="interact-form-item" data-interact-field="interactionTime">
+                            <div class="form-label">
+                                强制触发
+                            </div>
+                            <div class="form-input-wrapper">
+                                <el-date-picker
+                                    v-model="interactFormData.interactionTime"
+                                   
+                                    style="width: 100%"
+                                    type="date"
+                                    placeholder="请选择日期"
+                                    :editable="false"
+                                />
+                            </div>
+                        </div>
+                        <div class="interact-form-item" data-interact-field="interactionQuestion">
+                            <div class="form-label">
+                                互动问题
+                            </div>
+                            <el-input
+                                v-model="interactFormData.interactionQuestion"
+                                type="textarea"
+                                :rows="4"
+                                placeholder="请设置互动问题"
+                                class="question-textarea"
+                            />
+                        </div>
+                    </div>
+                    <div v-else class="interact-content">
                         {{ detailData?.warmReminder }}
-                        <span class="edit-tag" @click="handleEditInteract(detailData)">点击编辑</span>
+                        <!-- <span class="edit-tag" @click="handleEditInteract(detailData)">点击编辑</span> -->
                     </div>
                 </div>
 
@@ -184,7 +220,7 @@
                                                 </div>
 
                                                 <div class="mt-8">
-                                                    <div class="box-item sub-item">
+                                                    <div class="box-item sub-item" :data-ratio-index="index">
                                                         <div class="form-l has-sub">
                                                             <div class="main-name">亩兑水量</div>
                                                             <div class="sub-name">(药剂:兑水量)</div>
@@ -201,17 +237,12 @@
                                                             </el-input>
                                                         </div>
                                                     </div>
-                                                    <div class="box-item sub-item">
+                                                    <div class="box-item sub-item" :data-dosage-index="index">
                                                         <div class="form-l has-sub">
                                                             <div class="main-name">单亩用量</div>
                                                             <div class="sub-name">(亩数:药剂)</div>
                                                         </div>
                                                         <div class="form-r input-box text-center">
-                                                            <!-- <el-input
-                                                            v-model="domain.muUsage"
-                                                            style="width: 100%"
-                                                            placeholder="请输入"
-                                                        /> -->
                                                             <el-input
                                                                 v-model="domain.dosage"
                                                                 type="number"
@@ -266,6 +297,7 @@
                             >
                                 <div
                                     class="medicine-box"
+                                    :data-price-index="mIndex"
                                 >
                                     <div class="form-index">药肥{{ mIndex + 1 }}</div>
                                     <div class="box-wrap">
@@ -412,7 +444,7 @@
                             </div>
                         </div>
                         <div class="info-content-wrap">
-                            <price-table :prescriptionData="dynamicValidateForm.prescription.prescriptionList">
+                            <price-table :prescriptionData="dynamicValidateForm.prescription">
                                 <template #bottomContent>
                                     <div class="price-bottom">
                                         <div class="info-title-wrap">
@@ -436,10 +468,8 @@
                                             </div>
                                             <div class="info-c">
                                                 亩单价<span class="main-text">{{
-                                                    quotationData.farmWorkServiceCost ||
-                                                    quotationData.manualServicePrice
-                                                        ? (quotationData.farmWorkServiceCost ||
-                                                              quotationData.manualServicePrice) + "元/亩"
+                                                    quotationData.serviceMuPrice
+                                                        ? (quotationData.serviceMuPrice) + "元/亩"
                                                         : "--"
                                                 }}</span>
                                             </div>
@@ -496,6 +526,21 @@ const store = useStore();
 const router = useRouter();
 const route = useRoute();
 
+const tagList = ref([
+    { label: "托管农事", value: 2 },
+    { label: "特别关注", value: 1 },
+    { label: "取消关注", value: 0 },
+]);
+
+const tagName = ref("");
+
+// 互动表单数据
+const interactFormData = ref({
+    phenologyId: "",
+    interactionTime: "",
+    interactionQuestion: "",
+});
+const phenologyList = ref([]);
 
 const isEdit = ref(true);
 
@@ -532,7 +577,7 @@ const showPriceSheetPopup = () => {
 
 const detailData = ref({});
 const getDetail = async () => {
-    const { data, code } = await VE_API.farm.getFarmWorkLib({ id: route.query.farmWorkId, farmId: route.query.farmId });
+    const { data, code } = await VE_API.farm.getFarmWorkLib({ id: route.query.farmWorkId, farmId: route.query.farmId, agriculturalId: route.query.agriculturalStoreId });
     if(code === 0) {
         detailData.value = data;
         dynamicValidateForm.executeDate = data.executeDate;
@@ -542,9 +587,22 @@ const getDetail = async () => {
             usageMode: "",
             pesticideFertilizerList: [],
         };
-        servicePricePerMu.value = detailData.value.farmWorkServiceCost || null;
+        servicePricePerMu.value = detailData.value.serviceMuPrice || null;
         const pesticideFertilizerCodes = data.prescription.pesticideFertilizerList.map(item => item.code);
         getPriceList(data.schemeId, pesticideFertilizerCodes);
+        
+        // 加载互动表单数据
+        if (data.id) {
+            // 重置互动表单数据
+            interactFormData.value = {
+                phenologyId: "",
+                interactionTime: "",
+                interactionQuestion: "",
+            };
+            // 按照 interactPopup.vue 的方式获取数据
+            await getPhenologyList(data.containerSpaceTimeId || route.query.containerSpaceTimeId);
+            await getFarmWorkArrangeDetail(route.query.id);
+        }
     }
 };
 
@@ -558,6 +616,9 @@ const getPriceList = async (schemeId, pesticideFertilizerCodes) => {
         item.price = priceInfo.price ?? item.price;
         item.brand = priceInfo.brand ?? item.brand;
     });
+
+    quotationData.value = {...detailData.value, ...dynamicValidateForm};
+    console.log('quotationData.value', quotationData.value)
 };
 
 const toEditPrescription = () => {
@@ -653,11 +714,11 @@ const modeList = ref([
 ]);
 
 const handleExecutionMethodChange = (index, val) => {
-    if (val == 1) {
-        servicePricePerMu.value = detailData.value.uavServicePrice;
-    } else {
-        servicePricePerMu.value = detailData.value.manualServicePrice;
-    }
+    // if (val == 1) {
+    //     servicePricePerMu.value = detailData.value.uavServicePrice;
+    // } else {
+    //     servicePricePerMu.value = detailData.value.manualServicePrice;
+    // }
 };
 
 // 表单
@@ -767,7 +828,8 @@ const handlePesticideFertilizerChange = (index) => {
             name: obj.name || obj.defaultName,
             typeName: obj.typeName,
             unit: obj.unit,
-            ratio: obj.defaultRatio || currentItem.ratio,
+            ratio: "", // 清空亩兑水量
+            dosage: "", // 清空单亩用量
             executeStyle: obj.executionMethod || 1,
         };
     }
@@ -799,15 +861,28 @@ const servicePricePerMu = ref(null);
 
 // 计算服务费用总计:亩单价 * 亩数
 const getServiceTotal = () => {
-    if (!servicePricePerMu.value || !detailData.value.area) return "--";
-    const total = (servicePricePerMu.value * detailData.value.area).toFixed(2);
+    const price = Number(servicePricePerMu.value || 0);
+    const area = Number(detailData.value?.farm?.mianji || detailData.value?.area || 0);
+    if (!price || !area) return "--";
+    const total = (price * area).toFixed(2);
     return total;
 };
 
 const submitForm = (formEl) => {
     if (!formEl) return;
-    formEl.validate((valid) => {
+    formEl.validate(async (valid) => {
         if (valid) {
+            // 校验农情互动,不通过,直接返回失败
+            if (!validateInteractForm()) return false;
+
+            // 校验药肥的亩兑水量和单亩用量是否填写
+            if (!validatePesticideDosage()) return;
+
+            // 保存报价信息前先校验是否填写完整
+            if (!validatePriceInfos()) return;
+
+            // 检验服务报价是否填写
+            if (!validateServicePrice()) return;
             submit();
         } else {
             console.log("error submit!");
@@ -815,13 +890,68 @@ const submitForm = (formEl) => {
     });
 };
 
+// 检验服务报价是否填写
+const validateServicePrice = () => {
+    if (!servicePricePerMu.value) {
+        ElMessage.warning("请完善服务报价信息");
+        return false;
+    }
+    return true;
+};
+
+// 校验药肥的亩兑水量和单亩用量是否填写
+const validatePesticideDosage = () => {
+    const list = dynamicValidateForm.prescription?.pesticideFertilizerList || [];
+    if (!list.length) return true; // 没有药肥就不校验
+
+    // 找到第一个未填写完整的药肥
+    for (let i = 0; i < list.length; i++) {
+        const item = list[i];
+        // 如果选择了药肥(有 code),就必须填写亩兑水量和单亩用量
+        if (item.code) {
+            const hasRatio = item.ratio !== undefined && item.ratio !== null && item.ratio !== "";
+            const hasDosage = item.dosage !== undefined && item.dosage !== null && item.dosage !== "";
+            
+            if (!hasRatio || !hasDosage) {
+                ElMessage.warning("请完善药物处方信息");
+                return false;
+            }
+        }
+    }
+    return true;
+};
+
+// 校验报价信息是否填写完整
+const validatePriceInfos = () => {
+    const list = dynamicValidateForm.prescription?.pesticideFertilizerList || [];
+    if (!list.length) return true; // 没有药肥就不校验
+
+    // 找到第一个未填写完整的药肥
+    const invalidIndex = list.findIndex((item) => {
+        // 只要选择了药肥(有 id),就必须填写单价和品牌
+        if (!item.id) return false; // 没选择药肥不校验
+        const hasPrice = item.price !== undefined && item.price !== null && item.price !== "";
+        const hasBrand = !!item.brand;
+        return !hasPrice || !hasBrand;
+    });
+
+    if (invalidIndex !== -1) {
+        ElMessage.warning("请先完善报价信息");
+        return false;
+    }
+    return true;
+};
+
 const submit = () => {
     const data = {
         id: route.query.farmWorkId,
         ...dynamicValidateForm,
+        serviceMuPrice: servicePricePerMu.value,
         prescription: dynamicValidateForm.prescription
     };
     VE_API.monitor.saveFarmWorkLib(data);
+    
+    handleSaveInteract()
 
     // 保存报价信息
     const priceList = {
@@ -841,20 +971,13 @@ const submit = () => {
             isEdit.value = false;
         }
     });
-    // VE_API.z_farm_work_record.issueFarmWorkRecord(data).then(async (res) => {
-    //     if (res.code === 0) {
-    //         await getDetail();
-    //         showPriceSheetPopup();
-    //     }
-    // });
-};
 
-const handleSaveInteractSuccess = () => {
-    // getDetail(route.query.id);
+    // 切换标记
+    VE_API.container_farm_work_arrange.toggleFollow({ id: route.query.farmWorkId, isFollow: tagName.value });
 };
 
-const handleDeleteInteract = () => {
-    // getDetail(route.query.id);
+const handleSaveInteractSuccess = () => {
+    getDetail();
 };
 
 const interactPopupRef = ref(null);
@@ -863,6 +986,117 @@ const handleEditInteract = (item) => {
         interactPopupRef.value.showPopup({...item, containerSpaceTimeId: route.query.containerSpaceTimeId,id:route.query.id});
     }
 };
+
+// 获取物候期列表
+const getPhenologyList = async (containerSpaceTimeId) => {
+    if (!containerSpaceTimeId) {
+        phenologyList.value = [];
+        return;
+    }
+    const res = await VE_API.monitor.listPhenology({ containerSpaceTimeId });
+    if (res.code === 0) {
+        phenologyList.value = res.data || [];
+    }
+};
+
+// 获取互动设置详情
+const getFarmWorkArrangeDetail = async (id) => {
+    if (!id) return;
+    const { data, code } = await VE_API.farm.getFarmWorkArrangeDetail({ id });
+    if(code === 0) {
+        tagName.value = data.isFollow;
+        interactFormData.value = {
+            phenologyId: data.phenologyId || "",
+            interactionTime: data.interactionTime || "",
+            interactionQuestion: data.interactionQuestion || "",
+        };
+    }
+};
+
+// 格式化日期
+const formatInteractDate = (date) => {
+    // 如果已经是字符串格式 YYYY-MM-DD,直接返回
+    if (typeof date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(date)) {
+        return date;
+    }
+    // 如果是 Date 对象,进行转换
+    if (date instanceof Date) {
+        let year = date.getFullYear();
+        let month = String(date.getMonth() + 1).padStart(2, "0");
+        let day = String(date.getDate()).padStart(2, "0");
+        return `${year}-${month}-${day}`;
+    }
+    // 其他情况返回原值
+    return date;
+};
+
+// 验证互动表单
+const validateInteractForm = () => {
+    if (!interactFormData.value.phenologyId) {
+        ElMessage.warning("请选择互动时间");
+        return false;
+    }
+    if (!interactFormData.value.interactionTime) {
+        ElMessage.warning("请选择强制触发时间");
+        return false;
+    }
+    if (!interactFormData.value.interactionQuestion?.trim()) {
+        ElMessage.warning("请设置互动问题");
+        return false;
+    }
+    return true;
+};
+
+// 保存互动设置
+const handleSaveInteract = async () => {
+
+    const paramsObj = {
+        id: route.query.id,
+        ...interactFormData.value,
+        interactionTime: formatInteractDate(interactFormData.value.interactionTime),
+    };
+
+    try {
+        const res = await VE_API.monitor.updateFarmWorkArrange(paramsObj);
+        if (res.code !== 0) {
+            ElMessage.error(res.message || "保存农情互动信息失败");
+            return false;
+        }
+        return true;
+    } catch (error) {
+        console.error("保存互动设置失败:", error);
+        ElMessage.error("保存失败,请重试");
+        return false;
+    }
+};
+
+// 删除互动设置
+const handleDeleteInteract = () => {
+    ElMessageBox.confirm("确定要删除该互动设置吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+    })
+        .then(async () => {
+            if (!detailData.value.id) return;
+            const res = await VE_API.monitor.deleteFarmWorkArrange({ id: detailData.value.id });
+            if (res.code === 0) {
+                ElMessage.success("删除成功");
+                // 清空表单数据
+                interactFormData.value = {
+                    phenologyId: "",
+                    interactionTime: "",
+                    interactionQuestion: "",
+                };
+                await getDetail(); // 重新获取详情
+            } else {
+                ElMessage.error(res.message || "删除失败");
+            }
+        })
+        .catch(() => {
+            // 用户取消,不做任何操作
+        });
+};
 </script>
 
 <style lang="scss" scoped>
@@ -1393,6 +1627,107 @@ const handleEditInteract = (item) => {
         color: #919191;
         font-size: 12px;
     }
+    .interact-form {
+        padding: 8px 0 20px 0px;
+
+        .interact-form-item {
+            display: flex;
+            align-items: baseline;
+            margin-bottom: 12px;
+
+            &:last-child {
+                margin-bottom: 0;
+            }
+
+            .form-label {
+                width: 70px;
+                color: rgba(0, 0, 0, 0.4);
+                font-weight: normal;
+                margin-right: 10px;
+                font-size: 14px;
+                flex: none;
+            }
+
+            .form-input-wrapper {
+                position: relative;
+                width: calc(100% - 70px);
+                ::v-deep {
+                    .el-input__inner {
+                        caret-color: transparent;
+                        padding-right: 40px;
+                    }
+
+                    .el-input__suffix {
+                        display: none;
+                    }
+                }
+            }
+
+            .question-textarea {
+                ::v-deep {
+                    .el-textarea__inner {
+                        resize: none;
+                        line-height: 1.5;
+                        min-height: 80px;
+                    }
+                }
+            }
+        }
+
+        .interact-buttons {
+            display: flex;
+            gap: 12px;
+            padding-top: 16px;
+
+            .btn-delete,
+            .btn-save {
+                flex: 1;
+                padding: 8px;
+                border-radius: 25px;
+                font-size: 16px;
+                text-align: center;
+                cursor: pointer;
+                transition: all 0.3s;
+                user-select: none;
+            }
+
+            .btn-delete {
+                background: #ffffff;
+                border: 1px solid #ff4d4f;
+                color: #ff4d4f;
+
+                &:hover {
+                    background: #fff5f5;
+                }
+
+                &:active {
+                    opacity: 0.8;
+                    transform: scale(0.98);
+                }
+            }
+
+            .btn-save {
+                background: #2199f8;
+                color: #fff;
+                border: none;
+
+                &:hover:not(.disabled) {
+                    background: #1a8ae6;
+                }
+
+                &:active:not(.disabled) {
+                    opacity: 0.9;
+                    transform: scale(0.98);
+                }
+
+                &.disabled {
+                    opacity: 0.6;
+                    cursor: not-allowed;
+                    pointer-events: none;
+                }
+            }
+        }
+    }
     .edit-tag {
         padding-left: 4px;
         color: #2199f8;

+ 1 - 1
src/views/old_mini/monitor/subPages/plan.vue

@@ -377,7 +377,7 @@ const handleRowClick = (item) => {
     curFarmObj.value = item;
     router.push({
         path: "/modify",
-        query: { id: item.id, farmId: route.query.farmId, farmWorkId: item.farmWorkId, containerSpaceTimeId: item.containerSpaceTimeId },
+        query: { id: item.id, farmId: route.query.farmId, farmWorkId: item.farmWorkId, containerSpaceTimeId: item.containerSpaceTimeId, agriculturalStoreId: route.query.agriculturalStoreId },
     });
 };
 

+ 1 - 1
src/views/old_mini/user/farmDetails.vue

@@ -320,7 +320,7 @@ const getFarmPastServiceCost = () => {
     });
 };
 const handleDetail = (path) => {
-    router.push(`/${path}?farmId=${farmIdVal.value}`);
+    router.push(`/${path}?farmId=${farmIdVal.value}&agriculturalStoreId=${route.query.agriculturalStoreId}`);
 };
 
 const handleShareReport = () => {

+ 3 - 3
src/views/old_mini/user/index.vue

@@ -64,7 +64,7 @@
                                         <div class="farm-info-footer-item-value">1450<span class="unit">元</span></div>
                                     </div>
                                 </div>
-                                <div class="footer-action" @click.stop="handleDetail('plan', ele.id)">农事规划</div>
+                                <div class="footer-action" @click.stop="handleDetail('plan', ele.id, ele.agriculturalStoreId)">农事规划</div>
                             </div>
                         </template>
                     </farm-info-card>
@@ -201,8 +201,8 @@ const handleItemClick = (data) => {
     router.push(`/farm_details?farmId=${data.id}&agriculturalStoreId=${data.agriculturalStoreId}&receiveUserId=${data.receiveUserId}`);
 };
 
-const handleDetail = (path, farmId) => {
-    router.push(`/${path}?farmId=${farmId}`);
+const handleDetail = (path, farmId, agriculturalStoreId) => {
+    router.push(`/${path}?farmId=${farmId}&agriculturalStoreId=${agriculturalStoreId}`);
 };
 </script>