index.vue 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. <template>
  2. <div class="base-container no-events">
  3. <fnHeader showDate></fnHeader>
  4. <div class="content">
  5. <navigation style="margin-left: 50px" @handleTab="handleTab"></navigation>
  6. <div class="left yes-events" :class="{ 'collapsed-left': isLeftShrink }">
  7. <div class="home-btn">
  8. <div class="btn" @click="changeLeftComponent(0)" :class="{ active: activeBtn === 0 }">实时感知</div>
  9. <div class="btn" @click="changeLeftComponent(1)" :class="{ active: activeBtn === 1 }">诊断识别</div>
  10. </div>
  11. <tool-list
  12. direction="left"
  13. ref="leftTool"
  14. :list="leftToolList[activeBtn]"
  15. @handleActive="handleActiveLeft"
  16. ></tool-list>
  17. <component :is="components[currentComponent]" />
  18. <!-- 箭头 -->
  19. <div class="arrow" @click="handleShrink('left')">
  20. <el-icon class="icon" :class="{ 'arrow-left': isLeftShrink }" color="#141414"
  21. ><DArrowLeft
  22. /></el-icon>
  23. </div>
  24. </div>
  25. <div class="home-bottom">
  26. <img v-if="!showSpaceTime" class="img yes-events" @click="handlePage" src="@/assets/images/home/table-btn-sk.png" alt="" />
  27. <space-time v-if="showSpaceTime" @collapse="handleSpaceTimeCollapse" :class="{ 'expanded': showSpaceTime }"></space-time>
  28. </div>
  29. <div class="right yes-events" :class="{ 'collapsed-right': isRightShrink }">
  30. <div class="home-btn">
  31. <div class="btn" @click="changeRightComponent(0)" :class="{ active: activeRightBtn === 0 }">
  32. 精细农事
  33. </div>
  34. <div class="btn" @click="changeRightComponent(1)" :class="{ active: activeRightBtn === 1 }">
  35. 人机执行
  36. </div>
  37. </div>
  38. <component :is="components[currentRightComponent]" @airLineCallback="airLineCallback" @startEditLine="startEditLine" />
  39. <tool-list
  40. direction="right"
  41. ref="rightTool"
  42. :list="rightToolList[activeRightBtn]"
  43. @handleActive="handleActiveRight"
  44. ></tool-list>
  45. <!-- 箭头 -->
  46. <div class="arrow" @click="handleShrink('right')">
  47. <el-icon class="icon" :class="{ 'arrow-right': isRightShrink }" color="#141414"><DArrowLeft /></el-icon>
  48. </div>
  49. </div>
  50. <div v-if="isEditLine" class="map-bg map-legend" style="right: 580px" @click="deleteLine">删除</div>
  51. <!-- 图例 -->
  52. <!-- <img class="legend yes-events" src="@/assets/images/home/legend-img.png" alt="" /> -->
  53. <div v-if="legendArr && legendArr.length" class="map-bg map-legend yes-events">
  54. <div class="item" v-for="(legend, legendI) in legendArr" :key="legendI">
  55. <span class="legend-block" :style="{ background: legend.color }"></span>
  56. {{ legend.name }}
  57. </div>
  58. </div>
  59. <div v-else class="map-bg map-legend yes-events">
  60. <div class="item">
  61. <img src="@/assets/images/map/status/status-bh.png" alt="" />
  62. 病害异常
  63. </div>
  64. <div class="item">
  65. <img src="@/assets/images/map/status/status-ch.png" alt="" />
  66. 虫害异常
  67. </div>
  68. <div class="item">
  69. <img src="@/assets/images/map/status/status-zc.png" alt="" />
  70. 正常
  71. </div>
  72. <!-- <div class="item">
  73. <img src="@/assets/images/map/status/defalut-icon.png" alt="" />
  74. 无照片
  75. </div> -->
  76. </div>
  77. </div>
  78. </div>
  79. <div ref="mapRef" class="bottom-map"></div>
  80. <!-- 图片弹窗 -->
  81. <PicturePreview :imageUrl="urls" :curIndex="urlsIndex"></PicturePreview>
  82. <album-carousel></album-carousel>
  83. <PdfDialog title="果园报告"></PdfDialog>
  84. <!-- 对比 -->
  85. <compareDialog></compareDialog>
  86. <div class="compare-start-btn yes-events" v-show="showCompareBtn" @click="showCompare">
  87. <img src="@/assets/images/home/compare-btn.png" alt="" />
  88. </div>
  89. <!-- 作物档案 -->
  90. <div class="file-wrap map-file" id="popup-file">
  91. <div class="file-title">
  92. <img src="@/assets/images/common/chart-yellow.png" alt="" />
  93. 作物档案
  94. <span id="tag-nh" class="tag">小农户</span>
  95. </div>
  96. <div class="overview-file">
  97. <div class="box-title">总体档案</div>
  98. <div class="base-data" id="file-overview"></div>
  99. <div class="list" id="file-text">
  100. <div class="list-item" v-for="item in photoList" :key="item.key">
  101. <div class="list-name">
  102. <img src="@/assets/images/common/title-icon.png" alt="" />
  103. {{ item.key }}
  104. </div>
  105. {{ item.statement }}
  106. </div>
  107. </div>
  108. </div>
  109. <div class="overview-file">
  110. <div class="box-title">产量信息</div>
  111. <div class="box-wrap" id="file-output">
  112. <div class="box-item">
  113. <div class="item-name"></div>
  114. <div class="item-val"></div>
  115. </div>
  116. </div>
  117. </div>
  118. <div class="overview-file">
  119. <div class="box-title">生态评估</div>
  120. <div class="box-wrap" id="file-quality">
  121. <div class="box-item">
  122. <div class="item-name"></div>
  123. <div class="item-val"></div>
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. <FarmFightTask class="farm-fight-task" :farmId="currentFarm.id"></FarmFightTask>
  129. </template>
  130. <script setup>
  131. import { onMounted, onUnmounted, ref } from "vue";
  132. import config from "@/api/config.js";
  133. import timeLine from "@/components/timeLine.vue";
  134. import PicturePreview from "@/components/PicturePreview.vue";
  135. import fnHeader from "@/components/fnHeader.vue";
  136. import navigation from "@/components/navigation.vue";
  137. import chartBox from "@/components/chartBox.vue";
  138. import toolList from "@/components/toolList.vue";
  139. import fileBar from "@/components/fileBar.vue";
  140. import HomeMap from "./map/homeMap";
  141. import homePage from "./components/homePage.vue";
  142. import phenologyPage from "./components/phenologyPage.vue";
  143. import indicatorChart from "./components/indicatorChart.vue";
  144. import homeFile from "./components/homeFile.vue";
  145. import { useRouter } from "vue-router";
  146. import SamplePointLayer from "./map/samplePointLayer";
  147. import { useStore } from "vuex";
  148. import RegionLayer from "./map/regionLayer";
  149. import BlueRegionLayer from "./map/blueRegionLayer";
  150. import eventBus from "@/api/eventBus";
  151. import AlbumCarousel from "./album_compoents/albumCarousel.vue";
  152. import compareDialog from "./album_compoents/compareDialog.vue";
  153. import album from "./album/index.vue";
  154. import PdfDialog from "../../components/PdfDialog";
  155. import StaticMapLayers from "@/components/static_map_change/Layers.js";
  156. import FarmFightTask from "./components/farmFightTask";
  157. import leftFly from "./components/leftComponents/leftFly.vue";
  158. import leftWeather from "./components/leftComponents/leftWeather.vue";
  159. import leftStation from "./components/leftComponents/leftStation.vue";
  160. import weatherPage from "./components/leftComponents/weatherPage.vue";
  161. import leftDiseases from "./components/leftComponents/leftDiseases.vue";
  162. import leftNutrition from "./components/leftComponents/leftNutrition.vue";
  163. import rightAerial from "./components/rightComponents/rightAerial.vue";
  164. import recordList from "./components/rightComponents/recordList.vue";
  165. import AirLineStringLayer from "./map/airLineStringLayer";
  166. import spaceTime from "./components/spaceTime/index.vue";
  167. const activeBtn = ref(0);
  168. const leftTool = ref(null);
  169. function changeLeftComponent(i) {
  170. activeBtn.value = i;
  171. handleActiveLeft(leftToolList[i][0]);
  172. // if(i){
  173. // isDisable.value = false
  174. // }else{
  175. // isDisable.value = true
  176. // }
  177. leftTool.value.resetActive(0);
  178. }
  179. const rightTool = ref(null);
  180. const activeRightBtn = ref(0);
  181. function changeRightComponent(i) {
  182. activeRightBtn.value = i;
  183. handleActiveRight(rightToolList[i][0]);
  184. rightTool.value.resetActive(0);
  185. }
  186. let store = useStore();
  187. const components = {
  188. leftFly,
  189. leftWeather,
  190. leftStation,
  191. homePage,
  192. weatherPage,
  193. phenologyPage,
  194. leftDiseases,
  195. leftNutrition,
  196. rightAerial,
  197. recordList,
  198. };
  199. //当前农场
  200. const currentFarm = {
  201. id: sessionStorage.getItem("farmId"),
  202. name: store.getters.userinfo.curFarmName,
  203. };
  204. //当前区域
  205. const currentRegion = {
  206. id: null,
  207. name: null,
  208. };
  209. let homeMap = new HomeMap();
  210. let staticMapLayers = null;
  211. let samplePointLayer = null;
  212. let regionLayer = null;
  213. let blueRegionLayer = null;
  214. let airLineStringLayer = null;
  215. const router = useRouter();
  216. const mapRef = ref();
  217. onMounted(() => {
  218. homeMap.initMap("POINT(113.61448114737868 23.585550924763083)", mapRef.value);
  219. // homeMap.initMap(store.getters.userinfo.location, mapRef.value);
  220. // regionLayer = new RegionLayer(homeMap.kmap.map, currentFarm, currentRegion)
  221. samplePointLayer = new SamplePointLayer(homeMap.kmap);
  222. VE_API.warning
  223. .fetchWarningLayer({
  224. k: "gspgjdfbt",
  225. resultType: "json",
  226. })
  227. .then(({ data }) => {
  228. staticMapLayers = new StaticMapLayers(homeMap.kmap, data);
  229. eventBus.on("showGspgjdfbt", function (v) {
  230. if (v) {
  231. staticMapLayers.showSingle("聚类结果3", true);
  232. } else {
  233. staticMapLayers.hideAll();
  234. }
  235. });
  236. });
  237. blueRegionLayer = new BlueRegionLayer(homeMap.kmap);
  238. airLineStringLayer = new AirLineStringLayer(homeMap.kmap);
  239. function changeStaticMapLayers(e) {
  240. // staticMapLayers.
  241. }
  242. getYellow();
  243. // getFarmLog()
  244. //区域切换监听事件
  245. eventBus.on("area:id", areaId);
  246. //选项卡子项事件监听
  247. // eventBus.on("handleTabItem", handleTabItem);
  248. // 是否开启指标对比
  249. eventBus.on("compareTree", handleCompare);
  250. eventBus.on("clickToCompare:point", toggleCompare);
  251. });
  252. onUnmounted(() => {
  253. eventBus.off("area:id", areaId);
  254. // eventBus.off("handleTabItem", handleTabItem);
  255. eventBus.off("compareTree", handleCompare);
  256. eventBus.off("clickToCompare:point", toggleCompare);
  257. });
  258. function handleCompare(v) {
  259. isShrink.value = v;
  260. if (v === false) {
  261. showCompareBtn.value = v;
  262. }
  263. }
  264. const showSpaceTime = ref(false);
  265. const handlePage = () => {
  266. showSpaceTime.value = true;
  267. // 收缩左右两边
  268. isLeftShrink.value = true;
  269. isRightShrink.value = true;
  270. };
  271. const handleSpaceTimeCollapse = () => {
  272. showSpaceTime.value = false;
  273. // 展开左右两边
  274. isLeftShrink.value = false;
  275. isRightShrink.value = false;
  276. };
  277. const blueList = ref([]);
  278. const getBlueRegionList = (callback) => {
  279. if (!organId.value) {
  280. return;
  281. }
  282. let selectAll = undefined;
  283. if (regionId.value === 0) {
  284. selectAll = 1;
  285. }
  286. const areaId = selectAll ? undefined : regionId.value;
  287. VE_API.farm.blueRegionList({ farmId: organId.value, regionId: areaId, selectAll }).then(({ data }) => {
  288. blueList.value = data.map((item) => {
  289. let color = "rgba(255, 255, 255, 0.5)"; //失效区域
  290. if (item.status === 2) {
  291. //物候期风险
  292. // color = "rgba(63, 255, 53, 0.5)";
  293. color = "#2BFE00";
  294. }
  295. if (item.status === 3) {
  296. //生长异常
  297. // color = "rgba(255, 252, 61, 0.5)";
  298. color = "#FF7410";
  299. }
  300. if (item.status === 4) {
  301. //病虫害
  302. // color = "rgba(255, 73, 73, 0.5)";
  303. color = "#F82121";
  304. }
  305. return {
  306. ...item,
  307. color,
  308. };
  309. });
  310. blueRegionLayer.initData(blueList.value);
  311. callback && callback();
  312. });
  313. };
  314. // 图例
  315. const legendArr = ref([]);
  316. const organId = ref(null);
  317. const regionId = ref(null);
  318. const tabName = ref("");
  319. const tabId = ref(0);
  320. eventBus.off("changePointLegend", toggleLegend);
  321. eventBus.on("changePointLegend", toggleLegend);
  322. function toggleLegend({ colorObj }) {
  323. legendArr.value = colorObj?.list;
  324. }
  325. //选项卡事件监听
  326. const handleTab = async ({ name, id, isUpdate, params, legend, colorObj }) => {
  327. eventBus.emit("changePointType", { legend, colorObj });
  328. legendArr.value = colorObj?.list;
  329. console.log("name, id, isUpdate, params", name, id, isUpdate, params, legend, colorObj);
  330. tabName.value = name;
  331. tabId.value = id;
  332. if (id === 0) {
  333. getBlueRegionList(() => {
  334. if (isUpdate) {
  335. handleTabItem(params);
  336. }
  337. });
  338. } else {
  339. getFarmIndexReport(() => {
  340. if (isUpdate) {
  341. handleTabItem(params);
  342. }
  343. });
  344. }
  345. // 切换点位数据
  346. // samplePointLayer.changePointType(name, params)
  347. };
  348. //区域切换监听事件
  349. function areaId({ areaId, farmId }) {
  350. organId.value = farmId;
  351. regionId.value = areaId;
  352. samplePointLayer.initData(farmId, areaId);
  353. if (tabId.value === 0) {
  354. getBlueRegionList();
  355. } else {
  356. getFarmIndexReport();
  357. }
  358. }
  359. //选项卡子项事件监听
  360. const handleTabItem = (e) => {
  361. // if (reportData.value.blueZoneList) {
  362. // const index = reportData.value.blueZoneList.findIndex((item) => item.key === e);
  363. // let arr = [];
  364. // if (reportData.value.blueZoneList.length) {
  365. // arr = blueListConvert(reportData.value.blueZoneList[index].obj, index);
  366. // }
  367. // blueRegionLayer.initData(arr, "87");
  368. // }
  369. };
  370. const getFarmIndexReport = (callback) => {
  371. // const params = { farmId:organId.value,regionId:regionId.value, type: tabName.value };
  372. // VE_API.farm.farmIndexReport(params).then(({data,code}) => {
  373. // if (code === 0) {
  374. // reportData.value = data || {};
  375. // let arr = []
  376. // if(data.blueZoneList.length){
  377. // arr = blueListConvert(data.blueZoneList[0].obj,0)
  378. // }
  379. // blueRegionLayer.initData(arr,'87')
  380. // callback && callback()
  381. // }
  382. // });
  383. };
  384. const indicatorChartData = ref({});
  385. const blueZone = ref("ws0y1meyhxp4");
  386. const getFarmLog = () => {
  387. console.log("getfarmlog");
  388. const params = {
  389. id: null,
  390. farmId: 766,
  391. blueZone: blueZone.value,
  392. };
  393. VE_API.warning.fetchFarmLog(params).then(({ data }) => {
  394. indicatorChartData.value = data || {};
  395. eventBus.emit("chart:updateOption", data);
  396. });
  397. };
  398. const urls = ref([]);
  399. const urlsIndex = ref(0);
  400. const getYellow = () => {
  401. VE_API.home.getYellowList().then((res) => {
  402. // urls.value = res.data.map(item =>{
  403. // return {
  404. // ...item,
  405. // imgPath:config.base_img_url2+item.cloudFilename
  406. // }
  407. // })
  408. // urls.value = [
  409. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-07.jpg",
  410. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-08.jpg",
  411. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-09.jpg",
  412. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-10.jpg",
  413. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-11.jpg",
  414. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-12.jpg",
  415. // "@/assets/images/home/HB-ws0y1menggxv/HB-ws0y1menggxv2025-01-13.jpg",
  416. // ]
  417. });
  418. };
  419. const btnIndex = ref(null);
  420. const btnName = ref("");
  421. const handleBtn = (e) => {
  422. btnName.value = "";
  423. btnIndex.value = e;
  424. eventBus.emit("clear:area");
  425. samplePointLayer.updateAreaStatus(e === 0 ? true : false);
  426. regionLayer.resetData();
  427. samplePointLayer.resetPoint();
  428. };
  429. //点击果园日志
  430. const handleSelectArea = () => {
  431. btnName.value = "";
  432. btnIndex.value = null;
  433. eventBus.emit("clear:area");
  434. regionLayer.resetData();
  435. samplePointLayer.resetPoint();
  436. samplePointLayer.updateAreaStatus(true);
  437. };
  438. //农事点击高亮
  439. const act = ref(null);
  440. const handleAct = (v) => {
  441. act.value = v;
  442. samplePointLayer.resetPoint();
  443. if (v === 1) {
  444. regionLayer.selectAreaMultiple([
  445. { value: 2, color: "blue" },
  446. { value: 4, color: "blue1" },
  447. { value: 5, color: "blue2" },
  448. { value: 7, color: "blue" },
  449. { value: 13, color: "blue2" },
  450. ]);
  451. }
  452. if (v === 2) {
  453. regionLayer.selectAreaMultiple([
  454. { value: 1, color: "blue" },
  455. { value: 2, color: "blue1" },
  456. { value: 9, color: "blue2" },
  457. { value: 12, color: "blue2" },
  458. ]);
  459. }
  460. };
  461. //柱状图点击事件监听
  462. eventBus.on("echart:barClick", (e) => {
  463. btnName.value = "";
  464. btnIndex.value = null;
  465. eventBus.emit("clear:area");
  466. samplePointLayer.updateAreaStatus(false);
  467. const arr = ["花穗伸长", "啃食虫害", "毛毡病"];
  468. const isDraw = arr.includes(e);
  469. const index = arr.indexOf(e);
  470. if (isDraw) {
  471. if (index === 0) {
  472. regionLayer.selectAreaMultiple([
  473. { value: 0, color: "green" },
  474. { value: 1, color: "green" },
  475. { value: 2, color: "green" },
  476. { value: 3, color: "green1" },
  477. { value: 4, color: "green1" },
  478. { value: 5, color: "green2" },
  479. { value: 6, color: "green1" },
  480. { value: 7, color: "green2" },
  481. { value: 8, color: "green2" },
  482. { value: 9, color: "green" },
  483. { value: 10, color: "green" },
  484. { value: 11, color: "green1" },
  485. { value: 12, color: "green2" },
  486. { value: 13, color: "green" },
  487. { value: 14, color: "green2" },
  488. ]);
  489. } else if (index === 1) {
  490. regionLayer.selectAreaMultiple([{ value: 6, color: "red" }]);
  491. } else {
  492. regionLayer.selectAreaMultiple([
  493. { value: 12, color: "red2" },
  494. { value: 10, color: "red" },
  495. { value: 1, color: "red" },
  496. ]);
  497. }
  498. }
  499. });
  500. //黄板点击事件监听
  501. eventBus.on("click:yellowBlock", (e) => {
  502. const arr = ["113.61396985128522", "113.61390710255375", "113.61491218688275"];
  503. if (arr[0] == e) {
  504. urls.value = ["HB-ws0y1menggxv"];
  505. urlsIndex.value = 0;
  506. }
  507. if (arr[1] == e) {
  508. urls.value = ["HB-ws0y1mg0pvd"];
  509. urlsIndex.value = 3;
  510. }
  511. if (arr[2] == e) {
  512. urls.value = ["HB-ws0y1mg9wpcp"];
  513. urlsIndex.value = 6;
  514. }
  515. eventBus.emit("dialog:show", true);
  516. });
  517. const showPoint = ref(true);
  518. const showType = ref("point");
  519. eventBus.on("click:updateArea", (e) => {
  520. blueZone.value = e.value;
  521. btnName.value = e.name;
  522. regionLayer.selectArea(e.name * 1 === 0 ? 0 : e.name * 1 - 1, "blue");
  523. //getFarmLog()
  524. });
  525. const currentComponent = ref("leftFly");
  526. const handleActiveLeft = (e) => {
  527. currentComponent.value = e.componentName;
  528. };
  529. const leftToolList = [
  530. [
  531. {
  532. title: "飞巡感知",
  533. componentName: "leftFly",
  534. },
  535. {
  536. title: "气象感知",
  537. componentName: "leftWeather",
  538. },
  539. {
  540. title: "人工感知",
  541. componentName: "phenologyPage",
  542. },
  543. {
  544. title: "站点感知",
  545. componentName: "leftStation",
  546. },
  547. ],
  548. [
  549. {
  550. title: "首页",
  551. name: "home",
  552. componentName: "homePage",
  553. },
  554. {
  555. title: "气象预警",
  556. componentName: "weatherPage",
  557. },
  558. {
  559. title: "物候调节",
  560. componentName: "phenologyPage",
  561. },
  562. {
  563. title: "病虫指标",
  564. componentName: "leftDiseases"
  565. },
  566. {
  567. title: "营养评估",
  568. componentName: "leftNutrition"
  569. },
  570. ],
  571. ];
  572. const rightIndex = ref(0);
  573. // const handleActiveRight = ({ index }) => {
  574. // rightIndex.value = index;
  575. // btnIndex.value = null;
  576. // btnName.value = "";
  577. // samplePointLayer.updateAreaStatus(false);
  578. // if (index !== 0) {
  579. // act.value = null;
  580. // }
  581. // };
  582. const currentRightComponent = ref("recordList");
  583. const handleActiveRight = (e) => {
  584. currentRightComponent.value = e.componentName;
  585. };
  586. function convertPointsToArray(data) {
  587. return data.map((item) => {
  588. // 提取POINT字符串中的坐标部分
  589. const coords = item.point.match(/POINT\(([^)]+)\)/)[1];
  590. // 将坐标拆分为经度和纬度,并转换为数字
  591. const [lng, lat] = coords.split(" ").map(Number);
  592. return [lng, lat];
  593. });
  594. }
  595. //添加航线回调
  596. const airLineCallback = (data) => {
  597. console.log("data", data);
  598. if (data?.id) {
  599. // VE_API.home.waylinePoint({droneId:data.id}).then(res =>{
  600. // const arr = convertPointsToArray(res.data)
  601. // airLineStringLayer.initData(arr,data.geom,data.code)
  602. // })
  603. const res = [
  604. {
  605. id: "13",
  606. droneId: "2",
  607. point: "POINT(110.603131056 21.36505974)",
  608. },
  609. {
  610. id: "14",
  611. droneId: "2",
  612. point: "POINT(110.599708557 21.36655847)",
  613. },
  614. {
  615. id: "15",
  616. droneId: "2",
  617. point: "POINT(110.600641966 21.36925613)",
  618. },
  619. {
  620. id: "16",
  621. droneId: "2",
  622. point: "POINT(110.59876442 21.36856673)",
  623. },
  624. {
  625. id: "17",
  626. droneId: "2",
  627. point: "POINT(110.596886873 21.37040512)",
  628. },
  629. ];
  630. const arr = convertPointsToArray(res);
  631. airLineStringLayer.initData(arr, data.geom, data.code);
  632. } else {
  633. airLineStringLayer.clearLayer();
  634. }
  635. };
  636. const isEditLine = ref(false)
  637. function startEditLine() {
  638. isEditLine.value = true
  639. // 监听选中要素变化
  640. airLineStringLayer.selectInteraction.on('select', (event) => {
  641. console.log('event.selected.length', event.selected.length);
  642. });
  643. airLineStringLayer.enterEditMode();
  644. }
  645. function deleteLine() {
  646. airLineStringLayer.deleteSelectedPoints();
  647. }
  648. const rightToolList = [
  649. [
  650. {
  651. title: "农事列表",
  652. componentName: "recordList",
  653. index: 0,
  654. },
  655. {
  656. title: "认证评估",
  657. componentName: "leftFly",
  658. index: 1,
  659. },
  660. ],
  661. [
  662. {
  663. title: "无人机",
  664. componentName: "rightAerial",
  665. index: 2,
  666. },
  667. {
  668. title: "农机设备",
  669. componentName: "leftFly",
  670. index: 2,
  671. },
  672. {
  673. title: "人工巡园",
  674. componentName: "leftFly",
  675. index: 2,
  676. },
  677. ],
  678. ];
  679. // 跳转果园档案
  680. const toFilePage = () => {
  681. router.push("/garden-file");
  682. };
  683. // 地图图例
  684. const showMapLegend = ref(true);
  685. const handleLegend = (e) => {
  686. blueRegionLayer.toggleLayer(e);
  687. };
  688. // 对比
  689. const compareData = ref([]);
  690. const showCompareBtn = ref(false);
  691. function toggleCompare(arr) {
  692. // eventBus.emit("clickToCompare:point",{farmId:fs.get("farmId"),sampleId:fs.get("sampleId"), data: fs.getProperties()})
  693. compareData.value = [];
  694. arr.map((fs) => {
  695. compareData.value.push({ farmId: fs.get("farmId"), sampleId: fs.get("id"), data: fs.getProperties() });
  696. });
  697. console.log("compareData", compareData.value);
  698. showCompareBtn.value = compareData.value.length > 1 ? true : false;
  699. }
  700. function showCompare() {
  701. eventBus.emit("showCompareDialog", compareData.value);
  702. }
  703. const isShrink = ref(false);
  704. const isLeftShrink = ref(false);
  705. const isRightShrink = ref(false);
  706. const handleShrink = (position) => {
  707. switch (position) {
  708. case "bottom":
  709. isShrink.value = !isShrink.value;
  710. break;
  711. case "left":
  712. isLeftShrink.value = !isLeftShrink.value;
  713. break;
  714. case "right":
  715. isRightShrink.value = !isRightShrink.value;
  716. break;
  717. }
  718. };
  719. const photoList = ref([
  720. { key: "病虫", statement: "病虫 2025年02月19日,发现毛毡病异常1级" },
  721. { key: "异常", statement: "2025年03月17日,发现花量大异常3级" },
  722. { key: "营养", statement: "无营养异常" },
  723. ]);
  724. </script>
  725. <style lang="scss" scoped>
  726. .base-container {
  727. width: 100%;
  728. height: 100vh;
  729. color: #fff;
  730. position: absolute;
  731. box-sizing: border-box;
  732. z-index: 1;
  733. .content {
  734. width: 100%;
  735. height: calc(100% - 74px - 48px - 54px);
  736. display: flex;
  737. justify-content: space-between;
  738. box-sizing: border-box;
  739. margin-top: 60px;
  740. .home-btn {
  741. position: absolute;
  742. top: -60px;
  743. left: 0;
  744. height: 54px;
  745. display: flex;
  746. border: 1px solid #444444;
  747. background: #101010;
  748. border-radius: 0 8px 8px 0;
  749. padding: 8px;
  750. box-sizing: border-box;
  751. width: 429px;
  752. .btn {
  753. flex: 1;
  754. background: rgba(79, 79, 79, 0.6);
  755. border-radius: 4px;
  756. font-size: 20px;
  757. font-family: "PangMenZhengDao";
  758. color: #fff;
  759. text-align: center;
  760. height: 38px;
  761. line-height: 38px;
  762. cursor: pointer;
  763. &.active {
  764. background: linear-gradient(180deg, #ffd887, #ed9e1e);
  765. color: #1d1d1d;
  766. }
  767. }
  768. .btn + .btn {
  769. margin-left: 8px;
  770. }
  771. }
  772. .left,
  773. .right {
  774. width: calc(376px + 54px);
  775. height: 100%;
  776. margin-top: 10px;
  777. box-sizing: border-box;
  778. display: flex;
  779. position: relative;
  780. transition: transform 0.3s;
  781. }
  782. .collapsed-left {
  783. transform: translateX(-430px);
  784. }
  785. .collapsed-right {
  786. transform: translateX(440px);
  787. }
  788. .arrow-left {
  789. transform: rotate(180deg);
  790. }
  791. .arrow-right {
  792. transform: rotate(-180deg);
  793. }
  794. .left,.right {
  795. background: #101010;
  796. border-radius: 4px;
  797. border: 1px solid #444444;
  798. .arrow {
  799. position: absolute;
  800. right: -16px;
  801. top: calc(50% - 40px);
  802. background: #fff;
  803. width: 16px;
  804. height: 80px;
  805. line-height: 80px;
  806. border-radius: 0 5px 5px 0;
  807. text-align: center;
  808. cursor: pointer;
  809. transition: transform 0.3s;
  810. }
  811. }
  812. .right {
  813. width: calc(376px + 54px + 10px);
  814. .album-r {
  815. .list-wrap {
  816. width: 375px;
  817. }
  818. }
  819. .list {
  820. width: 100%;
  821. height: 100%;
  822. .btn-wrap {
  823. width: 100%;
  824. height: 25px;
  825. line-height: 25px;
  826. margin: 10px 0;
  827. display: flex;
  828. align-items: center;
  829. justify-content: space-between;
  830. div {
  831. width: 48%;
  832. height: 100%;
  833. color: #ffd489;
  834. border: 1px solid rgba(255, 213, 137, 0.6);
  835. border-radius: 2px;
  836. text-align: center;
  837. font-size: 12px;
  838. cursor: pointer;
  839. &.active {
  840. background: #ffd489;
  841. color: #000;
  842. }
  843. }
  844. }
  845. .img-box {
  846. width: 100%;
  847. height: calc(100% - 35px);
  848. overflow: auto;
  849. }
  850. .img-box1 {
  851. width: 100%;
  852. height: calc(100% - 10px);
  853. overflow: auto;
  854. margin-top: 10px;
  855. }
  856. .img-box2 {
  857. width: 100%;
  858. height: calc(100% - 45px);
  859. overflow: auto;
  860. margin-top: 10px;
  861. }
  862. img {
  863. width: 100%;
  864. height: auto;
  865. object-fit: cover;
  866. margin-bottom: 12px;
  867. cursor: pointer;
  868. }
  869. .mt {
  870. margin-top: -12px;
  871. }
  872. .list-wrap {
  873. ::v-deep {
  874. .chart-content {
  875. padding: 16px 0 0 0;
  876. }
  877. }
  878. }
  879. }
  880. .arrow{
  881. left: -16px;
  882. transform: rotate(180deg);
  883. }
  884. }
  885. .overflow {
  886. overflow: auto;
  887. }
  888. .home-bottom {
  889. display: flex;
  890. align-items: flex-end;
  891. width: calc(100% - 20px - 430px * 2);
  892. height: 300px;
  893. align-self: flex-end;
  894. justify-content: center;
  895. z-index: 100;
  896. .img {
  897. width: 268px;
  898. height: 66px;
  899. cursor: pointer;
  900. }
  901. .time-wrap {
  902. height: 85px;
  903. }
  904. .fly-icon {
  905. width: 148px;
  906. height: 100%;
  907. margin-left: 27px;
  908. }
  909. .log-box {
  910. height: 34%;
  911. width: calc(100% - 340px - 28px);
  912. margin-right: 28px;
  913. .box-name {
  914. width: 89px;
  915. height: 22px;
  916. text-align: center;
  917. line-height: 22px;
  918. border-radius: 20px;
  919. margin: 10px 0 5px 6px;
  920. cursor: pointer;
  921. background: linear-gradient(0deg, #bba269 0%, #3d3523 100%);
  922. }
  923. .log-content {
  924. font-size: 12px;
  925. line-height: 1.5;
  926. padding: 0 18px;
  927. }
  928. .chart-wrap {
  929. width: 100%;
  930. height: calc(100% - 50px);
  931. .line {
  932. margin-top: 10px;
  933. margin-bottom: 12px;
  934. }
  935. img {
  936. width: 100%;
  937. margin-bottom: 10px;
  938. }
  939. }
  940. }
  941. .garden-file {
  942. position: relative;
  943. top: 10px;
  944. // height: 30%;
  945. // min-height: 210px;
  946. // width: 640px;
  947. transition: all 0.3s;
  948. // width: 800px;
  949. // height: 320px;
  950. width: 100vw;
  951. height: 100vh;
  952. overflow: hidden;
  953. &.isShrink {
  954. height: 66px;
  955. width: 450px;
  956. overflow: hidden;
  957. .arrow {
  958. .icon {
  959. transform: rotate(90deg);
  960. }
  961. }
  962. }
  963. .arrow {
  964. position: absolute;
  965. right: 56px;
  966. top: 36px;
  967. background: #fff;
  968. height: 16px;
  969. width: 80px;
  970. line-height: 16px;
  971. border-radius: 0 0 5px 5px;
  972. text-align: center;
  973. cursor: pointer;
  974. .icon {
  975. transform: rotate(270deg);
  976. }
  977. }
  978. }
  979. .file-box {
  980. height: 25%;
  981. min-height: 210px;
  982. width: 340px;
  983. position: relative;
  984. img {
  985. width: 100%;
  986. margin-top: 12px;
  987. }
  988. .arrow-icon {
  989. top: -32px;
  990. left: 50%;
  991. position: absolute;
  992. background: #fff;
  993. width: 16px;
  994. height: 80px;
  995. line-height: 80px;
  996. border-radius: 5px 0 0 5px;
  997. text-align: center;
  998. transform: translateX(-50%) rotate(270deg);
  999. }
  1000. .edit-btn {
  1001. padding: 2px 24px;
  1002. background: #ffd489;
  1003. border-radius: 4px;
  1004. color: #000;
  1005. }
  1006. }
  1007. }
  1008. .legend {
  1009. position: fixed;
  1010. bottom: 8px;
  1011. right: 64px;
  1012. // width: 525px;
  1013. height: 20px;
  1014. }
  1015. .map-bg {
  1016. position: fixed;
  1017. z-index: 2;
  1018. background: rgba(35, 35, 35, 0.8);
  1019. border-radius: 18px;
  1020. padding: 7px 16px;
  1021. right: 460px;
  1022. }
  1023. .map-btn {
  1024. top: 19px;
  1025. cursor: pointer;
  1026. }
  1027. .map-legend {
  1028. bottom: 34px;
  1029. .item {
  1030. display: flex;
  1031. align-items: center;
  1032. font-size: 14px;
  1033. img {
  1034. width: 16px;
  1035. margin-right: 6px;
  1036. }
  1037. .legend-block {
  1038. width: 16px;
  1039. height: 16px;
  1040. box-sizing: border-box;
  1041. border-radius: 50%;
  1042. border: 2px solid #fff;
  1043. margin-right: 6px;
  1044. }
  1045. }
  1046. .legend-title {
  1047. border-bottom: 1px solid rgba(102, 102, 102, 0.35);
  1048. }
  1049. .item + .item {
  1050. padding-top: 10px;
  1051. }
  1052. }
  1053. }
  1054. }
  1055. .bottom-map {
  1056. width: 100%;
  1057. height: 100vh;
  1058. position: absolute;
  1059. z-index: 0;
  1060. }
  1061. .compare-start-btn {
  1062. position: absolute;
  1063. z-index: 2;
  1064. left: 50%;
  1065. transform: translateX(-50%);
  1066. cursor: pointer;
  1067. bottom: 106px;
  1068. // right: 445px;
  1069. img {
  1070. height: 55px;
  1071. }
  1072. }
  1073. </style>
  1074. <style lang="less">
  1075. .file-wrap {
  1076. &.map-file {
  1077. width: 367px;
  1078. position: relative;
  1079. background: url("@/assets/images/home/file-bg.png") no-repeat top center / 100% 100%;
  1080. margin-left: 12px;
  1081. padding: 12px;
  1082. .file-title {
  1083. font-size: 20px;
  1084. color: #ffd489;
  1085. .tag {
  1086. border: 1px solid #ffd489;
  1087. border-radius: 4px;
  1088. font-size: 12px;
  1089. display: inline-block;
  1090. width: 44px;
  1091. height: 20px;
  1092. text-align: center;
  1093. line-height: 18px;
  1094. margin-left: 8px;
  1095. padding: 1px 4px;
  1096. }
  1097. }
  1098. .overview-file {
  1099. padding-top: 20px;
  1100. .box-title {
  1101. font-size: 16px;
  1102. padding-left: 13px;
  1103. margin-bottom: 16px;
  1104. position: relative;
  1105. display: flex;
  1106. justify-content: space-between;
  1107. color: #fff;
  1108. &::before {
  1109. content: "";
  1110. position: absolute;
  1111. left: 0;
  1112. top: 3px;
  1113. width: 3px;
  1114. height: 16px;
  1115. background: #fff;
  1116. border-radius: 11px;
  1117. }
  1118. }
  1119. .title {
  1120. color: #f3c11d;
  1121. font-size: 16px;
  1122. font-family: "PangMenZhengDao";
  1123. margin-bottom: 20px;
  1124. .big {
  1125. width: 13px;
  1126. height: 13px;
  1127. margin: -10px 0 0 4px;
  1128. }
  1129. .small {
  1130. width: 7px;
  1131. height: 7px;
  1132. margin-left: -3px;
  1133. }
  1134. }
  1135. .base-data {
  1136. background: rgba(207, 207, 207, 0.1);
  1137. border-radius: 4px;
  1138. padding: 6px 0;
  1139. display: flex;
  1140. .base-item {
  1141. flex: 1;
  1142. text-align: center;
  1143. .label {
  1144. font-size: 12px;
  1145. color: #666666;
  1146. }
  1147. .value {
  1148. padding-top: 2px;
  1149. font-size: 16px;
  1150. color: #ffffff;
  1151. }
  1152. }
  1153. .base-item + .base-item {
  1154. border-left: 1px solid rgba(102, 102, 102, 0.42);
  1155. }
  1156. }
  1157. .list {
  1158. margin-top: 15px;
  1159. width: max-content;
  1160. font-size: 14px;
  1161. .list-item {
  1162. color: #bbbbbb;
  1163. display: flex;
  1164. margin-bottom: 8px;
  1165. .list-name {
  1166. color: #f3c11d;
  1167. margin-right: 6px;
  1168. img {
  1169. width: 17px;
  1170. height: 13px;
  1171. }
  1172. }
  1173. }
  1174. }
  1175. }
  1176. .overview-file + .overview-file {
  1177. margin-top: 8px;
  1178. }
  1179. .box-wrap {
  1180. display: flex;
  1181. .box-item {
  1182. // flex: 1;
  1183. min-width: 109px;
  1184. display: flex;
  1185. flex-direction: column;
  1186. justify-content: center;
  1187. align-items: center;
  1188. padding: 6px;
  1189. box-sizing: border-box;
  1190. background: rgba(207, 207, 207, 0.1);
  1191. border-radius: 4px;
  1192. border: 1px solid rgba(207, 207, 207, 0.1);
  1193. cursor: pointer;
  1194. .item-name {
  1195. font-size: 12px;
  1196. color: #666666;
  1197. width: max-content;
  1198. }
  1199. .item-val {
  1200. font-size: 18px;
  1201. color: #fff;
  1202. width: max-content;
  1203. padding-top: 3px;
  1204. }
  1205. &.active {
  1206. background: rgba(255, 212, 137, 0.16);
  1207. border: 1px solid #ffd489;
  1208. .item-name {
  1209. color: #bbbbbb;
  1210. }
  1211. }
  1212. }
  1213. .box-item + .box-item {
  1214. margin-left: 8px;
  1215. }
  1216. }
  1217. }
  1218. }
  1219. .farm-fight-task {
  1220. position: fixed;
  1221. top: 100px;
  1222. left: 25%;
  1223. z-index: 1000;
  1224. }
  1225. /* Space-time组件展开时的样式 */
  1226. ::v-deep .expanded {
  1227. position: fixed;
  1228. width: 96% !important;
  1229. margin: 0 auto;
  1230. }
  1231. </style>