浏览代码

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

lxf 1 月之前
父节点
当前提交
c4c7e82ca1

+ 5 - 0
src/api/modules/farm.js

@@ -42,4 +42,9 @@ module.exports = {
         url: config.base_dev_url + "v2/farm/deleteFarm",
         type: "get",
     },
+    //查询单个农事编排信息
+    getFarmWorkArrangeDetail: {
+        url: config.base_dev_url + "container_farm_work_arrange/get",
+        type: "get",
+    },
 }

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

@@ -30,5 +30,10 @@ module.exports = {
     getFarmPastServiceCost: {
         url: config.base_dev_url + "z_farm_work_record_cost/statistics",
         type: "get",
-    }
+    },
+    //农资查询服务农场的最新广播
+    getLatestBroadcast: {
+        url: config.base_dev_url + "farm_broadcast/latestByServiceFarm",
+        type: "post",
+    },
 }

+ 16 - 1
src/api/modules/z_farm_work_record.js

@@ -46,5 +46,20 @@ module.exports = {
     getOrderReceivingSimpleList:{
         url: url + "/getOrderReceivingSimpleList",
         type: "get",
-    }
+    },
+    //根据城市的坐标返回区县列表
+    getDistrictListByCity:{
+        url: config.base_dev_url + "city/districtListbyPoint",
+        type: "get",
+    },
+    //农资关注农场
+    followFarm: {
+        url: config.base_dev_url + "z_agricultural_store_farm/follow",
+        type: "post",
+    },
+    //农资取消关注农场
+    unfollowFarm: {
+        url: config.base_dev_url + "z_agricultural_store_farm/unfollow",
+        type: "post",
+    },
 }

+ 25 - 27
src/components/pageComponents/FarmInfoCard.vue

@@ -30,34 +30,29 @@
             </slot>
         </div>
         <!-- 底部提示框:需求信息和预计收益 -->
-        <template v-if="showBottomTip">
+        <template v-if="data.broadcasts && data.broadcasts.length > 0">
             <slot name="bottomTip">
-                <div class="item-footer remind-footer" v-if="data.day">
-                    <div>
-                        距离农事执行已
-                        <span class="service-count">{{ data.day }}</span>
-                        天,提醒用户拍照!
-                    </div>
+                <div class="item-footer remind-footer">
+                    <div class="remind-cont" v-html="data.broadcasts[0].content"></div>
                     <span class="remind-text" @click.stop="handleRemind">提醒他</span>
                 </div>
-                <div class="item-footer item-bottom-tip" v-if="data.estimatedIncome">
+                <!-- <div class="item-footer item-bottom-tip" v-if="data.estimatedIncome">
                     <div>
                         当前农场有 <span>{{ data.farmInfo }}</span> 的农情需求
                     </div>
                     <div class="income-text">
                         预计收益 <span>{{ data.estimatedIncome }}元</span>
                     </div>
-                </div>
+                </div> -->
             </slot>
         </template>
-        <share-sheet class="share-sheet" teleport="#app" v-model:show="showShare" title="立即分享给好友" :options="options" @select="onSelect" />
+        <upload-execute ref="uploadExecuteRef" :onlyShare="true" />
     </div>
 </template>
 
 <script setup>
 import { computed, useSlots, ref } from "vue";
-import { ShareSheet } from "vant";
-
+import uploadExecute from "@/views/old_mini/task_condition/components/uploadExecute.vue";
 const props = defineProps({
     data: {
         type: Object,
@@ -83,25 +78,19 @@ const hasRightSlot = computed(() => {
     return !!slots.right;
 });
 
-const showBottomTip = computed(() => {
-    return props.data.day !== undefined || props.data.estimatedIncome !== undefined || !!slots.bottomTip;
-});
-
 const handleClick = () => {
     emit("click", props.data);
 };
 
-const showShare = ref(false);
-const options = [
-    { name: "飞鸟用户", icon: "https://birdseye-img.sysuimars.com/birdseye-look-mini/Group%201321316260.png" },
-    { name: "微信", icon: "wechat" },
-];
-const onSelect = (option) => {
-    showShare.value = false;
-    console.log(option);
-};
+const uploadExecuteRef = ref(null);
 const handleRemind = () => {
-    showShare.value = true;
+    // const data = {
+    //     ...props.data,
+    //     farmMiniUserId: props.data.receiveUserId,
+    //     farmId: props.data.id,
+    //     type: "remindUser"
+    // }
+    // uploadExecuteRef.value.showPopup(data);
 };
 </script>
 
@@ -193,9 +182,18 @@ const handleRemind = () => {
         &.remind-footer {
             justify-content: space-between;
         }
-        span {
+        .remind-cont{
+            width: calc(100% - 42px);
+            ::v-deep{
+                p{
+                    margin: 0;
+                }
+            }
+        }
+        .remind-text {
             color: #2199f8;
             font-weight: 500;
+            width: 40px;
         }
         .service-count {
             margin: 0 2px;

+ 123 - 0
src/components/pageComponents/LocationSearch.vue

@@ -0,0 +1,123 @@
+<template>
+    <el-select
+        v-model="locationVal"
+        filterable
+        remote
+        clearable
+        reserve-keyword
+        placeholder="搜索位置"
+        :remote-method="remoteMethod"
+        :loading="loading"
+        @change="handleSearchRes"
+        popper-class="location-search-popper"
+        :class="customClass"
+        @clear="handleClear"
+    >
+        <el-option
+            v-for="(item, index) in locationOptions.list"
+            :key="index"
+            :label="item.title"
+            :value="{ value: item.point, item }"
+        >
+            <span>{{ item.title }}</span>
+            <span class="sub-title">{{ item.province }}{{ item.city }}{{ item.district }}</span>
+        </el-option>
+    </el-select>
+</template>
+
+<script setup>
+import { ref, reactive } from "vue";
+import { transformFromGCJToWGS } from "@/utils/WSCoordinate.js";
+
+const MAP_KEY = "CZLBZ-LJICQ-R4A5J-BN62X-YXCRJ-GNBUT";
+
+const props = defineProps({
+    userLocation: {
+        type: String,
+        default: "113.61702297075017,23.584863449735067",
+    },
+    customClass: {
+        type: String,
+        default: "",
+    },
+});
+
+const emit = defineEmits(["change"]);
+
+const locationVal = ref(null);
+const locationOptions = reactive({
+    list: [],
+});
+const loading = ref(false);
+
+const remoteMethod = async (keyword) => {
+    if (keyword) {
+        locationOptions.list = [];
+        loading.value = true;
+        const params = {
+            key: MAP_KEY,
+            keyword,
+            location: props.userLocation,
+        };
+        await VE_API.old_mini_map.getCtiyList({ word: keyword }).then(({ data }) => {
+            if (data && data.length) {
+                data.forEach((item) => {
+                    item.point = item.location.lat + "," + item.location.lng;
+                    locationOptions.list.push(item);
+                });
+            }
+        });
+        VE_API.old_mini_map.search(params).then(({ data }) => {
+            loading.value = false;
+            data.forEach((item) => {
+                item.point = item.location.lat + "," + item.location.lng;
+                locationOptions.list.push(item);
+            });
+        });
+    } else {
+        locationOptions.list = [];
+    }
+};
+
+const handleSearchRes = (v) => {
+    if (!v) return;
+    const parts = v.value.split(",");
+    let { latitude, longitude } = transformFromGCJToWGS(parseFloat(parts[0]), parseFloat(parts[1]));
+    const coordinateArray = [longitude, latitude];
+    
+    emit("change", {
+        coordinateArray,
+        point: `POINT (${coordinateArray[0]} ${coordinateArray[1]})`,
+        address: v.item?.title || v.item?.address,
+        pointAddress: v.item?.province + v.item?.city + v.item?.district,
+        city: v.item?.city + v.item?.district || '',
+        item: v.item,
+    });
+};
+
+const handleClear = () => {
+    emit("change", {
+        coordinateArray: null,
+        point: null,
+        address: null,
+    });
+    locationVal.value = null;
+    locationOptions.list = [];
+    loading.value = false;
+};
+</script>
+
+<style lang="scss">
+.location-search-popper {
+    .el-select-dropdown__list {
+        max-width: 96vw;
+        overflow-x: auto;
+    }
+    .sub-title {
+        padding-left: 6px;
+        font-size: 12px;
+        color: #ccc;
+    }
+}
+</style>
+

+ 324 - 0
src/components/pageComponents/ServiceInfo.vue

@@ -0,0 +1,324 @@
+<template>
+    <div class="service-info">
+        <div class="main-content">
+            <div class="service-title">
+                <img class="label-icon" src="@/assets/img/home/label-icon.png" alt="">
+                服务信息
+            </div>
+            <div class="service-content">
+                <div class="service-item">
+                    <div class="sub-title">服务作物</div>
+                    <div class="tag-group" v-if="!isEdit">
+                        <div class="tag-item" v-for="(item, idx) in crops" :key="'c-'+idx">{{ item.name }}</div>
+                    </div>
+                    <div class="tag-group add-tag-group" v-else>
+                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in crops" :key="'ce-'+idx">
+                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name, 'crops')" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
+                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('crops', idx)"><Close /></el-icon>
+                        </div>
+                        <div class="tag-item last-add" @click="handleAdd('作物')"><el-icon class="add-icon"><Plus /></el-icon>作物</div>
+                    </div>
+                </div>
+                <div class="service-item">
+                    <div class="sub-title">服务类型</div>
+                    <div class="tag-group" v-if="!isEdit">
+                        <div class="tag-item" v-for="(item, idx) in serviceTypes" :key="'t-'+idx">{{ item.name }}</div>
+                    </div>
+                    <div class="tag-group add-tag-group" v-else>
+                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in serviceTypes" :key="'te-'+idx">
+                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name, 'serviceTypes')" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
+                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('serviceTypes', idx)"><Close /></el-icon>
+                        </div>
+                        <div class="tag-item last-add" @click="handleAdd('类型')"><el-icon class="add-icon"><Plus /></el-icon>类型</div>
+                    </div>
+                </div>
+                <div class="service-item">
+                    <div class="sub-title">农机设备</div>
+                    <div class="tag-group" v-if="!isEdit">
+                        <div class="tag-item" v-for="(item, idx) in machines" :key="'m-'+idx">{{ item.name }}</div>
+                    </div>
+                    <div class="tag-group add-tag-group" v-else>
+                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in machines" :key="'me-'+idx">
+                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name, 'machines')" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
+                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('machines', idx)"><Close /></el-icon>
+                        </div>
+                        <div class="tag-item last-add" @click="handleAdd('设备')"><el-icon class="add-icon"><Plus /></el-icon>设备</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <popup class="add-tag-popup" round v-model:show="showAddPopup">
+            <div class="popup-title" v-if="isEditPopup">编辑标签</div>
+            <div class="popup-title" v-else>添加{{addTypeName}}<span class="ml-2">标签</span></div>
+            <el-input class="popup-input" v-model="input" placeholder="标签" size="large" />
+            <div class="popup-button">
+                <div class="cancel" @click="showAddPopup = false">取消</div>
+                <div @click="handleConfirm">{{isEditPopup ? '确定' : '添加'}}</div>
+            </div>
+        </popup>
+    </div>
+</template>
+
+<script setup>
+import { ref } from "vue";
+import { Popup } from "vant";
+import { Edit, Close, Plus } from '@element-plus/icons-vue'
+
+const props = defineProps({
+    crops: {
+        type: Array,
+        default: () => []
+    },
+    serviceTypes: {
+        type: Array,
+        default: () => []
+    },
+    machines: {
+        type: Array,
+        default: () => []
+    },
+    isEdit: {
+        type: Boolean,
+        default: false
+    }
+});
+
+const emit = defineEmits(['update:crops', 'update:serviceTypes', 'update:machines', 'update:isEdit']);
+
+const showAddPopup = ref(false);
+const input = ref("");
+const addTypeName = ref("");
+const isEditPopup = ref(false);
+const currentCategory = ref('');
+const currentEditIndex = ref(-1);
+const currentEditName = ref('');
+
+function handleAdd(type) {
+    isEditPopup.value = false;
+    addTypeName.value = type;
+    input.value = "";
+    showAddPopup.value = true;
+    // 根据类型设置当前分类
+    if (type === '作物') {
+        currentCategory.value = 'crops';
+    } else if (type === '类型') {
+        currentCategory.value = 'serviceTypes';
+    } else if (type === '设备') {
+        currentCategory.value = 'machines';
+    }
+    currentEditIndex.value = -1;
+}
+
+function handleDelete(category, index) {
+    if (category === 'crops') {
+        const newCrops = [...props.crops];
+        newCrops.splice(index, 1);
+        emit('update:crops', newCrops);
+    }
+    if (category === 'serviceTypes') {
+        const newServiceTypes = [...props.serviceTypes];
+        newServiceTypes.splice(index, 1);
+        emit('update:serviceTypes', newServiceTypes);
+    }
+    if (category === 'machines') {
+        const newMachines = [...props.machines];
+        newMachines.splice(index, 1);
+        emit('update:machines', newMachines);
+    }
+}
+
+function handleEdit(val, category) {
+    isEditPopup.value = true;
+    input.value = val;
+    showAddPopup.value = true;
+    currentCategory.value = category;
+    currentEditName.value = val;
+    // 找到对应的索引
+    let targetArray = [];
+    if (category === 'crops') {
+        targetArray = props.crops;
+    } else if (category === 'serviceTypes') {
+        targetArray = props.serviceTypes;
+    } else if (category === 'machines') {
+        targetArray = props.machines;
+    }
+    currentEditIndex.value = targetArray.findIndex(item => item.name === val && item.isSelf === 1);
+}
+
+function handleConfirm() {
+    if (!input.value.trim()) {
+        return;
+    }
+    
+    if (isEditPopup.value && currentEditIndex.value >= 0) {
+        // 编辑模式
+        if (currentCategory.value === 'crops') {
+            const newCrops = [...props.crops];
+            newCrops[currentEditIndex.value].name = input.value.trim();
+            emit('update:crops', newCrops);
+        } else if (currentCategory.value === 'serviceTypes') {
+            const newServiceTypes = [...props.serviceTypes];
+            newServiceTypes[currentEditIndex.value].name = input.value.trim();
+            emit('update:serviceTypes', newServiceTypes);
+        } else if (currentCategory.value === 'machines') {
+            const newMachines = [...props.machines];
+            newMachines[currentEditIndex.value].name = input.value.trim();
+            emit('update:machines', newMachines);
+        }
+    } else {
+        // 添加模式
+        const newItem = { name: input.value.trim(), isSelf: 1 };
+        if (currentCategory.value === 'crops') {
+            const newCrops = [...props.crops, newItem];
+            emit('update:crops', newCrops);
+        } else if (currentCategory.value === 'serviceTypes') {
+            const newServiceTypes = [...props.serviceTypes, newItem];
+            emit('update:serviceTypes', newServiceTypes);
+        } else if (currentCategory.value === 'machines') {
+            const newMachines = [...props.machines, newItem];
+            emit('update:machines', newMachines);
+        }
+    }
+    
+    showAddPopup.value = false;
+    input.value = "";
+    currentEditIndex.value = -1;
+    currentEditName.value = '';
+}
+</script>
+
+<style lang="scss" scoped>
+.service-info {
+    .main-content {
+        max-height: calc(100% - 40px);
+        overflow: auto;
+        padding: 15px 12px;
+        margin: 14px 12px;
+        border-radius: 12px;
+        background: #fff;
+        .service-title {
+            font-size: 18px;
+            color: #222222;
+            font-weight: 500;
+            margin-bottom: 10px;
+            .label-icon {
+                width: 14px;
+                padding-right: 5px;
+            }
+        }
+        .service-content {
+            margin-top: 12px;
+            padding-top: 12px;
+            border-top: 1px solid #F5F5F5;
+            .service-item {
+                .sub-title {
+                    font-size: 16px;
+                    font-weight: 500;
+                    color: rgba(0, 0, 0, 0.9);
+                }
+                .tag-group {
+                    display: flex;
+                    align-items: center;
+                    flex-wrap: wrap;
+                    gap: 0 12px;
+                    font-size: 16px;
+                    .tag-item {
+                        margin-top: 10px;
+                        position: relative;
+                        background: #E8F5FF;
+                        border-radius: 8px;
+                        color: #2199f8;
+                        padding: 0 12px;
+                        box-sizing: border-box;
+                        min-width: 26vw;
+                        height: 48px;
+                        text-align: center;
+                        line-height: 48px;
+                        .text { display: inline-flex; align-items: center; }
+                        .edit-icon { margin-left: 8px; }
+                        .del-icon {
+                            position: absolute;
+                            right: -8px;
+                            top: -8px;
+                            background: #2199F8;
+                            border-radius: 50%;
+                            width: 16px; height: 16px;
+                            font-size: 10px;
+                            display: flex; align-items: center; justify-content: center;
+                            color: #fff;
+                        }
+                    }
+                    &.add-tag-group {
+                        .tag-item {
+                            color: #000000;
+                            background: none;
+                            border: 1px solid #999999;
+                            &.self {
+                                border: 1px solid #2199F8;
+                                background: #E8F5FF;
+                                color: #2199F8;
+                            }
+                            &.last-add {
+                                background: #F7F7F7;
+                                color: #343434;
+                                border: none;
+                                display: flex;
+                                align-items: center;
+                                justify-content: center;
+                                .add-icon {
+                                    font-size: 14px;
+                                    font-weight: bold;
+                                    margin-right: 3px;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            .service-item + .service-item {
+                margin-top: 20px;
+            }
+        }
+    }
+}
+
+.add-tag-popup{
+    width: 90%;
+    padding: 20px 16px;
+    .popup-title{
+        font-size: 18px;
+        font-weight: 500;
+        text-align: center;
+        margin-bottom: 12px;
+    }
+    .ml-2 {
+        margin-left: 3px;
+    }
+    .popup-input{
+        margin-bottom: 30px;
+    }
+    .popup-button{
+        display: flex;
+        padding-top: 20px;
+        border-top: 1px solid rgba(0, 0, 0, 0.1);
+        div{
+            flex: 1;
+            font-size: 16px;
+            padding: 9px;
+            border-radius: 20px;
+            background: #2199F8;
+            color: #fff;
+            text-align: center;
+            cursor: pointer;
+        }
+        .cancel{
+            margin-right: 20px;
+            color: #000;
+            background: #fff;
+            border: 1px solid #999999;
+        }
+    }
+}
+</style>
+

+ 31 - 14
src/components/popup/reviewUploadPopup.vue

@@ -1,9 +1,9 @@
 <template>
     <popup v-model:show="show" closeable :close-on-click-overlay="false" class="upload-popup" @closed="handleClosed">
         <div class="upload-content">
-            <div class="upload-tips"><span class="required">*</span>请上传复核照片</div>
-            <upload exampleImg class="upload-wrap" @handleUpload="handleUpload">
-                <img class="example" src="@/assets/img/home/example-4.png" alt="" />
+            <div class="upload-tips"><span class="required">*</span>{{ tipText }}</div>
+            <upload :exampleImg="showExampleImg" :maxCount="maxCount" class="upload-wrap" @handleUpload="handleUpload">
+                <img v-if="showExampleImg" class="example" src="@/assets/img/home/example-4.png" alt="" />
                 <img class="example" src="@/assets/img/home/plus.png" alt="" />
             </upload>
             <div class="upload-footer">
@@ -29,6 +29,18 @@ const props = defineProps({
         type: [String, Number],
         default: null,
     },
+    tipText: {
+        type: String,
+        default: "请上传复核照片",
+    },
+    showExampleImg: {
+        type: Boolean,
+        default: true,
+    },
+    maxCount: {
+        type: Number,
+        default: 3,
+    },
 });
 
 const emit = defineEmits(["update:modelValue", "success"]);
@@ -60,17 +72,22 @@ const handleUploadConfirm = () => {
         ElMessage.warning("请上传照片");
         return;
     }
-    const params = {
-        recordId: props.recordId,
-        executeEvidence: images.value,
-    };
-    VE_API.monitor.addReviewImg(params).then((res) => {
-        if (res.code === 0) {
-            ElMessage.success("上传成功");
-            show.value = false;
-            emit("success");
-        }
-    });
+    if(props.recordId){
+        const params = {
+            recordId: props.recordId,
+            executeEvidence: images.value,
+        };
+        VE_API.monitor.addReviewImg(params).then((res) => {
+            if (res.code === 0) {
+                ElMessage.success("上传成功");
+                show.value = false;
+                emit("success");
+            }
+        });
+    }else{
+        show.value = false;
+        emit("success", images.value);  
+    }
 };
 
 const handleClosed = () => {

+ 154 - 104
src/components/taskItem.vue

@@ -1,11 +1,13 @@
 <template>
-    <div class="farm-item" :class="{'done': status, 'hall': isHall}">
+    <div class="farm-item" :class="{ done: status, hall: isHall }">
         <div class="item-top">
             <div class="top-l">
                 <div class="item-name">{{ itemData?.farmWorkName }}</div>
                 <div class="item-time">{{ itemData?.executeDate }}</div>
             </div>
-            <div class="top-r" @click="toDetail(status, itemData.id, itemData.farmWorkLibId)">{{ status === 0 ? "查看处方" : "查看详情" }}</div>
+            <div class="top-r" @click="toDetail(status, itemData.id, itemData.farmWorkLibId)">
+                {{ status === 0 ? "查看处方" : "查看详情" }}
+            </div>
         </div>
         <div class="item-box" v-if="status === 0">
             <!-- <div class="title-wrap">
@@ -47,13 +49,15 @@
             <div class="img-text-wrap">
                 <div class="left-wrap">
                     <div class="left-img">
-                        <img src="@/assets/img/home/farm.png" alt="">
+                        <img src="@/assets/img/home/farm.png" alt="" />
                     </div>
                     <div class="right-text">
                         <div class="farm-info">
                             {{ itemData?.farmName }}
                             <div class="info-tag-wrap">
-                                <div class="tag-item second" v-if="itemData?.farmArea">{{ formatArea(itemData?.farmArea) }}亩</div>
+                                <div class="tag-item second" v-if="itemData?.farmArea">
+                                    {{ formatArea(itemData?.farmArea) }}亩
+                                </div>
                                 <div class="tag-item primary">{{ itemData?.typeName }}</div>
                             </div>
                         </div>
@@ -61,8 +65,11 @@
                     </div>
                 </div>
                 <div class="right-wrap" v-if="isHall">
-                    <el-icon><Plus /></el-icon>
-                    <span>关注</span>
+                    <div class="click-item" v-if="!itemData?.isFollow" @click="handleFollow(itemData)">
+                        <el-icon><Plus /></el-icon>
+                        <span>关注</span>
+                    </div>
+                    <span v-else class="follow-text" @click="handleFollow(itemData)">已关注</span>
                 </div>
             </div>
             <slot name="footer"></slot>
@@ -78,34 +85,46 @@
                 <div class="desc-info two-text" v-if="!expiredDay">
                     <div class="desc-info-item">
                         <div>复核成效</div>
-                        <span class="value">促进分蘖芽萌发、加快分蘖生长,同时补充氮素等关键养分,增强植株长势,为形成足够穗数、提高群体产量打基础。</span>
+                        <span class="value"
+                            >促进分蘖芽萌发、加快分蘖生长,同时补充氮素等关键养分,增强植株长势,为形成足够穗数、提高群体产量打基础。</span
+                        >
                     </div>
                 </div>
                 <div class="review-image" v-if="!expiredDay">
                     <div class="review-image-item" v-if="triggerImg.length">
                         <div class="review-image-item-title">农事前</div>
                         <photo-provider :photo-closable="true">
-                                <photo-consumer v-for="src in [triggerImg[triggerImg.length - 1].cloudFilename]" intro="农事前照片" :key="src" :src="base_img_url2 + src">
-                                    <div class="img-item">
-                                        <img :src="base_img_url2 + src + resize" class="view-box">
-                                    </div>
-                                </photo-consumer>
+                            <photo-consumer
+                                v-for="src in [triggerImg[triggerImg.length - 1].cloudFilename]"
+                                intro="农事前照片"
+                                :key="src"
+                                :src="base_img_url2 + src"
+                            >
+                                <div class="img-item">
+                                    <img :src="base_img_url2 + src + resize" class="view-box" />
+                                </div>
+                            </photo-consumer>
                         </photo-provider>
                     </div>
                     <div class="review-image-item" v-if="detailItem?.reviewImage?.length">
                         <div class="review-image-item-title">农事后</div>
                         <photo-provider :photo-closable="true">
-                                <photo-consumer v-for="src in [detailItem.reviewImage[detailItem.reviewImage.length - 1]]" intro="农事后照片" :key="src" :src="base_img_url2 + src">
-                                    <div class="img-item">
-                                        <img :src="base_img_url2 + src + resize" class="view-box">
-                                    </div>
-                                </photo-consumer>
+                            <photo-consumer
+                                v-for="src in [detailItem.reviewImage[detailItem.reviewImage.length - 1]]"
+                                intro="农事后照片"
+                                :key="src"
+                                :src="base_img_url2 + src"
+                            >
+                                <div class="img-item">
+                                    <img :src="base_img_url2 + src + resize" class="view-box" />
+                                </div>
+                            </photo-consumer>
                         </photo-provider>
                     </div>
                 </div>
 
                 <!-- 过期农事 -->
-                 <div v-if="expiredDay">
+                <div v-if="expiredDay">
                     <div class="desc-info pt-10">
                         <div class="desc-info-item">
                             <span>复核时间:</span>
@@ -118,32 +137,29 @@
                             距离农事执行已 <span class="val-text">15</span>天,提醒用户拍照,增加信誉度!
                         </div>
                     </div>
-                 </div>
+                </div>
             </div>
-            
+
             <slot name="footer"></slot>
 
             <div class="item-footer" v-if="status === 1">
-                <div class="footer-l farm-name-text van-ellipsis" :style="{ width: detailItem?.reviewImage?.length ? 'calc(100% - 85px)' : 'calc(100% - 180px)' }">
-                    来自<span class="name-text">{{ itemData.farmName || '未知农场' }}</span>
+                <div
+                    class="footer-l farm-name-text van-ellipsis"
+                    :style="{ width: detailItem?.reviewImage?.length ? 'calc(100% - 85px)' : 'calc(100% - 180px)' }"
+                >
+                    来自<span class="name-text">{{ itemData.farmName || "未知农场" }}</span>
                 </div>
                 <div class="footer-r">
-                    <div class="btn warning" v-if="detailItem?.reviewImage?.length" @click="shareResult">
-                        分享成果
-                    </div>
+                    <div class="btn warning" v-if="detailItem?.reviewImage?.length" @click="shareResult">分享成果</div>
                     <template v-else>
-                        <div class="btn secondary-text" @click="remindUser">
-                            提醒用户拍照
-                        </div>
-                        <div class="btn photo-text" @click="handleUploadPhoto">
-                            上传照片
-                        </div>
+                        <div class="btn secondary-text" @click="remindUser">提醒用户拍照</div>
+                        <div class="btn photo-text" @click="handleUploadPhoto">上传照片</div>
                     </template>
                 </div>
             </div>
         </div>
     </div>
-    
+
     <!-- 处方卡片 -->
     <Teleport to="body">
         <detail-dialog ref="detailDialogRef" />
@@ -154,14 +170,15 @@
 
     <upload-execute ref="uploadExecuteRef" :onlyShare="true" />
 
-     <!-- 上传照片弹窗 -->
-     <review-upload-popup v-model="showUpload" :record-id="sectionId" @success="handleUploadSuccess" />
+    <!-- 上传照片弹窗 -->
+    <review-upload-popup v-model="showUpload" :record-id="sectionId" @success="handleUploadSuccess" />
 </template>
 
 <script setup>
-import { onMounted, ref } from 'vue';
+import { onMounted, ref } from "vue";
 import { useRouter } from "vue-router";
 import { base_img_url2 } from "@/api/config";
+import { ElMessage, ElMessageBox } from "element-plus";
 import detailDialog from "@/components/detailDialog.vue";
 import uploadExecute from "@/views/old_mini/task_condition/components/uploadExecute.vue";
 import reviewPopup from "@/views/old_mini/task_condition/components/reviewPopup.vue";
@@ -172,47 +189,71 @@ const resize = "?x-oss-process=image/resize,p_120/format,webp/quality,q_100";
 const props = defineProps({
     status: {
         type: Number,
-        default: 0
+        default: 0,
     },
     itemData: {
         type: Object,
-        default: () => ({})
+        default: () => ({}),
     },
     isHall: {
         type: Boolean,
-        default: false
-    }
-})
+        default: false,
+    },
+});
 
-const expiredDay = ref(0) // 过期天数
+const expiredDay = ref(0); // 过期天数
 const uploadExecuteRef = ref(null);
 const router = useRouter();
 const detailDialogRef = ref(null);
 const reviewPopupRef = ref(null);
 const toPage = () => {
-    router.push("/report_detail")
-}
+    router.push("/report_detail");
+};
+
+const handleFollow = ({ farmId, isFollow }) => {
+    ElMessageBox.confirm(`${isFollow ? "确定要取消关注该农场吗?" : "确定要关注该农场吗?"}`, "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+    })
+        .then(() => {
+            const api = isFollow ? VE_API.z_farm_work_record.unfollowFarm : VE_API.z_farm_work_record.followFarm;
+            api({ farmId }).then(({ code,msg }) => {
+                if (code === 0) {
+                    ElMessage.success(msg);
+                    emit("handleFollowSuccess");
+                } else {
+                    ElMessage.error(msg);
+                }
+            });
+        })
+        .catch(() => {});
+};
 
 const shareResult = () => {
     if (detailItem.value?.reviewImage?.length) {
-        const preImg = triggerImg.value.length ? base_img_url2 + triggerImg.value[triggerImg.value.length - 1].cloudFilename : '';
-        const resImg = detailItem.value?.reviewImage?.length ? base_img_url2 + detailItem.value.reviewImage[detailItem.value.reviewImage.length - 1] : '';
+        const preImg = triggerImg.value.length
+            ? base_img_url2 + triggerImg.value[triggerImg.value.length - 1].cloudFilename
+            : "";
+        const resImg = detailItem.value?.reviewImage?.length
+            ? base_img_url2 + detailItem.value.reviewImage[detailItem.value.reviewImage.length - 1]
+            : "";
         reviewPopupRef.value.handleShowPopup(detailItem.value.id, preImg, resImg);
     }
-}
+};
 
 const remindUser = () => {
-    uploadExecuteRef.value.showPopup({...props.itemData, type: 'remindUser'});
-}
+    uploadExecuteRef.value.showPopup({ ...props.itemData, type: "remindUser" });
+};
 
 const showUpload = ref(false);
 const sectionId = ref(null);
 const handleUploadPhoto = () => {
     showUpload.value = true;
     sectionId.value = props.itemData.id;
-}
+};
 
-const emit = defineEmits(["handleUploadSuccess"]);
+const emit = defineEmits(["handleUploadSuccess", "handleFollowSuccess"]);
 
 const triggerImg = ref([]);
 const detailItem = ref({});
@@ -220,25 +261,25 @@ const getTriggerImg = async () => {
     if (!detailItem.value?.id) return;
     const { data } = await VE_API.z_farm_work_record.getTriggerImg({ farmWorkRecordId: detailItem.value.id });
     triggerImg.value = data || [];
-}
+};
 
 // 更新触发图片(上传成功后调用)
 const updateTriggerImg = async () => {
     if (!props.itemData?.id) return;
-    
+
     // 重新获取详情
     await getItemDetail(props.itemData.id);
-    
+
     // 如果是已完成状态(status === 1),需要重新获取触发图片
     if (props.status === 1) {
         await getTriggerImg();
     }
     // 如果是待完成状态(status === 0),详情已经更新,itemData 会在 getSimpleList 后更新
-}
+};
 
-const handleUploadSuccess = async () => { 
+const handleUploadSuccess = async () => {
     emit("handleUploadSuccess");
-}
+};
 
 onMounted(async () => {
     // 若已带处方列表,直接生成;否则在需要时拉取详情后生成
@@ -252,25 +293,26 @@ onMounted(async () => {
 
         getTriggerImg();
     }
-})
+});
 
 // 将所有需要暴露的方法放在 defineExpose 中
 defineExpose({
-    updateTriggerImg
-})
-const prescriptionText = ref('');
+    updateTriggerImg,
+});
+const prescriptionText = ref("");
 function buildPrescriptionText(list) {
     try {
         return list
-            .map(group => (group.pesticideFertilizerList || [])
-                .map(p => p.defaultName || p.pesticideFertilizerName || '')
-                .filter(Boolean)
-                .join('+')
+            .map((group) =>
+                (group.pesticideFertilizerList || [])
+                    .map((p) => p.defaultName || p.pesticideFertilizerName || "")
+                    .filter(Boolean)
+                    .join("+")
             )
             .filter(Boolean)
-            .join('+');
+            .join("+");
     } catch {
-        return '';
+        return "";
     }
 }
 async function getItemDetail(id) {
@@ -282,7 +324,7 @@ async function getItemDetail(id) {
 const getPrescriptionInfo = () => prescriptionText.value;
 
 function formatArea(val) {
-    const num = typeof val === 'number' ? val : parseFloat(val);
+    const num = typeof val === "number" ? val : parseFloat(val);
     if (Number.isNaN(num)) return val;
     return Number.isInteger(num) ? num : num.toFixed(2);
 }
@@ -292,23 +334,23 @@ const toDetail = (status, id, farmWorkId) => {
         // 复核成效
         router.push({
             path: "/review_work",
-            query: { json: JSON.stringify({ id, goBack: true }) }
+            query: { json: JSON.stringify({ id, goBack: true }) },
         });
     } else {
-        detailDialogRef.value.showDialog(farmWorkId, '', false);
+        detailDialogRef.value.showDialog(farmWorkId, "", false);
     }
-}
+};
 </script>
 
 <style lang="scss" scoped>
 .farm-item {
-    background: #CFE9FF;
+    background: #cfe9ff;
     border-radius: 14px;
     &.done {
-        background: #EBEBEB;
+        background: #ebebeb;
         .item-top {
             .item-name {
-                background: #C5C5C5;
+                background: #c5c5c5;
                 border: none;
                 color: #fff;
             }
@@ -321,7 +363,7 @@ const toDetail = (status, id, farmWorkId) => {
         }
     }
     &.hall {
-        background: #CFE9FF;
+        background: #cfe9ff;
         .item-top {
             .item-name {
                 color: #ffffff;
@@ -345,11 +387,11 @@ const toDetail = (status, id, farmWorkId) => {
         }
         .item-name {
             margin-right: 8px;
-            color: #2199F8;
+            color: #2199f8;
             padding: 0 10px;
             height: 29px;
             border-radius: 4px;
-            border: 1px solid #2199F8;
+            border: 1px solid #2199f8;
             line-height: 29px;
             background: #fff;
         }
@@ -360,7 +402,7 @@ const toDetail = (status, id, farmWorkId) => {
         border: 1px solid rgba(183, 183, 183, 0.1);
         padding: 10px 12px;
     }
-.item-footer {
+    .item-footer {
         margin-top: 10px;
         padding-top: 11px;
         border-top: 1px solid rgba(0, 0, 0, 0.1);
@@ -369,12 +411,12 @@ const toDetail = (status, id, farmWorkId) => {
         justify-content: space-between;
         font-size: 12px;
         .footer-l {
-            color: #8B8B8B;
+            color: #8b8b8b;
             font-size: 12px;
             &.primary-btn {
                 display: inline-flex;
                 align-items: center;
-                border: 1px solid #2199F8;
+                border: 1px solid #2199f8;
                 background: rgba(33, 153, 248, 0.1);
                 padding: 0 12px;
                 height: 32px;
@@ -382,7 +424,7 @@ const toDetail = (status, id, farmWorkId) => {
                 display: flex;
                 align-items: center;
                 border-radius: 20px;
-                color: #2199F8;
+                color: #2199f8;
                 .share-icon {
                     width: 12px;
                     padding-right: 4px;
@@ -390,7 +432,7 @@ const toDetail = (status, id, farmWorkId) => {
             }
             &.farm-name-text {
                 font-size: 14px;
-                color: #6F7274;
+                color: #6f7274;
                 width: calc(100% - 180px);
                 .name-text {
                     padding-left: 4px;
@@ -411,27 +453,27 @@ const toDetail = (status, id, farmWorkId) => {
                 &.second {
                     // border: 1px solid #8B8B8B;
                     // color: #8B8B8B;
-                    color: #2199F8;
+                    color: #2199f8;
                     background: rgba(33, 153, 248, 0.1);
                 }
                 &.primary {
-                    background: #2199F8;
+                    background: #2199f8;
                     color: #fff;
                 }
                 .btn-icon {
                     padding-right: 4px;
                 }
                 &.warning {
-                    color: #FF953D;
+                    color: #ff953d;
                     background: #fff;
-                    border: 1px solid #FF953D;
+                    border: 1px solid #ff953d;
                 }
                 &.secondary-text {
-                    color: #2199F8;
-                    border: 1px solid #2199F8;
+                    color: #2199f8;
+                    border: 1px solid #2199f8;
                 }
-                &.photo-text{
-                    background: #2199F8;
+                &.photo-text {
+                    background: #2199f8;
                     color: #fff;
                 }
             }
@@ -459,7 +501,7 @@ const toDetail = (status, id, farmWorkId) => {
         }
         .text-more {
             padding-left: 10px;
-            color: #2199F8;
+            color: #2199f8;
             white-space: nowrap;
         }
     }
@@ -484,7 +526,7 @@ const toDetail = (status, id, farmWorkId) => {
                 padding-left: 8px;
                 .farm-info {
                     font-size: 14px;
-                    color: #1D2129;
+                    color: #1d2129;
                     display: flex;
                     align-items: center;
                     .info-tag-wrap {
@@ -499,12 +541,12 @@ const toDetail = (status, id, farmWorkId) => {
                             border-radius: 2px;
                             font-size: 12px;
                             &.second {
-                                color: #1D2129;
-                                background: #F4F4F4;
+                                color: #1d2129;
+                                background: #f4f4f4;
                             }
                             &.primary {
-                                color: #2199F8;
-                                background: #E8F3FF;
+                                color: #2199f8;
+                                background: #e8f3ff;
                             }
                         }
                     }
@@ -512,15 +554,23 @@ const toDetail = (status, id, farmWorkId) => {
                 .farm-addr {
                     padding-top: 2px;
                     font-size: 12px;
-                    color: #86909C;
+                    color: #86909c;
                 }
             }
         }
         .right-wrap {
             display: flex;
             align-items: center;
-            color: #FF953D;
+            color: #ff953d;
             font-size: 12px;
+            .click-item {
+                display: flex;
+                align-items: center;
+                gap: 2px;
+            }
+            .follow-text {
+                color: #d0d0d0;
+            }
         }
     }
     .title-wrap {
@@ -565,18 +615,18 @@ const toDetail = (status, id, farmWorkId) => {
                 }
             }
             .expired-day {
-                color: #FF953D;
+                color: #ff953d;
             }
             .expired-text {
                 margin-top: 4px;
                 padding: 6px 8px;
-                background: linear-gradient(90deg,rgba(33, 153, 248, 0.2), rgba(33, 153, 248, 0));
+                background: linear-gradient(90deg, rgba(33, 153, 248, 0.2), rgba(33, 153, 248, 0));
                 border-radius: 4px;
-                color: #2E2E2E;
+                color: #2e2e2e;
                 font-size: 12px;
                 width: 100%;
                 .val-text {
-                    color: #2199F8;
+                    color: #2199f8;
                 }
             }
         }
@@ -586,7 +636,7 @@ const toDetail = (status, id, farmWorkId) => {
         .pt-10 {
             padding-top: 10px;
         }
-        
+
         .review-image {
             display: flex;
             align-items: center;
@@ -635,7 +685,7 @@ const toDetail = (status, id, farmWorkId) => {
         }
         .report-text {
             margin-top: 10px;
-            color: #FF953D;
+            color: #ff953d;
             font-size: 12px;
             height: 32px;
             line-height: 32px;
@@ -645,7 +695,7 @@ const toDetail = (status, id, farmWorkId) => {
             padding-left: 11px;
             background: linear-gradient(90deg, rgba(255, 149, 61, 0.1), rgba(255, 149, 61, 0));
             .done-icon {
-                background: #FF953D;
+                background: #ff953d;
                 width: 10px;
                 height: 10px;
                 border-radius: 50%;

+ 10 - 1
src/components/upload.vue

@@ -7,7 +7,7 @@
             <el-icon class="icon" size="16"><Warning /></el-icon>
             <span>上传照片可精准预测最佳病虫防治时间</span>
         </div>
-        <uploader class="uploader" v-model="fileList" multiple :max-count="3" :after-read="afterRead" @delete="deleteImg">
+        <uploader class="uploader" v-model="fileList" :multiple="props.maxCount > 1" :max-count="props.maxCount" :after-read="afterRead" @delete="deleteImg">
             <template v-if="exampleImg">
                 <slot v-if="!fileList.length"></slot>
                 <img class="plus" v-else src="@/assets/img/home/plus.png" alt="">
@@ -45,6 +45,10 @@ const props = defineProps({
     type: Boolean,
     default: false
   },
+  maxCount: {
+    type: Number,
+    default: 3
+  },
 })
 
 
@@ -63,6 +67,11 @@ const afterRead = async (files) => {
     if (!Array.isArray(files)) {
       files = [files];
     }
+    // 如果 maxCount 为 1,先清空之前的图片数组
+    if (props.maxCount === 1) {
+      fileArr.value = [];
+      imgArr.value = [];
+    }
     for(let file of files){
       // 将文件上传至服务器
       let fileVal = file.file;

+ 171 - 127
src/views/old_mini/farm_manage/components/demandHall.vue

@@ -4,12 +4,10 @@
         <div class="map-container" ref="mapContainer"></div>
 
         <div class="search-wrap">
-            <el-input
+            <location-search
                 class="search"
-                v-model="searchValue"
-                placeholder="搜索位置"
-                @search="search"
-                :prefix-icon="Search"
+                user-location="113.61702297075017,23.584863449735067"
+                @change="handleLocationChange"
             />
         </div>
 
@@ -23,7 +21,12 @@
             <template #header>
                 <div class="header-bar"></div>
                 <div class="select-group">
-                    <el-select class="select-item" v-model="selectParma.farmWorkTypeId" placeholder="农事类型" @change="getSimpleList">
+                    <el-select
+                        class="select-item"
+                        v-model="selectParma.farmWorkTypeId"
+                        placeholder="农事类型"
+                        @change="getSimpleList"
+                    >
                         <el-option
                             v-for="item in farmWorkTypeList"
                             :key="item.id"
@@ -31,36 +34,37 @@
                             :value="item.id"
                         />
                     </el-select>
-                    <el-select class="select-item" v-model="areaValue1" placeholder="Select">
+                    <el-select
+                        class="select-item"
+                        v-model="selectParma.districtCode"
+                        placeholder="区域筛选"
+                        @change="getSimpleList"
+                    >
                         <el-option
-                            v-for="item in areaOptions1"
-                            :key="item.value"
-                            :label="item.label"
-                            :value="item.value"
+                            v-for="item in districtList"
+                            :key="item.code"
+                            :label="item.name"
+                            :value="item.code"
                         />
                     </el-select>
                 </div>
                 <div class="user-btn" v-if="height === anchors[0]" @click.stop="toPage">
-                    <img class="user-icon" src="@/assets/img/home/user-icon.png" alt="">
+                    <img class="user-icon" src="@/assets/img/home/user-icon.png" alt="" />
                     新增用户
                 </div>
             </template>
             <div class="hall-content">
                 <div class="farm-list" ref="cardContentRef" :style="{ height: `${cardContentHeight}px` }">
                     <div class="task-item" v-for="item in taskList" :key="item">
-                        <task-item :item-data="item" :isHall="true">
+                        <task-item :item-data="item" :isHall="true" @handleFollowSuccess="getSimpleList">
                             <template #footer>
                                 <div class="item-footer">
-                                    <div class="footer-l" @click="toDetail(item)">
-                                        查看详情
-                                    </div>
+                                    <div class="footer-l" @click="toDetail(item)">查看详情</div>
                                     <div class="footer-r">
                                         <!-- <div class="btn second">
                                             转发给客户
                                         </div> -->
-                                        <div class="btn primary" @click="showPriceSheetPopup(item)">
-                                            生成报价单
-                                        </div>
+                                        <div class="btn primary" @click="showPriceSheetPopup(item)">生成报价单</div>
                                     </div>
                                 </div>
                             </template>
@@ -82,15 +86,18 @@ import { computed, nextTick, onMounted, ref } from "vue";
 import { useStore } from "vuex";
 import IndexMap from "../map/index";
 import taskItem from "@/components/taskItem.vue";
-import { Search } from "@element-plus/icons-vue";
 import priceSheetPopup from "@/components/popup/priceSheetPopup.vue";
 import { useRouter } from "vue-router";
+import LocationSearch from "@/components/pageComponents/LocationSearch.vue";
+import { Point } from "ol/geom";
+import Feature from "ol/Feature";
+import { convertPointToArray } from "@/utils/index";
 const props = defineProps({
     isCapital: {
         type: Boolean,
-        default: false
-    }
-})
+        default: false,
+    },
+});
 
 const store = useStore();
 const tabBarHeight = computed(() => store.state.home.tabBarHeight);
@@ -100,58 +107,74 @@ const router = useRouter();
 const anchors = ref([310 + tabBarHeight.value, Math.round(1 * window.innerHeight) - 44]);
 const height = ref(anchors.value[0]);
 
-
 const indexMap = new IndexMap();
 const mapContainer = ref(null);
+const mapPoint = ref(null);
 
 onMounted(() => {
-    const point = store.state.home.miniUserLocationPoint;
+    mapPoint.value = store.state.home.miniUserLocationPoint;
     getFarmWorkTypeList();
-    getSimpleList()
+    getSimpleList();
+    getDistrictListByCity();
     nextTick(() => {
-        indexMap.initMap(point, mapContainer.value, props.isCapital);
-        getStatisticsAreaByDistrict()
+        indexMap.initMap(mapPoint.value, mapContainer.value, props.isCapital);
+        getStatisticsAreaByDistrict();
     });
-})
+});
 
 defineExpose({
-    getSimpleList
-})
+    getSimpleList,
+});
+
+//根据城市的坐标返回区县列表
+const districtList = ref([]);
+function getDistrictListByCity() {
+    VE_API.z_farm_work_record.getDistrictListByCity({ point: mapPoint.value }).then(({ data }) => {
+        districtList.value = data || [];
+        districtList.value.unshift({ code: 0, name: "全部" });
+    });
+}
 
+//农事类型列表
 const farmWorkTypeList = ref([]);
 function getFarmWorkTypeList() {
-    VE_API.z_farm_work_record.getFarmWorkTypeList().then(({data}) => {
+    VE_API.z_farm_work_record.getFarmWorkTypeList().then(({ data }) => {
         farmWorkTypeList.value = data;
+        farmWorkTypeList.value.unshift({ id: 0, name: "全部" });
     });
 }
 const selectParma = ref({
     farmWorkTypeId: null,
-    areaValue1: null
+    districtCode: null,
 });
+
+//需求大厅接单简单农事记录列表
 const taskList = ref([]);
 function getSimpleList() {
-    const location = store.state.home.miniUserLocationPoint;
     const params = {
-        ...selectParma.value,
-        location,
-    }
-    VE_API.z_farm_work_record.getOrderReceivingSimpleList(params).then(({data}) => {
-        if (Array.isArray(data) && data.length > 0) {
+        farmWorkTypeId: selectParma.value.farmWorkTypeId || null,
+        districtCode: selectParma.value.districtCode || null,
+        location: mapPoint.value,
+    };
+    VE_API.z_farm_work_record
+        .getOrderReceivingSimpleList(params)
+        .then(({ data }) => {
             taskList.value = data || [];
-        }
-    }).catch((error) => {
-        taskList.value = [];
-    });
+        })
+        .catch((error) => {
+            taskList.value = [];
+        });
 }
 
 const toPage = () => {
     router.push("/create_farm?type=client&isReload=true&from=task_condition");
-}
+};
 
+//按区县统计服务亩数
 function getStatisticsAreaByDistrict() {
-    VE_API.z_farm_work_record.statisticsAreaByDistrict({flowStatus:'1,2,3'}).then(({data}) => {
-        if(data && data.length > 0) {
-            indexMap.initDataHall(data)
+    VE_API.z_farm_work_record.statisticsAreaByDistrict({ flowStatus: "1,2,3" }).then(({ data }) => {
+        if (data && data.length > 0) {
+            indexMap.initDataHall(data);
         }
     });
 }
@@ -159,22 +182,45 @@ function getStatisticsAreaByDistrict() {
 function toDetail(item) {
     router.push({
         path: "/completed_work",
-        query: { json: JSON.stringify({ id: item.id }) }
+        query: { json: JSON.stringify({ id: item.id }) },
     });
 }
 
 const cardContentHeight = ref(230);
-const searchValue = ref("");
-const search = () => {
-    console.log(searchValue.value);
-};
 
-const areaValue1 = ref("1");
-const areaOptions1 = [
-    { value: "1", label: "区域筛选" },
-    { value: "2", label: "2" },
-    { value: "3", label: "3" },
-];
+// 处理位置搜索变化
+function handleLocationChange(data) {
+    if (data && data.coordinateArray) {
+        mapPoint.value = data.point;
+        // 更新地图位置
+        if (indexMap && indexMap.kmap) {
+            indexMap.kmap.getView().animate({
+                center: data.coordinateArray,
+                zoom: 16,
+                duration: 500,
+            });
+            // 更新点击点
+            if (indexMap.clickPointLayer) {
+                indexMap.clickPointLayer.source.clear();
+                const point = new Feature(new Point(data.coordinateArray));
+                indexMap.clickPointLayer.addFeature(point);
+            }
+        }
+        // 更新区县列表
+        getDistrictListByCity();
+        // 重新获取列表
+        getSimpleList();
+    } else {
+        // 重置为初始位置
+        mapPoint.value = store.state.home.miniUserLocationPoint;
+        indexMap.clickPointLayer.source.clear();
+        // 更新区县列表
+        getDistrictListByCity();
+        // 重新获取列表
+        getSimpleList();
+        getStatisticsAreaByDistrict();
+    }
+}
 
 const cardContentRef = ref(null);
 const handleHeightChange = ({ height }) => {
@@ -186,7 +232,6 @@ const handleHeightChange = ({ height }) => {
     }
 };
 
-
 const priceSheetPopupRef = ref(null);
 const showPriceSheetPopup = (item) => {
     VE_API.z_farm_work_record.getDetail({ id: item.id }).then(({ data }) => {
@@ -194,8 +239,6 @@ const showPriceSheetPopup = (item) => {
         priceSheetPopupRef.value.handleShowPopup(res);
     });
 };
-
-
 </script>
 
 <style lang="scss" scoped>
@@ -215,7 +258,8 @@ const showPriceSheetPopup = (item) => {
         width: calc(100% - 24px);
         left: 12px;
         ::v-deep {
-            .el-input__wrapper {
+            .el-input__wrapper,
+            .el-select__wrapper {
                 box-shadow: none;
                 border-radius: 20px;
             }
@@ -264,61 +308,61 @@ const showPriceSheetPopup = (item) => {
             color: #999999;
             padding-top: 20px;
         }
-        
-    .item-footer {
-        margin-top: 10px;
-        padding-top: 11px;
-        border-top: 1px solid rgba(0, 0, 0, 0.1);
-        display: flex;
-        align-items: center;
-        justify-content: space-between;
-        font-size: 12px;
-        .footer-l {
-            // display: inline-flex;
-            // align-items: center;
-            // border: 1px solid #2199F8;
-            // background: rgba(33, 153, 248, 0.1);
-            // padding: 0 12px;
-            // height: 32px;
-            // box-sizing: border-box;
-            // display: flex;
-            // align-items: center;
-            // border-radius: 20px;
-            // color: #2199F8;
-            color: #8B8B8B;
-            font-size: 12px;
-            .share-icon {
-                width: 12px;
-                padding-right: 4px;
-            }
-        }
-        .footer-r {
+
+        .item-footer {
+            margin-top: 10px;
+            padding-top: 11px;
+            border-top: 1px solid rgba(0, 0, 0, 0.1);
             display: flex;
             align-items: center;
-            gap: 8px;
-            .btn {
-                height: 32px;
-                line-height: 32px;
-                padding: 0 12px;
-                border-radius: 20px;
+            justify-content: space-between;
+            font-size: 12px;
+            .footer-l {
+                // display: inline-flex;
+                // align-items: center;
+                // border: 1px solid #2199F8;
+                // background: rgba(33, 153, 248, 0.1);
+                // padding: 0 12px;
+                // height: 32px;
+                // box-sizing: border-box;
+                // display: flex;
+                // align-items: center;
+                // border-radius: 20px;
+                // color: #2199F8;
+                color: #8b8b8b;
+                font-size: 12px;
+                .share-icon {
+                    width: 12px;
+                    padding-right: 4px;
+                }
+            }
+            .footer-r {
                 display: flex;
                 align-items: center;
-                box-sizing: border-box;
-                &.second {
-                    // border: 1px solid #8B8B8B;
-                    // color: #8B8B8B;
-                    color: #2199F8;
-                    background: rgba(33, 153, 248, 0.1);
-                }
-                &.primary {
-                    background: #2199F8;
-                    color: #fff;
+                gap: 8px;
+                .btn {
+                    height: 32px;
+                    line-height: 32px;
+                    padding: 0 12px;
+                    border-radius: 20px;
+                    display: flex;
+                    align-items: center;
+                    box-sizing: border-box;
+                    &.second {
+                        // border: 1px solid #8B8B8B;
+                        // color: #8B8B8B;
+                        color: #2199f8;
+                        background: rgba(33, 153, 248, 0.1);
+                    }
+                    &.primary {
+                        background: #2199f8;
+                        color: #fff;
+                    }
                 }
             }
-            }
         }
     }
-    
+
     .select-group {
         display: flex;
         padding: 0 12px;
@@ -357,24 +401,24 @@ const showPriceSheetPopup = (item) => {
         background: #969799;
     }
 }
-        .user-btn {
-            position: absolute;
-            z-index: 10;
-            top: -42px;
-            right: 12px;
-            background: #fff;
-            height: 32px;
-            display: flex;
-            align-items: center;
-            border-radius: 5px;
-            padding: 0 8px;
-            font-size: 12px;
-            color: #2199F8;
-            .user-icon {
-                width: 16px;
-                margin-right: 4px;
-            }
-        }
+.user-btn {
+    position: absolute;
+    z-index: 10;
+    top: -42px;
+    right: 12px;
+    background: #fff;
+    height: 32px;
+    display: flex;
+    align-items: center;
+    border-radius: 5px;
+    padding: 0 8px;
+    font-size: 12px;
+    color: #2199f8;
+    .user-icon {
+        width: 16px;
+        margin-right: 4px;
+    }
+}
 
 .floating-panel {
     width: 100%;

+ 1 - 1
src/views/old_mini/farm_manage/map/index.js

@@ -21,7 +21,7 @@ class IndexMap {
       style: (f) => {
         return new Style({
           image: new Icon({
-            src: require("@/assets/img/home/farm-point.png"),
+            src: require("@/assets/img/home/garden-point.png"),
             scale: 0.5,
             anchor: [0.5, 1],
           }),

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

@@ -182,11 +182,11 @@ const cellItems = computed(() => {
             },
             {
                 title: "报价维护",
-                path: "/offer_price?identity=NZ&role=2",
+                path: "/offer_price",
             },
             {
                 title: "服务维护",
-                path: "/service_manage?identity=NZ&role=2",
+                path: "/service_manage",
             },
         ];
     }

+ 92 - 148
src/views/old_mini/mine/pages/register.vue

@@ -20,7 +20,7 @@
                             type="tel"
                             name="tel"
                             label="联系电话"
-                            :rules="[{ required: true,validator: validatorTel, message: '请输入电话号码'}]"
+                            :rules="[{ required: true, validator: validatorTel, message: '请输入电话号码' }]"
                             placeholder="请输入电话号码"
                         />
                         <field
@@ -90,12 +90,7 @@
                             </field>
                         </template>
                         <div class="flex" v-else>
-                            <field
-                                v-model="formData.address"
-                                label="服务区域"
-                                readonly
-                                placeholder="默认位置"
-                            />
+                            <field v-model="formData.address" label="服务区域" readonly placeholder="默认位置" />
                             <el-dropdown trigger="click">
                                 <div class="el-dropdown-link">
                                     {{ dropdownName }}
@@ -116,6 +111,11 @@
                                 </template>
                             </el-dropdown>
                         </div>
+                        <upload v-show="pageType === 'NZ'" exampleImg :maxCount="1" class="upload-wrap" @handleUpload="handleUploadSuccess">
+                            <div class="upload-btn">
+                                点击上传营业执照
+                            </div>
+                        </upload>
                     </div>
                 </div>
                 <div class="card" v-if="pageType == 'EXPERT'">
@@ -127,51 +127,14 @@
                         <el-input v-model="input" :rows="5" type="textarea" placeholder="描述:" />
                     </div>
                 </div>
-                <div class="card" v-else>
-                    <div class="card-title">
-                        <img src="@/assets/img/mine/label-icon.png" alt="" />
-                        <span>服务信息</span>
-                    </div>
-                    <div class="checkbox-group">
-                        <div class="name">服务作物</div>
-                        <el-checkbox-group v-model="checkboxGroup" size="large">
-                            <el-checkbox-button
-                                @change="(e) => changeCheckBox(e, index)"
-                                v-for="(item, index) in cities"
-                                :key="index"
-                                :value="item.name"
-                            >
-                                {{ item.name }}
-                            </el-checkbox-button>
-                        </el-checkbox-group>
-                    </div>
-                    <div class="checkbox-group">
-                        <div class="name">服务类型</div>
-                        <el-checkbox-group v-model="checkboxGroup1" size="large">
-                            <el-checkbox-button
-                                @change="(e) => changeCheckBox1(e, index)"
-                                v-for="(item, index) in cities1"
-                                :key="index"
-                                :value="item.name"
-                            >
-                                {{ item.name }}
-                            </el-checkbox-button>
-                        </el-checkbox-group>
-                    </div>
-                    <div class="checkbox-group">
-                        <div class="name">农机设备</div>
-                        <el-checkbox-group v-model="checkboxGroup2" size="large">
-                            <el-checkbox-button
-                                @change="(e) => changeCheckBox2(e, index)"
-                                v-for="(item, index) in cities2"
-                                :key="index"
-                                :value="item.name"
-                            >
-                                {{ item.name }}
-                            </el-checkbox-button>
-                        </el-checkbox-group>
-                    </div>
-                </div>
+                <template v-else>
+                    <ServiceInfo 
+                        v-model:crops="crops"
+                        v-model:serviceTypes="serviceTypes"
+                        v-model:machines="machines"
+                        v-model:isEdit="isEdit"
+                    />
+                </template>
                 <Button class="button" round block type="primary" native-type="submit"> 提交 </Button>
             </Form>
         </div>
@@ -182,28 +145,35 @@
 import customHeader from "@/components/customHeader.vue";
 import { Field, Form, Button } from "vant";
 import { onActivated, ref } from "vue";
-import { useRoute ,useRouter} from "vue-router";
-import { ElMessage } from 'element-plus'
+import { useRoute, useRouter } from "vue-router";
+import { ElMessage } from "element-plus";
+import upload from "@/components/upload";
+import ServiceInfo from "@/components/pageComponents/ServiceInfo.vue";
 const route = useRoute();
 const router = useRouter();
 
-const formRef  = ref(null)
+const formRef = ref(null);
 const formData = ref({
     name: "",
     tel: "",
-    subjectName:'',
+    subjectName: "",
     point: "",
-    serviceCropsJson:[],
-    agriculturalEquipmentJson:[]
+    serviceCropsJson: [],
+    agriculturalEquipmentJson: [],
+    licenseImg: [],
 });
 
-const validatorTel = (val) =>{
+const validatorTel = (val) => {
     const phoneRegex = /^1[3-9]\d{9}$/;
-    if(!phoneRegex.test(val)) return '请输入正确的电话号码'
-}
+    if (!phoneRegex.test(val)) return "请输入正确的电话号码";
+};
 
 const onSubmit = () => {
-    formData.value.point = "POINT(113.1093017627431 22.574540836684672)"
+    formData.value.point = "POINT(113.1093017627431 22.574540836684672)";
+    if (pageType.value === "NZ" && !formData.value.licenseImg) {
+        ElMessage.warning("请上传营业执照");
+        return;
+    }
     VE_API.mine.register(formData.value).then(res =>{
         if(res.code===0){
             ElMessage.success('注册成功,待审核')
@@ -214,9 +184,9 @@ const onSubmit = () => {
     })
 };
 
-const resetForm = () =>{
-    formRef.value.resetValidation()
-}
+const resetForm = () => {
+    formRef.value.resetValidation();
+};
 
 const number = ref("请选择");
 const numberList = ["请选择", "10", "20", "30", "40"];
@@ -242,7 +212,6 @@ const handleDropdown = (item, index) => {
     active.value = index;
 };
 
-const value = ref("");
 const input = ref("");
 
 const pageName = ref("");
@@ -253,36 +222,31 @@ const identityTyepe = {
 };
 // NF: "农服",
 
-const checkboxGroup = ref(["荔枝", "龙眼"]);
-const cities = ref([{ name: "荔枝" }, { name: "龙眼" }]);
-const changeCheckBox = (e, i) => {
-    console.log("e", i, e);
-    if (e === false) {
-        cities.value.splice(i, 1);
-    }
-};
+// 服务信息数据,转换为 ServiceInfo 组件需要的格式
+const isEdit = ref(true); // 默认编辑状态
+const crops = ref([
+    { name: "荔枝", isSelf: 0 },
+    { name: "龙眼", isSelf: 1 }
+]);
+const serviceTypes = ref([
+    { name: "播种", isSelf: 1 },
+    { name: "收获", isSelf: 0 }
+]);
+const machines = ref([
+    { name: "收割机", isSelf: 1 },
+    { name: "灌溉机", isSelf: 0 }
+]);
 
-const checkboxGroup1 = ref(["播种"]);
-const cities1 = ref([{ name: "播种" }, { name: "收获" }]);
-const changeCheckBox1 = (e, i) => {
-    if (e === false) {
-        cities.value.splice(i, 1);
-    }
+const handleUploadSuccess = (data) => {
+    formData.value.licenseImg = data.imgArr[0];
 };
 
-const checkboxGroup2 = ref(["收割机"]);
-const cities2 = ref([{ name: "收割机" }, { name: "灌溉机" }]);
-const changeCheckBox2 = (e, i) => {
-    if (e === false) {
-        cities.value.splice(i, 1);
-    }
-};
 
 onActivated(() => {
     pageName.value = identityTyepe[route.query.identity];
     pageType.value = route.query.identity;
-    formData.value = {}
-    resetForm()
+    formData.value = {};
+    resetForm();
 });
 </script>
 
@@ -291,6 +255,11 @@ onActivated(() => {
     width: 100%;
     height: 100vh;
     background-color: #f5f7fb;
+    ::v-deep{
+        .main-content {
+            margin: 12px 0;
+        }
+    }
     .content {
         height: calc(100% - 40px);
         padding: 12px;
@@ -358,14 +327,27 @@ onActivated(() => {
                         font-size: 12px;
                         padding: 14px 0;
                         border-radius: 8px;
-                        border: 1px solid #2199f8;
-                        background: #f5f5f5;
+                        border: 1px solid rgba(33, 153, 248, 0.2);
+                        background: #fff;
                         margin-left: 5px;
                     }
                 }
                 .el-icon--right {
                     margin-left: 4px;
                 }
+                .upload-btn {
+                    color: #2199f8;
+                    font-size: 16px;
+                    padding: 12px 0;
+                    text-align: center;
+                    width: 170px;
+                    border-radius: 8px;
+                    border: 1px solid #2199f8;
+                    background: #fff;
+                }
+                .upload-wrap{
+                    margin-top: 12px;
+                }
             }
         }
         .card + .card {
@@ -396,63 +378,6 @@ onActivated(() => {
                 font-size: 14px;
             }
         }
-        .checkbox-group {
-            .name {
-                font-size: 16px;
-                color: rgba(0, 0, 0, 0.9);
-                margin-bottom: 10px;
-            }
-            ::v-deep {
-                .el-checkbox-group {
-                    .el-checkbox-button {
-                        margin-right: 12px;
-                        margin-bottom: 10px;
-                        .el-checkbox-button__inner {
-                            border-radius: 8px;
-                            background: #fff;
-                            color: #000;
-                            border: 1px solid #999999;
-                            box-shadow: none;
-                            font-size: 16px;
-                            padding: 15px;
-                            width: 101px;
-                            box-sizing: border-box;
-                        }
-                    }
-                    .is-checked {
-                        .el-checkbox-button__inner {
-                            background: #e8f5ff;
-                            color: #2199f8;
-                            border: 1px solid #2199f8;
-                            position: relative;
-                            &::before {
-                                content: "x";
-                                position: absolute;
-                                top: -10px;
-                                right: -10px;
-                                width: 20px;
-                                height: 20px;
-                                border-radius: 50%;
-                                font-size: 12px;
-                                text-align: center;
-                                line-height: 16px;
-                                color: #ffffff;
-                                background: #2199f8;
-                            }
-                        }
-                    }
-                }
-            }
-            .btn {
-                background: #2199f8;
-                border-radius: 20px;
-                color: #fff;
-                padding: 0 10px;
-                font-size: 12px;
-                height: 24px;
-                line-height: 24px;
-            }
-        }
 
         .button {
             border-radius: 8px;
@@ -474,4 +399,23 @@ onActivated(() => {
         color: #2199f8;
     }
 }
+
+.image-preview {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.8);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    z-index: 1000;
+}
+
+.image-preview img {
+    max-width: 90%;
+    max-height: 90%;
+    object-fit: contain;
+}
 </style>

+ 11 - 1
src/views/old_mini/modify_work/completedWork.vue

@@ -180,7 +180,7 @@
                             <el-icon><ArrowRight /></el-icon>
                         </div> -->
                     </div>
-                    <div class="info-content">水稻移栽后返青成活(新根萌发、心叶展开),进入分蘖始期</div>
+                    <div class="info-content">{{ farmStatusText }}</div>
                 </div>
                 <div class="box-wrap farm-photo" v-if="triggerImg.length">
                     <div class="photo-list">
@@ -570,6 +570,9 @@ onActivated(async () => {
     if (id) {
         await getDetail(id);
         getTriggerImg(id);
+
+        //查询农场现状信息
+        getFarmWorkArrangeDetail(detailData.value.farmWorkArrangeId);
     }
     parmasPage.value = {
         farmMiniUserId: curRole.value == 2 ? detailData.value.farmMiniUserId : detailData.value.users[0]?.userId,
@@ -714,6 +717,13 @@ onActivated(async () => {
     // }
 });
 
+const farmStatusText = ref('');
+const getFarmWorkArrangeDetail = (id) => {
+    VE_API.farm.getFarmWorkArrangeDetail({ id }).then(({ data }) => {
+        farmStatusText.value = data.farmStatus;
+    });
+};
+
 function getServiceCost(cost, area) {
     if (!cost || !area) return "--";
     return (parseFloat(cost) * parseFloat(area)).toFixed(2);

+ 3 - 1
src/views/old_mini/plan/index.vue

@@ -73,7 +73,9 @@ const containerId = ref(null);
 const handleTabChange = (id, item) => {
     containerId.value = item.containerId;
     active.value = id;
-    isEditVal.value = id ? true : false;
+    if(!route.query.containerId){
+        isEditVal.value = id ? true : false;
+    }
 };
 
 onActivated(() => {

+ 7 - 212
src/views/old_mini/service_manage/index.vue

@@ -1,53 +1,12 @@
 <template>
     <div class="service-manage">
         <custom-header name="服务维护"></custom-header>
-        <div class="main-content">
-            <div class="service-title">
-                <img class="label-icon" src="@/assets/img/home/label-icon.png" alt="">
-                服务信息
-            </div>
-            <div class="service-content">
-                <div class="service-item">
-                    <div class="sub-title">服务作物</div>
-                    <div class="tag-group" v-if="!isEdit">
-                        <div class="tag-item" v-for="(item, idx) in crops" :key="'c-'+idx">{{ item.name }}</div>
-                    </div>
-                    <div class="tag-group add-tag-group" v-else>
-                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in crops" :key="'ce-'+idx">
-                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name)" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
-                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('crops', idx)"><Close /></el-icon>
-                        </div>
-                        <div class="tag-item last-add" @click="handleAdd('作物')"><el-icon class="add-icon"><Plus /></el-icon>作物</div>
-                    </div>
-                </div>
-                <div class="service-item">
-                    <div class="sub-title">服务类型</div>
-                    <div class="tag-group" v-if="!isEdit">
-                        <div class="tag-item" v-for="(item, idx) in serviceTypes" :key="'t-'+idx">{{ item.name }}</div>
-                    </div>
-                    <div class="tag-group add-tag-group" v-else>
-                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in serviceTypes" :key="'te-'+idx">
-                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name)" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
-                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('serviceTypes', idx)"><Close /></el-icon>
-                        </div>
-                        <div class="tag-item last-add" @click="handleAdd('类型')"><el-icon class="add-icon"><Plus /></el-icon>类型</div>
-                    </div>
-                </div>
-                <div class="service-item">
-                    <div class="sub-title">农机设备</div>
-                    <div class="tag-group" v-if="!isEdit">
-                        <div class="tag-item" v-for="(item, idx) in machines" :key="'m-'+idx">{{ item.name }}</div>
-                    </div>
-                    <div class="tag-group add-tag-group" v-else>
-                        <div class="tag-item" :class="{ self: item.isSelf === 1 }" v-for="(item, idx) in machines" :key="'me-'+idx">
-                            <span class="text">{{ item.name }}<el-icon @click.stop="handleEdit(item.name)" v-if="item.isSelf===1" class="edit-icon"><Edit /></el-icon></span>
-                            <el-icon v-if="item.isSelf===1" class="del-icon" @click.stop="handleDelete('machines', idx)"><Close /></el-icon>
-                        </div>
-                        <div class="tag-item last-add" @click="handleAdd('设备')"><el-icon class="add-icon"><Plus /></el-icon>设备</div>
-                    </div>
-                </div>
-            </div>
-        </div>
+        <ServiceInfo 
+            v-model:crops="crops"
+            v-model:serviceTypes="serviceTypes"
+            v-model:machines="machines"
+            v-model:isEdit="isEdit"
+        />
         
         <div class="page-action" v-if="isEdit">
             <div class="btn-item cancel" @click="isEdit = false">取消</div>
@@ -59,36 +18,14 @@
             <div class="btn-item primary center-btn" @click="isEdit = true">编辑服务类型</div>
         </div>
     </div>
-
-    <popup class="add-tag-popup" round v-model:show="showAddPopup">
-        <div class="popup-title" v-if="isEditPopup">编辑标签</div>
-        <div class="popup-title" v-else>添加{{addTypeName}}<span class="ml-2">标签</span></div>
-        <el-input class="popup-input" v-model="input" placeholder="标签" size="large" />
-        <div class="popup-button">
-            <div class="cancel" @click="showAddPopup = false">取消</div>
-            <div>{{isEditPopup ? '确定' : '添加'}}</div>
-        </div>
-    </popup>
 </template>
 
 <script setup>
 import { ref } from "vue";
 import customHeader from "@/components/customHeader.vue";
-import { Popup} from "vant";
-import { Edit, Close, Plus } from '@element-plus/icons-vue'
+import ServiceInfo from "@/components/pageComponents/ServiceInfo.vue";
 
 const isEdit = ref(false);
-const showAddPopup = ref(false);
-
-const input = ref("");
-
-const addTypeName = ref("");
-function handleAdd(type) {
-    isEditPopup.value = false
-    addTypeName.value = type;
-    input.value = "";
-    showAddPopup.value = true;
-}
 
 // 三类数据:数组对象形式,随意赋值 isSelf=0/1
 const crops = ref([
@@ -106,19 +43,6 @@ const machines = ref([
     { name: "收割机", isSelf: 1 },
     { name: "M3E", isSelf: 0 }
 ]);
-
-function handleDelete(category, index) {
-    if (category === 'crops') crops.value.splice(index, 1);
-    if (category === 'serviceTypes') serviceTypes.value.splice(index, 1);
-    if (category === 'machines') machines.value.splice(index, 1);
-}
-
-const isEditPopup = ref(false);
-function handleEdit(val) {
-    isEditPopup.value = true;
-    input.value = val;
-    showAddPopup.value = true;
-}
 </script>
 
 <style lang="scss" scoped>
@@ -126,97 +50,6 @@ function handleEdit(val) {
     width: 100%;
     height: 100vh;
     background: #F5F7FB;
-    .main-content {
-        max-height: calc(100% - 40px);
-        overflow: auto;
-        padding: 15px 12px;
-        margin: 14px 12px;
-        border-radius: 12px;
-        background: #fff;
-        .service-title {
-            font-size: 18px;
-            color: #222222;
-            font-weight: 500;
-            margin-bottom: 10px;
-            .label-icon {
-                width: 14px;
-                padding-right: 5px;
-            }
-        }
-        .service-content {
-            margin-top: 12px;
-            padding-top: 12px;
-            border-top: 1px solid #F5F5F5;
-            .service-item {
-                .sub-title {
-                    font-size: 16px;
-                    font-weight: 500;
-                    color: rgba(0, 0, 0, 0.9);
-                }
-                .tag-group {
-                    display: flex;
-                    align-items: center;
-                    flex-wrap: wrap;
-                    gap: 0 12px;
-                    font-size: 16px;
-                    .tag-item {
-                        margin-top: 10px;
-                        position: relative;
-                        background: #E8F5FF;
-                        border-radius: 8px;
-                        color: #2199f8;
-                        padding: 0 12px;
-                        box-sizing: border-box;
-                        min-width: 26vw;
-                        height: 48px;
-                        text-align: center;
-                        line-height: 48px;
-                        .text { display: inline-flex; align-items: center; }
-                        .edit-icon { margin-left: 8px; }
-                        .del-icon {
-                            position: absolute;
-                            right: -8px;
-                            top: -8px;
-                            background: #2199F8;
-                            border-radius: 50%;
-                            width: 16px; height: 16px;
-                            font-size: 10px;
-                            display: flex; align-items: center; justify-content: center;
-                            color: #fff;
-                        }
-                    }
-                    &.add-tag-group {
-                        .tag-item {
-                            color: #000000;
-                            background: none;
-                            border: 1px solid #999999;
-                            &.self {
-                                border: 1px solid #2199F8;
-                                background: #E8F5FF;
-                                color: #2199F8;
-                            }
-                            &.last-add {
-                                background: #F7F7F7;
-                                color: #343434;
-                                border: none;
-                                display: flex;
-                                align-items: center;
-                                justify-content: center;
-                                .add-icon {
-                                    font-size: 14px;
-                                    font-weight: bold;
-                                    margin-right: 3px;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            .service-item + .service-item {
-                margin-top: 20px;
-            }
-        }
-    }
     
     .page-action {
         position: fixed;
@@ -258,42 +91,4 @@ function handleEdit(val) {
         }
     }
 }
-
-
-.add-tag-popup{
-    width: 90%;
-    padding: 20px 16px;
-    .popup-title{
-        font-size: 18px;
-        font-weight: 500;
-        text-align: center;
-        margin-bottom: 12px;
-    }
-    .ml-2 {
-        margin-left: 3px;
-    }
-    .popup-input{
-        margin-bottom: 30px;
-    }
-    .popup-button{
-        display: flex;
-        padding-top: 20px;
-        border-top: 1px solid rgba(0, 0, 0, 0.1);
-        div{
-            flex: 1;
-            font-size: 16px;
-            padding: 9px;
-            border-radius: 20px;
-            background: #2199F8;
-            color: #fff;
-            text-align: center;
-        }
-        .cancel{
-            margin-right: 20px;
-            color: #000;
-            background: #fff;
-            border: 1px solid #999999;
-        }
-    }
-}
 </style>

+ 24 - 4
src/views/old_mini/user/index.vue

@@ -27,20 +27,18 @@
                         :key="ele.agriculturalStoreId"
                         class="list-item"
                         :data="{
+                            ...ele,
                             farmName: ele.name,
                             area: ele.mianji + '亩',
                             variety: ele.speciesName,
                             address: ele.address,
                             mapImage: ele.mapImage || '/map.png',
                             maxWidth: '90px',
-                            // day: 15,
-                            // farmInfo: '梢期杀虫',
-                            // estimatedIncome: ele.estimatedIncome || 2585
                         }"
                         @click="handleItemClick(ele)"
                     >
                         <template #right>
-                            <div @click.stop="handleChat(ele)">{{ ele.receiveUserId ? '在线沟通' : '分享农场' }}</div>
+                            <div @click.stop="handleChat(ele)">{{ ele.receiveUserId ? '在线沟通' : '分享认领' }}</div>
                         </template>
                     </farm-info-card>
                 </collapse-item>
@@ -91,9 +89,31 @@ const getUserList = async () => {
         // 清空现有的子项
         dataList.value[0].children = [];
         dataList.value[1].children = data || [];
+        getLatestBroadcast();
     }
 };
 
+const getLatestBroadcast = () => {
+    VE_API.user.getLatestBroadcast({sourceTypes:[0,1]}).then(({ data }) => {
+        if (data && typeof data === 'object') {
+            // 遍历广播数据,key 是 farmId(字符串格式)
+            Object.keys(data).forEach(farmIdStr => {
+                const farmId = Number(farmIdStr);
+                const broadcasts = data[farmIdStr] || [];
+                
+                // 在农场列表中找到对应的农场
+                const farmItem = dataList.value[1].children.find(item => item.id === farmId || item.farmId === farmId);
+                
+                if (farmItem && broadcasts.length > 0) {
+                    // 将广播数据合并到农场项中
+                    farmItem.broadcasts = broadcasts;
+                }
+            });
+            console.log("dataList.value", dataList.value);
+        }
+    });
+};
+
 const input = ref("");
 //新建分组
 const showGroupPopup = ref(false);