瀏覽代碼

feat:对接品种确权页面功能

wangsisi 1 月之前
父節點
當前提交
667a35cb26
共有 5 個文件被更改,包括 190 次插入94 次删除
  1. 8 0
      src/api/modules/variety.js
  2. 0 2
      src/views/home/index.vue
  3. 114 53
      src/views/varietyMap/index.vue
  4. 63 38
      src/views/varietyMap/map.vue
  5. 5 1
      src/views/warningHome/index.vue

+ 8 - 0
src/api/modules/variety.js

@@ -8,5 +8,13 @@ module.exports = {
     pointList: {
         url: config.base_url + "lz_sample/list",
         type: "post",
+    },
+    speciesData: {
+        url: config.base_url + "species_item/list",
+        type: "get",
+    },
+    updateSpeciesItem: {
+        url: config.base_url + "lz_sample/updateSpeciesItem",
+        type: "post",
     }
 }

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

@@ -201,7 +201,6 @@ const handleTab = async ({name,id,isUpdate,params}) =>{
         }
       })
     }else{
-      console.log('456456');
       getFarmIndexReport((()=>{
         if(isUpdate){
           handleTabItem(params)
@@ -224,7 +223,6 @@ function areaId({areaId,farmId}){
 
 //选项卡子项事件监听
 const handleTabItem = (e) =>{
-  console.log('e',e);
   if(reportData.value.blueZoneList){
     const index = reportData.value.blueZoneList.findIndex(item => item.key===e)
     let arr = []

+ 114 - 53
src/views/varietyMap/index.vue

@@ -9,7 +9,7 @@
                 </div>
                 <chart-box class="left-cont" name="品种列表" color="yellow">
                     <div class="box">
-                        <div class="add-cont" v-if="baseData.length===0">
+                        <div class="add-cont" v-if="baseData.length === 0">
                             <div>暂无数据</div>
                             <div class="tips-text">请先添加品种,再框选右侧区域,进行品种确权</div>
                             <div class="button" @click="handleAdd">
@@ -19,8 +19,11 @@
                         </div>
                         <template v-else>
                             <div class="box-item" v-for="item in baseData" :key="item.speciesItemId">
-                                <div>{{item.speciesItemName}}</div>
-                                <span>{{item.sampleCount}}颗</span>
+                                <div>
+                                    <div class="circle" :style="{background:item.color}"></div>
+                                    {{ item.speciesItemName }}
+                                </div>
+                                <span>{{ item.sampleCount||0 }}颗</span>
                             </div>
                             <div class="button" @click="handleAdd">
                                 <el-icon class="icon"><Plus /></el-icon>
@@ -42,9 +45,14 @@
                     <my-map></my-map>
                     <div class="checkbox-list">
                         <span class="text">全部设置为</span>
-                        <el-checkbox-group class="checkbox" v-model="checkedCities" @change="handleCheckedCitiesChange">
-                            <el-checkbox v-for="city in cities" :key="city" :label="city.label" :value="city.value">
-                                {{ city.label }}
+                        <el-checkbox-group
+                            class="checkbox"
+                            v-model="checkedCities"
+                            :min="1"
+                            @change="handleCheckedCitiesChange"
+                        >
+                            <el-checkbox v-for="item in baseData" :key="item.speciesItemId" :value="item.speciesItemId">
+                                {{ item.speciesItemName }}
                             </el-checkbox>
                         </el-checkbox-group>
                         <div class="add" @click="handleAdd">
@@ -53,8 +61,8 @@
                         </div>
                     </div>
                     <div class="footer-btn">
-                        <div class="cancel">取消</div>
-                        <div>保存</div>
+                        <div class="cancel" @click="handleCancel">取消</div>
+                        <div @click="handleSave">保存</div>
                     </div>
                 </div>
             </div>
@@ -69,11 +77,13 @@
         align-center
         :before-close="handleClose"
     >
-        <el-input class="input" size="large" v-model="input" placeholder="请输入品种名称" />
+        <el-select v-model="input" size="large" placeholder="请选择品种名称">
+            <el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id" />
+        </el-select>
         <template #footer>
             <div class="dialog-footer">
-                <div class="btn" @click="dialogVisible = false">取消</div>
-                <div @click="dialogVisible = false">确定</div>
+                <div class="btn" @click="handleClose">取消</div>
+                <div @click="handleOk">确定</div>
             </div>
         </template>
     </el-dialog>
@@ -92,49 +102,69 @@ const store = useStore();
 
 const router = useRouter();
 const route = useRoute();
+const farmId = sessionStorage.getItem("farmId");
 onMounted(() => {
     getList();
-    eventBus.on('map:list',getMapList)
+    getSpeciesData();
+    eventBus.on("map:list", getMapList);
 });
 
-onUnmounted(()=>{
-    eventBus.off('map:list',getMapList)
-})
+onUnmounted(() => {
+    eventBus.off("map:list", getMapList);
+});
 
-function getMapList(arr){
-    console.log('arr',arr);
+const selectPoint = ref([])
+function getMapList(arr) {
+    selectPoint.value = arr
 }
 
 //清除框选
-const handleClear = () =>{
-    eventBus.emit('handle:clear')
-}
+const handleClear = () => {
+    eventBus.emit("handle:clear");
+};
 
-const baseData = ref([])
+const baseData = ref([]);
 const getList = () => {
     const params = {
-        farmId:sessionStorage.getItem('farmId'),
-        regionId:sessionStorage.getItem('regionId')
-    }
-    VE_API.variety.speciesItemList(params).then(res =>{
+        farmId,
+        regionId: sessionStorage.getItem("regionId"),
+    };
+    VE_API.variety.speciesItemList(params).then((res) => {
         baseData.value = res.data || []
-    })
+        eventBus.emit('species:list',res.data)
+    });
 };
 
-const checkedCities = ref(["0"]);
-const cities = [
-    {
-        label:"品种1",
-        value:"0"
-    },
-    {
-        label:"品种2",
-        value:"1"
+const checkedCities = ref([]);
+const handleCheckedCitiesChange = (e) => {
+    if(e.length){
+        checkedCities.value = [e[e.length -1]];
     }
-];
-const handleCheckedCitiesChange = (value) => {
 };
 
+const handleSave = () =>{
+    const params = selectPoint.value.map(item =>{
+        return {
+            id:item.id,
+            speciesItemId:checkedCities.value[0]
+        }
+    })
+    if(params.length===0) return ElMessage.warning('请选择最少一棵树')
+    if(checkedCities.value.length===0) return ElMessage.warning('请选择品种')
+    VE_API.variety.updateSpeciesItem(params).then(res =>{
+        if(res.code===0){
+            getList()
+            checkedCities.value = []
+            ElMessage.success('添加成功')
+        }
+    })
+}
+
+const handleCancel = () =>{
+    checkedCities.value = []
+    eventBus.emit('handle:clear')
+}
+
 const goBack = () => {
     router.go(-1);
 };
@@ -142,13 +172,30 @@ const goBack = () => {
 //添加品种弹窗
 const dialogVisible = ref(false);
 const input = ref("");
+const options = ref([])
 const handleAdd = () => {
     dialogVisible.value = true;
 };
+// 获取品种列表----下拉框
+const getSpeciesData = () => {
+    VE_API.variety.speciesData({ farmId }).then(res =>{
+        options.value = res.data || []
+    });
+};
 
 const handleClose = () => {
     dialogVisible.value = false;
     input.value = "";
+}
+
+const handleOk = () =>{
+    const arr = options.value.filter(item =>item.id === input.value)
+    baseData.value.push({
+        ...arr[0],
+        speciesItemId:arr[0].id,
+        speciesItemName:arr[0].name,
+    })
+    handleClose()
 };
 </script>
 
@@ -231,7 +278,7 @@ const handleClose = () => {
                             margin-top: 8px;
                         }
                     }
-                    .box-item{
+                    .box-item {
                         width: 94%;
                         display: flex;
                         align-items: center;
@@ -239,13 +286,25 @@ const handleClose = () => {
                         border-radius: 5px;
                         border: 1px solid #666666;
                         padding: 12px;
-                        div{
+                        .circle{
+                            border-radius: 50%;
+                            border: 1px solid #fff;
+                            width: 11px;
+                            height: 11px;
+                            margin-right: 7px;
+                        }
+                        div {
                             font-size: 18px;
+                            display: flex;
+                            align-items: center;
                         }
-                        span{
+                        span {
                             color: #9f9f9f;
                         }
                     }
+                    .box-item + .box-item{
+                        margin-top: 12px;
+                    }
                 }
             }
         }
@@ -272,7 +331,7 @@ const handleClose = () => {
                         margin-right: 8px;
                     }
                 }
-                .button{
+                .button {
                     color: #fff;
                     padding: 5px 15px;
                     border-radius: 4px;
@@ -286,7 +345,7 @@ const handleClose = () => {
                 clip-path: inset(0px round 4px);
                 height: calc(100% - 31px - 16px);
                 position: relative;
-                .checkbox-list{
+                .checkbox-list {
                     position: absolute;
                     z-index: 2;
                     right: 42px;
@@ -296,27 +355,27 @@ const handleClose = () => {
                     display: flex;
                     flex-direction: column;
                     padding: 20px;
-                    .text{
+                    .text {
                         color: #9f9f9f;
                         margin-bottom: 12px;
                         font-size: 16px;
                     }
-                    .checkbox{
+                    .checkbox {
                         display: flex;
                         flex-direction: column;
-                        ::v-deep{
-                            .el-checkbox__label{
+                        ::v-deep {
+                            .el-checkbox__label {
                                 color: #fff;
                                 font-size: 16px;
                             }
-                            .el-checkbox__inner{
+                            .el-checkbox__inner {
                                 width: 18px;
                                 height: 18px;
                             }
-                            .el-checkbox__input.is-checked .el-checkbox__inner{
-                                background: #FFD489;
-                                border-color: #FFD489;
-                                &::after{
+                            .el-checkbox__input.is-checked .el-checkbox__inner {
+                                background: #ffd489;
+                                border-color: #ffd489;
+                                &::after {
                                     border-color: #000;
                                     border-width: 2px;
                                     height: 10px;
@@ -327,16 +386,17 @@ const handleClose = () => {
                             }
                         }
                     }
-                    .add{
+                    .add {
                         margin-top: 12px;
                         border: 1px solid #fff;
                         border-radius: 4px;
                         background: rgba(255, 255, 255, 0.2);
                         display: flex;
                         align-items: center;
+                        justify-content: center;
                         padding: 8px;
                         cursor: pointer;
-                        .icon{
+                        .icon {
                             margin-right: 4px;
                         }
                     }
@@ -390,6 +450,7 @@ const handleClose = () => {
         border-radius: 5px;
         color: #1d1d1d;
         text-align: center;
+        cursor: pointer;
     }
     .btn {
         border: 1px solid #9f9f9f;

+ 63 - 38
src/views/varietyMap/map.vue

@@ -7,17 +7,28 @@ import { ref, onMounted, onUnmounted } from "vue";
 import AMapLoader from "@amap/amap-jsapi-loader";
 import eventBus from "@/api/eventBus";
 import { convertPointToArray } from "@/utils/index";
+import { deepClone } from "@/common/commonFun";
 
 const map = ref(null);
 const mouseTool = ref(null);
 const selectedArea = ref(null);
 const selectedPoints = ref([]);
 const allPoints = ref([]);
-const defalutIcon = ref(null)
-const activeIcon = ref(null)
-
-const defalutOffset = ref(null)
-const activeOffset = ref(null)
+const defalutAllPoints = ref([])
+
+// 自定义圆点样式
+const createMarkerContent = (color = 'rgba(0, 0, 0, 0.4)') => {
+    return `
+        <div style="
+            width: 15px;
+            height: 15px;
+            background-color: ${color};
+            border: 1px solid #fff;
+            border-radius: 50%;
+        ">
+        </div>
+    `;
+}
 
 // 初始化地图
 const initMap = async () => {
@@ -30,7 +41,7 @@ const initMap = async () => {
             // 创建地图实例
             map.value = new AMap.Map("map-container", {
                 zoom: 18, // 初始缩放级别
-                center: [113.6149629 ,23.58594117],
+                center: allPoints.value[0].lngLat,
                 layers: [
                     // 卫星
                     new AMap.TileLayer.Satellite(),
@@ -40,32 +51,35 @@ const initMap = async () => {
             // 初始化 MouseTool
             mouseTool.value = new AMap.MouseTool(map.value);
 
-            defalutIcon.value = new AMap.Icon({
-              // 图标的取图地址
-              image: require('@/assets/images/map/status/defalut-icon.png'),
-              // 图标所用图片大小
-              imageSize: new AMap.Size(26, 26),
-            });
-            activeIcon.value = new AMap.Icon({
-              // 图标的取图地址
-              image: require('@/assets/images/map/status/active-icon.png'),
-              // 图标所用图片大小
-              imageSize: new AMap.Size(40, 40),
-            });
-
-            defalutOffset.value = new AMap.Pixel(-5, -5)
-            activeOffset.value = new AMap.Pixel(-12, -14)
-
-            // 添加示例点位
+            // // 添加点位
             allPoints.value.forEach((point) => {
                 point.icon = new AMap.Marker({
                     position: point.lngLat,
                     map: map.value,
-                    icon:defalutIcon.value,
-                    offset: defalutOffset.value,
+                    content: createMarkerContent(point.color),
+                    offset: new AMap.Pixel(-7, -7),
                 });
                 point.type = 'defalutIcon'
+
+                // 绑定点击事件
+                point.icon.on('click', () => {
+                    if(point.type === 'defalutIcon'){
+                        point.icon.setContent(createMarkerContent('#FFD489')); // 修改颜色
+                        point.type = 'activeIcon'
+                    }else{
+                        point.icon.setContent(createMarkerContent(point.color)); // 修改颜色
+                        point.type = 'defalutIcon'
+                    }
+                });
+
+                defalutAllPoints.value.push(point)
             });
+
+            const latLngs = allPoints.value.map(item =>item.icon)
+            map.value.setFitView(latLngs,{
+                padding: [0, 0, 0, 0], // 上下左右的边距
+                maxZoom: 18, // 最大缩放级别
+            })
             startRectangleSelection()
 
             // 监听框选完成事件
@@ -83,6 +97,14 @@ const initMap = async () => {
     }
 };
 
+const resetData = () =>{
+    allPoints.value = defalutAllPoints.value
+    allPoints.value.forEach(item =>{
+        item.icon.setContent(createMarkerContent(item.color))
+        item.type = 'defalutIcon'
+    })
+}
+
 // 开始框选
 const startRectangleSelection = () => {
     if (mouseTool.value) {
@@ -101,11 +123,7 @@ const clearSelection = () => {
     if (selectedArea.value) {
         map.value.remove(selectedArea.value); // 移除框选区域
         selectedArea.value = null;
-        selectedPoints.value.forEach(item =>{
-          item.icon.setIcon(defalutIcon.value)
-          item.icon.setOffset(defalutOffset.value)
-          item.type = 'defalutIcon'
-        })
+        resetData()
         selectedPoints.value = []; // 清空选中的点位
     }
 };
@@ -113,19 +131,16 @@ const clearSelection = () => {
 // 检查框选区域内的点位
 const checkPointsInArea = () => {
     if (!selectedArea.value) return;
-
     const bounds = selectedArea.value.getBounds(); // 获取框选区域的边界
     selectedPoints.value = allPoints.value.filter((point) => {
         return bounds.contains(point.lngLat); // 判断点位是否在框选区域内
     });
     selectedPoints.value.forEach(item =>{
         if(item.type==='defalutIcon'){
-            item.icon.setIcon(activeIcon.value)
-            item.icon.setOffset(activeOffset.value)
+            item.icon.setContent(createMarkerContent('#FFD489'))
             item.type = 'activeIcon'
         }else{
-            item.icon.setIcon(defalutIcon.value)
-            item.icon.setOffset(defalutOffset.value)
+            item.icon.setContent(createMarkerContent(item.color))
             item.type = 'defalutIcon'
         }
     })
@@ -133,6 +148,7 @@ const checkPointsInArea = () => {
     eventBus.emit('map:list',arr)
 };
 
+const speciesArr = ref([])
 const getList = () =>{
     const params = {
         farmId:sessionStorage.getItem('farmId'),
@@ -140,23 +156,32 @@ const getList = () =>{
     }
     VE_API.variety.pointList(params).then(res =>{
         allPoints.value = res.data.map(item =>{
+            const bgColor = speciesArr.value.filter(ele =>ele.speciesItemId === item.speciesItemId)
             return{
                 ...item,
+                color:bgColor[0].color,
                 lngLat:convertPointToArray(item.point)
             }
         })
-        initMap();
+        initMap()
     })
 }
 
+function getSpeciesList(arr){
+    speciesArr.value = arr
+    getList()
+}
+
 // 组件挂载时初始化地图
 onMounted(() => {
-    getList()
     eventBus.on('handle:clear',clearSelection)
+    eventBus.on('species:list',getSpeciesList)
 });
 
 onUnmounted(()=>{
-  eventBus.off('handle:clear',clearSelection)
+    map.value.destroy()// 销毁地图实例以释放资源
+    eventBus.off('handle:clear',clearSelection)
+    eventBus.off('species:list',getSpeciesList)
 })
 </script>
 

+ 5 - 1
src/views/warningHome/index.vue

@@ -99,7 +99,7 @@ import "./map/mockFarmLayer";
 import StaticMapLayers from "@/components/static_map_change/Layers.js"
 import StaticMapLegend from "@/components/static_map_change/legend.vue"
 import StaticMapPointLayers from "@/components/static_map_change/pointLayer.js"
-import { onMounted, ref } from "vue";
+import { onMounted, onUnmounted, ref } from "vue";
 import fnHeader from "@/components/fnHeader.vue";
 import WarningMap from "./warningMap";
 import AlarmLayer from "./map/alarmLayer";
@@ -166,6 +166,10 @@ onMounted(() => {
 });
 sessionStorage.removeItem("farmId")
 
+onUnmounted(()=>{
+    eventBus.off("alarmList:changeMapLayer")
+})
+
 // ai与地图交互
 const hideChatMapLayer = ref(true)
 const handleMapLayer = ({mapName}) => {