index.vue 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  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" @updateLegend="updateLegend"></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. //区域切换监听事件
  240. eventBus.on("area:id", areaId);
  241. //选项卡子项事件监听
  242. // 是否开启指标对比
  243. eventBus.on("compareTree", handleCompare);
  244. eventBus.on("clickToCompare:point", toggleCompare);
  245. });
  246. onUnmounted(() => {
  247. eventBus.off("area:id", areaId);
  248. eventBus.off("compareTree", handleCompare);
  249. eventBus.off("clickToCompare:point", toggleCompare);
  250. });
  251. function handleCompare(v) {
  252. isShrink.value = v;
  253. if (v === false) {
  254. showCompareBtn.value = v;
  255. }
  256. }
  257. const showSpaceTime = ref(false);
  258. const handlePage = () => {
  259. showSpaceTime.value = true;
  260. // 收缩左右两边
  261. isLeftShrink.value = true;
  262. isRightShrink.value = true;
  263. };
  264. const handleSpaceTimeCollapse = () => {
  265. showSpaceTime.value = false;
  266. // 展开左右两边
  267. isLeftShrink.value = false;
  268. isRightShrink.value = false;
  269. };
  270. const blueList = ref([]);
  271. const getBlueRegionList = (callback) => {
  272. if (!organId.value) {
  273. return;
  274. }
  275. let selectAll = undefined;
  276. if (regionId.value === 0) {
  277. selectAll = 1;
  278. }
  279. const areaId = selectAll ? undefined : regionId.value;
  280. VE_API.farm.blueRegionList({ farmId: organId.value, regionId: areaId, selectAll }).then(({ data }) => {
  281. blueList.value = data.map((item) => {
  282. let color = "rgba(255, 255, 255, 0.5)"; //失效区域
  283. if (item.status === 2) {
  284. //物候期风险
  285. // color = "rgba(63, 255, 53, 0.5)";
  286. color = "#2BFE00";
  287. }
  288. if (item.status === 3) {
  289. //生长异常
  290. // color = "rgba(255, 252, 61, 0.5)";
  291. color = "#FF7410";
  292. }
  293. if (item.status === 4) {
  294. //病虫害
  295. // color = "rgba(255, 73, 73, 0.5)";
  296. color = "#F82121";
  297. }
  298. return {
  299. ...item,
  300. color,
  301. };
  302. });
  303. blueRegionLayer.initData(blueList.value);
  304. callback && callback();
  305. });
  306. };
  307. // 图例
  308. const legendArr = ref([]);
  309. const organId = ref(null);
  310. const regionId = ref(null);
  311. const tabName = ref("");
  312. const tabId = ref(0);
  313. function updateLegend(matchedData,parsedLegendConfig,isInit) {
  314. legendArr.value = parsedLegendConfig;
  315. // 将匹配的数据传递给samplePointLayer进行点位颜色更新
  316. if (samplePointLayer && matchedData && matchedData.length > 0) {
  317. if (isInit) {
  318. samplePointLayer.initData(organId.value, regionId.value,true,matchedData);
  319. }else{
  320. samplePointLayer.updatePointColors(matchedData);
  321. }
  322. }
  323. }
  324. //选项卡事件监听
  325. const handleTab = async ({ name, id, isUpdate, params, legend, colorObj }) => {
  326. tabName.value = name;
  327. tabId.value = id;
  328. // if (id === 0) {
  329. // getBlueRegionList(() => {
  330. // if (isUpdate) {
  331. // handleTabItem(params);
  332. // }
  333. // });
  334. // } else {
  335. // getFarmIndexReport(() => {
  336. // if (isUpdate) {
  337. // handleTabItem(params);
  338. // }
  339. // });
  340. // }
  341. // 切换点位数据
  342. // samplePointLayer.changePointType(name, params)
  343. };
  344. //区域切换监听事件
  345. function areaId({ areaId, farmId }) {
  346. organId.value = farmId;
  347. regionId.value = areaId;
  348. if (tabId.value === 0) {
  349. getBlueRegionList();
  350. }
  351. }
  352. const blueZone = ref("ws0y1meyhxp4");
  353. const urls = ref([]);
  354. const urlsIndex = ref(0);
  355. const btnIndex = ref(null);
  356. const btnName = ref("");
  357. //柱状图点击事件监听
  358. eventBus.on("echart:barClick", (e) => {
  359. btnName.value = "";
  360. btnIndex.value = null;
  361. eventBus.emit("clear:area");
  362. samplePointLayer.updateAreaStatus(false);
  363. const arr = ["花穗伸长", "啃食虫害", "毛毡病"];
  364. const isDraw = arr.includes(e);
  365. const index = arr.indexOf(e);
  366. if (isDraw) {
  367. if (index === 0) {
  368. regionLayer.selectAreaMultiple([
  369. { value: 0, color: "green" },
  370. { value: 1, color: "green" },
  371. { value: 2, color: "green" },
  372. { value: 3, color: "green1" },
  373. { value: 4, color: "green1" },
  374. { value: 5, color: "green2" },
  375. { value: 6, color: "green1" },
  376. { value: 7, color: "green2" },
  377. { value: 8, color: "green2" },
  378. { value: 9, color: "green" },
  379. { value: 10, color: "green" },
  380. { value: 11, color: "green1" },
  381. { value: 12, color: "green2" },
  382. { value: 13, color: "green" },
  383. { value: 14, color: "green2" },
  384. ]);
  385. } else if (index === 1) {
  386. regionLayer.selectAreaMultiple([{ value: 6, color: "red" }]);
  387. } else {
  388. regionLayer.selectAreaMultiple([
  389. { value: 12, color: "red2" },
  390. { value: 10, color: "red" },
  391. { value: 1, color: "red" },
  392. ]);
  393. }
  394. }
  395. });
  396. //黄板点击事件监听
  397. eventBus.on("click:yellowBlock", (e) => {
  398. const arr = ["113.61396985128522", "113.61390710255375", "113.61491218688275"];
  399. if (arr[0] == e) {
  400. urls.value = ["HB-ws0y1menggxv"];
  401. urlsIndex.value = 0;
  402. }
  403. if (arr[1] == e) {
  404. urls.value = ["HB-ws0y1mg0pvd"];
  405. urlsIndex.value = 3;
  406. }
  407. if (arr[2] == e) {
  408. urls.value = ["HB-ws0y1mg9wpcp"];
  409. urlsIndex.value = 6;
  410. }
  411. eventBus.emit("dialog:show", true);
  412. });
  413. eventBus.on("click:updateArea", (e) => {
  414. blueZone.value = e.value;
  415. btnName.value = e.name;
  416. regionLayer.selectArea(e.name * 1 === 0 ? 0 : e.name * 1 - 1, "blue");
  417. //getFarmLog()
  418. });
  419. const currentComponent = ref("leftFly");
  420. const handleActiveLeft = (e) => {
  421. currentComponent.value = e.componentName;
  422. };
  423. const leftToolList = [
  424. [
  425. {
  426. title: "飞巡感知",
  427. componentName: "leftFly",
  428. },
  429. {
  430. title: "气象感知",
  431. componentName: "leftWeather",
  432. },
  433. {
  434. title: "人工感知",
  435. componentName: "phenologyPage",
  436. },
  437. {
  438. title: "站点感知",
  439. componentName: "leftStation",
  440. },
  441. ],
  442. [
  443. {
  444. title: "首页",
  445. name: "home",
  446. componentName: "homePage",
  447. },
  448. {
  449. title: "气象预警",
  450. componentName: "weatherPage",
  451. },
  452. {
  453. title: "物候调节",
  454. componentName: "phenologyPage",
  455. },
  456. {
  457. title: "病虫指标",
  458. componentName: "leftDiseases"
  459. },
  460. {
  461. title: "营养评估",
  462. componentName: "leftNutrition"
  463. },
  464. ],
  465. ];
  466. const rightIndex = ref(0);
  467. // const handleActiveRight = ({ index }) => {
  468. // rightIndex.value = index;
  469. // btnIndex.value = null;
  470. // btnName.value = "";
  471. // samplePointLayer.updateAreaStatus(false);
  472. // if (index !== 0) {
  473. // act.value = null;
  474. // }
  475. // };
  476. const currentRightComponent = ref("recordList");
  477. const handleActiveRight = (e) => {
  478. currentRightComponent.value = e.componentName;
  479. };
  480. function convertPointsToArray(data) {
  481. return data.map((item) => {
  482. // 提取POINT字符串中的坐标部分
  483. const coords = item.point.match(/POINT\(([^)]+)\)/)[1];
  484. // 将坐标拆分为经度和纬度,并转换为数字
  485. const [lng, lat] = coords.split(" ").map(Number);
  486. return [lng, lat];
  487. });
  488. }
  489. //添加航线回调
  490. const airLineCallback = (data) => {
  491. console.log("data", data);
  492. if (data?.id) {
  493. // VE_API.home.waylinePoint({droneId:data.id}).then(res =>{
  494. // const arr = convertPointsToArray(res.data)
  495. // airLineStringLayer.initData(arr,data.geom,data.code)
  496. // })
  497. const res = [
  498. {
  499. id: "13",
  500. droneId: "2",
  501. point: "POINT(110.603131056 21.36505974)",
  502. },
  503. {
  504. id: "14",
  505. droneId: "2",
  506. point: "POINT(110.599708557 21.36655847)",
  507. },
  508. {
  509. id: "15",
  510. droneId: "2",
  511. point: "POINT(110.600641966 21.36925613)",
  512. },
  513. {
  514. id: "16",
  515. droneId: "2",
  516. point: "POINT(110.59876442 21.36856673)",
  517. },
  518. {
  519. id: "17",
  520. droneId: "2",
  521. point: "POINT(110.596886873 21.37040512)",
  522. },
  523. ];
  524. const arr = convertPointsToArray(res);
  525. airLineStringLayer.initData(arr, data.geom, data.code);
  526. } else {
  527. airLineStringLayer.clearLayer();
  528. }
  529. };
  530. const isEditLine = ref(false)
  531. function startEditLine() {
  532. isEditLine.value = true
  533. // 监听选中要素变化
  534. airLineStringLayer.selectInteraction.on('select', (event) => {
  535. console.log('event.selected.length', event.selected.length);
  536. });
  537. airLineStringLayer.enterEditMode();
  538. }
  539. function deleteLine() {
  540. airLineStringLayer.deleteSelectedPoints();
  541. }
  542. const rightToolList = [
  543. [
  544. {
  545. title: "农事列表",
  546. componentName: "recordList",
  547. index: 0,
  548. },
  549. {
  550. title: "认证评估",
  551. componentName: "leftFly",
  552. index: 1,
  553. },
  554. ],
  555. [
  556. {
  557. title: "无人机",
  558. componentName: "rightAerial",
  559. index: 2,
  560. },
  561. {
  562. title: "农机设备",
  563. componentName: "leftFly",
  564. index: 2,
  565. },
  566. {
  567. title: "人工巡园",
  568. componentName: "leftFly",
  569. index: 2,
  570. },
  571. ],
  572. ];
  573. // 对比
  574. const compareData = ref([]);
  575. const showCompareBtn = ref(false);
  576. function toggleCompare(arr) {
  577. // eventBus.emit("clickToCompare:point",{farmId:fs.get("farmId"),sampleId:fs.get("sampleId"), data: fs.getProperties()})
  578. compareData.value = [];
  579. arr.map((fs) => {
  580. compareData.value.push({ farmId: fs.get("farmId"), sampleId: fs.get("id"), data: fs.getProperties() });
  581. });
  582. console.log("compareData", compareData.value);
  583. showCompareBtn.value = compareData.value.length > 1 ? true : false;
  584. }
  585. function showCompare() {
  586. eventBus.emit("showCompareDialog", compareData.value);
  587. }
  588. const isShrink = ref(false);
  589. const isLeftShrink = ref(false);
  590. const isRightShrink = ref(false);
  591. const handleShrink = (position) => {
  592. switch (position) {
  593. case "bottom":
  594. isShrink.value = !isShrink.value;
  595. break;
  596. case "left":
  597. isLeftShrink.value = !isLeftShrink.value;
  598. break;
  599. case "right":
  600. isRightShrink.value = !isRightShrink.value;
  601. break;
  602. }
  603. };
  604. const photoList = ref([
  605. { key: "病虫", statement: "病虫 2025年02月19日,发现毛毡病异常1级" },
  606. { key: "异常", statement: "2025年03月17日,发现花量大异常3级" },
  607. { key: "营养", statement: "无营养异常" },
  608. ]);
  609. </script>
  610. <style lang="scss" scoped>
  611. .base-container {
  612. width: 100%;
  613. height: 100vh;
  614. color: #fff;
  615. position: absolute;
  616. box-sizing: border-box;
  617. z-index: 1;
  618. .content {
  619. width: 100%;
  620. height: calc(100% - 74px - 48px - 54px);
  621. display: flex;
  622. justify-content: space-between;
  623. box-sizing: border-box;
  624. margin-top: 60px;
  625. .home-btn {
  626. position: absolute;
  627. top: -60px;
  628. left: 0;
  629. height: 54px;
  630. display: flex;
  631. border: 1px solid #444444;
  632. background: #101010;
  633. border-radius: 0 8px 8px 0;
  634. padding: 8px;
  635. box-sizing: border-box;
  636. width: 429px;
  637. .btn {
  638. flex: 1;
  639. background: rgba(79, 79, 79, 0.6);
  640. border-radius: 4px;
  641. font-size: 20px;
  642. font-family: "PangMenZhengDao";
  643. color: #fff;
  644. text-align: center;
  645. height: 38px;
  646. line-height: 38px;
  647. cursor: pointer;
  648. &.active {
  649. background: linear-gradient(180deg, #ffd887, #ed9e1e);
  650. color: #1d1d1d;
  651. }
  652. }
  653. .btn + .btn {
  654. margin-left: 8px;
  655. }
  656. }
  657. .left,
  658. .right {
  659. width: calc(376px + 54px);
  660. height: 100%;
  661. margin-top: 10px;
  662. box-sizing: border-box;
  663. display: flex;
  664. position: relative;
  665. transition: transform 0.3s;
  666. }
  667. .collapsed-left {
  668. transform: translateX(-430px);
  669. }
  670. .collapsed-right {
  671. transform: translateX(440px);
  672. }
  673. .arrow-left {
  674. transform: rotate(180deg);
  675. }
  676. .arrow-right {
  677. transform: rotate(-180deg);
  678. }
  679. .left,.right {
  680. background: #101010;
  681. border-radius: 4px;
  682. border: 1px solid #444444;
  683. .arrow {
  684. position: absolute;
  685. right: -16px;
  686. top: calc(50% - 40px);
  687. background: #fff;
  688. width: 16px;
  689. height: 80px;
  690. line-height: 80px;
  691. border-radius: 0 5px 5px 0;
  692. text-align: center;
  693. cursor: pointer;
  694. transition: transform 0.3s;
  695. }
  696. }
  697. .right {
  698. width: calc(376px + 54px + 10px);
  699. .album-r {
  700. .list-wrap {
  701. width: 375px;
  702. }
  703. }
  704. .list {
  705. width: 100%;
  706. height: 100%;
  707. .btn-wrap {
  708. width: 100%;
  709. height: 25px;
  710. line-height: 25px;
  711. margin: 10px 0;
  712. display: flex;
  713. align-items: center;
  714. justify-content: space-between;
  715. div {
  716. width: 48%;
  717. height: 100%;
  718. color: #ffd489;
  719. border: 1px solid rgba(255, 213, 137, 0.6);
  720. border-radius: 2px;
  721. text-align: center;
  722. font-size: 12px;
  723. cursor: pointer;
  724. &.active {
  725. background: #ffd489;
  726. color: #000;
  727. }
  728. }
  729. }
  730. .img-box {
  731. width: 100%;
  732. height: calc(100% - 35px);
  733. overflow: auto;
  734. }
  735. .img-box1 {
  736. width: 100%;
  737. height: calc(100% - 10px);
  738. overflow: auto;
  739. margin-top: 10px;
  740. }
  741. .img-box2 {
  742. width: 100%;
  743. height: calc(100% - 45px);
  744. overflow: auto;
  745. margin-top: 10px;
  746. }
  747. img {
  748. width: 100%;
  749. height: auto;
  750. object-fit: cover;
  751. margin-bottom: 12px;
  752. cursor: pointer;
  753. }
  754. .mt {
  755. margin-top: -12px;
  756. }
  757. .list-wrap {
  758. ::v-deep {
  759. .chart-content {
  760. padding: 16px 0 0 0;
  761. }
  762. }
  763. }
  764. }
  765. .arrow{
  766. left: -16px;
  767. transform: rotate(180deg);
  768. }
  769. }
  770. .overflow {
  771. overflow: auto;
  772. }
  773. .home-bottom {
  774. display: flex;
  775. align-items: flex-end;
  776. width: calc(100% - 20px - 430px * 2);
  777. height: 300px;
  778. align-self: flex-end;
  779. justify-content: center;
  780. z-index: 100;
  781. .img {
  782. width: 268px;
  783. height: 66px;
  784. cursor: pointer;
  785. }
  786. .time-wrap {
  787. height: 85px;
  788. }
  789. .fly-icon {
  790. width: 148px;
  791. height: 100%;
  792. margin-left: 27px;
  793. }
  794. .log-box {
  795. height: 34%;
  796. width: calc(100% - 340px - 28px);
  797. margin-right: 28px;
  798. .box-name {
  799. width: 89px;
  800. height: 22px;
  801. text-align: center;
  802. line-height: 22px;
  803. border-radius: 20px;
  804. margin: 10px 0 5px 6px;
  805. cursor: pointer;
  806. background: linear-gradient(0deg, #bba269 0%, #3d3523 100%);
  807. }
  808. .log-content {
  809. font-size: 12px;
  810. line-height: 1.5;
  811. padding: 0 18px;
  812. }
  813. .chart-wrap {
  814. width: 100%;
  815. height: calc(100% - 50px);
  816. .line {
  817. margin-top: 10px;
  818. margin-bottom: 12px;
  819. }
  820. img {
  821. width: 100%;
  822. margin-bottom: 10px;
  823. }
  824. }
  825. }
  826. .garden-file {
  827. position: relative;
  828. top: 10px;
  829. // height: 30%;
  830. // min-height: 210px;
  831. // width: 640px;
  832. transition: all 0.3s;
  833. // width: 800px;
  834. // height: 320px;
  835. width: 100vw;
  836. height: 100vh;
  837. overflow: hidden;
  838. &.isShrink {
  839. height: 66px;
  840. width: 450px;
  841. overflow: hidden;
  842. .arrow {
  843. .icon {
  844. transform: rotate(90deg);
  845. }
  846. }
  847. }
  848. .arrow {
  849. position: absolute;
  850. right: 56px;
  851. top: 36px;
  852. background: #fff;
  853. height: 16px;
  854. width: 80px;
  855. line-height: 16px;
  856. border-radius: 0 0 5px 5px;
  857. text-align: center;
  858. cursor: pointer;
  859. .icon {
  860. transform: rotate(270deg);
  861. }
  862. }
  863. }
  864. .file-box {
  865. height: 25%;
  866. min-height: 210px;
  867. width: 340px;
  868. position: relative;
  869. img {
  870. width: 100%;
  871. margin-top: 12px;
  872. }
  873. .arrow-icon {
  874. top: -32px;
  875. left: 50%;
  876. position: absolute;
  877. background: #fff;
  878. width: 16px;
  879. height: 80px;
  880. line-height: 80px;
  881. border-radius: 5px 0 0 5px;
  882. text-align: center;
  883. transform: translateX(-50%) rotate(270deg);
  884. }
  885. .edit-btn {
  886. padding: 2px 24px;
  887. background: #ffd489;
  888. border-radius: 4px;
  889. color: #000;
  890. }
  891. }
  892. }
  893. .legend {
  894. position: fixed;
  895. bottom: 8px;
  896. right: 64px;
  897. // width: 525px;
  898. height: 20px;
  899. }
  900. .map-bg {
  901. position: fixed;
  902. z-index: 2;
  903. background: rgba(35, 35, 35, 0.8);
  904. border-radius: 18px;
  905. padding: 7px 16px;
  906. right: 460px;
  907. }
  908. .map-btn {
  909. top: 19px;
  910. cursor: pointer;
  911. }
  912. .map-legend {
  913. bottom: 34px;
  914. .item {
  915. display: flex;
  916. align-items: center;
  917. font-size: 14px;
  918. img {
  919. width: 16px;
  920. margin-right: 6px;
  921. }
  922. .legend-block {
  923. width: 16px;
  924. height: 16px;
  925. box-sizing: border-box;
  926. border-radius: 50%;
  927. border: 2px solid #fff;
  928. margin-right: 6px;
  929. }
  930. }
  931. .legend-title {
  932. border-bottom: 1px solid rgba(102, 102, 102, 0.35);
  933. }
  934. .item + .item {
  935. padding-top: 10px;
  936. }
  937. }
  938. }
  939. }
  940. .bottom-map {
  941. width: 100%;
  942. height: 100vh;
  943. position: absolute;
  944. z-index: 0;
  945. }
  946. .compare-start-btn {
  947. position: absolute;
  948. z-index: 2;
  949. left: 50%;
  950. transform: translateX(-50%);
  951. cursor: pointer;
  952. bottom: 126px;
  953. // right: 445px;
  954. img {
  955. height: 55px;
  956. }
  957. }
  958. </style>
  959. <style lang="less">
  960. .file-wrap {
  961. &.map-file {
  962. width: 367px;
  963. position: relative;
  964. background: url("@/assets/images/home/file-bg.png") no-repeat top center / 100% 100%;
  965. margin-left: 12px;
  966. padding: 12px;
  967. .file-title {
  968. font-size: 20px;
  969. color: #ffd489;
  970. .tag {
  971. border: 1px solid #ffd489;
  972. border-radius: 4px;
  973. font-size: 12px;
  974. display: inline-block;
  975. width: 44px;
  976. height: 20px;
  977. text-align: center;
  978. line-height: 18px;
  979. margin-left: 8px;
  980. padding: 1px 4px;
  981. }
  982. }
  983. .overview-file {
  984. padding-top: 20px;
  985. .box-title {
  986. font-size: 16px;
  987. padding-left: 13px;
  988. margin-bottom: 16px;
  989. position: relative;
  990. display: flex;
  991. justify-content: space-between;
  992. color: #fff;
  993. &::before {
  994. content: "";
  995. position: absolute;
  996. left: 0;
  997. top: 3px;
  998. width: 3px;
  999. height: 16px;
  1000. background: #fff;
  1001. border-radius: 11px;
  1002. }
  1003. }
  1004. .title {
  1005. color: #f3c11d;
  1006. font-size: 16px;
  1007. font-family: "PangMenZhengDao";
  1008. margin-bottom: 20px;
  1009. .big {
  1010. width: 13px;
  1011. height: 13px;
  1012. margin: -10px 0 0 4px;
  1013. }
  1014. .small {
  1015. width: 7px;
  1016. height: 7px;
  1017. margin-left: -3px;
  1018. }
  1019. }
  1020. .base-data {
  1021. background: rgba(207, 207, 207, 0.1);
  1022. border-radius: 4px;
  1023. padding: 6px 0;
  1024. display: flex;
  1025. .base-item {
  1026. flex: 1;
  1027. text-align: center;
  1028. .label {
  1029. font-size: 12px;
  1030. color: #666666;
  1031. }
  1032. .value {
  1033. padding-top: 2px;
  1034. font-size: 16px;
  1035. color: #ffffff;
  1036. }
  1037. }
  1038. .base-item + .base-item {
  1039. border-left: 1px solid rgba(102, 102, 102, 0.42);
  1040. }
  1041. }
  1042. .list {
  1043. margin-top: 15px;
  1044. width: max-content;
  1045. font-size: 14px;
  1046. .list-item {
  1047. color: #bbbbbb;
  1048. display: flex;
  1049. margin-bottom: 8px;
  1050. .list-name {
  1051. color: #f3c11d;
  1052. margin-right: 6px;
  1053. img {
  1054. width: 17px;
  1055. height: 13px;
  1056. }
  1057. }
  1058. }
  1059. }
  1060. }
  1061. .overview-file + .overview-file {
  1062. margin-top: 8px;
  1063. }
  1064. .box-wrap {
  1065. display: flex;
  1066. .box-item {
  1067. // flex: 1;
  1068. min-width: 109px;
  1069. display: flex;
  1070. flex-direction: column;
  1071. justify-content: center;
  1072. align-items: center;
  1073. padding: 6px;
  1074. box-sizing: border-box;
  1075. background: rgba(207, 207, 207, 0.1);
  1076. border-radius: 4px;
  1077. border: 1px solid rgba(207, 207, 207, 0.1);
  1078. cursor: pointer;
  1079. .item-name {
  1080. font-size: 12px;
  1081. color: #666666;
  1082. width: max-content;
  1083. }
  1084. .item-val {
  1085. font-size: 18px;
  1086. color: #fff;
  1087. width: max-content;
  1088. padding-top: 3px;
  1089. }
  1090. &.active {
  1091. background: rgba(255, 212, 137, 0.16);
  1092. border: 1px solid #ffd489;
  1093. .item-name {
  1094. color: #bbbbbb;
  1095. }
  1096. }
  1097. }
  1098. .box-item + .box-item {
  1099. margin-left: 8px;
  1100. }
  1101. }
  1102. }
  1103. }
  1104. .farm-fight-task {
  1105. position: fixed;
  1106. top: 100px;
  1107. left: 25%;
  1108. z-index: 1000;
  1109. }
  1110. /* Space-time组件展开时的样式 */
  1111. .expanded {
  1112. position: fixed !important;
  1113. width: 96% !important;
  1114. margin: 0 auto;
  1115. }
  1116. </style>