Menu.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. <template>
  2. <template v-if="$store.state.menuState % 2">
  3. <div class="menu">
  4. <ul class="menu-list">
  5. <li
  6. class="menu-item"
  7. v-for="(menu, index) in currentMenu"
  8. :key="index"
  9. @click="click(index)"
  10. :class="{ active: activeIndex == index }"
  11. >
  12. <router-link
  13. :to="menu.path"
  14. v-if="menu?.children?.length"
  15. @mouseenter="subMenuShow(menu?.children, index)"
  16. >
  17. <el-tooltip
  18. class="item"
  19. effect="dark"
  20. :content="menu.text"
  21. placement="bottom"
  22. :show-after="500"
  23. :enterable="false"
  24. hide-after="10"
  25. >
  26. <div
  27. class="menu-icon svg-icon"
  28. :class="
  29. activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'
  30. "
  31. >
  32. <SvgIcon :svgid="menu.icon"></SvgIcon>
  33. </div>
  34. </el-tooltip>
  35. </router-link>
  36. <router-link :to="menu.path" v-else>
  37. <el-tooltip
  38. class="item"
  39. effect="dark"
  40. :content="menu.text"
  41. placement="bottom"
  42. :show-after="500"
  43. :enterable="false"
  44. hide-after="10"
  45. >
  46. <div
  47. class="menu-icon svg-icon"
  48. :class="
  49. activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'
  50. "
  51. >
  52. <SvgIcon :svgid="menu.icon"></SvgIcon>
  53. </div>
  54. </el-tooltip>
  55. </router-link>
  56. <!-- <el-tooltip
  57. v-else
  58. class="item"
  59. effect="dark"
  60. :content="menu.text"
  61. placement="bottom"
  62. :show-after="500"
  63. :enterable="false"
  64. hide-after="10"
  65. >
  66. <div
  67. class="menu-icon svg-icon"
  68. :class="activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'"
  69. >
  70. <SvgIcon :svgid="menu.icon"></SvgIcon>
  71. </div>
  72. </el-tooltip> -->
  73. </li>
  74. </ul>
  75. </div>
  76. <div class="sub-menu" v-show="isShowSubMenu" @mouseleave="subMenuHide">
  77. <ul class="menu-list">
  78. <li
  79. class="menu-item"
  80. v-for="(menus, indexs) in subMenu"
  81. @click="subclick(indexs)"
  82. :key="indexs"
  83. :class="{ active: subIndex == parentIndex + '' + indexs }"
  84. >
  85. <router-link :to="menus.path">
  86. <div class="menu-icon svg-icon">
  87. <!-- <SvgIcon :svgid="menu.icon"></SvgIcon> -->
  88. </div>
  89. <div
  90. class="sub-menu-text"
  91. :class="subIndex == activeIndex + '' + indexs ? 'green' : 'gray'"
  92. >
  93. {{ menus.text }}
  94. </div>
  95. </router-link>
  96. </li>
  97. </ul>
  98. </div>
  99. <div
  100. class="icon-fixed svg-icon"
  101. :class="fixed ? 'svg-icon-green' : 'svg-icon-gray'"
  102. @click="handleClickFixed"
  103. >
  104. <SvgIcon svgid="svg-unfixed" v-if="fixed == false"></SvgIcon>
  105. <SvgIcon svgid="svg-fixed" v-if="fixed == true"></SvgIcon>
  106. </div>
  107. </template>
  108. <template v-else>
  109. <div class="menu">
  110. <ul class="menu-list">
  111. <li
  112. class="menu-item"
  113. v-for="(menu, index) in currentMenu"
  114. :key="index"
  115. @click="click(index)"
  116. :class="{ active: activeIndex == index }"
  117. >
  118. <router-link
  119. :to="menu.path"
  120. v-if="menu?.children?.length"
  121. @mouseenter="subMenuShow(menu?.children, index)"
  122. >
  123. <el-tooltip
  124. class="item"
  125. effect="dark"
  126. :content="menu.text"
  127. placement="bottom"
  128. :show-after="500"
  129. :enterable="false"
  130. hide-after="10"
  131. >
  132. <div
  133. class="menu-icon svg-icon"
  134. :class="
  135. activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'
  136. "
  137. >
  138. <SvgIcon :svgid="menu.icon"></SvgIcon>
  139. </div>
  140. </el-tooltip>
  141. </router-link>
  142. <router-link :to="menu.path" v-else>
  143. <el-tooltip
  144. class="item"
  145. effect="dark"
  146. :content="menu.text"
  147. placement="bottom"
  148. :show-after="500"
  149. :enterable="false"
  150. hide-after="10"
  151. >
  152. <div
  153. class="menu-icon svg-icon"
  154. :class="
  155. activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'
  156. "
  157. >
  158. <SvgIcon :svgid="menu.icon"></SvgIcon>
  159. </div>
  160. </el-tooltip>
  161. </router-link>
  162. <!-- <el-tooltip
  163. v-else
  164. class="item"
  165. effect="dark"
  166. :content="menu.text"
  167. placement="bottom"
  168. :show-after="500"
  169. :enterable="false"
  170. hide-after="10"
  171. >
  172. <div
  173. class="menu-icon svg-icon"
  174. :class="activeIndex == index ? 'svg-icon-green' : 'svg-icon-gray'"
  175. >
  176. <SvgIcon :svgid="menu.icon"></SvgIcon>
  177. </div>
  178. </el-tooltip> -->
  179. </li>
  180. </ul>
  181. </div>
  182. <div class="sub-menu" v-show="isShowSubMenu" @mouseleave="subMenuHide">
  183. <ul class="menu-list">
  184. <li
  185. class="menu-item"
  186. v-for="(menus, indexs) in subMenu"
  187. @click="subclick(indexs)"
  188. :key="indexs"
  189. :class="{ active: subIndex == parentIndex + '' + indexs }"
  190. >
  191. <router-link :to="menus.path">
  192. <div class="menu-icon svg-icon">
  193. <!-- <SvgIcon :svgid="menu.icon"></SvgIcon> -->
  194. </div>
  195. <div
  196. class="sub-menu-text"
  197. :class="subIndex == activeIndex + '' + indexs ? 'green' : 'gray'"
  198. >
  199. {{ menus.text }}
  200. </div>
  201. </router-link>
  202. </li>
  203. </ul>
  204. </div>
  205. <div
  206. class="icon-fixed svg-icon"
  207. :class="fixed ? 'svg-icon-green' : 'svg-icon-gray'"
  208. @click="handleClickFixed"
  209. >
  210. <SvgIcon svgid="svg-unfixed" v-if="fixed == false"></SvgIcon>
  211. <SvgIcon svgid="svg-fixed" v-if="fixed == true"></SvgIcon>
  212. </div>
  213. </template>
  214. </template>
  215. <script>
  216. import SvgIcon from "@com/coms/icon/svg-icon.vue";
  217. import { fillterMenuRoutes } from "@/utills/handleRoutes.js";
  218. export default {
  219. components: {
  220. SvgIcon,
  221. },
  222. props: {},
  223. data() {
  224. return {
  225. currRoot: "home",
  226. menuData: [
  227. {
  228. id: "stateMonitor",
  229. text: "全景监视",
  230. data: [],
  231. },
  232. {
  233. id: "economicsOperation",
  234. text: "经济运行",
  235. data: [],
  236. },
  237. {
  238. id: "integratedAlarm",
  239. text: "综合报警",
  240. data: [],
  241. },
  242. {
  243. id: "health",
  244. text: "智慧检修",
  245. data: [],
  246. },
  247. {
  248. id: "powerGenerating",
  249. text: "发电能力分析",
  250. data: [],
  251. },
  252. {
  253. id: "report",
  254. text: "智能报表",
  255. data: [],
  256. },
  257. ],
  258. activeIndex: 0,
  259. isShowSubMenu: false,
  260. parentIndex: -1,
  261. subMenu: [],
  262. subIndex: -1,
  263. fixed: true,
  264. reFresh: true,
  265. rePagePath: [
  266. "/economicsOperation/stationAnalyse/stationElectricAnalyse",
  267. "/economicsOperation/windAnalyse/singleWindAnasyle",
  268. ],
  269. };
  270. },
  271. methods: {
  272. handleClickFixed() {
  273. this.fixed = !this.fixed;
  274. this.$store.commit("changeIsFixed", this.fixed);
  275. },
  276. fillterMenuRoutes,
  277. click(index) {
  278. // this.reFresh = false;
  279. this.activeIndex = index;
  280. this.subIndex = index + "" + 0;
  281. },
  282. subMenuShow(children, index) {
  283. this.isShowSubMenu = true;
  284. this.parentIndex = index;
  285. this.subMenu = Array.isArray(children) ? children : [];
  286. },
  287. subMenuHide() {
  288. this.isShowSubMenu = false;
  289. this.parentIndex = -1;
  290. this.subMenu = [];
  291. },
  292. subclick(index) {
  293. this.reFresh = false;
  294. this.activeIndex = this.parentIndex;
  295. this.subIndex = this.activeIndex + "" + index;
  296. this.isShowSubMenu = false;
  297. },
  298. },
  299. created() {
  300. if (this.$store.state.moudleName) {
  301. this.currRoot = this.menuData.find(
  302. (i) => i.text == this.$store.state.moudleName
  303. )?.id;
  304. }
  305. },
  306. computed: {
  307. currentMenu() {
  308. let stateRoutes = JSON.parse(
  309. JSON.stringify(this.$store.state.routes.routes)
  310. );
  311. if (stateRoutes.length) {
  312. let routeObj = stateRoutes.find((i) => i.path == "/" + this.currRoot);
  313. let currData = [];
  314. if (routeObj && Object.keys(routeObj).length) {
  315. let a = JSON.parse(JSON.stringify(routeObj));
  316. if (a?.children?.length) {
  317. a.children.forEach((path) => {
  318. if (!path.hidden) {
  319. if (path.showChild != true && path?.children?.length) {
  320. currData.push({
  321. text: path.meta.title,
  322. icon: path.meta.icon,
  323. fullPath: path.path,
  324. path: `/${this.currRoot}/${path.path}`,
  325. children: [],
  326. });
  327. let cu = currData.find((i) => i.text == path.meta.title);
  328. path.children.forEach((cputh) => {
  329. let caputh = "";
  330. if (cputh.path.includes(":")) {
  331. caputh = `${cputh.path.substring(
  332. 0,
  333. cputh.path.indexOf("/:")
  334. )}/SXJ_KGDL_GJY_FDC_STA/SXJ_KGDL_GJY_F_WT_0001_EQ`;
  335. } else if (cputh.path == "decision1Mx") {
  336. caputh = "";
  337. } else {
  338. caputh = cputh.path;
  339. }
  340. if (caputh.length) {
  341. cu["children"].push({
  342. text: cputh.meta.title,
  343. icon: cputh.meta.icon,
  344. path: `/${this.currRoot}/${path.path}/${caputh}`,
  345. children: [],
  346. });
  347. }
  348. });
  349. cu.path = cu.children[0].path;
  350. } else {
  351. currData.push({
  352. text: path.meta.title,
  353. icon: path.meta.icon,
  354. fullPath: path.path,
  355. path: `/${this.currRoot}/${path.path}`,
  356. children: [],
  357. });
  358. }
  359. }
  360. });
  361. this.$store.commit("changeMenuData", currData);
  362. // console.log(currData);
  363. return currData;
  364. } else {
  365. this.$store.commit("changeMenuData", []);
  366. return [];
  367. }
  368. } else {
  369. this.$store.commit("changeMenuData", []);
  370. return [];
  371. }
  372. } else {
  373. this.$store.commit("changeMenuData", []);
  374. return [];
  375. }
  376. },
  377. isFixed() {
  378. return JSON.parse(localStorage.getItem("isFixed"));
  379. },
  380. },
  381. watch: {
  382. isFixed: {
  383. handler(val) {
  384. if (!val) {
  385. this.$store.commit("changeIsFixed", true);
  386. } else {
  387. this.fixed = val;
  388. }
  389. },
  390. immediate: true,
  391. },
  392. // 监听路由
  393. $route: {
  394. handler: function (val, oldVal) {
  395. // if (this.reFresh) {
  396. this.menuData.some((element, index) => {
  397. if (val.path.includes(element.id)) {
  398. this.$nextTick(() => {
  399. this.currRoot = element.id;
  400. this.$nextTick(() => {
  401. this.currentMenu.forEach((element, index) => {
  402. if (val.path.includes(element.fullPath)) {
  403. this.activeIndex = index;
  404. element.children &&
  405. element.children.forEach((i, inx) => {
  406. if (val.path == i.path) {
  407. this.subIndex = index + "" + inx;
  408. }
  409. });
  410. return true;
  411. }
  412. });
  413. });
  414. });
  415. return true;
  416. }
  417. });
  418. if (val.path.includes("/home")) {
  419. this.currRoot = "home";
  420. this.activeIndex = 0;
  421. return;
  422. }
  423. // }
  424. // this.reFresh = true;
  425. const someRes = this.rePagePath.some((path) => {
  426. return path === val.path;
  427. });
  428. if (someRes) {
  429. this.$nextTick(() => {
  430. this.$store.commit("changeMenuState");
  431. });
  432. } else {
  433. this.$store.commit("changeMenuState");
  434. }
  435. },
  436. //深度观察监听
  437. deep: true,
  438. },
  439. },
  440. };
  441. </script>
  442. <style lang="less">
  443. .menu {
  444. padding-top: 20px;
  445. z-index: 3001;
  446. .menu-list {
  447. margin: 0;
  448. padding: 0;
  449. list-style: none;
  450. .menu-item {
  451. padding: 20px 0;
  452. text-align: center;
  453. .menu-icon {
  454. display: flex;
  455. justify-content: center;
  456. }
  457. &.active i {
  458. color: #05bb4c;
  459. transition: color 1s;
  460. }
  461. }
  462. }
  463. i {
  464. font-size: 16px;
  465. color: rgba(255, 255, 255, 50%);
  466. }
  467. }
  468. .sub-menu {
  469. position: absolute;
  470. top: 0;
  471. left: 50px;
  472. width: 184px;
  473. height: 100%;
  474. padding-top: 10px;
  475. background: fade(#192a26, 75);
  476. border-right: 1px solid fade(@green, 50);
  477. box-shadow: inset 11px 0px 20px 0px fade(#021412, 60);
  478. .menu-list {
  479. margin: 0;
  480. padding: 0;
  481. list-style: none;
  482. .menu-item {
  483. display: flex;
  484. text-align: center;
  485. line-height: 1.5;
  486. padding: 8px 0;
  487. background: #121d1c;
  488. a {
  489. display: flex;
  490. width: 100%;
  491. height: 100%;
  492. padding: 0 10px;
  493. font-size: 14px;
  494. text-decoration: unset;
  495. white-space: nowrap;
  496. .menu-icon {
  497. display: flex;
  498. align-items: center;
  499. svg {
  500. width: 14px;
  501. height: 14px;
  502. use {
  503. fill: fade(@green, 75);
  504. }
  505. }
  506. }
  507. }
  508. &.active {
  509. background: #323e70;
  510. .menu-icon {
  511. display: flex;
  512. svg use {
  513. fill: fade(@white, 75);
  514. }
  515. }
  516. }
  517. .sub-menu-text {
  518. margin-left: 10px;
  519. color: @gray-l;
  520. }
  521. & + .menu-item {
  522. border-top: 1px solid fade(@darkgray, 40);
  523. }
  524. }
  525. }
  526. i {
  527. font-size: 2.222vh;
  528. color: rgba(255, 255, 255, 50%);
  529. }
  530. }
  531. .icon-fixed {
  532. padding-bottom: 20px;
  533. }
  534. </style>