index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. <template>
  2. <!-- left+top布局 !-->
  3. <template v-if="layout == 'mix'">
  4. <nav ref="navbar" class="adminui-header">
  5. <div id="header" class="adminui-header-left">
  6. <div class="logo-bar">
  7. <img class="logo" src="/img/logo.svg" />
  8. <span>{{ appName }}</span>
  9. </div>
  10. <div
  11. class="panel-item hidden-sm-and-down"
  12. @click="
  13. $store.commit(
  14. 'TOGGLE_menuIsCollapse',
  15. !$store.state.global.menuIsCollapse
  16. )
  17. "
  18. >
  19. <el-icon
  20. ><indent v-if="menuIsCollapse" /><outdent v-else
  21. /></el-icon>
  22. </div>
  23. <div
  24. class="panel-item hidden-sm-and-down"
  25. @click="refreshTab()"
  26. >
  27. <el-icon><refresh /></el-icon>
  28. </div>
  29. <el-menu
  30. v-if="!ismobile"
  31. class="nav"
  32. mode="horizontal"
  33. :ellipsis="false"
  34. >
  35. <el-menu-item
  36. v-for="menu in topMenuList"
  37. :index="menu.meta.id"
  38. :key="menu.meta.id"
  39. :ref="menu.meta.id"
  40. @click="showMenu(menu)"
  41. >
  42. <el-icon size="16px"
  43. ><component
  44. :is="menu.meta.icon || el - icon - menu"
  45. /></el-icon>
  46. {{ $t2(menu.meta.code) || menu.meta.title }}
  47. </el-menu-item>
  48. <el-sub-menu>
  49. <template #title
  50. ><el-icon size="16px"><more></more></el-icon
  51. >更多</template
  52. >
  53. <el-menu-item
  54. v-for="menu in topHideMenuList"
  55. :index="menu.meta.id"
  56. :key="menu.meta.id"
  57. :ref="menu.meta.id"
  58. @click="showMenu(menu)"
  59. ><el-icon size="16px"
  60. ><component
  61. :is="menu.meta.icon || el - icon - menu"
  62. /></el-icon>
  63. {{
  64. $t2(menu.meta.code) || menu.meta.title
  65. }}</el-menu-item
  66. >
  67. </el-sub-menu>
  68. </el-menu>
  69. </div>
  70. <div class="adminui-header-right">
  71. <userbar></userbar>
  72. </div>
  73. </nav>
  74. <section class="aminui-wrapper">
  75. <div
  76. v-if="(!ismobile && nextMenu.length > 0) || !pmenu.component"
  77. :class="
  78. menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'
  79. "
  80. >
  81. <!-- <div v-if="!menuIsCollapse" class="adminui-side-top">
  82. <h2>{{$t2(pmenu.meta.code) || pmenu.meta.title }}</h2>
  83. </div> -->
  84. <div class="adminui-side-scroll">
  85. <el-scrollbar>
  86. <el-menu
  87. :default-active="active"
  88. router
  89. :collapse="menuIsCollapse"
  90. :unique-opened="$CONFIG.MENU_UNIQUE_OPENED"
  91. >
  92. <NavMenu :navMenus="nextMenu"></NavMenu>
  93. </el-menu>
  94. </el-scrollbar>
  95. </div>
  96. <!-- <div class="adminui-side-bottom" @click="$store.commit('TOGGLE_menuIsCollapse', !$store.state.global.menuIsCollapse)">
  97. <el-icon size="12px"><expand v-if="menuIsCollapse"/><fold v-else /></el-icon>
  98. </div> -->
  99. </div>
  100. <Side-m v-if="ismobile"></Side-m>
  101. <div class="aminui-body el-container">
  102. <Tags v-if="!ismobile && layoutTags"></Tags>
  103. <div class="adminui-main" id="adminui-main">
  104. <Topbar2 v-if="!ismobile && toolbarTags"></Topbar2>
  105. <router-view v-slot="{ Component }">
  106. <keep-alive>
  107. <component :is="Component" :key="$route.fullPath" />
  108. </keep-alive>
  109. </router-view>
  110. <iframe-view></iframe-view>
  111. </div>
  112. </div>
  113. </section>
  114. </template>
  115. <!-- 左侧布局 -->
  116. <template v-else-if="layout == 'left'">
  117. <header class="adminui-header">
  118. <div class="adminui-header-left">
  119. <div class="logo-bar">
  120. <img class="logo" src="/img/logo.svg" />
  121. <span>{{ appName }}</span>
  122. </div>
  123. <div
  124. class="panel-item hidden-sm-and-down"
  125. @click="
  126. $store.commit(
  127. 'TOGGLE_menuIsCollapse',
  128. !$store.state.global.menuIsCollapse
  129. )
  130. "
  131. >
  132. <el-icon
  133. ><indent v-if="menuIsCollapse" /><outdent v-else
  134. /></el-icon>
  135. </div>
  136. <div
  137. class="panel-item hidden-sm-and-down"
  138. @click="refreshTab()"
  139. >
  140. <el-icon><refresh /></el-icon>
  141. </div>
  142. </div>
  143. <div class="adminui-header-right">
  144. <userbar></userbar>
  145. </div>
  146. </header>
  147. <section class="aminui-wrapper">
  148. <div
  149. v-if="!ismobile"
  150. :class="
  151. menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'
  152. "
  153. >
  154. <div class="adminui-side-scroll">
  155. <el-scrollbar>
  156. <el-menu
  157. :default-active="active"
  158. router
  159. :collapse="menuIsCollapse"
  160. :unique-opened="$CONFIG.MENU_UNIQUE_OPENED"
  161. >
  162. <NavMenu :navMenus="menu"></NavMenu>
  163. </el-menu>
  164. </el-scrollbar>
  165. </div>
  166. <!-- <div class="adminui-side-bottom" @click="$store.commit('TOGGLE_menuIsCollapse', !$store.state.global.menuIsCollapse)">
  167. <el-icon><expand v-if="menuIsCollapse"/><fold v-else /></el-icon>
  168. </div> -->
  169. </div>
  170. <Side-m v-if="ismobile"></Side-m>
  171. <div class="aminui-body el-container">
  172. <Tags v-if="!ismobile && layoutTags"></Tags>
  173. <div class="adminui-main" id="adminui-main">
  174. <Topbar2 v-if="!ismobile && toolbarTags"></Topbar2>
  175. <router-view v-slot="{ Component }">
  176. <keep-alive>
  177. <component :is="Component" :key="$route.fullPath" />
  178. </keep-alive>
  179. </router-view>
  180. <iframe-view></iframe-view>
  181. </div>
  182. </div>
  183. </section>
  184. </template>
  185. <!-- 顶部菜单布局 -->
  186. <template v-else-if="layout == 'top'">
  187. <nav ref="navbar" class="adminui-header">
  188. <div class="adminui-header-left">
  189. <div class="logo-bar">
  190. <img class="logo" src="/img/logo.svg" />
  191. <span>{{ appName }}</span>
  192. </div>
  193. <div v-if="!ismobile" class="adminui-header-menu">
  194. <el-menu
  195. class="nav"
  196. mode="horizontal"
  197. :default-active="active"
  198. :ellipsis="false"
  199. router
  200. >
  201. <NavMenu2 :navMenus="topMenuList"></NavMenu2>
  202. <el-sub-menu>
  203. <template #title
  204. ><el-icon size="16px"><more></more></el-icon>
  205. 更多</template
  206. >
  207. <NavMenu2 :navMenus="topHideMenuList"></NavMenu2>
  208. </el-sub-menu>
  209. </el-menu>
  210. </div>
  211. </div>
  212. <div class="adminui-header-right">
  213. <Side-m v-if="ismobile"></Side-m>
  214. <userbar></userbar>
  215. </div>
  216. </nav>
  217. <section class="aminui-wrapper">
  218. <div class="aminui-body el-container">
  219. <Tags v-if="!ismobile && layoutTags"></Tags>
  220. <div class="adminui-main" id="adminui-main">
  221. <Topbar2 v-if="!ismobile && toolbarTags"></Topbar2>
  222. <router-view v-slot="{ Component }">
  223. <keep-alive>
  224. <component :is="Component" :key="$route.fullPath" />
  225. </keep-alive>
  226. </router-view>
  227. <iframe-view></iframe-view>
  228. </div>
  229. </div>
  230. </section>
  231. </template>
  232. <!-- 默认布局 -->
  233. <template v-else>
  234. <section class="aminui-wrapper">
  235. <div v-if="!ismobile" class="aminui-side-split">
  236. <div class="aminui-side-split-top">
  237. <router-link :to="$CONFIG.DASHBOARD_URL">
  238. <img class="logo" :title="appName" src="/img/logo.svg" />
  239. </router-link>
  240. </div>
  241. <div class="adminui-side-split-scroll">
  242. <el-scrollbar>
  243. <ul>
  244. <li
  245. v-for="item in menu"
  246. :key="item"
  247. :class="
  248. pmenu.meta.id == item.meta.id
  249. ? 'active'
  250. : ''
  251. "
  252. @click="showMenu(item)"
  253. >
  254. <span>
  255. <el-icon
  256. ><component
  257. :is="
  258. item.meta.icon ||
  259. el - icon - menu
  260. "
  261. /></el-icon>
  262. <p>
  263. {{
  264. $t2(item.meta.code) ||
  265. item.meta.title
  266. }}
  267. </p>
  268. </span>
  269. </li>
  270. </ul>
  271. </el-scrollbar>
  272. </div>
  273. </div>
  274. <div
  275. v-if="(!ismobile && nextMenu.length > 0) || !pmenu.component"
  276. :class="
  277. menuIsCollapse ? 'aminui-side isCollapse' : 'aminui-side'
  278. "
  279. >
  280. <div v-if="!menuIsCollapse" class="adminui-side-top">
  281. <h2>{{ $t2(pmenu.meta.code) || pmenu.meta.title }}</h2>
  282. </div>
  283. <div class="adminui-side-scroll">
  284. <el-scrollbar>
  285. <el-menu
  286. :default-active="active"
  287. router
  288. :collapse="menuIsCollapse"
  289. :unique-opened="$CONFIG.MENU_UNIQUE_OPENED"
  290. >
  291. <NavMenu :navMenus="nextMenu"></NavMenu>
  292. </el-menu>
  293. </el-scrollbar>
  294. </div>
  295. <!-- <div class="adminui-side-bottom" @click="$store.commit('TOGGLE_menuIsCollapse', !$store.state.global.menuIsCollapse)">
  296. <el-icon><expand v-if="menuIsCollapse"/><fold v-else /></el-icon>
  297. </div> -->
  298. </div>
  299. <Side-m v-if="ismobile"></Side-m>
  300. <div class="aminui-body el-container">
  301. <Topbar>
  302. <userbar></userbar>
  303. </Topbar>
  304. <Tags v-if="!ismobile && layoutTags"></Tags>
  305. <div class="adminui-main" id="adminui-main">
  306. <router-view v-slot="{ Component }">
  307. <keep-alive>
  308. <component :is="Component" :key="$route.fullPath" />
  309. </keep-alive>
  310. </router-view>
  311. <iframe-view></iframe-view>
  312. </div>
  313. </div>
  314. </section>
  315. </template>
  316. <div class="main-maximize-exit" @click="exitMaximize">
  317. <el-icon><close /></el-icon>
  318. </div>
  319. </template>
  320. <script>
  321. import SideM from "./components/sideM.vue";
  322. import Topbar from "./components/topbar.vue";
  323. import Topbar2 from "./components/topbar2.vue";
  324. import Tags from "./components/tags.vue";
  325. import NavMenu from "./components/NavMenu.vue";
  326. import NavMenu2 from "./components/NavMenu2.vue";
  327. import userbar from "./components/userbar.vue";
  328. import iframeView from "./components/iframeView.vue";
  329. export default {
  330. name: "index",
  331. components: {
  332. SideM,
  333. Topbar,
  334. Topbar2,
  335. Tags,
  336. NavMenu,
  337. NavMenu2,
  338. userbar,
  339. iframeView,
  340. },
  341. inject: ["refresh"],
  342. data() {
  343. return {
  344. settingDialog: false,
  345. topMenuList: [],
  346. topHideMenuList: [],
  347. menu: [],
  348. nextMenu: [],
  349. pmenu: { meta: {} },
  350. active: "",
  351. };
  352. },
  353. computed: {
  354. ismobile() {
  355. return this.$store.state.global.ismobile;
  356. },
  357. layout() {
  358. return this.$store.state.global.layout;
  359. },
  360. toolbarTags() {
  361. return (
  362. this.$store.state.global.toolbarTags &&
  363. this.$route.meta.hiddenBreadcrumb !== "1"
  364. );
  365. },
  366. layoutTags() {
  367. return this.$store.state.global.layoutTags;
  368. },
  369. appName() {
  370. return this.$store.state.global.appName;
  371. },
  372. menuIsCollapse() {
  373. return this.$store.state.global.menuIsCollapse;
  374. },
  375. },
  376. created() {
  377. this.onLayoutResize();
  378. window.addEventListener("resize", this.onLayoutResize);
  379. var menu = this.$router.getMenu();
  380. this.menu = this.filterUrl(menu);
  381. this.showThis();
  382. },
  383. watch: {
  384. $route() {
  385. this.showThis();
  386. },
  387. layout: {
  388. handler(val) {
  389. document.body.setAttribute("data-layout", val);
  390. if (this.layout === "mix" || this.layout === "top") {
  391. this.$nextTick(() => {
  392. this.fixTopMenu();
  393. window.addEventListener("resize", this.fixTopMenu);
  394. });
  395. }
  396. },
  397. immediate: true,
  398. },
  399. },
  400. mounted() {
  401. if (this.layout === "mix" || this.layout === "top") {
  402. this.fixTopMenu();
  403. window.addEventListener("resize", this.fixTopMenu);
  404. }
  405. },
  406. methods: {
  407. fixTopMenu() {
  408. let width = window.getComputedStyle(this.$refs.navbar).width;
  409. let menuWidth = 200;
  410. let size = (parseInt(width) - 600) / menuWidth;
  411. this.topMenuList = [];
  412. this.topHideMenuList = [];
  413. this.menu.forEach((item, index) => {
  414. if (index < size - 1) {
  415. this.topMenuList.push(item);
  416. } else {
  417. this.topHideMenuList.push(item);
  418. }
  419. });
  420. },
  421. onLayoutResize() {
  422. this.$store.commit("SET_ismobile", document.body.clientWidth < 992);
  423. },
  424. //路由监听高亮
  425. showThis() {
  426. if (this.$route.meta.breadcrumb) {
  427. this.pmenu = this.$route.meta.breadcrumb[0];
  428. this.nextMenu = this.filterUrl(this.pmenu.children);
  429. }
  430. this.$nextTick(() => {
  431. this.active = this.$route.meta.active || this.$route.fullPath;
  432. });
  433. },
  434. //点击显示
  435. showMenu(route) {
  436. this.pmenu = route;
  437. this.nextMenu = this.filterUrl(route.children);
  438. if (
  439. (!route.children || route.children.length == 0) &&
  440. route.component
  441. ) {
  442. this.$router.push({ path: route.path });
  443. }
  444. },
  445. //TAB 刷新
  446. refreshTab() {
  447. this.refresh();
  448. },
  449. //转换外部链接的路由
  450. filterUrl(map) {
  451. var newMap = [];
  452. map &&
  453. map.forEach((item) => {
  454. item.meta = item.meta ? item.meta : {};
  455. //处理隐藏
  456. if (item.meta.isShow !== "1") {
  457. return false;
  458. }
  459. //处理http
  460. if (item.meta.target == "iframe") {
  461. item.path = `/i/${item.meta.id}`;
  462. }
  463. //递归循环
  464. if (item.children && item.children.length > 0) {
  465. item.children = this.filterUrl(item.children);
  466. }
  467. newMap.push(item);
  468. });
  469. return newMap;
  470. },
  471. //退出最大化
  472. exitMaximize() {
  473. document.getElementById("app").classList.remove("main-maximize");
  474. },
  475. },
  476. };
  477. </script>