index.vue 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325
  1. <template>
  2. <div class="base-container no-events">
  3. <fnHeader showDate :autoGo="true" hideSwitch></fnHeader>
  4. <div class="content">
  5. <div class="warning-l left">
  6. <div class="warning-top">
  7. <div class="top-l yes-events">
  8. <div>
  9. <el-cascader
  10. style="width: 184px"
  11. :show-all-levels="false"
  12. v-model="areaVal"
  13. :props="props1"
  14. :options="areaListOptions"
  15. @change="toggleArea"
  16. popper-class="area-cascader"
  17. />
  18. </div>
  19. </div>
  20. <div class="top-r yes-events">
  21. <div class="data-box" @click="toggleBox('面积')" :class="{ active: activeBoxName === '面积' }">
  22. <div class="data-value">
  23. <span>{{ areaVal.includes("3186") ? 31.2 : 419.89 }}</span
  24. >万亩
  25. </div>
  26. <div class="data-name">种植面积</div>
  27. </div>
  28. <div
  29. class="data-box"
  30. v-if="areaVal.includes('3186')"
  31. @click="toggleBox('从化荔枝')"
  32. :class="{ active: activeBoxName === '从化荔枝' }"
  33. >
  34. <div class="data-value"><span>11.9</span>万亩</div>
  35. <div class="data-name">疑似失管面积</div>
  36. </div>
  37. <div class="data-box" @click="toggleBox('产量')" :class="{ active: activeBoxName === '产量' }">
  38. <div class="data-value">
  39. <span>{{ areaVal.includes("3186") ? 10.4 : 192.12 }}</span
  40. >万吨
  41. </div>
  42. <div class="data-name">预估产量</div>
  43. </div>
  44. </div>
  45. </div>
  46. <div class="warning-alarm yes-events" v-show="activeBaseTab === '预警分布'">
  47. <alarm-list></alarm-list>
  48. </div>
  49. <div class="time-wrap yes-events">
  50. <time-line></time-line>
  51. </div>
  52. </div>
  53. <div class="action-legend" v-if="activeBaseTab !== '农场分布' && activeBaseTab !== '农服管理'">
  54. <el-tree
  55. ref="treeRef"
  56. class="yes-events"
  57. style="max-width: 250px"
  58. :data="treeActionData"
  59. show-checkbox
  60. node-key="id"
  61. :default-expanded-keys="defaultExpandedKeys"
  62. :default-checked-keys="defaultCheckedKeys"
  63. :props="defaultProps"
  64. @check="getTreeChecks"
  65. >
  66. <template #default="{ node, data }">
  67. <div class="custom-tree-node">
  68. <span>{{ node.label }}</span>
  69. <div v-if="node.level === 1" class="level-legend">
  70. <span class="legend-dot" :style="{ backgroundColor: data.color }"></span>
  71. <span class="legend-text" :style="{ color: data.color }">图例</span>
  72. </div>
  73. </div>
  74. </template>
  75. </el-tree>
  76. </div>
  77. <div v-if="!showDetail" class="warning-r right chart-wrap yes-events">
  78. <chart-list :activeBaseTab="activeBaseTab"></chart-list>
  79. <!-- <farmInfoGroup></farmInfoGroup> -->
  80. </div>
  81. <div v-else class="warning-r right yes-events">
  82. <farmInfoGroup></farmInfoGroup>
  83. </div>
  84. <!-- 地图图例 -->
  85. <map-legend :type="activeBaseTab"></map-legend>
  86. <!-- 地图搜索 -->
  87. <div class="warning-search yes-events">
  88. <el-select
  89. v-model="locationVal"
  90. filterable
  91. remote
  92. reserve-keyword
  93. placeholder="搜索地区"
  94. :remote-method="remoteMethod"
  95. :loading="loading"
  96. @change="handleSearchRes"
  97. class="v-select"
  98. popper-class="focus-farm-select"
  99. style="width: 375px"
  100. >
  101. <template #prefix>
  102. <el-icon class="el-input__icon"><search /></el-icon>
  103. </template>
  104. <el-option
  105. v-for="(item, index) in locationOptions.list"
  106. :key="index"
  107. :label="item.title"
  108. :value="item.point"
  109. >
  110. <span>{{ item.title }}</span>
  111. <span class="sub-title">{{ item.province }}{{ item.city }}{{ item.district }}</span>
  112. </el-option>
  113. </el-select>
  114. </div>
  115. <div class="base-tabs yes-events">
  116. <div
  117. v-for="item in baseTabs"
  118. :key="item"
  119. class="tab-item"
  120. :class="{ active: item === activeBaseTab }"
  121. @click="handleTabClick(item)"
  122. >
  123. {{ item }}
  124. </div>
  125. </div>
  126. </div>
  127. </div>
  128. <div ref="mapRef" class="bottom-map"></div>
  129. <div id="popup" class="ol-popup-warning">
  130. <div class="warning-info-title">
  131. <div class="icon">
  132. <img src="@/assets/images/common/chart-icon.png" />
  133. </div>
  134. <div id="popup-title"></div>
  135. <div class="close" @click="destroyPopup">
  136. <img src="@/assets/images/warningHome/close-btn.png" />
  137. </div>
  138. </div>
  139. <div id="popup-content" class="info-content"></div>
  140. </div>
  141. <track-dialog></track-dialog>
  142. </template>
  143. <script setup>
  144. import "./map/mockFarmLayer";
  145. import StaticMapLayers from "@/components/static_map_change/Layers.js";
  146. import StaticMapPointLayers from "@/components/static_map_change/pointLayer.js";
  147. import { onMounted, onUnmounted, ref, reactive, nextTick } from "vue";
  148. import fnHeader from "@/components/fnHeader.vue";
  149. import WarningMap from "./warningMap";
  150. import AlarmLayer from "./map/alarmLayer";
  151. import DistributionLayer from "./map/distributionLayer";
  152. import trackDialog from "./components/trackDialog.vue";
  153. import alarmList from "./components/alarmList.vue";
  154. import timeLine from "./components/timeLine.vue";
  155. import eventBus from "@/api/eventBus";
  156. import { areaListOptions } from "./area";
  157. import { useStore } from "vuex";
  158. import farmInfoGroup from "./components/farmInfoGroup.vue";
  159. import mapLegend from "./components/mapLegend.vue";
  160. import chartList from "./components/chart_components/chartList.vue";
  161. let store = useStore();
  162. let warningMap = new WarningMap();
  163. let alarmLayer = null;
  164. let staticMapLayers = null;
  165. let staticMapPointLayers = null;
  166. let distributionLayer = null;
  167. const areaVal = ref(["3"]);
  168. const mapRef = ref(null);
  169. const showDetail = ref(false);
  170. const treeRef = ref(null);
  171. const defaultProps = {
  172. children: "items",
  173. label: "name",
  174. };
  175. import lz from "@/assets/images/map/type/荔枝.png";
  176. import ly from "@/assets/images/map/type/龙眼.png";
  177. import sd from "@/assets/images/map/type/水稻.png";
  178. import xm from "@/assets/images/map/type/小麦.png";
  179. import bc from "@/assets/images/map/type/小麦.png";
  180. import lb from "@/assets/images/map/type/小麦.png";
  181. // 冷链冷库、加工厂图标(与图例保持一致)
  182. import coldChainIcon from "@/assets/images/common/legend-icon-1.png";
  183. import factoryIcon from "@/assets/images/common/legend-icon-2.png";
  184. const originTreeData = [
  185. {
  186. id: 1,
  187. label: "果类",
  188. color: "#51B2FF",
  189. fillColor: "rgba(5, 49, 84, 0.5)",
  190. geom: "MULTIPOLYGON (((113.58668302396221 23.244659822289524, 113.32095411231998 23.24298858095617, 112.99338890476295 23.002328435946534, 113.13878785387456 22.604570799124076, 113.59503930394511 22.86862839611681, 113.58668302396221 23.244659822289524)))",
  191. children: [
  192. {
  193. id: 4,
  194. label: "荔枝",
  195. color: "#2199F8",
  196. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%8D%94%E6%9E%9D.png",
  197. imgName: lz,
  198. wktArr: [
  199. "POINT(113.33722309500006 23.204074978290652)",
  200. "POINT(113.53593237057355 23.188789823486065)",
  201. "POINT(113.36970447853234 23.064596505297875)",
  202. ],
  203. },
  204. {
  205. id: 55,
  206. label: "龙眼",
  207. color: "#2199F8",
  208. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E7%B3%96.png",
  209. imgName: ly,
  210. wktArr: [
  211. "POINT(113.29900983080294 22.949956545068478)",
  212. "POINT(113.10412186488536 22.800924630297875)",
  213. "POINT(113.32384842738536 22.776086033715462)",
  214. "POINT(113.22640444442656 22.90983245840535)",
  215. ],
  216. },
  217. ],
  218. },
  219. {
  220. id: 2,
  221. label: "粮食",
  222. color: "#FF8E1C",
  223. fillColor: "rgba(83, 46, 8, 0.5)",
  224. geom: "MULTIPOLYGON (((112.42256410334443 23.14863707066071, 112.09584019992684 22.842930537988664, 112.25060416300033 22.62511471413565, 112.80278650958275 22.749307864685775, 112.75119857777094 23.13144100957107, 112.42256410334443 23.14863707066071)))",
  225. children: [
  226. {
  227. id: 5,
  228. label: "水稻",
  229. color: "#FAA53D",
  230. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%8C%82%E7%BB%BF.png",
  231. imgName: sd,
  232. wktArr: [
  233. "POINT(112.70843577567298 22.969169477864167)",
  234. "POINT(112.23636397199755 22.85839626464389)",
  235. "POINT(112.35889247053002 23.008153324438585)",
  236. "POINT(112.47894566011911 22.9017143340381)",
  237. ],
  238. },
  239. {
  240. id: 6,
  241. label: "小麦",
  242. color: "#FAA53D",
  243. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%97%A0%E6%A0%B8.png",
  244. imgName: xm,
  245. wktArr: [
  246. "POINT(112.36777193304151 22.73892833157863)",
  247. "POINT(112.26684873669083 22.71150357559281)",
  248. "POINT(112.65408646638161 22.84862740364581)",
  249. ],
  250. },
  251. ],
  252. },
  253. {
  254. id: 3,
  255. label: "蔬菜",
  256. color: "#25BC07",
  257. fillColor: "rgba(0, 69, 4, 0.5)",
  258. children: [
  259. {
  260. id: 7,
  261. label: "白菜",
  262. color: "#7ABB00",
  263. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E8%8F%9C.png",
  264. imgName: bc,
  265. wktArr: [
  266. "POINT(110.34100329503417 21.516399336978793)",
  267. "POINT(113.89499662443995 22.653799122199416)",
  268. "POINT(113.9329988323152 22.653600638732314)",
  269. "POINT(113.94400024786592 22.614900553599)",
  270. ],
  271. },
  272. {
  273. id: 8,
  274. label: "萝卜",
  275. color: "#7ABB00",
  276. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%90%9D%E8%8F%9C.png",
  277. imgName: lb,
  278. wktArr: [
  279. "POINT(110.34100329503417 21.516399336978793)",
  280. "POINT(113.89499662443995 22.653799122199416)",
  281. "POINT(113.9329988323152 22.653600638732314)",
  282. "POINT(113.94400024786592 22.614900553599)",
  283. ],
  284. },
  285. ],
  286. },
  287. ];
  288. const phenologyData = [
  289. {
  290. id: 1,
  291. label: "果类",
  292. color: "#51B2FF",
  293. fillColor: "rgba(5, 49, 84, 0.5)",
  294. geom: "MULTIPOLYGON (((113.58668302396221 23.244659822289524, 113.32095411231998 23.24298858095617, 112.99338890476295 23.002328435946534, 113.13878785387456 22.604570799124076, 113.59503930394511 22.86862839611681, 113.58668302396221 23.244659822289524)))",
  295. children: [
  296. {
  297. id: 4,
  298. label: "荔枝",
  299. color: "#2199F8",
  300. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%8D%94%E6%9E%9D.png",
  301. imgName: lz,
  302. children: [
  303. {
  304. id: 13,
  305. label: "秋梢期",
  306. color: "#58B5FF",
  307. imgName: lz,
  308. wktArr: [
  309. "POINT(113.33722309500006 23.204074978290652)",
  310. "POINT(113.53593237057355 23.188789823486065)",
  311. ],
  312. },
  313. {
  314. id: 14,
  315. label: "膨果期",
  316. color: "#1688E3",
  317. imgName: lz,
  318. wktArr: [
  319. "POINT(113.32095411231998 23.24298858095617)",
  320. ],
  321. },
  322. {
  323. id: 15,
  324. label: "成熟期",
  325. color: "#3D8CCB",
  326. imgName: lz,
  327. wktArr: [
  328. "POINT(113.36970447853234 23.064596505297875)",
  329. ],
  330. },
  331. ],
  332. },
  333. {
  334. id: 55,
  335. label: "龙眼",
  336. color: "#2199F8",
  337. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E7%B3%96.png",
  338. imgName: ly,
  339. children: [
  340. {
  341. id: 16,
  342. label: "秋梢期",
  343. color: "#5986AA",
  344. imgName: ly,
  345. wktArr: [
  346. "POINT(113.29900983080294 22.949956545068478)",
  347. "POINT(113.10412186488536 22.800924630297875)",
  348. ],
  349. },
  350. {
  351. id: 17,
  352. label: "膨果期",
  353. color: "#79ABD3",
  354. imgName: ly,
  355. wktArr: [
  356. "POINT(113.32384842738536 22.776086033715462)",
  357. "POINT(113.22640444442656 22.90983245840535)",
  358. ],
  359. },
  360. ],
  361. },
  362. ],
  363. },
  364. {
  365. id: 2,
  366. label: "粮食",
  367. color: "#FF8E1C",
  368. fillColor: "rgba(83, 46, 8, 0.5)",
  369. geom: "MULTIPOLYGON (((112.42256410334443 23.14863707066071, 112.09584019992684 22.842930537988664, 112.25060416300033 22.62511471413565, 112.80278650958275 22.749307864685775, 112.75119857777094 23.13144100957107, 112.42256410334443 23.14863707066071)))",
  370. children: [
  371. {
  372. id: 5,
  373. label: "水稻",
  374. color: "#FAA53D",
  375. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%8C%82%E7%BB%BF.png",
  376. imgName: sd,
  377. children: [
  378. {
  379. id: 10,
  380. label: "拔节期",
  381. color: "#985400",
  382. imgName: sd,
  383. wktArr: [
  384. "POINT(112.36777193304151 22.73892833157863)",
  385. ],
  386. },
  387. {
  388. id: 11,
  389. label: "孕穗期",
  390. color: "#512D00",
  391. imgName: sd,
  392. wktArr: [
  393. "POINT(112.26684873669083 22.71150357559281)",
  394. ],
  395. },
  396. {
  397. id: 12,
  398. label: "抽穗期",
  399. color: "#DD871D",
  400. imgName: sd,
  401. wktArr: [
  402. "POINT(112.65408646638161 22.84862740364581)",
  403. ],
  404. },
  405. ],
  406. },
  407. {
  408. id: 6,
  409. label: "小麦",
  410. color: "#FAA53D",
  411. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E6%97%A0%E6%A0%B8.png",
  412. imgName: xm,
  413. children: [
  414. {
  415. id: 18,
  416. label: "拔节期",
  417. color: "#FAA53D",
  418. imgName: xm,
  419. wktArr: [
  420. "POINT(112.36777193304151 22.73892833157863)",
  421. ],
  422. },
  423. ],
  424. },
  425. ],
  426. },
  427. {
  428. id: 3,
  429. label: "蔬菜",
  430. color: "#25BC07",
  431. fillColor: "rgba(0, 69, 4, 0.5)",
  432. children: [
  433. {
  434. id: 7,
  435. label: "白菜",
  436. color: "#7ABB00",
  437. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E8%8F%9C.png",
  438. imgName: bc,
  439. children: [
  440. {
  441. id: 19,
  442. label: "拔节期",
  443. color: "#7ABB00",
  444. imgName: bc,
  445. wktArr: [
  446. "POINT(110.34100329503417 21.516399336978793)",
  447. "POINT(113.89499662443995 22.653799122199416)",
  448. "POINT(113.9329988323152 22.653600638732314)",
  449. "POINT(113.94400024786592 22.614900553599)",
  450. ],
  451. },
  452. ],
  453. },
  454. {
  455. id: 8,
  456. label: "萝卜",
  457. color: "#7ABB00",
  458. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%90%9D%E8%8F%9C.png",
  459. imgName: lb,
  460. children: [
  461. {
  462. id: 20,
  463. label: "拔节期",
  464. color: "#7ABB00",
  465. imgName: lb,
  466. wktArr: [
  467. "POINT(110.34100329503417 21.516399336978793)",
  468. "POINT(113.89499662443995 22.653799122199416)",
  469. "POINT(113.9329988323152 22.653600638732314)",
  470. "POINT(113.94400024786592 22.614900553599)",
  471. ],
  472. },
  473. ],
  474. },
  475. ],
  476. },
  477. ];
  478. const treeActionData = ref(originTreeData);
  479. // 物候期分布下,当前激活的“二级”节点(只允许一个)
  480. const activePhenologySecondId = ref(null);
  481. // 树的默认展开与默认选中(展开/选中第一个“果类”及其子节点)
  482. const defaultExpandedKeys = ref();
  483. const defaultCheckedKeys = ref();
  484. // 顶部基础 tabs
  485. const baseTabs = ["作物分布", "物候期分布", "预警分布", "农场分布", "农服管理"];
  486. const activeBaseTab = ref("作物分布");
  487. const legendImg = ref("");
  488. const warningLayers = ref({});
  489. onMounted(async () => {
  490. warningMap.initMap(store.getters.userinfo.location, mapRef.value);
  491. alarmLayer = new AlarmLayer(warningMap.kmap);
  492. staticMapLayers = new StaticMapLayers(warningMap.kmap);
  493. staticMapPointLayers = new StaticMapPointLayers(warningMap.kmap);
  494. distributionLayer = new DistributionLayer(warningMap.kmap);
  495. await getSpeciesListData();
  496. // 作物分布默认选中
  497. await handleDistributionTreeDefault()
  498. await handleDistributionLayer();
  499. eventBus.emit("warningMap:init", warningMap.kmap);
  500. // 图例数据
  501. eventBus.on("alarmList:warningLayers", (data) => {
  502. warningLayers.value = data;
  503. });
  504. // 预警分布图层联动:仅在“预警分布”tab 显示时,才在地图上显示对应图层
  505. eventBus.on("alarmList:changeMapLayer", ({ name, legendUrl }) => {
  506. // 47 行:只在 activeBaseTab === '预警分布' 时显示预警列表
  507. // 这里保持一致:只有在该 tab 下才显示地图图层,否则直接隐藏
  508. if (activeBaseTab.value !== "预警分布") {
  509. staticMapLayers && staticMapLayers.hideAll();
  510. legendImg.value = "";
  511. return;
  512. }
  513. if (legendUrl) {
  514. legendImg.value = legendUrl;
  515. staticMapLayers && staticMapLayers.showSingle(name, true);
  516. } else {
  517. legendImg.value = warningLayers.value[`${name}图例`];
  518. let text = "";
  519. if (name === "日间温度") {
  520. text = "从化地块日温";
  521. } else if (name === "夜间温度") {
  522. text = "从化地块夜温";
  523. } else if (name === "土壤水分") {
  524. text = "从化地块水分";
  525. }
  526. if (text !== "") {
  527. staticMapLayers && staticMapLayers.showSingle(text, true);
  528. } else {
  529. staticMapLayers && staticMapLayers.hideAll();
  530. }
  531. }
  532. });
  533. // ai与地图交互
  534. eventBus.off("chat:showMapLayer", handleMapLayer);
  535. eventBus.on("chat:showMapLayer", handleMapLayer);
  536. });
  537. sessionStorage.removeItem("farmId");
  538. onUnmounted(() => {
  539. eventBus.off("alarmList:changeMapLayer");
  540. });
  541. // 作物分布默认选中并展开第一个节点,在地图上显示对应分布图层
  542. const handleDistributionLayer = async () => {
  543. // 默认选中并展开第一个“果类”节点,在地图上显示对应分布图层
  544. const firstCategory = treeActionData.value[0];
  545. if (firstCategory) {
  546. await getDistributionData(firstCategory.id);
  547. }
  548. };
  549. // 作物分布树形结构默认展开与默认选中
  550. const handleDistributionTreeDefault = () => {
  551. defaultExpandedKeys.value = [treeActionData.value[0]?.id];
  552. defaultCheckedKeys.value = [
  553. treeActionData.value[0]?.id,
  554. ...(treeActionData.value[0]?.children?.map((c) => c.id) || []),
  555. ];
  556. };
  557. // 物候期分布默认选中并展开第一个节点,在地图上显示对应分布图层
  558. const handlePhenologyLayer = async () => {
  559. const firstCategory = treeActionData.value[0].children[0];
  560. if (firstCategory) {
  561. // 递归查找最后一层的节点(没有子节点的叶子节点)
  562. const getLastLevelNodes = (node) => {
  563. const lastLevelNodes = [];
  564. if ((!node.items || node.items.length === 0) && (!node.children || node.children.length === 0)) {
  565. lastLevelNodes.push(node);
  566. } else {
  567. const children = node.items || node.children || [];
  568. children.forEach((child) => {
  569. lastLevelNodes.push(...getLastLevelNodes(child));
  570. });
  571. }
  572. return lastLevelNodes;
  573. };
  574. const lastLevelNodes = getLastLevelNodes(firstCategory);
  575. const lastLevelIds = lastLevelNodes.map((n) => n.id);
  576. // 并发请求所有数据
  577. const promises = lastLevelIds.map((id) => getDistributionData(id));
  578. const results = await Promise.all(promises);
  579. const finalMapData = results.flat();
  580. distributionLayer.initData(finalMapData);
  581. }
  582. };
  583. // 物候期分布树形结构默认展开与默认选中
  584. const handlePhenologyTreeDefault = () => {
  585. defaultCheckedKeys.value = [
  586. treeActionData.value[0]?.children[0]?.id,
  587. ...(treeActionData.value[0]?.children[0]?.children?.map((c) => c.id) || []),
  588. ];
  589. defaultExpandedKeys.value = [treeActionData.value[0]?.children[0]?.id];
  590. };
  591. // 预警分布默认选中并展开第一个节点,在地图上显示对应分布图层
  592. const handleAlarmLayer = async () => {
  593. const firstCategory = treeActionData.value[0].children[0];
  594. if (firstCategory) {
  595. // 递归查找最后一层的节点(没有子节点的叶子节点)
  596. const getLastLevelNodes = (node) => {
  597. const lastLevelNodes = [];
  598. if ((!node.items || node.items.length === 0) && (!node.children || node.children.length === 0)) {
  599. lastLevelNodes.push(node);
  600. } else {
  601. const children = node.items || node.children || [];
  602. children.forEach((child) => {
  603. lastLevelNodes.push(...getLastLevelNodes(child));
  604. });
  605. }
  606. return lastLevelNodes;
  607. };
  608. const lastLevelNodes = getLastLevelNodes(firstCategory);
  609. const lastLevelIds = lastLevelNodes.map((n) => n.id);
  610. // 并发请求所有数据
  611. const promises = lastLevelIds.map((id) => getDistributionData(id));
  612. const results = await Promise.all(promises);
  613. const finalMapData = results.flat();
  614. distributionLayer.initData(finalMapData);
  615. }
  616. };
  617. // 预警分布树形结构默认展开与默认选中
  618. const handleAlarmTreeDefault = () => {
  619. defaultCheckedKeys.value = [
  620. treeActionData.value[0]?.children[0]?.id
  621. ];
  622. defaultExpandedKeys.value = [treeActionData.value[0]?.id];
  623. };
  624. // ai与地图交互
  625. const hideChatMapLayer = ref(true);
  626. const handleMapLayer = ({ mapName, isHome }) => {
  627. if (!isHome) {
  628. hideChatMapLayer.value = false;
  629. }
  630. staticMapPointLayers.hidePoint();
  631. staticMapLayers.hideAll();
  632. // 重置时间轴
  633. // eventBus.emit("map_click_alarm")
  634. if (mapName === "植保机") {
  635. staticMapLayers.show("分散种植", true);
  636. staticMapPointLayers.showPoint();
  637. } else if (mapName) {
  638. // staticMapLayers.show("作物种类")
  639. if (isHome) {
  640. staticMapLayers.show(mapName, true);
  641. } else {
  642. staticMapLayers.showSingle(mapName, true);
  643. }
  644. }
  645. };
  646. const toggleChatMapLayer = () => {
  647. hideChatMapLayer.value = true;
  648. eventBus.emit("chat:hideMapLayer");
  649. staticMapLayers.hideAll();
  650. };
  651. const destroyPopup = () => {
  652. eventBus.emit("map:destroyPopup");
  653. };
  654. const handleTabClick = (item) => {
  655. activeBaseTab.value = item;
  656. // 切换 Tab 时,先清空农场分布图层上的旧数据
  657. if (distributionLayer) {
  658. distributionLayer.clear();
  659. }
  660. // 所有操作前,先清空图层和选中项
  661. legendImg.value = "";
  662. staticMapLayers && staticMapLayers.hideAll();
  663. // 通知预警列表组件清空默认选中项
  664. eventBus.emit("warningHome:clearAlarm");
  665. treeActionData.value = originTreeData;
  666. // 使用 nextTick 确保树组件数据更新后再设置选中状态
  667. nextTick(() => {
  668. if (treeRef.value) {
  669. // 先清空所有选中项
  670. treeRef.value.setCheckedKeys([]);
  671. // 再设置新的选中项
  672. treeRef.value.setCheckedKeys(defaultCheckedKeys.value);
  673. }
  674. });
  675. switch (item) {
  676. case "作物分布":
  677. handleDistributionTreeDefault();
  678. handleDistributionLayer();
  679. break;
  680. case "物候期分布":
  681. treeActionData.value = phenologyData;
  682. handlePhenologyTreeDefault()
  683. handlePhenologyLayer();
  684. break;
  685. case "预警分布":
  686. handleAlarmTreeDefault()
  687. handleAlarmLayer();
  688. // 通知预警列表组件默认选中第一个(因子)项
  689. eventBus.emit("warningHome:activeFirstAlarmFactor");
  690. break;
  691. case "农场分布":
  692. const cropData = [
  693. {
  694. id: 4,
  695. label: "荔枝-物候期",
  696. color: "#2199F8",
  697. farmName: "荔博园",
  698. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E8%8D%94%E6%9E%9D.png",
  699. imgName: lz,
  700. wktArr: [
  701. "POINT(113.33722309500006 23.204074978290652)",
  702. "POINT(113.53593237057355 23.188789823486065)",
  703. "POINT(113.36970447853234 23.064596505297875)",
  704. ],
  705. },
  706. {
  707. id: 55,
  708. label: "荔枝-秋梢期",
  709. color: "#FF8E1C",
  710. farmName: "荔博园",
  711. imgUrl: "https://birdseye-img.sysuimars.com/temp/pz/%E7%99%BD%E7%B3%96.png",
  712. imgName: lz,
  713. wktArr: [
  714. "POINT(113.29900983080294 22.949956545068478)",
  715. "POINT(113.22640444442656 22.90983245840535)",
  716. ],
  717. },
  718. ];
  719. // 设施图层测试数据
  720. const facilityData = [
  721. {
  722. id: 201,
  723. label: "冷链冷库",
  724. imgName: coldChainIcon,
  725. wktArr: ["POINT(113.35 23.10)"],
  726. },
  727. {
  728. id: 202,
  729. label: "加工厂",
  730. imgName: factoryIcon,
  731. wktArr: ["POINT(113.25 23.02)"],
  732. },
  733. ];
  734. distributionLayer.initData(cropData);
  735. distributionLayer.initFacilityData(facilityData);
  736. break;
  737. default:
  738. break;
  739. }
  740. };
  741. const getSpeciesListData = async () => {
  742. const res = await VE_API.species.speciesList();
  743. treeActionData.value = res.data;
  744. };
  745. const getDistributionData = async (speciesId) => {
  746. const {data} = await VE_API.agri_land_crop.queryDistribution({
  747. year: 2025,
  748. quarter: 1,
  749. speciesId
  750. });
  751. return data;
  752. };
  753. const props1 = {
  754. checkStrictly: true,
  755. };
  756. const toggleArea = (v) => {
  757. activeBoxName.value = null;
  758. const val = v[v.length - 1];
  759. if (val === "3" || val === "3186") {
  760. eventBus.emit("warningHome:toggleArea", val);
  761. }
  762. };
  763. const activeBoxName = ref(null);
  764. const toggleBox = (name) => {
  765. activeBoxName.value = name;
  766. legendImg.value = warningLayers.value[`${name}图例`];
  767. eventBus.emit("warningHome:toggleMapLayer", name);
  768. };
  769. // 搜索
  770. const locationVal = ref("");
  771. const loading = ref(false);
  772. const MAP_KEY = "CZLBZ-LJICQ-R4A5J-BN62X-YXCRJ-GNBUT";
  773. const handleSearchRes = (v) => {
  774. warningMap.setMapCenter(v);
  775. // onRest();
  776. };
  777. const locationOptions = reactive({
  778. list: [],
  779. });
  780. const remoteMethod = async (keyword) => {
  781. if (keyword) {
  782. locationOptions.list = [];
  783. loading.value = true;
  784. const params = {
  785. key: MAP_KEY,
  786. keyword,
  787. // location: location.value,
  788. location: "22.574540836684672,113.1093017627431",
  789. };
  790. await VE_API.old_mini_map.getCtiyList({ word: keyword }).then(({ data }) => {
  791. if (data && data.length) {
  792. data.forEach((item) => {
  793. item.point = item.location.lat + "," + item.location.lng;
  794. locationOptions.list.push(item);
  795. });
  796. }
  797. });
  798. VE_API.old_mini_map.search(params).then(({ data }) => {
  799. loading.value = false;
  800. data.forEach((item) => {
  801. item.point = item.location.lat + "," + item.location.lng;
  802. locationOptions.list.push(item);
  803. });
  804. });
  805. } else {
  806. locationOptions.list = [];
  807. }
  808. };
  809. // 根据节点 id 在当前树数据中计算其层级(1/2/3)及所属的二级节点 id
  810. const getNodeLevelInfo = (id) => {
  811. const roots = treeActionData.value || [];
  812. for (const root of roots) {
  813. if (root.id === id) {
  814. return { level: 1, secondId: null };
  815. }
  816. if (root.children) {
  817. for (const second of root.children) {
  818. if (second.id === id) {
  819. return { level: 2, secondId: second.id };
  820. }
  821. if (second.children) {
  822. for (const third of second.children) {
  823. if (third.id === id) {
  824. return { level: 3, secondId: second.id };
  825. }
  826. }
  827. }
  828. }
  829. }
  830. }
  831. return { level: 0, secondId: null };
  832. };
  833. const getTreeChecks = async (nodeData, data) => {
  834. const { checkedNodes } = data;
  835. let finalCheckedNodes = checkedNodes;
  836. // 物候期分布:限制"二级只能选一个,三级不限个数"
  837. if ((activeBaseTab.value === "物候期分布" || activeBaseTab.value === "预警分布") && treeRef.value) {
  838. const tree = treeRef.value;
  839. const { level, secondId } = getNodeLevelInfo(nodeData.id);
  840. if (level === 2 || level === 3) {
  841. const currentSecondId = secondId;
  842. // 判断当前这个二级分支下,是否还有被选中的节点(包含二级自己或其子级)
  843. const hasAnyCheckedInCurrentSecond = checkedNodes.some((n) => {
  844. const info = getNodeLevelInfo(n.id);
  845. return info.secondId === currentSecondId || (info.level === 2 && n.id === currentSecondId);
  846. });
  847. if (hasAnyCheckedInCurrentSecond) {
  848. // 仍有节点被选中 → 保证只有当前这个二级分支被选中,其它分支全部取消
  849. activePhenologySecondId.value = currentSecondId;
  850. const roots = treeActionData.value || [];
  851. roots.forEach((root) => {
  852. (root.children || []).forEach((second) => {
  853. if (second.id !== currentSecondId) {
  854. // 取消其它二级及其所有子级勾选
  855. tree.setChecked(second.id, false, true);
  856. } else {
  857. // 保持当前二级选中,子级按用户选择
  858. tree.setChecked(second.id, true, false);
  859. }
  860. });
  861. });
  862. } else {
  863. // 当前二级分支已经被全部取消勾选 → 清空激活记录,允许"全部不选"
  864. activePhenologySecondId.value = null;
  865. }
  866. }
  867. // 对树进行了 setChecked 操作后,重新从树组件拿一次最新的选中节点列表
  868. // 这里只需要最后一层(叶子节点 / 有 wktArr 的节点),不用父级节点
  869. const allCheckedNodes = treeRef.value.getCheckedNodes(false, true);
  870. finalCheckedNodes = allCheckedNodes.filter((n) => !n.children || n.children.length === 0 || n.wktArr);
  871. }
  872. // 任意 tab 下,最终都用当前选中的节点驱动地图渲染
  873. // 提取最后一级节点的 id 到数组(没有子节点的叶子节点)
  874. const lastLevelIds = finalCheckedNodes
  875. .filter((n) => (!n.items || n.items.length === 0) && (!n.children || n.children.length === 0))
  876. .map((n) => n.id);
  877. // 并发请求所有数据,等待所有 Promise 完成
  878. const promises = lastLevelIds.map((id) => {
  879. const node = finalCheckedNodes.find((n) => n.id === id);
  880. if (node) {
  881. return getDistributionData(node.id);
  882. }
  883. return Promise.resolve([]);
  884. });
  885. // 等待所有请求完成,并将结果扁平化
  886. const results = await Promise.all(promises);
  887. const finalMapData = results.flat();
  888. distributionLayer.initData(finalMapData);
  889. };
  890. </script>
  891. <style lang="scss" scoped>
  892. .base-container {
  893. width: 100%;
  894. height: 100vh;
  895. color: #fff;
  896. position: absolute;
  897. box-sizing: border-box;
  898. z-index: 1;
  899. ::v-deep {
  900. .focus-farm {
  901. top: 42px;
  902. }
  903. }
  904. .content {
  905. width: 100%;
  906. height: calc(100% - 74px - 48px);
  907. padding: 16px 20px 0 27px;
  908. display: flex;
  909. justify-content: space-between;
  910. box-sizing: border-box;
  911. position: relative;
  912. .left,
  913. .right {
  914. width: calc(376px + 54px);
  915. height: 100%;
  916. box-sizing: border-box;
  917. // display: flex;
  918. }
  919. .right {
  920. // width: 395px;
  921. width: 376px;
  922. overflow: auto;
  923. position: relative;
  924. .list {
  925. width: 100%;
  926. height: 100%;
  927. }
  928. }
  929. .chart-wrap {
  930. padding: 8px;
  931. background: #101010;
  932. border: 1px solid #444444;
  933. }
  934. .action-legend {
  935. flex: 1;
  936. padding: 0 13px;
  937. display: flex;
  938. justify-content: flex-end;
  939. align-items: baseline;
  940. ::v-deep {
  941. .el-tree {
  942. background: #232323;
  943. border: 1px solid #444444;
  944. border-radius: 5px;
  945. padding: 10px 0;
  946. --el-tree-node-content-height: 34px;
  947. --el-tree-node-hover-bg-color: rgba(255, 212, 137, 0.05);
  948. --el-tree-text-color: #ffd489;
  949. --el-tree-expand-icon-color: #ffd489;
  950. .el-checkbox {
  951. --el-checkbox-bg-color: transparent;
  952. --el-checkbox-input-border: 1px solid #ffd489;
  953. --el-checkbox-checked-input-border-color: #ffd489;
  954. --el-checkbox-checked-bg-color: #ffd489;
  955. --el-checkbox-checked-icon-color: #000;
  956. --el-checkbox-input-border-color-hover: #ffd489;
  957. }
  958. }
  959. .el-tree-node__content {
  960. padding-right: 30px;
  961. }
  962. }
  963. .custom-tree-node {
  964. display: flex;
  965. align-items: center;
  966. justify-content: space-between;
  967. gap: 8px;
  968. }
  969. .level-legend {
  970. display: flex;
  971. align-items: center;
  972. gap: 4px;
  973. padding: 0 5px;
  974. height: 17px;
  975. background: rgba(255, 255, 255, 0.1);
  976. border-radius: 2px;
  977. font-size: 10px;
  978. .legend-dot {
  979. width: 4px;
  980. height: 4px;
  981. border-radius: 50%;
  982. }
  983. }
  984. }
  985. .warning-r {
  986. .map-legend {
  987. position: absolute;
  988. bottom: -33px;
  989. left: -360px;
  990. width: 340px;
  991. img {
  992. width: 340px;
  993. opacity: 0.6;
  994. }
  995. }
  996. .chat-legend {
  997. bottom: -12px;
  998. }
  999. }
  1000. .base-tabs {
  1001. position: fixed;
  1002. top: 32px;
  1003. left: 390px;
  1004. display: flex;
  1005. align-items: center;
  1006. .tab-item {
  1007. padding: 7px 12px 9px;
  1008. margin-right: 28px;
  1009. text-align: center;
  1010. font-family: "PangMenZhengDao";
  1011. font-size: 16px;
  1012. color: #fff;
  1013. background: rgba(28, 36, 41, 0.8);
  1014. border-radius: 4px;
  1015. cursor: pointer;
  1016. border: 1px solid transparent;
  1017. &.active {
  1018. color: #ffdf9a;
  1019. background: rgba(19, 22, 16, 0.8);
  1020. border: 1px solid #ffd489;
  1021. }
  1022. }
  1023. }
  1024. .warning-search {
  1025. position: fixed;
  1026. right: 207px;
  1027. top: 28px;
  1028. display: flex;
  1029. align-items: center;
  1030. .focus-farm {
  1031. padding-left: 15px;
  1032. }
  1033. ::v-deep {
  1034. .el-select__wrapper {
  1035. background: #1d1d1d;
  1036. box-shadow: 0 0 0 1px rgba(255, 212, 137, 0.3) inset;
  1037. height: 50px;
  1038. line-height: 50px;
  1039. .el-select__caret,
  1040. .el-select__prefix {
  1041. color: rgba(255, 212, 137, 0.6);
  1042. }
  1043. }
  1044. .el-select__input {
  1045. color: rgba(255, 212, 137, 0.6);
  1046. }
  1047. .el-select__placeholder {
  1048. color: rgba(255, 212, 137, 0.6);
  1049. font-size: 20px;
  1050. font-family: "PangMenZhengDao";
  1051. // text-align: center;
  1052. }
  1053. }
  1054. }
  1055. .warning-top {
  1056. display: flex;
  1057. width: max-content;
  1058. align-items: center;
  1059. .top-l {
  1060. display: flex;
  1061. flex-direction: column;
  1062. align-items: center;
  1063. .type-box {
  1064. margin-top: 10px;
  1065. background: rgba(29, 29, 29, 0.54);
  1066. border: 1px solid rgba(255, 212, 137, 0.3);
  1067. border-radius: 2px;
  1068. text-align: center;
  1069. line-height: 48px;
  1070. height: 48px;
  1071. width: 184px;
  1072. }
  1073. ::v-deep {
  1074. .el-input__wrapper {
  1075. background: rgba(29, 29, 29, 0.54);
  1076. box-shadow: 0 0 0 1px rgba(255, 212, 137, 0.3) inset;
  1077. height: 50px;
  1078. line-height: 50px;
  1079. padding: 0 10px;
  1080. .el-input__inner {
  1081. color: #f7be5a;
  1082. font-size: 20px;
  1083. font-family: "PangMenZhengDao";
  1084. text-align: center;
  1085. }
  1086. }
  1087. .el-select__wrapper {
  1088. background: rgba(29, 29, 29, 0.54);
  1089. box-shadow: 0 0 0 1px rgba(255, 212, 137, 0.3) inset;
  1090. height: 50px;
  1091. line-height: 50px;
  1092. .el-select__caret {
  1093. color: #ffd489;
  1094. }
  1095. }
  1096. .el-select__placeholder {
  1097. color: #f7be5a;
  1098. font-size: 20px;
  1099. font-family: "PangMenZhengDao";
  1100. text-align: center;
  1101. }
  1102. }
  1103. }
  1104. .top-r {
  1105. display: flex;
  1106. .data-box {
  1107. cursor: pointer;
  1108. margin-left: 20px;
  1109. width: 200px;
  1110. height: 104px;
  1111. background: url("@/assets/images/warningHome/box-bg.png") no-repeat center center / 100% 100%;
  1112. display: flex;
  1113. flex-direction: column;
  1114. align-items: center;
  1115. &.active {
  1116. position: relative;
  1117. &::before {
  1118. content: "";
  1119. position: absolute;
  1120. bottom: -26px;
  1121. left: 0;
  1122. right: 0;
  1123. width: 35px;
  1124. height: 17px;
  1125. margin: 0 auto;
  1126. background: url("@/assets/images/warningHome/triangle.png") no-repeat center center / cover;
  1127. }
  1128. }
  1129. .data-value {
  1130. padding-top: 15px;
  1131. font-size: 20px;
  1132. color: rgba(255, 212, 137, 0.4);
  1133. font-family: "PangMenZhengDao";
  1134. span {
  1135. font-size: 38px;
  1136. color: #f7be5a;
  1137. padding-right: 2px;
  1138. }
  1139. }
  1140. .data-name {
  1141. color: #cecece;
  1142. font-size: 16px;
  1143. }
  1144. }
  1145. }
  1146. }
  1147. .warning-alarm {
  1148. width: 88px;
  1149. padding-top: 14px;
  1150. }
  1151. .time-wrap {
  1152. position: fixed;
  1153. bottom: 20px;
  1154. left: 20px;
  1155. width: 1080px;
  1156. height: 71px;
  1157. }
  1158. }
  1159. }
  1160. .bottom-map {
  1161. width: 100%;
  1162. height: 100vh;
  1163. position: absolute;
  1164. z-index: 0;
  1165. }
  1166. </style>
  1167. <style lang="less">
  1168. .ol-scale-line {
  1169. left: auto;
  1170. right: 435px;
  1171. bottom: 13px;
  1172. .ol-scale-line-inner {
  1173. max-width: 80px;
  1174. width: 80px !important;
  1175. color: #fff;
  1176. border-color: #fff;
  1177. }
  1178. }
  1179. .focus-farm-select {
  1180. &.el-popper.is-light {
  1181. background: #232323;
  1182. border-color: rgba(255, 212, 137, 0.3);
  1183. box-shadow: 0px 0px 12px rgba(255, 212, 137, 0.3);
  1184. .el-select-dropdown__item {
  1185. background: none;
  1186. color: rgba(255, 212, 137, 0.6);
  1187. }
  1188. .el-select-dropdown__item.is-selected {
  1189. background: rgba(255, 212, 137, 0.2);
  1190. color: #ffd489;
  1191. }
  1192. }
  1193. &.el-popper.is-light .el-popper__arrow:before {
  1194. background: #232323;
  1195. border-color: rgba(255, 212, 137, 0.3);
  1196. }
  1197. }
  1198. .ol-popup-warning {
  1199. position: relative;
  1200. width: 295px;
  1201. background: rgb(35, 35, 35, 0.86);
  1202. color: #fff;
  1203. font-size: 16px;
  1204. border-radius: 4px;
  1205. .warning-info-title {
  1206. display: flex;
  1207. padding: 6px 10px;
  1208. background: rgba(255, 255, 255, 0.05);
  1209. font-size: 18px;
  1210. border-radius: 4px 4px 0 0;
  1211. .icon {
  1212. padding-right: 6px;
  1213. }
  1214. .close {
  1215. position: absolute;
  1216. right: 12px;
  1217. top: 4px;
  1218. }
  1219. }
  1220. .info-content {
  1221. padding: 16px 20px 40px 20px;
  1222. line-height: 26px;
  1223. text-indent: 2em;
  1224. }
  1225. }
  1226. .area-cascader {
  1227. &.el-popper.is-light {
  1228. background: #232323;
  1229. border-color: rgba(255, 212, 137, 0.3);
  1230. box-shadow: 0px 0px 12px rgba(255, 212, 137, 0.3);
  1231. .el-cascader-menu {
  1232. color: rgba(255, 212, 137, 0.6);
  1233. border-color: rgba(255, 212, 137, 0.3);
  1234. }
  1235. .el-cascader-node.in-active-path,
  1236. .el-cascader-node.is-active,
  1237. .el-cascader-node.is-selectable.in-checked-path {
  1238. color: #f7be5a;
  1239. background: transparent;
  1240. }
  1241. .el-radio__input.is-checked .el-radio__inner {
  1242. background: #f7be5a;
  1243. border-color: #f7be5a;
  1244. }
  1245. .el-cascader-node:not(.is-disabled):hover,
  1246. .el-cascader-node:not(.is-disabled):focus,
  1247. .el-cascader-node:not(.is-disabled):hover {
  1248. background: rgba(255, 212, 137, 0.2);
  1249. }
  1250. }
  1251. .el-radio__inner {
  1252. background-color: rgba(255, 212, 137, 0.3);
  1253. border-color: rgba(255, 212, 137, 0.6);
  1254. }
  1255. &.el-popper.is-light .el-popper__arrow:before {
  1256. background: #232323;
  1257. border-color: rgba(255, 212, 137, 0.3);
  1258. }
  1259. }
  1260. </style>