index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  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 yes-events">
  7. <div class="btn-common">四川省-简阳市-平泉街道</div>
  8. </div>
  9. </div>
  10. <!-- 顶部基础 tabs -->
  11. <div class="base-tabs yes-events">
  12. <div v-for="tab in baseTabs" :key="tab" class="tab-item" :class="{ active: activeBaseTab === tab }"
  13. @click="handleBaseTabClick(tab)">
  14. {{ tab }}
  15. </div>
  16. </div>
  17. <div class="btn-common smart-farm-btn yes-events" @click="handleSmartFarmClick">智慧农场</div>
  18. <!-- 地图图例 -->
  19. <!-- <map-legend></map-legend> -->
  20. <land-use-legend @change="handleLegendChange"></land-use-legend>
  21. <div class="show-point yes-events" v-show="showPoint" @click="handleShowPointClick"></div>
  22. </div>
  23. </div>
  24. <div ref="mapRef" class="bottom-map"></div>
  25. <track-dialog></track-dialog>
  26. </template>
  27. <script setup>
  28. import "./map/mockFarmLayer";
  29. import StaticMapLayers from "@/components/static_map_change/Layers.js";
  30. import StaticMapPointLayers from "@/components/static_map_change/pointLayer.js"
  31. import { onMounted, onUnmounted, ref, nextTick } from "vue";
  32. import fnHeader from "@/components/fnHeader.vue";
  33. import landUseLegend from "./components/landUseLegend.vue";
  34. import WarningMap from "./warningMap";
  35. import trackDialog from "./components/trackDialog.vue";
  36. import AlarmLayer from "./map/alarmLayer";
  37. import DistributionLayer from "./map/distributionLayer";
  38. import BoundaryLayer from "./map/boundaryLayer";
  39. import eventBus from "@/api/eventBus";
  40. import { useStore } from "vuex";
  41. import { useRouter, useRoute } from "vue-router";
  42. let store = useStore();
  43. const router = useRouter();
  44. const route = useRoute();
  45. let warningMap = new WarningMap();
  46. let alarmLayer = null;
  47. let staticMapLayers = null;
  48. let distributionLayer = null;
  49. let staticMapPointLayers = null;
  50. let boundaryLayer = null;
  51. const mapRef = ref(null);
  52. const treeRef = ref(null);
  53. const treeActionData = ref([]);
  54. // 保存原始数据,用于恢复
  55. const originalTreeData = ref([]);
  56. // 物候期分布下,当前激活的"二级"节点(只允许一个)
  57. const activePhenologySecondId = ref(null);
  58. // 当前选中的年份和季度
  59. const currentYear = ref(2025);
  60. const currentQuarter = ref(1);
  61. const isLandRecognition = ref(false);
  62. // 顶部基础 tabs
  63. const baseTabs = ["物候期分布", "长势等级", "水利", "灌渠与泵站", "资源", "导出报告"];
  64. const activeBaseTab = ref("物候期分布");
  65. const warningLayers = ref({});
  66. const showPoint = ref(false)
  67. const handleBaseTabClick = (tab) => {
  68. activeBaseTab.value = tab;
  69. showPoint.value = false
  70. staticMapPointLayers.hidePoint()
  71. if (tab === "资源") {
  72. staticMapPointLayers.showPoint()
  73. }else if (tab === "灌渠与泵站") {
  74. showPoint.value = true
  75. }
  76. };
  77. const handleSmartFarmClick = () => {
  78. window.open("https://feiniao-pc-gly.feiniaotech.com/#/login");
  79. };
  80. const handleShowPointClick = () => {
  81. eventBus.emit("chat:showTrackDialog")
  82. }
  83. onMounted(async () => {
  84. // 使用 nextTick 确保 DOM 已经渲染完成,地图容器有正确的尺寸
  85. await nextTick();
  86. warningMap.initMap(store.getters.userinfo.location, mapRef.value);
  87. // 地图初始化后,更新地图尺寸以确保正确渲染
  88. if (warningMap.kmap && warningMap.kmap.map) {
  89. // 使用 setTimeout 确保地图容器尺寸已计算
  90. setTimeout(() => {
  91. warningMap.kmap.map.updateSize();
  92. }, 0);
  93. }
  94. alarmLayer = new AlarmLayer(warningMap.kmap);
  95. staticMapLayers = new StaticMapLayers(warningMap.kmap);
  96. staticMapPointLayers = new StaticMapPointLayers(warningMap.kmap);
  97. distributionLayer = new DistributionLayer(warningMap.kmap);
  98. boundaryLayer = new BoundaryLayer(warningMap.kmap);
  99. await getSpeciesListData();
  100. getDistributionData();
  101. // 数据加载完成后,再次更新地图尺寸以确保正确渲染
  102. if (warningMap.kmap && warningMap.kmap.map) {
  103. setTimeout(() => {
  104. warningMap.kmap.map.updateSize();
  105. }, 100);
  106. }
  107. // 胜华村的村界
  108. getVillageBoundary()
  109. eventBus.emit("warningMap:init", warningMap.kmap);
  110. // 检查是否从地块识别页面跳转过来
  111. if (route.query.wkt) {
  112. // 使用nextTick确保所有图层都已初始化
  113. await nextTick();
  114. // 解码WKT数据
  115. const wkt = decodeURIComponent(route.query.wkt);
  116. if (wkt) {
  117. // 显示地块识别模式
  118. isLandRecognition.value = true;
  119. // 将WKT转换为distributionLayer需要的格式
  120. const plotData = {
  121. geom: wkt,
  122. color: "#00A342", // 绿色,与地块识别页面的颜色一致
  123. label: "识别地块",
  124. };
  125. // 在地图上显示地块
  126. if (distributionLayer) {
  127. try {
  128. distributionLayer.setAreaGeometry([plotData.geom]);
  129. } catch (error) {
  130. console.error("初始化地块数据失败:", error);
  131. }
  132. }
  133. }
  134. }
  135. // 图例数据
  136. eventBus.on("alarmList:warningLayers", (data) => {
  137. warningLayers.value = data;
  138. });
  139. // 监听图表组件的地图更新事件
  140. eventBus.on("chartList:updateMap", async ({ statType }) => {
  141. if (!distributionLayer) return;
  142. // 使用 statType 参数请求地图数据
  143. getDistributionData(statType);
  144. });
  145. // 预警分布图层联动:仅在"预警分布"tab 显示时,才在地图上显示对应图层
  146. eventBus.on("alarmList:changeMapLayer", ({ name, legendUrl }) => {
  147. // 47 行:只在 activeBaseTab === '预警分布' 时显示预警列表
  148. // 这里保持一致:只有在该 tab 下才显示地图图层,否则直接隐藏
  149. if (activeBaseTab.value !== "预警分布") {
  150. staticMapLayers && staticMapLayers.hideAll();
  151. return;
  152. }
  153. if (legendUrl) {
  154. staticMapLayers && staticMapLayers.showSingle(name, true);
  155. } else {
  156. let text = "";
  157. if (name === "日间温度") {
  158. text = "从化地块日温";
  159. } else if (name === "夜间温度") {
  160. text = "从化地块夜温";
  161. } else if (name === "土壤水分") {
  162. text = "从化地块水分";
  163. }
  164. if (text !== "") {
  165. staticMapLayers && staticMapLayers.showSingle(text, true);
  166. } else {
  167. staticMapLayers && staticMapLayers.hideAll();
  168. }
  169. }
  170. });
  171. // 窗口大小改变时更新地图尺寸
  172. const handleResize = () => {
  173. if (warningMap.kmap && warningMap.kmap.map) {
  174. warningMap.kmap.map.updateSize();
  175. }
  176. };
  177. window.addEventListener("resize", handleResize);
  178. // 在组件卸载时清理
  179. onUnmounted(() => {
  180. window.removeEventListener("resize", handleResize);
  181. });
  182. });
  183. // 加载东莞市行政区边界(使用远程 GeoJSON 数据)
  184. const getVillageBoundary = async () => {
  185. const url =
  186. "https://birdseye-img.sysuimars.com/geojson/mlxy/%E4%B8%9C%E8%8E%9E%E8%A1%8C%E6%94%BF%E5%8C%BA.geojson";
  187. try {
  188. const response = await fetch(url);
  189. if (!response.ok) {
  190. console.error("获取行政区 GeoJSON 失败:", response.statusText);
  191. return;
  192. }
  193. const geojson = await response.json();
  194. if (!geojson || !Array.isArray(geojson.features)) {
  195. console.error("行政区 GeoJSON 格式不正确:", geojson);
  196. return;
  197. }
  198. // 将 GeoJSON MultiPolygon 转成 boundaryLayer 需要的 WKT 格式数据
  199. const geoJsonMultiPolygonToWkt = (geometry) => {
  200. if (!geometry || geometry.type !== "MultiPolygon" || !Array.isArray(geometry.coordinates)) {
  201. return "";
  202. }
  203. const polygons = geometry.coordinates
  204. .map((polygon) => {
  205. // polygon: [ [ [x, y], ... ] ] => 每个 polygon 可能包含多个 ring
  206. const rings = polygon
  207. .map((ring) => {
  208. const coords = ring.map((coord) => `${coord[0]} ${coord[1]}`).join(", ");
  209. return `(${coords})`;
  210. })
  211. .join(", ");
  212. return `(${rings})`;
  213. })
  214. .join(", ");
  215. return `MULTIPOLYGON (${polygons})`;
  216. };
  217. const villageBoundary = geojson.features
  218. .map((f, index) => {
  219. const wkt = geoJsonMultiPolygonToWkt(f.geometry);
  220. if (!wkt) return null;
  221. const props = f.properties || {};
  222. return {
  223. id: props.code || props["区划码"] || index,
  224. name: props["地名"] || props.ENG_NAME || "行政区边界",
  225. geom: wkt,
  226. };
  227. })
  228. .filter((item) => item);
  229. if (!villageBoundary.length) {
  230. console.warn("未能从 GeoJSON 中解析出有效的行政区边界");
  231. return;
  232. }
  233. boundaryLayer && boundaryLayer.initData(villageBoundary);
  234. } catch (error) {
  235. console.error("加载行政区 GeoJSON 出错:", error);
  236. }
  237. };
  238. // 时间轴
  239. eventBus.on("weatherTime:changeTime", ({ index, year, quarter }) => {
  240. handleTimeChange(index, year, quarter);
  241. });
  242. const handleTimeChange = (index, year, quarter) => {
  243. // 更新当前选中的年份和季度
  244. currentYear.value = year;
  245. currentQuarter.value = quarter;
  246. // 如果当前在作物分布或物候期分布tab,需要重新加载地图数据
  247. if (activeBaseTab.value === "作物分布" || activeBaseTab.value === "物候期分布") {
  248. // 重新获取当前选中的节点数据
  249. if (treeRef.value) {
  250. const checkedNodes = treeRef.value.getCheckedNodes(false, true);
  251. if (checkedNodes && checkedNodes.length > 0) {
  252. getTreeChecks(checkedNodes[0], { checkedNodes });
  253. }
  254. }
  255. }
  256. };
  257. sessionStorage.removeItem("farmId");
  258. onUnmounted(() => {
  259. eventBus.off("alarmList:changeMapLayer");
  260. eventBus.off("chartList:updateMap");
  261. // 时间轴
  262. eventBus.off("weatherTime:changeTime");
  263. });
  264. const getSpeciesListData = async () => {
  265. const res = await VE_API.species.speciesList();
  266. treeActionData.value = res.data;
  267. // 保存原始数据副本(深拷贝)
  268. originalTreeData.value = JSON.parse(JSON.stringify(res.data));
  269. };
  270. const getDistributionData = async (statType = null) => {
  271. const { data } = await VE_API.agri_land_crop.queryDistribution({ statType: statType || 0 });
  272. // 把点位图层去掉:不返回 centerPoint,只保留地块相关信息
  273. const list = Array.isArray(data)
  274. ? data.map((item) => {
  275. const { centerPoint, ...rest } = item || {};
  276. return rest;
  277. })
  278. : [];
  279. distributionLayer.initData(list);
  280. };
  281. const fetchFarmList = (phenologyIds) => {
  282. const params = {
  283. year: currentYear.value,
  284. quarter: currentQuarter.value,
  285. phenologyIds: phenologyIds || [],
  286. };
  287. return new Promise((resolve, reject) => {
  288. VE_API.warning
  289. .fetchFarmList(params)
  290. .then((res) => {
  291. if (res.code === 0 && res.data && res.data.length > 0) {
  292. // 将接口数据转换为地图需要的格式
  293. const cropData = res.data.map((item) => {
  294. // 组合作物名称和物候期名称作为 label
  295. const label = item.phenologyName
  296. ? `${item.speciesName}-${item.phenologyName}`
  297. : item.speciesName;
  298. return {
  299. ...item,
  300. label: label,
  301. color: item.speciesColor || "#2199F8",
  302. centerPoint: item.point, // 使用 point 作为 centerPoint
  303. };
  304. });
  305. // 渲染作物数据到地图
  306. distributionLayer.initData(cropData, "label");
  307. resolve(cropData);
  308. } else {
  309. // 接口返回空数据时,清空地图
  310. distributionLayer.initData([]);
  311. resolve([]);
  312. }
  313. })
  314. .catch((error) => {
  315. // 错误时也清空地图
  316. distributionLayer.initData([]);
  317. reject(error);
  318. });
  319. });
  320. };
  321. // 根据节点 id 在当前树数据中计算其层级(1/2/3)及所属的二级节点 id
  322. const getNodeLevelInfo = (id) => {
  323. const roots = treeActionData.value || [];
  324. for (const root of roots) {
  325. if (root.id === id) {
  326. return { level: 1, secondId: null };
  327. }
  328. const rootChildren = root.items || root.children || [];
  329. for (const second of rootChildren) {
  330. if (second.id === id) {
  331. return { level: 2, secondId: second.id };
  332. }
  333. const secondChildren = second.items || second.children || [];
  334. for (const third of secondChildren) {
  335. if (third.id === id) {
  336. return { level: 3, secondId: second.id };
  337. }
  338. }
  339. }
  340. }
  341. return { level: 0, secondId: null };
  342. };
  343. const getTreeChecks = async (nodeData, data) => {
  344. const { checkedNodes } = data;
  345. let finalCheckedNodes = checkedNodes;
  346. // 物候期分布:限制"二级只能选一个,三级不限个数"
  347. if (
  348. (activeBaseTab.value === "物候期分布" ||
  349. activeBaseTab.value === "预警分布" ||
  350. activeBaseTab.value === "农场分布") &&
  351. treeRef.value
  352. ) {
  353. const tree = treeRef.value;
  354. const { level, secondId } = getNodeLevelInfo(nodeData.id);
  355. if (level === 2 || level === 3) {
  356. const currentSecondId = secondId;
  357. // 判断当前这个二级分支下,是否还有被选中的节点(包含二级自己或其子级)
  358. const hasAnyCheckedInCurrentSecond = checkedNodes.some((n) => {
  359. const info = getNodeLevelInfo(n.id);
  360. return info.secondId === currentSecondId || (info.level === 2 && n.id === currentSecondId);
  361. });
  362. if (hasAnyCheckedInCurrentSecond) {
  363. // 仍有节点被选中 → 保证只有当前这个二级分支被选中,其它分支全部取消
  364. activePhenologySecondId.value = currentSecondId;
  365. const roots = treeActionData.value || [];
  366. roots.forEach((root) => {
  367. const rootChildren = root.items || root.children || [];
  368. rootChildren.forEach((second) => {
  369. if (second.id !== currentSecondId) {
  370. // 取消其它二级及其所有子级勾选
  371. tree.setChecked(second.id, false, true);
  372. }
  373. // 对于当前二级节点,不手动设置其选中状态
  374. // 让 Element Plus 根据子节点的选中状态自动计算半选中状态
  375. // 这样当部分三级节点被选中时,二级节点会自动显示半选中状态
  376. });
  377. });
  378. } else {
  379. // 当前二级分支已经被全部取消勾选 → 清空激活记录,允许"全部不选"
  380. activePhenologySecondId.value = null;
  381. }
  382. }
  383. // 对树进行了 setChecked 操作后,重新从树组件拿一次最新的选中节点列表
  384. // 这里只需要最后一层(叶子节点 / 有 wktArr 的节点),不用父级节点
  385. const allCheckedNodes = treeRef.value.getCheckedNodes(false, true);
  386. finalCheckedNodes = allCheckedNodes.filter((n) => !n.children || n.children.length === 0 || n.wktArr);
  387. }
  388. // 任意 tab 下,最终都用当前选中的节点驱动地图渲染
  389. // 提取最后一级节点的 id 到数组(没有子节点的叶子节点)
  390. const field = activeBaseTab.value === "物候期分布" || activeBaseTab.value === "农场分布" ? "originalId" : "id";
  391. const lastLevelIds = finalCheckedNodes
  392. .filter((n) => (!n.items || n.items.length === 0) && (!n.children || n.children.length === 0))
  393. .map((n) => n[field]);
  394. if (lastLevelIds && lastLevelIds.length === 0) {
  395. distributionLayer.initData([]);
  396. return;
  397. }
  398. if (activeBaseTab.value === "物候期分布") {
  399. const phenologyData = await getDistributionData(null, lastLevelIds);
  400. distributionLayer.initData(phenologyData, "phenologyName");
  401. return;
  402. }
  403. if (activeBaseTab.value === "农场分布") {
  404. await fetchFarmList(lastLevelIds);
  405. return;
  406. }
  407. // 并发请求所有数据,等待所有 Promise 完成
  408. const promises = lastLevelIds.map((id) => {
  409. const node = finalCheckedNodes.find((n) => n.id === id);
  410. if (node) {
  411. return getDistributionData(node.id);
  412. }
  413. return Promise.resolve([]);
  414. });
  415. // 等待所有请求完成,并将结果扁平化
  416. const results = await Promise.all(promises);
  417. const finalMapData = results.flat();
  418. distributionLayer.initData(finalMapData);
  419. };
  420. // 处理图例变化
  421. const handleLegendChange = (data) => {
  422. console.log("图例变化:", data);
  423. // 通过 eventBus 将选中的类别信息传递给饼图组件
  424. if (data.checked) {
  425. eventBus.emit("landUseLegend:change", {
  426. category: data.category,
  427. nonGrain: data.nonGrain,
  428. children: data.children,
  429. });
  430. }
  431. };
  432. </script>
  433. <style lang="scss" scoped>
  434. .base-container {
  435. width: 100%;
  436. height: 100vh;
  437. color: #fff;
  438. position: absolute;
  439. box-sizing: border-box;
  440. z-index: 1;
  441. overflow: hidden;
  442. .content {
  443. width: 100%;
  444. height: calc(100% - 74px - 48px);
  445. padding: 16px 20px 0 27px;
  446. display: flex;
  447. justify-content: space-between;
  448. box-sizing: border-box;
  449. position: relative;
  450. .show-point{
  451. position: absolute;
  452. top: calc(50% - 250px);
  453. left: calc(50% - 250px);
  454. width: 500px;
  455. height: 500px;
  456. // background: red;
  457. z-index: 2;
  458. }
  459. .left,
  460. .right {
  461. width: calc(376px + 54px);
  462. height: 100%;
  463. box-sizing: border-box;
  464. // display: flex;
  465. }
  466. .right {
  467. // width: 395px;
  468. width: 376px;
  469. overflow: auto;
  470. position: relative;
  471. .list {
  472. width: 100%;
  473. height: 100%;
  474. }
  475. }
  476. .chart-wrap {
  477. padding: 8px;
  478. background: #101010;
  479. border: 1px solid #444444;
  480. }
  481. .btn-common {
  482. color: #f7be5a;
  483. font-size: 20px;
  484. font-family: "PangMenZhengDao";
  485. margin-right: 15px;
  486. border: 2px solid rgba(255, 212, 137, 0.3);
  487. border-radius: 4px;
  488. padding: 8px 14px 11px;
  489. background: rgba(29, 29, 29, 0.54);
  490. cursor: pointer;
  491. }
  492. .smart-farm-btn{
  493. position: fixed;
  494. top: 35px;
  495. right: 200px;
  496. padding: 10px 45px 13px;
  497. }
  498. .warning-top {
  499. display: flex;
  500. align-items: center;
  501. width: max-content;
  502. }
  503. .base-tabs {
  504. display: flex;
  505. position: fixed;
  506. top: 35px;
  507. left: 390px;
  508. .tab-item {
  509. border-radius: 6px;
  510. padding: 6px 15px 8px;
  511. margin-right: 12px;
  512. text-align: center;
  513. font-size: 20px;
  514. font-family: "PangMenZhengDao";
  515. color: #ffffff;
  516. background: rgba(37, 50, 57, 0.6);
  517. cursor: pointer;
  518. border: 2px solid transparent;
  519. &.active {
  520. background: rgba(115, 74, 2, 0.16);
  521. color: #FFD489;
  522. border-color: #FFD489;
  523. }
  524. }
  525. }
  526. }
  527. }
  528. .bottom-map {
  529. width: 100%;
  530. height: 100vh;
  531. position: absolute;
  532. z-index: 0;
  533. }
  534. </style>
  535. <style lang="less">
  536. .ol-scale-line {
  537. left: auto;
  538. right: 435px;
  539. bottom: 13px;
  540. .ol-scale-line-inner {
  541. max-width: 80px;
  542. width: 80px !important;
  543. color: #fff;
  544. border-color: #fff;
  545. }
  546. }
  547. .focus-farm-select {
  548. &.el-popper.is-light {
  549. background: #232323;
  550. border-color: rgba(255, 212, 137, 0.3);
  551. box-shadow: 0px 0px 12px rgba(255, 212, 137, 0.3);
  552. .el-select-dropdown__item {
  553. background: none;
  554. color: rgba(255, 212, 137, 0.6);
  555. }
  556. .el-select-dropdown__item.is-selected {
  557. background: rgba(255, 212, 137, 0.2);
  558. color: #ffd489;
  559. }
  560. }
  561. &.el-popper.is-light .el-popper__arrow:before {
  562. background: #232323;
  563. border-color: rgba(255, 212, 137, 0.3);
  564. }
  565. }
  566. .ol-popup-warning {
  567. position: relative;
  568. width: 295px;
  569. background: rgb(35, 35, 35, 0.86);
  570. color: #fff;
  571. font-size: 16px;
  572. border-radius: 4px;
  573. .warning-info-title {
  574. display: flex;
  575. padding: 6px 10px;
  576. background: rgba(255, 255, 255, 0.05);
  577. font-size: 18px;
  578. border-radius: 4px 4px 0 0;
  579. .icon {
  580. padding-right: 6px;
  581. }
  582. .close {
  583. position: absolute;
  584. right: 12px;
  585. top: 4px;
  586. }
  587. }
  588. .info-content {
  589. padding: 16px 20px 40px 20px;
  590. line-height: 26px;
  591. text-indent: 2em;
  592. }
  593. }
  594. .area-cascader {
  595. &.el-popper.is-light {
  596. background: #232323;
  597. border-color: rgba(255, 212, 137, 0.3);
  598. box-shadow: 0px 0px 12px rgba(255, 212, 137, 0.3);
  599. .el-cascader-menu {
  600. color: rgba(255, 212, 137, 0.6);
  601. border-color: rgba(255, 212, 137, 0.3);
  602. }
  603. .el-cascader-node.in-active-path,
  604. .el-cascader-node.is-active,
  605. .el-cascader-node.is-selectable.in-checked-path {
  606. color: #f7be5a;
  607. background: transparent;
  608. }
  609. .el-radio__input.is-checked .el-radio__inner {
  610. background: #f7be5a;
  611. border-color: #f7be5a;
  612. }
  613. .el-cascader-node:not(.is-disabled):hover,
  614. .el-cascader-node:not(.is-disabled):focus,
  615. .el-cascader-node:not(.is-disabled):hover {
  616. background: rgba(255, 212, 137, 0.2);
  617. }
  618. }
  619. .el-radio__inner {
  620. background-color: rgba(255, 212, 137, 0.3);
  621. border-color: rgba(255, 212, 137, 0.6);
  622. }
  623. .el-radio__inner::after {
  624. background: #000;
  625. }
  626. &.el-popper.is-light .el-popper__arrow:before {
  627. background: #232323;
  628. border-color: rgba(255, 212, 137, 0.3);
  629. }
  630. }
  631. </style>