Forráskód Böngészése

Merge branch 'master' of http://www.sysuimars.cn:3000/feiniao/agriculture-one-map

lxf 1 hete
szülő
commit
c3d477f33e

+ 0 - 33
src/api/modules/authentic.js

@@ -1,33 +0,0 @@
-import config from "../config";
-
-export default {
-  getList: {
-    url: config.base_url + "plugin_ownership/list",
-    type: "get",
-  },
-  getDetails: {
-    url: config.base_url + "plugin_ownership/get",
-    type: "get",
-  },
-  saveData: {
-    url: config.base_url + "plugin_ownership/save",
-    type: "post",
-  },
-  deleteData: {
-    url: config.base_url + "plugin_ownership/delete",
-    type: "post",
-  },
-  exportData: {
-    url: config.base_url + "plugin_ownership/exportList",
-    type: "post",
-  },
-  getArea: {
-    url: config.base_url_python + "geom/area",
-    type: "post",
-  },
-  fetchSlopeArea: {
-    url: config.base_url + "poi/calculateSlopeArea",
-    type: "post",
-  },
-};
-

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

@@ -1,21 +0,0 @@
-import config from "../config"
-
-export default {
-    speciesItemList: {
-        url: config.base_url + "lz_sample/speciesItemList",
-        type: "get",
-    },
-    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",
-    }
-}
-

+ 25 - 1
src/api/modules/warning.js

@@ -10,10 +10,34 @@ export default {
         url: config.base_url + "poi/districtById",
         type: "get",
     },
-
     transformLocation: {
         url: "/ws/geocoder/v1",
         type: "get"
     },
+    // 获取作物种植面积占比
+    fetchStatSpeciesAreaYield: {
+        url: config.one_map_url + "agri_land_crop/stat_species_area_yield",
+        type: "get",
+    },
+    //统计指定物种在下级区划中的面积占比
+    fetchStatRegionAreaRatio: {
+        url: config.one_map_url + "agri_land_crop/stat_region_area_ratio",
+        type: "get",
+    },
+    //返回去年的年度+季度,以及今年从第一季度到当前季度的集合
+    fetchYearQuarter: {
+        url: config.one_map_url + "agri_common/year_quarters",
+        type: "get",
+    },
+    //统计最近三年每种物种每季度的种植面积趋势(按物种分组)
+    fetchAreaTrend: {
+        url: config.one_map_url + "agri_land_crop/stat_last_three_years",
+        type: "post",
+    },
+    //查询地区作物面积与预估产量
+    fetchRegionCropAreaYield: {
+        url: config.one_map_url + "agri_region_crop/query_area_yield",
+        type: "get",
+    },
 }
 

+ 0 - 12
src/router/mainRoutes.js

@@ -24,12 +24,6 @@ export default [
         name: "GardenFile",
         component: () => import(/* @vite-ignore */ "@/views/file/index.vue"),
     },
-    //地块确权页面
-    {
-        path: "/authentic",
-        name: "Authentic",
-        component: () => import(/* @vite-ignore */ "@/views/authentic/index.vue"),
-    },
     //新增农事
     {
         path: "/add_farm",
@@ -48,10 +42,4 @@ export default [
         name: "WorkCompleted",
         component: () => import(/* @vite-ignore */ "@/views/workDetail/completed.vue"),
     },
-    // 品种确权页面
-    {
-        path: "/variety_map",
-        name: "VarietyMap",
-        component: () => import(/* @vite-ignore */ "@/views/varietyMap/index.vue"),
-    },
 ];

+ 0 - 294
src/views/authentic/Pdf.vue

@@ -1,294 +0,0 @@
-<template>
-  <el-dialog
-      class="my-dialog"
-      fullscreen
-      append-to-body
-      :model-value="showDialog"
-      @close="closeDialog()"
-  >
-    <div class="pdf-main">
-      <div class="title" >
-        <div class="name" ></div>
-        <div class="pdf-close cursor-pointer" @click="closeDialog"></div>
-      </div>
-      <div id="printTest" class="pdf-dialog-box">
-        <div class="pdf-my-body"  >
-          <div class="pdfBox">
-            <div class="a4" id="pdfDom">
-              <div class="a4_title">确权单</div>
-              <table class="a4_table" border=1 style="border-collapse: collapse;">
-                <tr>
-                  <td class="name">农场地址</td>
-                  <td class="text">{{rowData.address}}</td>
-                  <td class="name">农场名称</td>
-                  <td class="text">{{rowData.farmName}}</td>
-                </tr>
-                <tr>
-                  <td class="name">创建时间</td>
-                  <td class="text">{{rowData.createDate}}</td>
-                  <td class="name">农场面积</td>
-                  <td class="text">{{rowData.area}}亩</td>
-                </tr>
-                <tr>
-                  <td class="name">作物物种</td>
-                  <td class="text">{{rowData.speciesTypeName}}</td>
-                  <td class="name">斜面面积</td>
-                  <td class="text">{{rowData.slopeMu}}亩</td>
-                </tr>
-                <tr>
-                  <td class="name">客户姓名</td>
-                  <td class="text">{{rowData.masterName}}</td>
-                  <td class="name">联系电话</td>
-                  <td class="text">{{rowData.masterTel}}</td>
-                </tr>
-                <tr>
-                  <td class="name">经纬度</td>
-                  <td colspan="3" class="text2">{{rowData.points}}</td>
-                </tr>
-              </table>
-              <div class="a4_sub_title">地块四至图</div>
-              <img :key="imgUrl" v-show="imgUrl" class="img-content img" style="z-index: 999" width="595" height="500" :src="imgUrl" />
-              <div :key="imgUrl" v-show="!imgUrl" style="width: 595px;height: 500px" class="img-content" ref="mapRef" id="mapRefId"></div>
-              <div class="signature">签名:______________</div>
-            </div>
-          </div>
-        </div>
-      </div>
-      <div style="text-align: left">
-         <el-button size="large" color="#626aef"  @click="handlePrint">保存</el-button>
-        <!-- <el-button size="large" color="#626aef"  v-print="printObj">打印</el-button> -->
-        <!--          <el-button size="large" color="#626aef"  @click="closeDialog">关闭</el-button>-->
-      </div>
-
-    </div>
-  </el-dialog>
-</template>
-
-<script setup>
-import {reactive, ref, toRefs, computed, nextTick, onMounted} from "vue";
-import {useStore} from "vuex";
-import {WKT} from "ol/format";
-import PdfMap from "./pdfMap";
-import { dateFormat } from "@/utils/date_util";
-import {getAreaByWkt} from "../../utils/map";
-import printPdf from "@/utils/html2Canvas";
-const emit = defineEmits(["closeDialog","success"])
-const state = useStore().state;
-const sendConfirmShow = ref(false)
-const mapRef = ref(null)
-let pdfMap = new PdfMap()
-let rowData = ref({})
-
-async function send(){
-  closeDialog();
-}
-
-const props = defineProps({
-  title:{
-    type:String,
-    required:true
-  },
-  showDialog: {
-    type: Boolean,
-    default: true,
-  },
-  rowId:{
-    type: Number,
-    required:true,
-  }
-});
-
-let printObj = {
-  id:"printTest",
-  popTitle: 'good print',
-  beforeOpenCallback (vue) {
-    toImg(true)
-    console.log('打开之前')
-  },
-  openCallback (vue) {
-    let {masterName, farmName, masterTel} = rowData.value
-    document.title =`${farmName}-${masterTel}-${masterName}`
-    console.log('执行了打印')
-  },
-  closeCallback (vue) {
-    document.title =`飞鸟确权平台`
-    console.log('关闭了打印工具')
-  }
-}
-
-let imgUrl = ref(null)
-const executor = ref([])
-const executorList = ref([])
-
-const formRef = ref(null);
-const {title, rowId} = toRefs(props);
-const closeDialog = (key) => {
-  switch (key){
-    case "sendConfirm":
-      sendConfirmShow.value = false;
-      return
-  }
-  emit("closeDialog", "pdf");
-};
-function toImg() {
-  // let canvas = pdfMap.kmap.map.getViewport().querySelector('canvas')
-  // let dataURL = canvas.toDataURL('image/webp');
-  //   imgUrl.value = dataURL;
-}
-
-const handlePrint = () =>{
-    let {masterName, farmName, masterTel} = rowData.value
-    const title =`${farmName}-${masterTel}-${masterName}`
-    printPdf(title)
-}
-
-onMounted(()=>{
-  VE_API.authentic.getDetails({id:rowId.value}).then(({data})=>{
-    data.createDate = dateFormat(new Date(), "YYYY-mm-dd HH:MM:SS");
-    data.area = data.mu
-    rowData.value = data
-    pdfMap.initMap(data,mapRef.value)
-    setTimeout(function(){
-      toImg(false)
-    },1500)
-  })
-})
-</script>
-
-<style lang="scss">
-$title-height:0px;
-$body-height:calc(100% - $title-height);
-
-.pdf-main{
-  left: 25%;
-  right: 25%;
-  top:10%;
-  bottom:10%;
-  background: rgba(1,17,22,0.8);
-  box-shadow: 0px 0px 20px 0px #00FFF0;
-  border-radius: 4px;
-  border: 2px solid rgba(81,233,240,0.6);
-  position: absolute;
-  .title{
-    width: 100%;
-    height: $title-height;
-    box-sizing: border-box;
-    background: rgba(0,77,101,0.8);
-    border-radius: 4px 4px 0px 0px;
-    border-bottom: 2px solid rgba(81,233,240,0.3);
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    .name{
-      margin-left: 20px;
-      font-size: 16px;
-      font-weight: 600;
-      color: #00FFF0;
-      height: 22px;
-    }
-    .pdf-close{
-      width: 16px;
-      height: 16px;
-      background-image: url("@/assets/img/close.png");
-      background-size: 100% 100%;
-    }
-  }
-}
-.pdf-dialog-box{
-  font-family: PingFangSC-Regular, PingFang SC;
-  width: 100%;
-  height: 100%;
-  .pdf-my-body{
-    width: 100%;
-    height: $body-height;
-    box-sizing: border-box;
-    padding: 20px;
-    ::-webkit-scrollbar-thumb {
-      /* 滚动条里面小方块 */
-      background: rgb(70, 71, 71);;
-      border-radius: 6px;
-    }
-    ::-webkit-scrollbar-track {
-      /* 滚动条里面轨道 */
-      background: #ededed;
-    }
-  }
-
-  .pdfBox{
-    height: calc(100%);
-    width: 100%;
-    overflow-y: scroll;
-    box-sizing: border-box;
-    background-color: rgba(141, 142, 142);
-    padding: 10px;
-
-  }
-
-  .a4{
-    font-family: PingFangSC-Medium, PingFang SC;
-    background-color: #FFFFFF;
-    width:595px;
-    height:auto;
-    margin: 0 auto;
-    padding: 15px 63px 15px 63px;
-    font-weight: 600;
-    color: #000000;
-    .a4_title{
-      width:595px;
-      height: 28px;
-      font-size: 24px;
-      text-align: center;
-      margin: 10px 0px 10px 0px;
-    }
-    .a4_sub_title{
-      font-size: 16px;
-      margin: 5px 0px 5px 0px;
-    }
-    .a4_table{
-      height: calc(842px - 33px - 26px - 600px);
-      max-height: calc(842px - 33px - 26px - 600px);
-      width:595px;
-      font-size: 12px;
-      .name{
-        width: 50px;
-        height: 20px;
-        line-height: 20px;
-        padding-right: 9px;
-        box-sizing: border-box;
-        text-align: right;
-      }
-      .text{
-        width: 122px;
-        height: 20px;
-        line-height: 20px;
-        text-align: left;
-        padding-left: 9px;
-        box-sizing: border-box;
-      }
-      .text2{
-        text-align: left;
-        font-size: 10px;
-        font-weight: normal;
-      }
-    }
-    .img-content{
-      z-index: 1000;
-      margin: 0 auto;
-    }
-    .img{
-      z-index: 999;
-    }
-    .signature{
-      width:595px;
-      height: 20px;
-      z-index: 1000;
-      margin-top: 15px;
-      text-align: right;
-    }
-  }
-
-
-}
-
-
-</style>

+ 0 - 578
src/views/authentic/authenticMap.js

@@ -1,578 +0,0 @@
-import config from "@/api/config.js";
-import * as KMap from "@/utils/ol-map/KMap";
-import * as util from "@/common/ol_common.js";
-import Style from "ol/style/Style";
-import Icon from "ol/style/Icon";
-import VectorLayer from "ol/layer/Vector.js";
-import WKT from "ol/format/WKT.js";
-import { reactive } from "vue";
-import Point from "ol/geom/Point.js";
-import Feature from "ol/Feature";
-import { newPoint } from "@/utils/map.js";
-import { Fill, Text,Circle,Stroke } from "ol/style";
-import { getArea } from "ol/sphere.js";
-import * as proj from "ol/proj";
-import proj4 from "proj4";
-import { register } from "ol/proj/proj4";
-import GeometryCollection from 'ol/geom/GeometryCollection.js';
-import { ElMessage } from "element-plus";
-import { useStore } from "vuex";
-import {bboxToFeature} from "../../utils/map";
-import * as turf from "@turf/turf";
-proj4.defs(
-  "EPSG:38572",
-  "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"
-);
-register(proj4);
-export let mapData = reactive({
-  isEdit: false,
-  isEditArea: false,
-  curPointData: {},
-  point: null,
-  selectPointArr: [],
-  isPointHide: null,
-  disabledForm : false,
-  selectPoint:'',
-  pointIndex:-1
-});
-
-function resetMapData(){
-  mapData.isEdit= false
-  mapData.isEditArea= false
-  mapData.curPointData= {}
-  mapData.point= null
-  mapData.selectPointArr= []
-  mapData.isPointHide= null
-  mapData.disabledForm= false
-  mapData.selectPoint= ''
-  mapData.pointIndex=-1
-}
-
-/**
- * @description 地图层对象
- */
-class AuthenticMap {
-  constructor() {
-    let that = this;
-    that.store = useStore();
-    let vectorStyle = new KMap.VectorStyle();
-    this.vectorStyle = vectorStyle;
-    // 位置图标
-    this.clickPointLayer = new KMap.VectorLayer("clickPointLayer", 9999, {
-      style: (f) => {
-        const style1 = new Style({
-          image: new Icon({
-            src: `/src/assets/images/map/${f.get("icon")}-icon.png`,
-            scale: 0.45,
-          }),
-        });
-        const style2 = new Style({
-          text: new Text({
-            font: "16px sans-serif",
-            text: f.get("farmName"),
-            offsetY: -40,
-            padding: [4, 3, 2, 106],
-            fill: new Fill({ color: "#fff" }), // 字体颜色
-          }),
-        });
-        const style3 = new Style({
-          image: new Icon({
-            src: `/src/assets/images/map/${f.get("iconBg")}.png`,
-            scale: 0.45,
-            displacement: [0, 90],
-          }),
-        });
-        return [style1, style2, style3];
-      },
-    });
-
-    this.locationLayer = new KMap.VectorLayer("locationLayer", 9999, {
-      style: () => {
-        return new Style({
-          image: new Icon({
-            src: "/src/assets/images/map/location.png",
-            scale: 0.45,
-          }),
-        });
-      },
-    });
-
-    this.selectPointLayer = new KMap.VectorLayer("selectPointLayer", 10000, {
-      style: () => {
-        return new Style({
-          // geometry: new Point(coord[0][i]),
-          image: new Circle({
-              radius: 6,
-              fill: new Fill({
-              color: 'red'
-              }),
-              stroke: new Stroke({
-              color: '#fff',
-              width: 1
-              }),
-            }),
-          });
-      },
-    });
-
-    // 存储绘制的地块特征
-    // this.drawnFeatures = [];
-    
-  }
-
-  initMap(location, target) {
-    let that = this
-    let level = 16;
-    let coordinate = util.wktCastGeom(location).getFirstCoordinate();
-    this.kmap = new KMap.Map(
-      target,
-      level,
-      coordinate[0],
-      coordinate[1],
-      null,
-      6,
-      22
-    );
-    this.kmap.initDraw((e) => {
-      if (e.type === "drawend") {
-        mapData.isEdit = true;
-        mapData.point = e.feature;
-      }
-    });
-    this.kmap.modifyDraw((e) => {
-      if(e.type === "modifyend"){
-        mapData.isEditArea = false;
-        mapData.isEditArea = true;
-      }
-    }, function(e){
-      let f = null
-      that.kmap.map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
-          f= feature
-      },{hitTolerance:10});
-      if(!f){
-        return false
-      }
-      let res = f.get("id") === mapData.curPointData.id || !f.get("id")
-      if(!res){
-        ElMessage.warning("编辑中")
-      }
-      console.log('f.get("height")',f);
-      res = f.get("height").length>0?false:res
-      return res
-    });
-    this.kmap.addLayer(this.clickPointLayer.layer);
-    this.kmap.addLayer(this.locationLayer.layer);
-    this.kmap.addLayer(this.selectPointLayer.layer);
-    this.addMapSingerClick();
-  }
-
-  fit(geometriesWkt){
-    let geometries = []
-    let f = new WKT();
-    for(let wkt of geometriesWkt){
-      geometries.push(f.readGeometry(wkt))
-    }
-    let extent = new GeometryCollection(geometries).getExtent()
-    this.kmap.fit(extent)
-  }
-
-  //撤销上一个点
-  undoLastDraw() {
-    // const coordinates = this.kmap.getLayerFeatures()[0].getGeometry().getCoordinates()
-    // coordinates[0][0].pop()
-    // this.kmap.getLayerFeatures()[0].getGeometry().getCoordinates(coordinates)
-  }
-
-  //      取消地块
-  cancelDraw() {
-    this.kmap.polygonLayer.source.removeFeature(mapData.point);
-  }
-
-  //   添加点位
-  addPoint(points) {
-    const arrPoints = [];
-    if (points && points.length > 0) {
-      points.forEach((item) => {
-        let f = newPoint({ ...item, icon: "point", iconBg: "name-bg" }, "point");
-        arrPoints.push(f);
-      });
-      this.clickPointLayer.source.addFeatures(arrPoints);
-    }
-  }
-
-  //  设置地图中心点位
-  setMapCenter(v,isPoint = true) {
-    let arrayOfNumbers = [];
-    const arrayOfStrings = v.split(",");
-    arrayOfNumbers = [arrayOfStrings[1], arrayOfStrings[0]];
-    this.kmap.map.getView().setCenter(arrayOfNumbers);
-    if(!isPoint) return
-    this.locationLayer.source.clear();
-    let point = new Feature(new Point(arrayOfNumbers));
-    this.locationLayer.addFeature(point);
-  }
-
-  // 开始勾画
-  startDraw() {
-    this.kmap.setDefaultCursor("crosshair");
-    this.kmap.startDraw();
-    this.kmap.endModify();
-  }
-  //结束勾画
-  endDraw() {
-    this.kmap.endDraw();
-    this.kmap.endModify();
-  }
-
-  // 开始编辑
-  startModify(type, feature) {
-    this.kmap.startModify();
-    this.kmap.endDraw();
-    if(type==='upload'){
-      mapData.point = feature
-      mapData.point.set("icon", "point-act");
-      this.kmap.polygonStyle(mapData.point);
-      mapData.isPointHide = mapData.point;
-    }else{
-      mapData.point.set("icon", "point-act");
-    }
-  }
-  //结束编辑
-  endModify() {
-    this.kmap.endModify();
-  }
-
-  // 清空单个数据
-  clearMapData(name, val, id) {
-    name && (mapData[name] = val);
-    this.clickPointLayer.source.forEachFeature((feature) => {
-        feature.set("icon", "point");
-        feature.set("iconBg", "name-bg");
-    });
-    const points = this.kmap.getLayerFeatures();
-    points.forEach((feature) => {
-        feature.set("icon", "point");
-    });
-    resetMapData()
-  }
-  //全选
-  allSelect(ids){
-    let arr = []
-    this.clickPointLayer.source.forEachFeature((feature) => {
-      if(!ids || ids.findIndex((id)=> id == feature.get('id')) > -1){
-        feature.set("icon", "point-act");
-        feature.set("iconBg", "name-act-bg");
-      }
-    });
-    const points = this.kmap.getLayerFeatures();
-    points.forEach((feature) => {
-      if(!ids || ids.findIndex((id)=> id == feature.get('id')) > -1) {
-        feature.set("icon", "point-act");
-        this.kmap.polygonStyle(feature);
-        mapData.isPointHide = feature;
-        arr.push(feature)
-      }
-    });
-    mapData.selectPointArr = arr;
-  }
-  //no全选
-  allUnSelect(){
-    this.clickPointLayer.source.forEachFeature((feature) => {
-        feature.set("icon", "point");
-        feature.set("iconBg", "name-bg");
-    });
-    const points = this.kmap.getLayerFeatures();
-    points.forEach((feature) => {
-        feature.set("icon", "point");
-        this.kmap.polygonStyle(feature);
-        mapData.isPointHide = feature;
-    });
-    mapData.selectPointArr = [];
-  }
-
-  //选中高亮样式
-
-  //选中点位方法
-  selectPonitFun(map,evt){
-    let that = this
-    map.forEachFeatureAtPixel(evt.pixel, function (f, layer) {
-      let d = 0.0002
-      let buff =  bboxToFeature(evt.pixel[0] - d,evt.pixel[1] - d, evt.pixel[0]+ d, evt.pixel[1] + d)
-      if (
-        layer instanceof VectorLayer &&
-        (
-          layer.get("name") === "defaultPolygonLayer")
-      ) {
-        const fs = map.getFeaturesAtPixel(evt.pixel);
-        let lonlat = map.getCoordinateFromPixel(evt.pixel);
-        if (fs.length > 0) {
-          const feature = fs[0];
-          const geometry = feature.getGeometry();
-          let coordinates = geometry.getCoordinates()[0]; // 获取多边形的顶点坐标
-            ElMessage.success("已选择该点位")
-            let list 
-            if(mapData.selectPointArr.length>0){
-              list = f.getGeometry().getCoordinates();
-            }else{
-              list = mapData.point.getGeometry().getCoordinates();
-            }
-            coordinates = list[0][0]
-            let arr = []
-            let i = 0;let curDistance = 0
-            for(let subArray of coordinates){
-              let from = turf.point(subArray);
-              let to = turf.point(lonlat);
-              let options = { units: "miles" };
-              let distance = turf.distance(from, to, options);
-              if(distance < 0.1){
-                if(curDistance == 0){
-                  arr = subArray
-                  curDistance = distance
-                  mapData.pointIndex = i
-                }else if(curDistance > distance){
-                  arr = subArray
-                  curDistance = distance
-                  mapData.pointIndex = i
-                }
-              }
-              i++
-            }
-            that.selectPointLayer.refresh();
-            let point = new Feature(new Point(arr));
-            that.selectPointLayer.addFeature(point);
-            mapData.selectPoint = coordinates
-        }
-      }
-    });
-  }
-
-  // 地图点击事件
-  addMapSingerClick() {
-    let that = this;
-    that.kmap.on("singleclick", (evt) => {
-      if(mapData.curPointData.id && !mapData.disabledForm && mapData.selectPointArr.length===1){
-        that.selectPonitFun(that.kmap.map,evt)
-        return;
-      }
-      if(!mapData.curPointData.id && mapData.isEdit){
-        that.selectPonitFun(that.kmap.map,evt)
-        return;
-      }
-      //判断是否是导入的数据
-      if(that.store.state.authentic.isEditStatus){
-        that.selectPonitFun(that.kmap.map,evt)
-        return;
-      }
-      let num = 0;
-      that.kmap.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
-        // 点击的图层是否是VectorLayer
-        if (
-          layer instanceof VectorLayer &&
-          (layer.get("name") === "clickPointLayer" ||
-            layer.get("name") === "defaultPolygonLayer")
-        ) {
-          // 每次点击,只走一遍该方法
-          num = num + 1;
-          if (num === 1) {
-            that.getSelectPointArr(feature.get("id"));
-            that.kmap.endDraw();
-          }
-        }
-      });
-    });
-  }
-
-  clearSelectPoint(){
-    this.selectPointLayer.source.clear();
-  }
-
-  setPoint(name) {
-    const arr = mapData.selectPointArr.filter(
-      (item) => item.values_.icon === "point-act"
-    );
-    if (arr.length > 0) {
-      mapData.point = arr[0];
-      mapData.point.set("icon", name);
-      mapData.isPointHide.set("icon", name);
-      mapData.point.set("iconBg", "name-bg");
-    }
-    if (arr.length === 1) {
-      mapData.selectPointArr = [];
-    }
-  }
-
-  //添加地块
-  setAreaGeometry(geometryArr) {
-    let that = this;
-    let res = []
-    geometryArr.map((item) => {
-      item.icon = "point";
-      item.iconHide = "false";
-      res.push(that.kmap.setLayerWkt(item.featureWkt, item));
-    });
-    return res
-  }
-
-  deletePointFun(point,callback){
-    const coordinates = point.getGeometry().getCoordinates();
-    let array = coordinates[0][0]
-    // 如果点存在,则删除它
-    if (mapData.pointIndex > -1) {
-      array.splice(mapData.pointIndex, 1); // 删除点
-      // 更新多边形的坐标
-      point.getGeometry().setCoordinates(coordinates); // 更新几何形状
-      mapData.pointIndex = -1
-    }
-    this.clearSelectPoint()
-    callback && callback(mapData.pointIndex)
-  }
-
-  // 移除点的功能
-  removePoint(callback) {
-    // 获取多边形的所有坐标
-    const features = this.kmap.getLayerFeatures()
-    if(mapData.selectPointArr.length>0){
-      features.forEach(item =>{
-        if(item.get("id")===mapData.selectPointArr[0].get("id")){
-            this.deletePointFun(item,callback)
-          }
-      })
-    }else{
-      this.deletePointFun(mapData.point,callback)
-    }
-  }
-
-  //   获取所有选中点位
-  getSelectPointArr(id) {
-    const arr = [];
-    this.clickPointLayer.source.forEachFeature((feature) => {
-      if (feature.get("id") === id) {
-        // 修改当前点位高亮
-        const icon = feature.get("icon") === "point" ? "point-act" : "point";
-        const iconBg =
-          feature.get("iconBg") === "name-bg" ? "name-act-bg" : "name-bg";
-        feature.set("icon", icon);
-        feature.set("iconBg", iconBg);
-        mapData.point = feature;
-        mapData.curPointData = feature.values_;
-      }
-      if (feature.get("icon") === "point-act") {
-        arr.push(feature);
-      }
-    });
-    const points = this.kmap.getLayerFeatures();
-    points.forEach((feature) => {
-      if (feature.get("id") === id) {
-        const icon = feature.get("icon") === "point" ? "point-act" : "point";
-        feature.set("icon", icon);
-        this.kmap.polygonStyle(feature);
-        mapData.isPointHide = feature;
-      }
-    });
-    mapData.selectPointArr = arr;
-  }
-
-  hidePoint() {
-    const feature = mapData.isPointHide;
-    feature.set("iconHide", "true");
-    this.kmap.polygonStyle(feature);
-  }
-
-  clearLayer() {
-    this.clickPointLayer.source.clear();
-    this.kmap.polygonLayer.source.clear();
-  }
-
-  addLayer() {
-    this.kmap.addLayer(this.kmap.polygonLayer.layer);
-    this.kmap.addLayer(this.clickPointLayer.layer);
-  }
-
-  //获取地块信息
-  getAreaGeometry(type) {
-    let features = null
-    if(type==='add') {
-      features = [mapData.point]
-    }else if(type==='upload'){
-      features = this.kmap.getLayerFeatures()
-    }else{
-      if(mapData.curPointData.id){
-        features = [this.kmap.getFeatureById(mapData.curPointData.id)];
-      }else{
-        features = [mapData.point]
-      }
-    }
-    let geometryArr = [];
-    let area = 0;
-    // 获取图层上的Polygon,转成geoJson用于回显
-    features.forEach((item) => {
-      geometryArr.push({ featureWkt: new WKT().writeFeature(item) });
-      let geom = item.getGeometry().clone();
-      geom.transform(proj.get("EPSG:4326"), proj.get("EPSG:38572"));
-      let areaItem = getArea(geom);
-      area = (areaItem + areaItem / 2) / 1000;
-    });
-    return { geometryArr, area: area.toFixed(2) };
-  }
-
-  /**
-   address
-   farmName
-   masterName
-   masterTel
-   speciesTypeName
-   ""
-   * @param form
-   */
-  search(form){
-    const points = this.kmap.getLayerFeatures();
-    let arr = []
-    let geomWkt = []
-    points.forEach((feature) => {
-      let condition = []
-      if(form.address != ''){
-        condition.push(feature.get("address").includes(form.address))
-      }
-      if(form.farmName != ''){
-        const text = feature.get("farmName")
-        if(text!==form.farmName) return
-        condition.push(feature.get("farmName").includes(form.farmName))
-      }
-      if(form.masterName != ''){
-        const text = feature.get("masterName")
-        if(text!==form.masterName) return
-        condition.push(feature.get("masterName").includes(form.masterName))
-      }
-      if(form.masterTel != ''){
-        const text = feature.get("masterTel")
-        if(text!==form.masterTel) return
-        condition.push(feature.get("masterTel").includes(form.masterTel))
-      }
-      if(form.speciesTypeName != ''){
-        const text = feature.get("speciesTypeName")
-        if(text!==form.speciesTypeName) return
-        condition.push(feature.get("speciesTypeName").includes(form.speciesTypeName))
-      }
-      let b = false
-      for(let item of condition){
-        if(item){
-          b = true
-        }else{
-          b = false
-          break
-        }
-      }
-      if(b){
-        arr.push(feature.get("id"))
-        geomWkt.push(new WKT().writeGeometry(feature.getGeometry()))
-      }
-    });
-    this.allUnSelect()
-    this.allSelect(arr)
-    if(geomWkt.length>0){
-      this.fit(geomWkt)
-    }
-  }
-}
-
-export default AuthenticMap;

+ 0 - 1013
src/views/authentic/index.vue

@@ -1,1013 +0,0 @@
-<template>
-    <div class="base-container">
-        <fnHeader :hideSwitch="true" headerName="飞鸟确权平台" :autoGo="false" :hideShadow="true"></fnHeader>
-        <div class="top-bg"></div>
-        <el-upload
-            ref="uploadRef"
-            class="upload-demo"
-            :limit="1"
-            :on-exceed="handleExceed"
-            :on-success="onSuccess"
-            :before-upload="beforeUpload"
-            action="https://feiniaotech-dev.sysuimars.cn/site/plugin_ownership/uploadFile"
-            :headers="headerUpload"
-        >
-            <template #trigger>
-                <div class="btn blue" :class="{ 'disabled-button': !disabledForm && isEdit }">
-                    <el-icon><Upload /></el-icon>
-                    <span>RTK点位数据导入</span>
-                </div>
-            </template>
-        </el-upload>
-        <div class="top">
-            <!-- <div class="back btn" @click="goBack">
-        <img class="icon" src="@/assets/images/common/back-icon.png" alt="" />
-        <span>返回</span>
-      </div> -->
-            <el-select
-                v-model="locationVal"
-                filterable
-                remote
-                :disabled="!disabledForm && isEdit"
-                effect="dark"
-                reserve-keyword
-                placeholder="搜索地区"
-                :remote-method="remoteMethod"
-                :loading="loading"
-                @change="handleSearchRes"
-                class="v-select"
-            >
-                <template #prefix>
-                    <el-icon class="el-input__icon"><search /></el-icon>
-                </template>
-                <el-option
-                    v-for="(item, index) in locationOptions.list"
-                    :key="index"
-                    :label="item.title"
-                    :value="item.point"
-                >
-                    <span>{{ item.title }}</span>
-                    <span class="sub-title">{{ item.province }}{{ item.city }}{{ item.district }}</span>
-                </el-option>
-            </el-select>
-            <div class="search">
-                <div class="add btn" :class="{ 'disabled-button': !disabledForm && isEdit }" @click="handleAdd">
-                    <el-icon><Plus /></el-icon>
-                    <span>创建</span>
-                </div>
-                <div class="upload btn" :class="{ 'disabled-button': !disabledForm && isEdit }" @click="handleExport">
-                    <img class="icon" src="@/assets/images/common/back-icon.png" alt="" />
-                    <span>导出</span>
-                </div>
-            </div>
-        </div>
-        <div class="content">
-            <el-form :inline="true" :model="formInlineSearch" class="search-form" ref="formInlineRef">
-                <div>
-                    <el-form-item label="生产队名称">
-                        <el-input v-model="formInlineSearch.address" placeholder="请输入生产队名称" clearable />
-                    </el-form-item>
-                    <el-form-item label="林段名称">
-                        <el-input v-model="formInlineSearch.farmName" placeholder="请输入林段名称" clearable />
-                    </el-form-item>
-                    <el-form-item label="橡胶品种">
-                        <el-input v-model="formInlineSearch.speciesTypeName" placeholder="请输入橡胶品种" clearable />
-                    </el-form-item>
-                    <!-- <el-form-item label="客户姓名">
-                        <el-input v-model="formInlineSearch.masterName" placeholder="请输入客户姓名" clearable />
-                    </el-form-item> -->
-                </div>
-                <div class="button">
-                    <el-button
-                        class="btn"
-                        :class="{ 'disabled-button': !disabledForm && isEdit }"
-                        type="primary"
-                        @click="onSearch"
-                        >查询</el-button
-                    >
-                    <el-button class="btn reset" :class="{ 'disabled-button': !disabledForm && isEdit }" @click="onRest"
-                        >重置</el-button
-                    >
-                </div>
-            </el-form>
-            <div class="box">
-                <div class="map-box" :class="{ 'cursor-pointer': mouseStyle }">
-                    <div ref="mapRef" class="map"></div>
-                </div>
-                <div class="tool-group">
-                    <!-- <div class="btn" @click="handleCancel">
-                        <img class="icon" src="@/assets/images/common/back-black-icon.png" alt="" />
-                        <span>撤销</span>
-                    </div> -->
-                    <!-- <div
-                        class="btn"
-                        @click="handleDeletePoint"
-                        v-show="mapData.selectPointArr.length > 0 && !disabledForm"
-                    >
-                        <el-icon size="15"><CloseBold /></el-icon>
-                        <span>删除点</span>
-                    </div> -->
-                    <div class="btn delete" @click="handleDelete" v-show="mapData.selectPointArr.length > 0">
-                        <el-icon size="15" color="#fff"><CloseBold /></el-icon>
-                        <span>删除地块</span>
-                    </div>
-                </div>
-                <div class="edit-popup" v-show="isEdit">
-                    <div class="edit-title">
-                        <div class="name">
-                            <img src="@/assets/images/common/chart-icon.png" alt="" />
-                            <span>地块属性</span>
-                        </div>
-                        <div class="btn-group">
-                            <div v-show="disabledForm" class="edit" @click="handleEdit">编辑</div>
-                            <div v-show="!disabledForm" class="edit" @click="handleDeletePoint">删除点</div>
-                            <div
-                                v-show="mapData.selectPointArr.length > 0"
-                                class="edit ml"
-                                :class="{ 'disabled-button': !disabledForm }"
-                                @click="handlePrint"
-                            >
-                                打印
-                            </div>
-                        </div>
-                    </div>
-                    <div class="edit-cont">
-                        <el-form
-                            :inline="true"
-                            ref="ruleFormRef"
-                            :disabled="disabledForm"
-                            :model="formInline"
-                            :rules="rules"
-                            label-position="top"
-                            class="form-inline"
-                            :class="{'no-area': store.state.authentic.isEditStatus}"
-                        >
-                            <el-form-item label="生产队名称" prop="address">
-                                <el-input v-model="formInline.address" placeholder="请输入生产队名称" clearable />
-                            </el-form-item>
-                            <el-form-item label="林段名称" prop="farmName">
-                                <el-input v-model="formInline.farmName" placeholder="请输入林段名称" clearable />
-                            </el-form-item>
-                            <el-form-item label="创建时间">
-                                <el-input v-model="formInline.createDate" clearable disabled />
-                            </el-form-item>
-                            <el-form-item label="林段面积">
-                                <el-input v-model="formInline.mu" disabled clearable />
-                            </el-form-item>
-                            <el-form-item label="橡胶品种" prop="speciesTypeName">
-                                <el-input v-model="formInline.speciesTypeName" placeholder="请输入橡胶品种" clearable />
-                            </el-form-item>
-                            <el-form-item label="斜面面积" v-show="!store.state.authentic.isEditStatus">
-                                <el-input v-model="formInline.slopeMu" disabled clearable />
-                            </el-form-item>
-                            <el-form-item label="橡胶株数" prop="plantNum">
-                                <el-input v-model="formInline.plantNum" placeholder="请输入橡胶株数" clearable />
-                            </el-form-item>
-                        </el-form>
-                        <div class="list-box" :class="{'no-area': store.state.authentic.isEditStatus}" v-show="pointList.length > 0">
-                            <span>边界点经纬度</span>
-                            <div class="list-cont">
-                                <div class="list-item" v-for="(item, index) in pointList" :key="index">
-                                    <span>A{{ index + 1 }}</span>
-                                    <div class="item-box">北纬{{ item[1] }}</div>
-                                    <div class="item-box">东经{{ item[0] }}</div>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="edit-footer">
-                        <div @click="onCancel" class="btn cancel">取消</div>
-                        <div @click="onSubmit" class="btn save">保存</div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- 导出弹窗 -->
-    <el-dialog v-model="dialogVisible" width="82%" center :show-close="false" modal-class="dialog-dark">
-        <div>
-            <el-table :data="gridData" border max-height="600" class="table-dark">
-                <el-table-column property="farmName" label="林段名称" show-overflow-tooltip />
-                <el-table-column property="address" label="生产队名称" width="230" show-overflow-tooltip />
-                <el-table-column property="createDate" label="创建时间" width="170" />
-                <el-table-column property="mu" label="林段面积">
-                    <template #default="scope">
-                        <span>{{ scope.row.mu }}亩</span>
-                    </template>
-                </el-table-column>
-                <el-table-column property="slopeMu" label="斜面面积">
-                    <template #default="scope">
-                        <span>{{ scope.row.slopeMu }}亩</span>
-                    </template>
-                </el-table-column>
-                <el-table-column property="speciesTypeName" label="橡胶品种" />
-                <el-table-column property="plantNum" label="橡胶株数" />
-                <el-table-column property="masterName" label="客户姓名" />
-                <!-- <el-table-column property="masterTel" width="120" label="联系电话" /> -->
-                <el-table-column property="points" label="边界点经纬度" width="480" show-overflow-tooltip />
-            </el-table>
-        </div>
-        <template #footer>
-            <div class="dialog-footer">
-                <el-button class="btn" @click="dialogVisible = false">取消</el-button>
-                <el-button class="btn" type="primary" @click="handleDowload"> 下载 </el-button>
-            </div>
-        </template>
-    </el-dialog>
-    <Pdf
-        :title="formInline.id + ''"
-        :showDialog="pdfShow"
-        @closeDialog="pdfShow = false"
-        v-if="formInline.id && pdfShow"
-        :rowId="formInline.id"
-    ></Pdf>
-</template>
-
-<script setup>
-import { onMounted, ref, reactive, watchEffect, watch } from "vue";
-import fnHeader from "@/components/fnHeader.vue";
-import AuthenticMap from "./authenticMap";
-import { mapData } from "./authenticMap";
-import { useRouter } from "vue-router";
-import { ElMessage, ElMessageBox } from "element-plus";
-import { dateFormat } from "@/utils/date_util";
-import { exportExcel, parseMultiPolygon } from "@/utils/index";
-import { useStore } from "vuex";
-import Pdf from "./Pdf";
-import {Feature} from "ol";
-const pdfShow = ref(false);
-const mouseStyle = ref(1);
-const router = useRouter();
-const store = useStore();
-
-let authenticMap = new AuthenticMap();
-const mapRef = ref();
-const userInfo = JSON.parse(sessionStorage.getItem("userinfo"));
-debugger
-const location = ref(userInfo.location);
-
-onMounted(() => {
-    authenticMap.initMap(location.value, mapRef.value);
-    getList();
-});
-
-// 获取地块列表
-const plotList = ref([]);
-const getList = (callback) => {
-    authenticMap.clearLayer();
-    return VE_API.authentic.getList(formInlineSearch).then(({ code, data }) => {
-        plotList.value = data || [];
-        const geom = [];
-        data.forEach((item) => {
-            geom.push({ featureWkt: item.geom, ...item });
-        });
-        authenticMap.setAreaGeometry(geom);
-        authenticMap.addPoint(data);
-        callback && callback(geom);
-    });
-};
-
-// 搜索
-const locationVal = ref("");
-const loading = ref(false);
-const MAP_KEY = "CZLBZ-LJICQ-R4A5J-BN62X-YXCRJ-GNBUT";
-
-const handleSearchRes = (v) => {
-    authenticMap.setMapCenter(v);
-    onRest();
-};
-
-const locationOptions = reactive({
-    list: [],
-});
-const remoteMethod = async (keyword) => {
-    if (keyword) {
-        locationOptions.list = [];
-        loading.value = true;
-        const params = {
-            key: MAP_KEY,
-            keyword,
-            //   location: location.value,
-            location: "22.574540836684672,113.1093017627431",
-        };
-        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 validatePhoneNumber = (rule, value, callback) => {
-    const phoneRegex = /^[1][3-9]\d{9}$/;
-    if (!value) {
-        callback(new Error("请输入联系电话"));
-    } else if (!phoneRegex.test(value)) {
-        callback(new Error("手机号码格式不正确"));
-    } else {
-        callback();
-    }
-};
-const rules = {
-    address: [{ required: true, message: "请输入生产队名称", trigger: "change" }],
-    farmName: [{ required: true, message: "请输入林段名称", trigger: "change" }],
-    speciesTypeName: [{ required: true, message: "请输入橡胶品种", trigger: "change" }],
-    masterName: [{ required: true, message: "请输入姓名", trigger: "change" }],
-    // masterTel: [{ required: true, validator: validatePhoneNumber, trigger: "change" }],
-};
-const ruleFormRef = ref(null);
-const initForm = {
-    id: "",
-    address: "",
-    farmName: "",
-    createDate: "",
-    mu: "",
-    slopeMu: "",
-    speciesTypeName: "",
-    plantNum: "",
-    masterName: "",
-    masterTel: "",
-    geom: "",
-};
-const formInline = reactive({
-    ...initForm,
-});
-const disabledForm = ref(false);
-
-// 筛选
-const formInlineRef = ref(null);
-const formInlineSearch = reactive({
-    ...initForm,
-});
-
-const onSearch = () => {
-    authenticMap.search(formInlineSearch);
-};
-
-const onRest = () => {
-    Object.assign(formInlineSearch, initForm);
-    isUpdata.value = false;
-    onCancel();
-};
-
-const isEdit = ref(false);
-const typeStr = ref("");
-
-// 编辑
-const handleEdit = () => {
-    typeStr.value = "edit";
-    disabledForm.value = false;
-    mapData.disabledForm = false;
-    authenticMap.startModify('edit');
-    authenticMap.clearSelectPoint()
-};
-
-// 取消
-const isUpdata = ref(true);
-const onCancel = () => {
-    authenticMap.clearSelectPoint()
-    isEdit.value = false;
-    store.commit("authentic/SET_ISEDIT_STATUS", false);
-    if (isUpdata.value) {
-        authenticMap.cancelDraw();
-        getList((geoms) => {
-            authenticMap.allUnSelect();
-        });
-    } else {
-        Object.assign(formInlineSearch, initForm);
-        getList((geoms) => {
-            authenticMap.allUnSelect();
-        });
-    }
-    authenticMap.setPoint("point");
-    authenticMap.clearMapData("isEdit", false, formInline.id);
-    authenticMap.endDraw();
-};
-
-// 保存
-const onSubmit = () => {
-    if (!ruleFormRef.value) return;
-    ruleFormRef.value.validate((valid, fields) => {
-        if (valid) {
-            formInline.mu = formInline.mu.split("亩")[0];
-            formInline.slopeMu = formInline.slopeMu.split("亩")[0];
-            if(heightArr.value.length>0){
-                formInline.height = heightArr.value
-            }
-            VE_API.authentic.saveData(formInline).then((res) => {
-                if (res.code === 0) {
-                    store.commit("authentic/SET_ISEDIT_STATUS", false);
-                    isUpdata.value = false;
-                    disabledForm.value = true;
-                    mapData.disabledForm = true;
-                    Object.assign(formInlineSearch, initForm);
-                    authenticMap.endDraw();
-                    getList().then(() => {
-                        isRefresh.value = false;
-                        isEdit.value = false;
-                        authenticMap.allUnSelect();
-                        authenticMap.clearMapData();
-                        // authenticMap.getSelectPointArr(
-                        //   point.id || plotList.value[plotList.value.length - 1].id
-                        // );
-                    });
-                }
-            })
-        }
-    });
-};
-
-//上传
-const uploadRef = ref(null);
-const headerUpload = { token: store.getters.token };
-// 校验文件格式和大小
-const beforeUpload = (file) => {
-    const isCsv = file.type === "application/vnd.ms-excel" || file.type === "text/csv" || file.name.endsWith(".csv");
-    updateFormInline({ ...initForm });
-    ruleFormRef.value.resetFields();
-    authenticMap.clearSelectPoint()
-    isEdit.value = false;
-    authenticMap.setPoint("point");
-    authenticMap.clearMapData("isEdit", false, formInline.id);
-    authenticMap.endDraw();
-    if (!isCsv) {
-        ElMessage.error("上传文件只能是 CSV 格式!");
-    }
-
-    return isCsv;
-};
-
-const handleExceed = (files) => {
-    uploadRef.value.clearFiles();
-    const file = files[0];
-    uploadRef.value.handleStart(file);
-};
-
-const heightArr = ref([]);
-const onSuccess = (res) => {
-    typeStr.value = "upload";
-    if (res.code === 0) {
-        ElMessage.success("上传成功");
-        store.commit("authentic/SET_ISEDIT_STATUS", true);
-        isEdit.value = true;
-        disabledForm.value = false;
-        formInline.createDate = dateFormat(new Date(), "YYYY-mm-dd HH:MM:SS");
-        const geom = [{ featureWkt: res.data.geom, ...res.data }];
-        let featureList = authenticMap.setAreaGeometry(geom);
-        authenticMap.fit([res.data.geom]);
-        updatePointList("upload", geom[0]);
-        heightArr.value = res.data.height;
-        const arr = pointList.value.map((item, index) => {
-            return [...item, res.data.height[index]];
-        });
-        getArea(arr);
-        authenticMap.startModify("upload", featureList[0]);
-        uploadRef.value.clearFiles();
-    } else {
-        ElMessage.error("上传失败");
-    }
-};
-
-// 获取面积/亩
-const getArea = (arr) => {
-    VE_API.authentic.getArea(arr).then((res) => {
-        const area = (res.data / 666.67).toFixed(2);
-        formInline.mu = area + "亩";
-    });
-};
-
-// 斜面面积
-const getSlopeArea = (arr) => {
-    VE_API.authentic.fetchSlopeArea({wkt: arr}).then(({data}) => {
-        const area = (data / 666.67).toFixed(2);
-        formInline.slopeMu = area + "亩";
-    });
-};
-
-// 打印
-const handlePrint = () => {
-    pdfShow.value = true;
-};
-
-// 返回
-const goBack = () => {
-    router.go(-1);
-};
-
-function updateFormInline(newData, name) {
-    Object.assign(formInline, newData);
-}
-
-// 删除地块
-const handleDelete = () => {
-    const id = mapData.selectPointArr.map((item) => item.values_.id);
-    if (id.length < 0) return ElMessage("请选择地块");
-    ElMessageBox.confirm("您确定删除该地块吗?", "提示", {
-        confirmButtonText: "确认",
-        cancelButtonText: "取消",
-        type: "warning",
-    })
-        .then(() => {
-            VE_API.authentic.deleteData(id).then((res) => {
-                isUpdata.value = false;
-                onCancel();
-            });
-        })
-        .catch(() => {});
-};
-
-// 创建
-const isRefresh = ref(true);
-const handleAdd = () => {
-    authenticMap.clearSelectPoint()
-    typeStr.value = "add";
-    isRefresh.value = false;
-    isEdit.value = false;
-    if (isUpdata.value) {
-        authenticMap.cancelDraw();
-        authenticMap.allUnSelect();
-    } else {
-        getList();
-        isUpdata.value = true;
-    }
-    updateFormInline({ ...initForm });
-    ruleFormRef.value.resetFields();
-    pointList.value = [];
-    authenticMap.clearMapData("curPointData", {});
-    authenticMap.clearMapData("isEdit", false);
-    authenticMap.setPoint("point");
-    authenticMap.startDraw();
-};
-
-// 删除点
-const handleDeletePoint = () => {
-    authenticMap.removePoint((index) => {
-        updatePointList(typeStr.value);
-        heightArr.value.splice(index,1)
-    });
-};
-
-// 撤销
-const handleCancel = () => {
-    authenticMap.undoLastDraw();
-};
-
-// 导出
-const gridData = ref([]);
-const dialogVisible = ref(false);
-const handleExport = () => {
-    if (mapData.selectPointArr.length < 1) return ElMessage("请选择地块");
-    const ids = mapData.selectPointArr.map((item) => item.values_.id);
-    VE_API.authentic.exportData(ids).then(({ data }) => {
-        gridData.value = data.map((item) => {
-            return {
-                ...item,
-                createDate: dateFormat(new Date(item.createDate), "YYYY-mm-dd HH:MM:SS"),
-            };
-        });
-        dialogVisible.value = true;
-    });
-};
-
-// 下载
-const handleDowload = () => {
-    const fieldLabels = [
-        "林段名称",
-        "生产队名称",
-        "创建时间",
-        "林段面积",
-        "橡胶品种",
-        "客户姓名",
-        // "联系电话",
-        "边界点经纬度",
-    ];
-    const fieldKeys = [
-        "farmName",
-        "address",
-        "createDate",
-        "mu",
-        "speciesTypeName",
-        "plantNum",
-        "masterName",
-        // "masterTel",
-        "points",
-    ];
-    const fileName = "农场数据" + dateFormat(new Date(), "YYYY-mm-dd HH:MM");
-    exportExcel(gridData.value, fieldLabels, fieldKeys, fileName);
-};
-
-const pointList = ref([]);
-
-// 获取编辑回显数据
-const getDetailsData = (id) => {
-    VE_API.authentic.getDetails({ id }).then(({ data }) => {
-        isEdit.value = true;
-        disabledForm.value = true;
-        mapData.disabledForm = true;
-
-        data.createDate = dateFormat(new Date(data.createDate), "YYYY-mm-dd HH:MM:SS");
-        updateFormInline({ ...data });
-        //   经纬度列表
-        let arr = JSON.parse(data.points);
-        // 删除最后数组最后一项闭合数据
-        arr.pop();
-        pointList.value = arr;
-        if(data.height.length>0){
-            heightArr.value = data.height
-            store.commit("authentic/SET_ISEDIT_STATUS", true);
-            // authenticMap.startModify("upload");
-        }
-        formInline.mu = data.mu + "亩";
-        formInline.slopeMu = data.slopeMu + "亩";
-    });
-};
-
-// 添加经纬度列表
-const updatePointList = (type, geom) => {
-  const { geometryArr, area } = authenticMap.getAreaGeometry(type);
-  let lastItem = null
-    if(type === 'upload'){
-      lastItem = geom
-    }else{
-      lastItem = geometryArr[geometryArr.length - 1];
-    }
-    formInline.geom = lastItem.featureWkt;
-    console.log("formInline.geom", formInline.geom)
-    getSlopeArea(formInline.geom)
-    let result = parseMultiPolygon(lastItem.featureWkt);
-    result.pop();
-    pointList.value = result;
-    //判断是否是导入数据
-    if (store.state.authentic.isEditStatus) {
-        const arr = pointList.value.map((item, index) => {
-            return [...item, heightArr.value[index]];
-        });
-        if (arr[0][2]) {
-            getArea(arr);
-        }
-    } else {
-        formInline.mu = area + "亩";
-    }
-};
-
-watchEffect(() => {
-    if (mapData.isEditArea) {
-        isUpdata.value = false;
-        updatePointList("edit");
-    }
-});
-
-watch(
-    () => mapData.isEdit,
-    (newVale, oldValue) => {
-        if (newVale && mapData.selectPointArr.length < 2 && !isRefresh.value) {
-            isEdit.value = true;
-            disabledForm.value = false;
-            mapData.disabledForm = false;
-            isUpdata.value = true;
-            formInline.createDate = dateFormat(new Date(), "YYYY-mm-dd HH:MM:SS");
-            updatePointList("add");
-            authenticMap.startModify('add');
-        }
-    }
-);
-
-watch(
-    () => mapData.selectPointArr,
-    (newVale, oldValue) => {
-        if (mapData.selectPointArr.length === 1) {
-            const obj = mapData.selectPointArr[0];
-            const id = obj.values_.id;
-            getDetailsData(id);
-            mapData.curPointData = obj.values_;
-        } else {
-            if (isRefresh.value) {
-                isEdit.value = false;
-                authenticMap.endDraw();
-                isRefresh.value = true;
-            }
-            if (mapData.selectPointArr.length === 0 || mapData.selectPointArr.length > 1) {
-                isEdit.value = false;
-            }
-        }
-    }
-);
-</script>
-
-<style lang="scss" scoped>
-::v-deep {
-    .el-upload-list {
-        display: none;
-    }
-}
-.base-container {
-    width: 100%;
-    height: 100vh;
-    color: #fff;
-    box-sizing: border-box;
-    z-index: 1;
-    position: relative;
-    .top-bg {
-        position: absolute;
-        top: 0;
-        width: 100%;
-        height: 74px;
-        background: #101010;
-        z-index: -1;
-    }
-    .upload-demo {
-        display: flex;
-        align-items: center;
-        justify-content: flex-end;
-        padding-right: 20px;
-        background: #101010;
-    }
-    .blue {
-        background: #2199f8;
-    }
-    .btn {
-        display: flex;
-        align-items: center;
-        padding: 6px 16px;
-        border-radius: 4px;
-        cursor: pointer;
-        .icon {
-            width: 13px;
-            height: 13px;
-        }
-        span {
-            margin-left: 10px;
-        }
-    }
-
-    .disabled-button {
-        pointer-events: none;
-        opacity: 0.5;
-        cursor: not-allowed;
-    }
-
-    .top {
-        display: flex;
-        justify-content: space-between;
-        // justify-content: flex-end;
-        width: 100%;
-        height: 40px;
-        background: #101010;
-        padding: 17px 20px 0 20px;
-        box-sizing: border-box;
-        display: flex;
-        align-items: center;
-        .back {
-            border: 1px solid rgba(255, 255, 255, 0.4);
-        }
-        .v-select {
-            width: 300px;
-            ::v-deep {
-                .el-select__wrapper {
-                    background: #101010;
-                    box-shadow: none;
-                    border: 1px solid rgba(255, 255, 255, 0.7);
-                    .el-select__input {
-                        color: #fff;
-                    }
-                }
-            }
-        }
-        .search {
-            display: flex;
-            align-items: center;
-            justify-content: flex-end;
-            width: 60%;
-            .input-with-select {
-                margin-left: 25px;
-            }
-
-            .upload {
-                background: #2199f8;
-                margin-left: 25px;
-            }
-            .add {
-                background: #fff;
-                color: #000;
-                margin-left: 25px;
-            }
-        }
-    }
-
-    .content {
-        width: 100%;
-        height: calc(100% - 74px - 40px - 32px);
-        box-sizing: border-box;
-        background: #101010;
-        padding: 13px 20px 20px 20px;
-        .search-form {
-            height: 40px;
-            margin: 5px 0;
-            display: flex;
-            justify-content: flex-end;
-            // justify-content: space-between;
-            ::v-deep {
-                .el-form-item__label {
-                    color: #fff;
-                }
-                .el-form-item__content {
-                    width: 190px;
-                }
-                .el-input__wrapper {
-                    background: #101010;
-                    box-shadow: none;
-                    border: 1px solid rgba(255, 255, 255, 0.7);
-                    .el-input__inner {
-                        color: #fff;
-                    }
-                }
-            }
-            .button {
-                display: flex;
-                .btn {
-                    width: 84px;
-                    &.reset {
-                        margin-left: 25px;
-                    }
-                }
-            }
-        }
-        .box {
-            border: 1px solid rgba(255, 255, 255, 0.4);
-            border-radius: 8px;
-            padding: 20px;
-            box-sizing: border-box;
-            background: #232323;
-            width: 100%;
-            height: calc(100% - 50px);
-            position: relative;
-            .map-box {
-                width: 100%;
-                height: 100%;
-                border-radius: 4px;
-                border: 1px solid rgba(255, 255, 255, 0.4);
-                .map {
-                    width: 100%;
-                    height: 100%;
-                }
-            }
-
-            .tool-group {
-                position: absolute;
-                display: flex;
-                right: calc(500px + 36px);
-                top: 42px;
-                .btn {
-                    background: #fff;
-                    color: #000;
-                    margin-right: 10px;
-                }
-                .delete {
-                    background: #e45c5c;
-                    color: #fff;
-                }
-            }
-            .edit-popup {
-                width: 500px;
-                height: calc(100% - 53px - 20px);
-                position: absolute;
-                top: 36px;
-                right: 36px;
-                border: 1px solid rgba(255, 255, 255, 0.4);
-                border-radius: 8px;
-                background: #232323;
-                .edit-title {
-                    padding: 0 10px;
-                    background: rgba(68, 68, 68, 0.4);
-                    border-bottom: 1px solid rgba(68, 68, 68, 0.4);
-                    display: flex;
-                    align-items: center;
-                    justify-content: space-between;
-                    .btn-group {
-                        display: flex;
-                        .ml {
-                            margin-left: 20px;
-                        }
-                    }
-                    .name {
-                        display: flex;
-                        padding: 12px 0px;
-                        align-items: center;
-                    }
-                    span {
-                        margin-left: 8px;
-                        font-size: 18px;
-                        font-family: "SOURCEHANTIFINE";
-                    }
-                    .edit {
-                        color: #2199f8;
-                        padding: 6px 20px;
-                        border: 1px solid #2199f8;
-                        border-radius: 4px;
-                        cursor: pointer;
-                    }
-                }
-                .edit-cont {
-                    padding: 16px;
-                    width: calc(100% - 32px);
-                    height: calc(100% - 64px - 84px);
-                    .form-inline {
-                        height: 320px;
-                        &.no-area {
-                            height: 260px;
-                        }
-                        ::v-deep {
-                            .el-input {
-                                width: 200px;
-                                --el-input-placeholder-color: #666666;
-                            }
-                            .el-form-item__label {
-                                color: #bbbbbb;
-                            }
-                            .el-input__wrapper {
-                                background: #232323;
-                                border: 1px solid #444444;
-                                box-shadow: none;
-                                .el-input__inner {
-                                    color: #fff;
-                                }
-                            }
-                        }
-                    }
-                    .list-box {
-                        width: 100%;
-                        height: calc(100% - 320px);
-                        &.no-area {
-                            height: calc(100% - 260px);
-                        }
-                        span {
-                            color: #bbbbbb;
-                        }
-                        .list-cont {
-                            width: 100%;
-                            height: calc(100% - 20px);
-                            border-radius: 4px;
-                            margin-top: 5px;
-                            background: rgba(68, 68, 68, 0.4);
-                            padding: 12px 16px;
-                            box-sizing: border-box;
-                            overflow-y: auto;
-
-                            .list-item {
-                                width: 100%;
-                                margin-bottom: 8px;
-                                display: flex;
-                                align-items: center;
-                                .item-box {
-                                    padding: 8px;
-                                    border: 1px solid #444444;
-                                    border-radius: 4px;
-                                    margin-left: 10px;
-                                }
-                            }
-                        }
-                    }
-                }
-                .edit-footer {
-                    width: 100%;
-                    height: 64px;
-                    display: flex;
-                    align-items: center;
-                    justify-content: flex-end;
-                    box-sizing: border-box;
-                    padding: 12px 16px;
-                    border-top: 1px solid rgba(68, 68, 68, 0.4);
-                    background: rgba(68, 68, 68, 0.4);
-                    .btn {
-                        padding: 10px 35px;
-                    }
-                    .cancel {
-                        border: 1px solid rgba(255, 255, 255, 0.4);
-                        margin-right: 16px;
-                    }
-                    .save {
-                        background: #2199f8;
-                    }
-                }
-            }
-        }
-    }
-}
-.dialog-footer {
-    .btn {
-        width: 200px;
-        height: 40px;
-    }
-}
-</style>

+ 0 - 161
src/views/authentic/pdfMap.js

@@ -1,161 +0,0 @@
-import config from "@/api/config.js";
-import * as KMap from "@/utils/ol-map/KMap";
-import * as util from "@/common/ol_common.js";
-import Style from "ol/style/Style";
-import Icon from "ol/style/Icon";
-import VectorLayer from "ol/layer/Vector.js";
-import WKT from "ol/format/WKT.js";
-import { reactive } from "vue";
-import Point from "ol/geom/Point.js";
-import Feature from "ol/Feature";
-import { newPoint } from "@/utils/map.js";
-import { Fill, Text } from "ol/style";
-import { getArea } from "ol/sphere.js";
-import * as proj from "ol/proj";
-import proj4 from "proj4";
-import { register } from "ol/proj/proj4";
-import {DragPan, MouseWheelZoom} from "ol/interaction";
-let mapData = reactive({
-  isEdit: false,
-  isEditArea: false,
-  curPointData: {},
-  point: null,
-  selectPointArr: [],
-  isPointHide: false,
-});
-proj4.defs(
-  "EPSG:38572",
-  "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"
-);
-register(proj4);
-
-/**
- * @description 地图层对象
- */
-class PdfMap {
-  constructor() {
-    let that = this;
-    let vectorStyle = new KMap.VectorStyle();
-    this.vectorStyle = vectorStyle;
-    // 位置图标
-    this.clickPointLayer = new KMap.VectorLayer("clickPointLayer", 9999, {
-      style: (f) => {
-        const style1 = new Style({
-          image: new Icon({
-            src: `/src/assets/images/map/${f.get("icon")}-icon.png`,
-            scale: 0.45,
-          }),
-        });
-        const style2 = new Style({
-          text: new Text({
-            font: "16px sans-serif",
-            text: f.get("farmName"),
-            offsetY: -40,
-            padding: [4, 3, 2, 106],
-            fill: new Fill({ color: "#fff" }), // 字体颜色
-          }),
-        });
-        const style3 = new Style({
-          image: new Icon({
-            src: `/src/assets/images/map/${f.get("iconBg")}.png`,
-            scale: 0.45,
-            displacement: [0, 90],
-          }),
-        });
-        return [style1, style2, style3];
-      },
-    });
-
-    this.locationLayer = new KMap.VectorLayer("locationLayer", 9999, {
-      style: () => {
-        return new Style({
-          image: new Icon({
-            src: "/src/assets/images/map/location.png",
-            scale: 0.45,
-          }),
-        });
-      },
-    });
-  }
-
-  initMap(data, target) {
-    let level = 16;
-    let coordinate = util.wktCastGeom(data.point).getFirstCoordinate();
-    this.kmap = new KMap.Map(
-      target,
-      level,
-      coordinate[0],
-      coordinate[1],
-      null,
-        6,
-        22
-    );
-    this.lock(false)
-    this.kmap.setLayerWkt(data.geom, data, true, [120, 120, 120, 120] )
-    this.kmap.addLayer(this.clickPointLayer.layer);
-    this.kmap.addLayer(this.locationLayer.layer);
-    this.addPoint(data)
-    this.getSelectPointArr(data.id)
-  }
-
-  getSelectPointArr(id) {
-    const arr = [];
-    this.clickPointLayer.source.forEachFeature((feature) => {
-      if (feature.get("id") === id) {
-        // 修改当前点位高亮
-        feature.set("icon", "point");
-        feature.set("iconBg", "name-act-bg");
-        mapData.point = feature;
-        mapData.curPointData = feature.values_;
-      }
-      arr.push(feature);
-    });
-    const points = this.kmap.getLayerFeatures();
-    points.forEach((feature) => {
-      if (feature.get("id") === id) {
-        feature.set("icon", "point-act");
-        this.kmap.polygonStyle(feature);
-        mapData.isPointHide = feature;
-      }
-    });
-    mapData.selectPointArr = arr;
-  }
-
-  //   添加点位
-  addPoint(point) {
-    const arrPoints = [];
-    arrPoints.push(
-        newPoint({ ...point, icon: "point", iconBg: "name-bg" }, "point")
-    );
-    this.clickPointLayer.source.addFeatures(arrPoints);
-  }
-
-  lock(lockval) {
-    let pan;
-    let mousezoom;
-    this.kmap.map.getInteractions().forEach(function (element) {
-      if (element instanceof DragPan)//获取 控制能否使用鼠标,手指拖动地图的对象
-        pan = element;
-      if(element instanceof MouseWheelZoom)//获取 控制能否使用滚轮滚动放大缩小地图的对象
-        mousezoom = element;
-      if (pan) {
-        if (lockval) {
-          pan.setActive(true);//此对象的setActive方法用来设置是否可以拖动滚动查看
-        }
-        else {
-          pan.setActive(false);
-        }
-      }
-      if (mousezoom) {
-        if (lockval) {
-          mousezoom.setActive(true);
-        }
-        else {
-          mousezoom.setActive(false);
-        }
-      }
-    });
-  }
-}
-
-export default PdfMap;

+ 0 - 481
src/views/varietyMap/index.vue

@@ -1,481 +0,0 @@
-<template>
-    <div class="base-container">
-        <fnHeader :hideSwitch="true" :hideShadow="true" showDate></fnHeader>
-        <div class="content">
-            <div class="content-left">
-                <div class="btn" @click="goBack">
-                    <img src="@/assets/images/common/back-icon.png" alt="" />
-                    返回
-                </div>
-                <chart-box class="left-cont" name="品种列表" color="yellow">
-                    <div class="box">
-                        <div class="add-cont" v-if="baseData.length === 0">
-                            <div>暂无数据</div>
-                            <div class="tips-text">请先添加品种,再框选右侧区域,进行品种确权</div>
-                            <div class="button" @click="handleAdd">
-                                <el-icon class="icon"><Plus /></el-icon>
-                                添加品种
-                            </div>
-                        </div>
-                        <template v-else>
-                            <div class="box-item" v-for="item in baseData" :key="item.speciesItemId">
-                                <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>
-                                添加品种
-                            </div>
-                        </template>
-                    </div>
-                </chart-box>
-            </div>
-            <div class="content-right">
-                <div class="map-header">
-                    <div class="title">
-                        <img src="@/assets/images/common/area-icon.png" alt="" />
-                        品种确权
-                    </div>
-                    <div class="button-group">
-                        <div class="button" @click="handleClear">清除框选</div>
-                        <div class="button start" @click="handleStart">开始框选</div>
-                        <div class="button end" @click="handleEnd">结束框选</div>
-                    </div>
-                </div>
-                <div class="map">
-                    <my-map ref="mapRef"></my-map>
-                    <div class="checkbox-list">
-                        <span class="text">全部设置为</span>
-                        <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">
-                            <el-icon class="icon"><Plus /></el-icon>
-                            添加品种
-                        </div>
-                    </div>
-                    <div class="footer-btn">
-                        <div class="cancel" @click="handleCancel">取消</div>
-                        <div @click="handleSave">保存</div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-    <!-- 添加品种弹窗 -->
-    <el-dialog
-        v-model="dialogVisible"
-        body-class="custom-dialog"
-        title="添加品种"
-        width="500"
-        align-center
-        :before-close="handleClose"
-    >
-        <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="handleClose">取消</div>
-                <div @click="handleOk">确定</div>
-            </div>
-        </template>
-    </el-dialog>
-</template>
-
-<script setup>
-import { onMounted, ref } from "vue";
-import { ElMessage } from "element-plus";
-import fnHeader from "@/components/fnHeader.vue";
-import myMap from "./map";
-import chartBox from "@/components/chartBox.vue";
-import { useRouter, useRoute } from "vue-router";
-import { useStore } from "vuex";
-import eventBus from "@/api/eventBus";
-const store = useStore();
-
-const router = useRouter();
-const route = useRoute();
-const farmId = sessionStorage.getItem("farmId");
-onMounted(() => {
-    getList();
-    getSpeciesData();
-});
-
-
-//清除框选
-const handleClear = () => {
-    eventBus.emit("handle:clear");
-};
-
-//开始框选
-const handleStart = () => {
-    eventBus.emit("handle:start");
-};
-
-//结束框选
-const handleEnd = () => {
-    eventBus.emit("handle:end");
-};
-
-const baseData = ref([]);
-const getList = () => {
-    const params = {
-        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([]);
-const handleCheckedCitiesChange = (e) => {
-    if(e.length){
-        checkedCities.value = [e[e.length -1]];
-    }
-};
-
-const mapRef = ref(null)
-const handleSave = () =>{
-    const selectPoint = mapRef.value.getSelectPoint()
-    const params = selectPoint.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);
-};
-
-//添加品种弹窗
-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>
-
-<style lang="scss" scoped>
-.base-container {
-    width: 100%;
-    height: 100vh;
-    color: #fff;
-    position: relative;
-    box-sizing: border-box;
-    z-index: 1;
-    background: #000;
-
-    .content {
-        width: 100%;
-        height: calc(100% - 74px);
-        display: flex;
-        justify-content: space-between;
-        box-sizing: border-box;
-        padding: 20px;
-        .content-left {
-            width: 473px;
-            height: 100%;
-            box-sizing: border-box;
-            .btn {
-                display: flex;
-                align-items: center;
-                justify-content: center;
-                border: 1px solid rgba(255, 255, 255, 0.78);
-                border-radius: 4px;
-                padding: 9px;
-                margin-bottom: 13px;
-                width: 104px;
-                cursor: pointer;
-                img {
-                    width: 14px;
-                    margin-right: 5px;
-                }
-            }
-            .left-cont {
-                width: 100%;
-                height: calc(100% - 48px - 4px);
-                .box {
-                    width: 100%;
-                    height: calc(100% - 58px);
-                    padding: 16px 12px;
-                    box-sizing: border-box;
-                    overflow-y: auto;
-                    display: flex;
-                    flex-direction: column;
-                    align-items: center;
-                    .button {
-                        color: #ffd489;
-                        display: flex;
-                        align-items: center;
-                        justify-content: center;
-                        border-radius: 8px;
-                        border: 1px solid #ffd489;
-                        padding: 8px 16px;
-                        background: rgba(255, 212, 137, 0.1);
-                        margin-top: 24px;
-                        width: 120px;
-                        font-size: 16px;
-                        box-sizing: border-box;
-                        cursor: pointer;
-                        .icon {
-                            margin-right: 4px;
-                        }
-                    }
-                    .add-cont {
-                        display: flex;
-                        flex-direction: column;
-                        align-items: center;
-                        font-size: 16px;
-                        .tips-text {
-                            width: 220px;
-                            text-align: center;
-                            color: #9f9f9f;
-                            font-size: 15px;
-                            margin-top: 8px;
-                        }
-                    }
-                    .box-item {
-                        width: 94%;
-                        display: flex;
-                        align-items: center;
-                        justify-content: space-between;
-                        border-radius: 5px;
-                        border: 1px solid #666666;
-                        padding: 12px;
-                        .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 {
-                            color: #9f9f9f;
-                        }
-                    }
-                    .box-item + .box-item{
-                        margin-top: 12px;
-                    }
-                }
-            }
-        }
-        .content-right {
-            width: calc(100% - 473px - 18px);
-            margin-left: 18px;
-            height: 100%;
-            background: #191919;
-            border: 0.6px solid #444444;
-            padding: 20px;
-            box-sizing: border-box;
-            border-radius: 8px;
-            .map-header {
-                display: flex;
-                align-items: flex-start;
-                justify-content: space-between;
-                .title {
-                    font-size: 22px;
-                    display: flex;
-                    align-items: flex-end;
-                    font-family: "PangMenZhengDao";
-                    margin-bottom: 16px;
-                    img {
-                        margin-right: 8px;
-                    }
-                }
-                .button {
-                    color: #fff;
-                    padding: 5px 15px;
-                    border-radius: 4px;
-                    font-size: 16px;
-                    border: 1px solid #fff;
-                    cursor: pointer;
-                }
-            }
-            .button-group{
-                display: flex;
-                div + div{
-                    margin-left: 10px;
-                }
-                .start{
-                    background: #f7be5a;
-                    color: #000;
-                }
-                .end{
-                    color: #f7be5a;
-                }
-            }
-            .map {
-                width: 100%;
-                clip-path: inset(0px round 4px);
-                height: calc(100% - 31px - 16px);
-                position: relative;
-                .checkbox-list {
-                    position: absolute;
-                    z-index: 2;
-                    right: 42px;
-                    bottom: 150px;
-                    background: rgba(0, 0, 0, 0.8);
-                    border-radius: 8px;
-                    display: flex;
-                    flex-direction: column;
-                    padding: 20px;
-                    .text {
-                        color: #9f9f9f;
-                        margin-bottom: 12px;
-                        font-size: 16px;
-                    }
-                    .checkbox {
-                        display: flex;
-                        flex-direction: column;
-                        ::v-deep {
-                            .el-checkbox__label {
-                                color: #fff;
-                                font-size: 16px;
-                            }
-                            .el-checkbox__inner {
-                                width: 18px;
-                                height: 18px;
-                            }
-                            .el-checkbox__input.is-checked .el-checkbox__inner {
-                                background: #ffd489;
-                                border-color: #ffd489;
-                                &::after {
-                                    border-color: #000;
-                                    border-width: 2px;
-                                    height: 10px;
-                                    left: 4px;
-                                    width: 5px;
-                                    top: 0;
-                                }
-                            }
-                        }
-                    }
-                    .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 {
-                            margin-right: 4px;
-                        }
-                    }
-                }
-                .footer-btn {
-                    position: absolute;
-                    right: 42px;
-                    bottom: 28px;
-                    z-index: 2;
-                    display: flex;
-                    width: 520px;
-                    div {
-                        text-align: center;
-                        width: calc(100% - 20px - 200px);
-                        font-size: 20px;
-                        color: #1d1d1d;
-                        background: #f7be5a;
-                        border-radius: 8px;
-                        border: 2px solid #fff;
-                        padding: 13px;
-                        cursor: pointer;
-                    }
-                    .cancel {
-                        margin-right: 20px;
-                        width: 200px;
-                        background: rgba(0, 0, 0, 0.6);
-                        color: #fff;
-                    }
-                }
-            }
-        }
-    }
-}
-
-.custom-dialog {
-    .el-dialog__body {
-        margin-top: 10px;
-    }
-    .input {
-        width: 100%;
-    }
-}
-.dialog-footer {
-    display: flex;
-    width: 100%;
-    margin-top: 25px;
-    div {
-        flex: 1;
-        padding: 10px;
-        background: #ffd489;
-        border-radius: 5px;
-        color: #1d1d1d;
-        text-align: center;
-        cursor: pointer;
-    }
-    .btn {
-        border: 1px solid #9f9f9f;
-        background: #fff;
-        margin-right: 14px;
-    }
-}
-</style>

+ 0 - 258
src/views/varietyMap/map.vue

@@ -1,258 +0,0 @@
-<template>
-    <div id="map-container"></div>
-</template>
-
-<script setup>
-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";
-import {base_img_url,base_img_url3} from "@/api/config";
-
-const map = ref(null);
-const mouseTool = ref(null);
-const selectedArea = ref(null);
-const selectedPoints = ref([]);
-const allPoints = ref([]);
-const defalutAllPoints = ref([])
-const pointList = ref([])
-
-const mapEventType = ref('rectangle')
-
-// 自定义圆点样式
-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 createMarkerImg = () => {
-    return `
-        <img style="width: 38px;height: 38px;" src="/src/assets/images/map/status/active-icon.png">
-    `;
-}
-// 初始化地图
-const initMap = async () => {
-    try {
-        const AMap = await AMapLoader.load({
-            key: "41769169f0f157e13a197e7eb0dd7b5b", // 替换为你的高德地图 Key
-            version: "2.0", // SDK 版本
-            plugins: ["AMap.MouseTool"], // 加载 MouseTool 插件
-        }).then((AMap) => {
-            // 创建地图实例
-            map.value = new AMap.Map("map-container", {
-                zoom: 18, // 初始缩放级别
-                center: [113.6149629 ,23.58594117],
-                layers: [
-                    // 卫星
-                    new AMap.TileLayer.Satellite(),
-                ],
-            });
-
-            //创建自定义切片图层,指定 getTileUrl 属性
-            var googleLayer = new AMap.TileLayer({
-                tileUrl: base_img_url + 'map/lby/[z]/[x]/[y].png',
-                zIndex:2
-            });
-
-            //将自定义图层添加到地图
-            map.value.add(googleLayer);
-
-            var googleLayer1 = new AMap.TileLayer({
-                tileUrl: base_img_url3 + 'map/lby/[z]/[x]/[y].png',
-                zIndex:2
-            });
-
-            //将自定义图层添加到地图
-            map.value.add(googleLayer1);
-
-            // 初始化 MouseTool
-            mouseTool.value = new AMap.MouseTool(map.value);
-            
-            startRectangleSelection()
-
-            // 监听框选完成事件
-            mouseTool.value.on("draw", (event) => {
-                if(mapEventType.value==='click') return
-                const { obj} = event;
-                if (obj instanceof AMap.Rectangle) {
-                    selectedArea.value = obj;
-                    map.value.remove(selectedArea.value);
-                    checkPointsInArea(); // 检查框选区域内的点位
-                }
-            });
-
-        });
-    } catch (error) {
-        console.error("地图加载失败:", error);
-    }
-};
-
-//重置数据
-const resetData = () =>{
-    allPoints.value = defalutAllPoints.value
-    allPoints.value.forEach(item =>{
-        item.icon.setContent(createMarkerContent(item.color))
-        item.icon.setOffset(new window.AMap.Pixel(-7, -7))
-        item.type = 'defalutIcon'
-    })
-}
-
-//初始化数据
-const initData = () =>{
-    defalutAllPoints.value = []
-    totalList.value.forEach(item => map.value.remove(item.icon))
-    totalList.value = []
-    allPoints.value.forEach(item =>{
-        item.icon = new window.AMap.Marker({
-            position: item.lngLat,
-            map: map.value,
-            content: createMarkerContent(item.color),
-            offset: new window.AMap.Pixel(-7, -7),
-        });
-        item.type = 'defalutIcon'
-
-        // 绑定点击事件
-        item.icon.on('click', () => {
-            mapEventType.value = 'click'
-            if(item.type === 'defalutIcon'){
-                item.icon.setContent(createMarkerImg()); 
-                item.icon.setOffset(new window.AMap.Pixel(-18, -18))
-                item.type = 'activeIcon'
-                const arr = pointList.value.filter(ele => ele.id === item.id)
-                if(arr.length===0){
-                    pointList.value.push(item)
-                }
-            }else{
-                item.icon.setContent(createMarkerContent(item.color)); 
-                item.icon.setOffset(new window.AMap.Pixel(-7, -7))
-                item.type = 'defalutIcon'
-            }
-
-            setTimeout(()=>{
-                mapEventType.value = 'draw'
-            },100)
-        });
-        defalutAllPoints.value.push(item)
-    })
-    map.value.setFitView(null, false, [0, 0, 0, 0]);
-}
-
-// 开始框选
-const startRectangleSelection = () => {
-    if (mouseTool.value) {
-        mouseTool.value.rectangle({
-            strokeColor: "#ffffff", // 框选区域边框颜色
-            strokeOpacity: 1, // 边框透明度
-            strokeWeight: 2, // 边框宽度
-            fillColor: "#000000", // 填充颜色
-            fillOpacity: 0.5, // 填充透明度
-        }); // 启用矩形框选工具
-        map.value.setDefaultCursor("crosshair");
-    }
-};
-
- // 停止绘制矩形
-const stopDrawRectangle = () => {
-    mouseTool.value.close(); // 关闭 mouseTool
-    map.value.setDefaultCursor("default");
-};
-
-// 清除框选
-const clearSelection = () => {
-    if (selectedArea.value) {
-        map.value.remove(selectedArea.value); // 移除框选区域
-        selectedArea.value = null;
-    }
-    resetData()                                                                                                                                                                                                                                                                                                                                      
-    selectedPoints.value = []; // 清空选中的点位
-};
-
-// 检查框选区域内的点位
-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.setContent(createMarkerImg())
-            item.icon.setOffset(new window.AMap.Pixel(-18, -18))
-            item.type = 'activeIcon'
-        }else{
-            item.icon.setContent(createMarkerContent(item.color))
-            item.icon.setOffset(new window.AMap.Pixel(-7, -7))
-            item.type = 'defalutIcon'
-        }
-    })
-};
-
-const speciesArr = ref([])
-const getList = () =>{
-    const params = {
-        farmId:sessionStorage.getItem('farmId'),
-        regionId:sessionStorage.getItem('regionId')
-    }
-    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)
-            }
-        })
-        initData()
-    })
-}
-
-const totalList = ref([])
-
-function getSelectPoint(){
-    totalList.value = selectedPoints.value.concat(pointList.value)
-    const arr = totalList.value.filter(item =>item.type==='activeIcon')
-    return arr
-}
-
-defineExpose({getSelectPoint})
-
-function getSpeciesList(arr){
-    speciesArr.value = arr
-    getList()
-}
-
-// 组件挂载时初始化地图
-onMounted(() => {
-    initMap()
-    eventBus.on('handle:clear',clearSelection)
-    eventBus.on('species:list',getSpeciesList)
-    eventBus.on('handle:start',startRectangleSelection)
-    eventBus.on('handle:end',stopDrawRectangle)
-});
-
-onUnmounted(()=>{
-    map.value.destroy()// 销毁地图实例以释放资源
-    eventBus.off('handle:clear',clearSelection)
-    eventBus.off('species:list',getSpeciesList)
-    eventBus.off('handle:start',startRectangleSelection)
-    eventBus.off('handle:end',stopDrawRectangle)
-})
-</script>
-
-<style scoped>
-#map-container {
-    width: 100%;
-    height: 100%;
-}
-</style>

+ 36 - 1
src/views/warningHome/components/chart_components/barChart.vue

@@ -3,19 +3,54 @@
 </template>
 
 <script setup>
-import { onMounted, ref } from "vue";
+import { onMounted, ref, watch } from "vue";
 import * as echarts from "echarts";
 import { barOption } from "./chartOption.js";
 import { deepClone } from "@/common/commonFun";
 
+const props = defineProps({
+    chartData: {
+        type: Object,
+        default: () => ({
+            categories: [],
+            values: [],
+        }),
+    },
+    yAxisFormatter: {
+        type: String,
+        default: "{value}%", // 默认百分比格式
+    },
+});
+
 const chartDom = ref(null);
 let myChart = null;
 
 const initData = () => {
     const newOption = deepClone(barOption);
+    
+    // 如果有传入数据,使用传入的数据
+    if (props.chartData && props.chartData.categories && props.chartData.categories.length > 0) {
+        newOption.xAxis.data = props.chartData.categories;
+        newOption.series[0].data = props.chartData.values;
+    }
+    
+    // 更新 yAxis 的 formatter
+    newOption.yAxis.axisLabel.formatter = props.yAxisFormatter;
+    
     myChart.setOption(newOption);
 };
 
+// 监听数据变化,更新图表
+watch(
+    () => [props.chartData, props.yAxisFormatter],
+    () => {
+        if (myChart) {
+            initData();
+        }
+    },
+    { deep: true }
+);
+
 onMounted(() => {
     myChart = echarts.init(chartDom.value);
     initData();

+ 219 - 13
src/views/warningHome/components/chart_components/chartList.vue

@@ -4,7 +4,7 @@
             <chart-box name="2025年广东省作物种植面积占比">
                 <div class="box-content">
                     <div class="chart-dom">
-                        <pie-chart></pie-chart>
+                        <pie-chart :chartData="pieChartData" :totalArea="totalArea"></pie-chart>
                     </div>
                     <div class="box-bg">
                         <div class="legend-list">
@@ -26,9 +26,9 @@
             <chart-box name="2025年广东省作物区域占比">
                 <div class="box-content">
                     <div class="chart-dom">
-                        <bar-chart :key="0"></bar-chart>
+                        <bar-chart :key="0" :chartData="regionChartData"></bar-chart>
                     </div>
-                    <div class="box-bg">从化区的作物种植面积最大,占比***</div>
+                    <div class="box-bg">{{ regionSummaryText }}</div>
                 </div>
             </chart-box>
         </div>
@@ -36,9 +36,11 @@
             <chart-box name="近三年主要作物种植面积变化趋势">
                 <div class="box-content">
                     <div class="chart-dom">
-                        <line-chart></line-chart>
+                        <line-chart :chartData="areaTrendChartData"></line-chart>
+                    </div>
+                    <div class="box-bg">
+                        这里是预警提示的内容,有点长,先用这些文字占位,后续开发会把内容不上的。这里是预警提示的内容,有点长,先用这些文字占位,后续开发会把内容不上的。
                     </div>
-                    <div class="box-bg">这里是预警提示的内容,有点长,先用这些文字占位,后续开发会把内容不上的。这里是预警提示的内容,有点长,先用这些文字占位,后续开发会把内容不上的。</div>
                 </div>
             </chart-box>
         </div>
@@ -46,9 +48,9 @@
             <chart-box name="2025年广东省作物预估产量对比">
                 <div class="box-content">
                     <div class="chart-dom">
-                        <bar-chart :key="1"></bar-chart>
+                        <bar-chart :key="1" :chartData="yieldChartData" :yAxisFormatter="'{value}吨'"></bar-chart>
                     </div>
-                    <div class="box-bg">从化区的作物种植面积最大,占比***</div>
+                    <div class="box-bg">{{ yieldSummaryText }}</div>
                 </div>
             </chart-box>
         </div>
@@ -59,7 +61,7 @@
 import chartBox from "@/components/chartBox.vue";
 import pieChart from "./pieChart.vue";
 import lineChart from "./lineChart.vue";
-import { computed } from "vue";
+import { computed, onMounted, ref } from "vue";
 import { pieOption } from "./chartOption.js";
 import barChart from "./barChart.vue";
 
@@ -69,19 +71,223 @@ const props = defineProps({
         default: "作物分布",
     },
 });
+
+// 图表数据
+const pieChartData = ref([]);
+const totalArea = ref(0);
+
+// 区域占比图表数据
+const regionChartData = ref({
+    categories: [], // 区域名称数组
+    values: [], // 占比百分比数组
+});
+
+// 区域占比摘要文字
+const regionSummaryText = ref("暂无数据");
+
+// 预估产量图表数据
+const yieldChartData = ref({
+    categories: [], // 作物名称数组
+    values: [], // 预估产量数组(单位:吨)
+});
+
+// 预估产量摘要文字
+const yieldSummaryText = ref("暂无数据");
+
+// 种植面积趋势图表数据
+const areaTrendChartData = ref({
+    xAxisData: [], // 时间轴数据
+    series: [], // 系列数据
+});
+
 // 计算图例数据
 const legendData = computed(() => {
-    const total = 3774; // 总种植面积
-    return pieOption.series[0].data.map((item, index) => {
-        const percent = ((item.value / total) * 100).toFixed(0);
+    if (!pieChartData.value.length || totalArea.value === 0) {
+        return [];
+    }
+    return pieChartData.value.map((item, index) => {
+        const percent = ((item.value / totalArea.value) * 100).toFixed(1);
         return {
             name: item.name,
-            value: item.value,
+            value: Math.round(item.value), // 显示整数
             percent: percent,
-            color: pieOption.color[index],
+            color: pieOption.color[index % pieOption.color.length],
         };
     });
 });
+
+onMounted(() => {
+    fetchStatSpeciesAreaYield();
+    fetchStatRegionAreaRatio();
+    fetchAreaTrend();
+});
+
+const fetchAreaTrend = () => {
+    const params = {
+        speciesIds: [1, 222, 60876],
+        adminCode: "156440000",
+        adminLevel: "province",
+    };
+    VE_API.warning.fetchAreaTrend(params).then((res) => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 收集所有唯一的时间点(year-quarter组合)
+            const timePointSet = new Set();
+            res.data.forEach((species) => {
+                species.timeSeries.forEach((item) => {
+                    const timeKey = `${item.year}Q${item.quarter}`;
+                    timePointSet.add(timeKey);
+                });
+            });
+
+            // 转换为数组并排序
+            const xAxisData = Array.from(timePointSet).sort((a, b) => {
+                const [yearA, quarterA] = a.split('Q').map(Number);
+                const [yearB, quarterB] = b.split('Q').map(Number);
+                if (yearA !== yearB) return yearA - yearB;
+                return quarterA - quarterB;
+            });
+
+            // 定义颜色映射(可以根据需要调整)
+            const colorMap = {
+                '荔枝': '#2199F8',
+                '籼稻': '#178B00',
+                '小麦': '#FAA53D',
+            };
+
+            // 为每个作物创建系列数据
+            const series = res.data.map((species) => {
+                // 创建时间点到种植面积的映射
+                const dataMap = new Map();
+                species.timeSeries.forEach((item) => {
+                    const timeKey = `${item.year}Q${item.quarter}`;
+                    dataMap.set(timeKey, item.plantArea);
+                });
+
+                // 根据 xAxisData 顺序生成数据数组
+                const data = xAxisData.map((timeKey) => {
+                    return dataMap.has(timeKey) ? parseFloat(dataMap.get(timeKey).toFixed(2)) : null;
+                });
+
+                return {
+                    name: species.speciesName,
+                    type: 'line',
+                    smooth: true,
+                    showSymbol: false,
+                    data: data,
+                    itemStyle: {
+                        color: colorMap[species.speciesName] || '#2199F8',
+                    },
+                    lineStyle: {
+                        color: colorMap[species.speciesName] || '#2199F8',
+                    },
+                };
+            });
+
+            // 更新图表数据
+            areaTrendChartData.value = {
+                xAxisData,
+                series,
+            };
+        }
+    });
+};
+
+const fetchStatRegionAreaRatio = () => {
+    const params = {
+        speciesId: 222,
+        adminCode: 156441400,
+        adminLevel: "city",
+    };
+    VE_API.warning.fetchStatRegionAreaRatio(params).then((res) => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 转换接口数据为图表格式
+            const categories = res.data.map((item) => item.adminName);
+            const values = res.data.map((item) => (item.areaRatio * 100).toFixed(2)); // 转换为百分比,保留两位小数
+
+            // 更新图表数据
+            regionChartData.value = {
+                categories,
+                values: values.map((v) => parseFloat(v)), // 转换为数字
+            };
+
+            // 找到最大占比的区域
+            let maxRatio = 0;
+            let maxRegion = "";
+            res.data.forEach((item) => {
+                if (item.areaRatio > maxRatio) {
+                    maxRatio = item.areaRatio;
+                    maxRegion = item.adminName;
+                }
+            });
+
+            // 更新摘要文字
+            if (maxRegion) {
+                const maxPercent = (maxRatio * 100).toFixed(1);
+                regionSummaryText.value = `${maxRegion}的作物种植面积最大,占比${maxPercent}%`;
+            } else {
+                regionSummaryText.value = "暂无数据";
+            }
+        } else {
+            regionSummaryText.value = "暂无数据";
+        }
+    });
+};
+
+const fetchStatSpeciesAreaYield = () => {
+    const params = {
+        year: 2025,
+        adminCode: null,
+        adminLevel: null,
+    };
+    VE_API.warning.fetchStatSpeciesAreaYield(params).then((res) => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 转换接口数据为图表格式(用于饼图)
+            const chartData = res.data.map((item) => ({
+                value: item.plantArea, // 种植面积
+                name: item.speciesName, // 作物名称
+                expectYield: item.expectYield, // 预估产量
+                speciesId: item.speciesId, // 作物ID
+            }));
+
+            // 计算总种植面积
+            const total = chartData.reduce((sum, item) => sum + item.value, 0);
+
+            // 更新饼图数据
+            pieChartData.value = chartData;
+            totalArea.value = total;
+
+            // 处理预估产量数据(用于柱状图)
+            const categories = res.data.map((item) => item.speciesName);
+            const values = res.data.map((item) => parseFloat(item.expectYield.toFixed(2))); // 保留两位小数
+
+            // 更新预估产量图表数据
+            yieldChartData.value = {
+                categories,
+                values,
+            };
+
+            // 找到最大预估产量的作物
+            let maxYield = 0;
+            let maxSpecies = "";
+            res.data.forEach((item) => {
+                if (item.expectYield > maxYield) {
+                    maxYield = item.expectYield;
+                    maxSpecies = item.speciesName;
+                }
+            });
+
+            // 更新摘要文字
+            if (maxSpecies) {
+                const maxYieldFormatted = maxYield.toFixed(1);
+                yieldSummaryText.value = `${maxSpecies}的预估产量最高,为${maxYieldFormatted}吨`;
+            } else {
+                yieldSummaryText.value = "暂无数据";
+            }
+        } else {
+            yieldSummaryText.value = "暂无数据";
+        }
+    });
+};
 </script>
 
 <style lang="scss" scoped>

+ 29 - 1
src/views/warningHome/components/chart_components/lineChart.vue

@@ -3,19 +3,47 @@
 </template>
 
 <script setup>
-import { onMounted, ref } from "vue";
+import { onMounted, ref, watch } from "vue";
 import * as echarts from "echarts";
 import { lineOption } from "./chartOption.js";
 import { deepClone } from "@/common/commonFun";
 
+const props = defineProps({
+    chartData: {
+        type: Object,
+        default: () => ({
+            xAxisData: [],
+            series: [],
+        }),
+    },
+});
+
 const chartDom = ref(null);
 let myChart = null;
 
 const initData = () => {
     const newOption = deepClone(lineOption);
+    
+    // 如果有传入数据,使用传入的数据
+    if (props.chartData && props.chartData.xAxisData && props.chartData.xAxisData.length > 0) {
+        newOption.xAxis.data = props.chartData.xAxisData;
+        newOption.series = props.chartData.series;
+    }
+    
     myChart.setOption(newOption);
 };
 
+// 监听数据变化,更新图表
+watch(
+    () => props.chartData,
+    () => {
+        if (myChart) {
+            initData();
+        }
+    },
+    { deep: true }
+);
+
 onMounted(() => {
     myChart = echarts.init(chartDom.value);
     initData();

+ 40 - 1
src/views/warningHome/components/chart_components/pieChart.vue

@@ -3,19 +3,58 @@
 </template>
 
 <script setup>
-import { onMounted, ref } from "vue";
+import { onMounted, ref, watch } from "vue";
 import * as echarts from "echarts";
 import { pieOption } from "./chartOption.js";
 import { deepClone } from "@/common/commonFun";
 
+const props = defineProps({
+    chartData: {
+        type: Array,
+        default: () => [],
+    },
+    totalArea: {
+        type: Number,
+        default: 0,
+    },
+});
+
 const chartDom = ref(null);
 let myChart = null;
 
 const initData = () => {
     const newOption = deepClone(pieOption);
+    
+    // 如果有传入数据,使用传入的数据
+    if (props.chartData && props.chartData.length > 0) {
+        newOption.series[0].data = props.chartData;
+        // 更新总种植面积
+        if (props.totalArea > 0) {
+            newOption.title.subtext = Math.round(props.totalArea).toString();
+            // 更新 tooltip 中的 total
+            newOption.tooltip.formatter = function (params) {
+                const data = params.data;
+                const total = props.totalArea;
+                const percent = (data.value / total * 100).toFixed(2);
+                return `${params.marker}${data.name}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${percent}%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${Math.round(data.value)}亩`;
+            };
+        }
+    }
+    
     myChart.setOption(newOption);
 };
 
+// 监听数据变化,更新图表
+watch(
+    () => [props.chartData, props.totalArea],
+    () => {
+        if (myChart) {
+            initData();
+        }
+    },
+    { deep: true }
+);
+
 onMounted(() => {
     myChart = echarts.init(chartDom.value);
     initData();

+ 48 - 69
src/views/warningHome/components/timeLine.vue

@@ -9,7 +9,7 @@
         </div>
         <div class="line">
             <div class="active-line" :style="{ width: numList[active] + '%' }"></div>
-            <div :class="['dot-item', { mr: index === 6 }]" v-for="(item, index) in list" :key="index">
+            <div :class="['dot-item', { mr: index === list.length - 1 }]" v-for="(item, index) in list" :key="index">
                 <div :class="['dot', { active: active === index }]"></div>
                 <span :class="{ text: active === index }">{{ item }}</span>
             </div>
@@ -18,9 +18,8 @@
 </template>
 
 <script setup>
-import { ref, onDeactivated,computed ,watch, onActivated} from "vue";
+import { ref, onDeactivated,computed ,watch, onMounted} from "vue";
 import { useStore } from "vuex";
-import eventBus from "@/api/eventBus";
 const store = useStore();
 
 const isShow = ref(true)
@@ -32,70 +31,64 @@ const isShow = ref(true)
 //         isShow.value = true
 //     }
 // });
-onActivated(()=>{
-    restActive()
+onMounted(()=>{
+    // restActive()
+    fetchYearQuarter()
 })
-// 果园切换监听事件
-eventBus.on("select:changeGarden", (e) => {
-    restActive()
-});
 
-//监听测报面板高度变化
-eventBus.on('report:shrink',(e)=>{
-    if(e>=Math.round(0.7 * window.innerHeight)){
-        clearTime();
-        active.value = 0;
-        isCounting.value = false;
-        eventBus.emit("weatherTime:resetTime")
-    }else{
-        restActive()
-    }
-})
+const fetchYearQuarter = () => {
+    VE_API.warning.fetchYearQuarter().then(res => {
+        if (res.code === 0 && res.data && res.data.length > 0) {
+            // 转换接口数据为时间轴显示格式
+            const formattedList = res.data.map((item) => 
+                formatYearQuarter(item.year, item.quarter)
+            );
+            
+            // 更新时间轴列表
+            list.value = formattedList;
+            
+            // 重置激活状态
+            // restActive();
+        }
+    });
+}
 
 const active = ref(0);
 const isCounting = ref(false);
 
-const numList = [7, 21, 37, 52, 68, 84, 99];
-
-function formatDateToMMDD(date) {
-    const month = String(date.getMonth() + 1).padStart(2, "0"); // 月份从0开始,需要加1,并确保是两位数
-    const day = String(date.getDate()).padStart(2, "0"); // 确保日期是两位数
-    return `${month}-${day}`;
-}
-
-function getCurrentDateAndNextSixDaysMMDD() {
-    const currentDate = new Date();
-    const dates = [];
-
-    for (let i = 0; i <= 6; i++) {
-        const newDate = new Date(currentDate);
-        newDate.setDate(currentDate.getDate() + i);
-        const formattedDate = formatDateToMMDD(newDate);
-        dates.push(formattedDate);
-    }
+// 计算进度条百分比位置(根据数据数量动态计算)
+const numList = computed(() => {
+    return [4,16.5,29.5,43.5,56.5,69.5,82.8,95.5];
+    // const count = list.value.length;
+    // if (count <= 1) return [100];
+    // const step = 100 / (count - 1);
+    // return Array.from({ length: count }, (_, i) => parseFloat((i * step).toFixed(1)));
+});
 
-    return dates;
+// 格式化年季度数据为显示文本
+function formatYearQuarter(year, quarter) {
+    return `${year}Q${quarter}`;
 }
 
-const list = getCurrentDateAndNextSixDaysMMDD();
+// 时间轴列表数据
+const list = ref([]);
 
 const incrementInterval = 3000; // 默认间隔3秒
-const specialIncrementInterval = 3000; // 特殊间隔5
+const specialIncrementInterval = 3000; // 特殊间隔3
 
 const timer = ref(null);
 const incrementCount = (type) => {
-    if (active.value === 6) {
+    const maxIndex = list.value.length - 1;
+    if (active.value >= maxIndex) {
         active.value = 0;
-        eventBus.emit("weatherTime:changeTime",{index: active.value, date: list[active.value]})
     } else {
         if(type!=='original'){
             active.value += 1;
-            eventBus.emit("weatherTime:changeTime",{index: active.value, date: list[active.value]})
         }
     }
 
     let time = incrementInterval;
-    if (active.value === 0 || active.value === 6) {
+    if (active.value === 0 || active.value === maxIndex) {
         time = specialIncrementInterval;
     }
     timer.value = setTimeout(() => {
@@ -106,7 +99,8 @@ const incrementCount = (type) => {
 const timerId = ref(null);
 const handleChange = () => {
     clearTime()
-    if (active.value === 0 || active.value === 6) {
+    const maxIndex = list.value.length - 1;
+    if (active.value === 0 || active.value === maxIndex) {
         timerId.value = setTimeout(() => {
             if (isCounting.value) incrementCount();
         }, specialIncrementInterval);
@@ -114,9 +108,6 @@ const handleChange = () => {
         incrementCount('original');
     }
     isCounting.value = !isCounting.value;
-    if (isCounting.value) {
-        eventBus.emit("weatherTime:changeTime", {index: 0, date: list[0]})
-    }
 };
 
 onDeactivated(() => {
@@ -141,10 +132,6 @@ const restActive = () => {
     handleChange();
 };
 
-eventBus.on("map_click_alarm", ()=>{
-  restActive()
-})
-
 defineExpose({ restActive });
 </script>
 
@@ -162,7 +149,7 @@ defineExpose({ restActive });
     .play {
         display: flex;
         align-items: center;
-        margin-right: 17px;
+        margin-right: 25px;
         .icon {
             width: 46px;
         }
@@ -170,7 +157,7 @@ defineExpose({ restActive });
     .line {
         background: linear-gradient(30deg, #fff 0% , rgba(44, 44, 44,0.6) 100%);
         border-radius: 2px;
-        width: 80%;
+        width: 90%;
         height: 2px;
         display: flex;
         justify-content: space-between;
@@ -196,7 +183,7 @@ defineExpose({ restActive });
                 height: 8px;
                 background: #E6E6E6;
                 border-radius: 50%;
-                margin: -2.2px 0 6px 14px;
+                margin: -2.2px 0 6px 28px;
                 position: relative;
                 &::after{
                     content: '';
@@ -209,14 +196,9 @@ defineExpose({ restActive });
                     border: 2px solid rgba(255,255,255,0.2);
                 }
             }
-            span {
-                margin-left: 3px;
-                letter-spacing: 0.5px;
-            }
             .active {
-                width: 6px;
-                height: 6px;
-                margin: -2px 0 5px 14px;
+                width: 8px;
+                height: 8px;
                 position: relative;
                 background: #F3C11D;
                 
@@ -225,22 +207,19 @@ defineExpose({ restActive });
                     position: absolute;
                     top: -2px;
                     left: -2px;
-                    width: 6px;
-                    height: 6px;
+                    width: 8px;
+                    height: 8px;
                     border-radius: 50%;
                     border: 2px solid rgba(243,193,29,0.2);
                 }
             }
             .text {
-                // color: #F3C11D;
                 background: #ED9E1E;
                 padding: 1px 10px;
                 border-radius: 36px;
+                margin-left: -8px;
             }
         }
-        .mr {
-            margin-right: -12px;
-        }
     }
 }
 </style>

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

@@ -1213,11 +1213,10 @@ const getTreeChecks = async (nodeData, data) => {
             padding-top: 14px;
         }
         .time-wrap {
-            position: absolute;
-            bottom: -20px;
-            left: 140px;
-            width: 46vw;
-            min-width: 700px;
+            position: fixed;
+            bottom: 20px;
+            left: 20px;
+            width: 1080px;
             height: 71px;
         }
     }