index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <a-layout class="vab-layout-wrap">
  3. <!-- 顶部横向排版 start -->
  4. <div>
  5. <a-layout-header
  6. class="vab-header"
  7. :style="`background:${$store.state.homeStyle}`"
  8. >
  9. <div style="width: 408px;display:inline-block;position:absolute;left:0">
  10. <vab-logo />
  11. </div>
  12. <div class="menu-outBox" style="display:none" >
  13. <a-menu
  14. class="vab-menu"
  15. theme=""
  16. mode="inline"
  17. v-model:selectedKeys="selectedKeys"
  18. v-model:openKeys="openKeys"
  19. :style="`width:${(routes.length-4)*100}px`"
  20. >
  21. <vab-menu
  22. v-for="route in routes"
  23. :key="route.path"
  24. :item="route"
  25. />
  26. </a-menu>
  27. </div>
  28. <div style="width: 340px;display:inline-block;position:absolute;right:0">
  29. <vab-avatar />
  30. </div>
  31. <a-row>
  32. <!-- <a-col
  33. :xs="10"
  34. :sm="10"
  35. :md="10"
  36. :lg="10"
  37. :xl="10"
  38. style="max-width: 400px"
  39. >
  40. <vab-logo />
  41. </a-col>
  42. <a-col
  43. :xs="14"
  44. :sm="14"
  45. :md="14"
  46. :lg="14"
  47. :xl="14"
  48. style="min-width: calc(100% - 400px)"
  49. > -->
  50. <!-- 菜单start -->
  51. <!-- <a-menu
  52. class="vab-menu"
  53. theme=""
  54. mode="inline"
  55. v-model:selectedKeys="selectedKeys"
  56. v-model:openKeys="openKeys"
  57. >
  58. <vab-menu
  59. v-for="route in routes"
  60. :key="route.path"
  61. :item="route"
  62. />
  63. </a-menu> -->
  64. <!-- 菜单end-->
  65. <!-- <vab-avatar /> -->
  66. <!-- </a-col> -->
  67. </a-row>
  68. </a-layout-header>
  69. </div>
  70. <!-- 顶部横向排版 end -->
  71. <div
  72. v-if="device === 'mobile' && !collapse"
  73. class="vab-mask"
  74. @click="handleFoldSideBar"
  75. ></div>
  76. <!-- 左侧菜单start -->
  77. <a-layout-sider
  78. collapsible
  79. class="vab-sider"
  80. width="220"
  81. v-model:collapsed="collapse"
  82. :class="classObj"
  83. :trigger="null"
  84. >
  85. <!-- 导航文字及缩进 start -->
  86. <div
  87. style="
  88. line-height: 50px;
  89. text-align: right;
  90. border-bottom: 1px solid rgba(0, 0, 0, 0.04);
  91. "
  92. >
  93. <span v-if="!collapse" style="margin-right: 79px">导航</span>
  94. <div
  95. style="display: inline-block"
  96. :style="{ 'margin-right': collapse ? '30px' : '20px' }"
  97. >
  98. <menu-unfold-outlined
  99. v-if="collapse"
  100. class="trigger"
  101. @click="toggleCollapse"
  102. />
  103. <menu-fold-outlined v-else class="trigger" @click="toggleCollapse" />
  104. </div>
  105. </div>
  106. <!-- 导航及缩进 end -->
  107. <!-- 菜单start -->
  108. <a-menu
  109. class="vab-menu"
  110. theme=""
  111. mode="inline"
  112. v-model:selectedKeys="selectedKeys"
  113. v-model:openKeys="openKeys"
  114. >
  115. <vab-menu v-for="route in routes" :key="route.path" :item="route" />
  116. </a-menu>
  117. <!-- 菜单end-->
  118. </a-layout-sider>
  119. <!-- 左侧菜单end -->
  120. <!-- 页面主体start -->
  121. <a-layout
  122. class="vab-layout"
  123. :class="'mobile' === device ? 'vab-mobile-layout' : ''"
  124. >
  125. <vab-tabs />
  126. <vab-content />
  127. </a-layout>
  128. </a-layout>
  129. <!-- 页面主体end -->
  130. </template>
  131. <script>
  132. import VabLogo from './vab-logo'
  133. import VabAvatar from './vab-avatar'
  134. import VabMenu from './vab-menu'
  135. import VabTabs from './vab-tabs'
  136. import VabContent from './vab-content'
  137. import { mapActions, mapGetters } from 'vuex'
  138. import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons-vue'
  139. export default {
  140. components: {
  141. VabLogo,
  142. VabAvatar,
  143. VabMenu,
  144. VabTabs,
  145. VabContent,
  146. MenuUnfoldOutlined,
  147. MenuFoldOutlined,
  148. },
  149. data() {
  150. return {
  151. selectedKeys: [],
  152. openKeys: [],
  153. }
  154. },
  155. computed: {
  156. ...mapGetters({
  157. collapse: 'settings/collapse',
  158. routes: 'routes/routes',
  159. device: 'settings/device',
  160. }),
  161. classObj() {
  162. return {
  163. 'vab-mobile': this.device === 'mobile',
  164. 'vab-collapse': this.collapse,
  165. }
  166. },
  167. },
  168. watch: {
  169. $route: {
  170. handler({ path, matched }) {
  171. matched[0].children.length > 1
  172. ? (this.selectedKeys = [path])
  173. : (this.selectedKeys = [matched[0].path])
  174. this.openKeys = [matched[0].path]
  175. },
  176. immediate: true,
  177. },
  178. },
  179. beforeMount() {
  180. window.addEventListener('resize', this.handleLayouts)
  181. },
  182. beforeUnmount() {
  183. window.removeEventListener('resize', this.handleLayouts)
  184. },
  185. mounted() {
  186. this.handleLayouts()
  187. },
  188. methods: {
  189. ...mapActions({
  190. toggleDevice: 'settings/toggleDevice',
  191. handleFoldSideBar: 'settings/foldSideBar',
  192. toggleCollapse: 'settings/toggleCollapse',
  193. }),
  194. handleLayouts() {
  195. const width = document.body.getBoundingClientRect().width
  196. if (this.width !== width) {
  197. const isMobile = width - 1 < 992
  198. this.toggleDevice(isMobile ? 'mobile' : 'desktop')
  199. this.width = width
  200. }
  201. },
  202. },
  203. }
  204. </script>
  205. <style lang="less">
  206. .vab-layout-wrap {
  207. height: 100%;
  208. .vab-sider {
  209. background-color: #fff;
  210. position: fixed;
  211. top: 60px;
  212. left: 0;
  213. height: 100vh;
  214. overflow: auto;
  215. .vab-menu {
  216. overflow-y: auto;
  217. height: calc(100vh - @vab-header-height);
  218. li {
  219. // margin-top: 10px;
  220. // margin-bottom: 10px;
  221. // line-height: 50px;
  222. // height: 50px;
  223. }
  224. }
  225. .vab-menu::-webkit-scrollbar {
  226. display: none;
  227. }
  228. }
  229. .vab-layout {
  230. height: calc(100vh - 0);
  231. overflow: auto;
  232. padding-left: 220px;
  233. transition: all 0.2s;
  234. background-color: #f0f3f4;
  235. padding-top: @vab-header-height;
  236. }
  237. .vab-mobile-layout {
  238. padding-left: 0;
  239. transition: all 0.2s;
  240. }
  241. .vab-collapse {
  242. .vab-logo .anticon + span {
  243. display: inline-block;
  244. max-width: 0;
  245. opacity: 0;
  246. transition: all 0.2s;
  247. }
  248. & + .vab-layout {
  249. padding-left: 81px;
  250. transition: all 0.2s;
  251. }
  252. }
  253. .vab-mask {
  254. position: fixed;
  255. top: 0;
  256. right: 0;
  257. bottom: 0;
  258. left: 0;
  259. z-index: 998;
  260. width: 100%;
  261. height: 100vh;
  262. overflow: hidden;
  263. background: #000;
  264. opacity: 0.5;
  265. }
  266. .vab-mobile {
  267. position: fixed !important;
  268. z-index: 999;
  269. &.vab-collapse {
  270. width: 0 !important;
  271. min-width: 0 !important;
  272. max-width: 0 !important;
  273. * {
  274. display: none !important;
  275. width: 0 !important;
  276. min-width: 0 !important;
  277. max-width: 0 !important;
  278. }
  279. .ant-menu-item,
  280. .ant-menu-submenu {
  281. display: none !important;
  282. width: 0 !important;
  283. min-width: 0 !important;
  284. max-width: 0 !important;
  285. }
  286. & + .vab-layout {
  287. padding-left: 0px !important;
  288. transition: all 0.2s;
  289. }
  290. }
  291. }
  292. .vab-header {
  293. padding: 0;
  294. background: #016ddb;
  295. color: #fff;
  296. position: fixed;
  297. top: 0;
  298. width: 100%;
  299. z-index: 999;
  300. height: @vab-header-height;
  301. line-height: @vab-header-height;
  302. .ant-col + .ant-col {
  303. display: flex;
  304. justify-content: flex-end;
  305. padding: 0 @vab-padding;
  306. }
  307. .trigger {
  308. height: @vab-header-height;
  309. padding: 0 @vab-padding;
  310. font-size: 18px;
  311. line-height: @vab-header-height;
  312. cursor: pointer;
  313. transition: color 0.3s;
  314. &:hover {
  315. color: #1890ff;
  316. }
  317. }
  318. }
  319. }
  320. .vab-header {
  321. .menu-outBox{
  322. display:inline-block;position:absolute;left:420px;width:calc(100% - 740px);overflow-x:auto
  323. }
  324. .menu-outBox::-webkit-scrollbar {
  325. /*滚动条整体样式*/
  326. // width: 1px; /*高宽分别对应横竖滚动条的尺寸*/
  327. height:8px;
  328. }
  329. .menu-outBox::-webkit-scrollbar-thumb {
  330. /*滚动条里面小方块*/
  331. // border-radius: 10px;
  332. background: rgba(1, 109, 219,.4);
  333. }
  334. .menu-outBox::-webkit-scrollbar-track {
  335. /*滚动条里面轨道*/
  336. // border-radius: 10px;
  337. background: rgb(245, 245, 265);
  338. }
  339. .ant-menu-inline{
  340. // width:200%;
  341. }
  342. .ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title{
  343. margin-top:10px;
  344. }
  345. .svg-icon{
  346. margin-right:3px!important;
  347. }
  348. .ant-menu-submenu-arrow::after,.ant-menu-submenu-arrow::before{
  349. background-image:none!important;
  350. }
  351. .ant-menu-inline > .ant-menu-item{
  352. height: 36px!important;
  353. line-height: 36px!important;
  354. margin-top: 12px;
  355. }
  356. .ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{
  357. background: rgba(255, 255, 255, 0.2)!important;
  358. border-radius:4px;
  359. // color:#000;
  360. }
  361. .ant-menu-item::after{
  362. border-right:0px solid #000!important
  363. }
  364. .ant-menu-inline .ant-menu-item:not(:last-child){
  365. margin-bottom:0!important;
  366. }
  367. .ant-menu-inline .ant-menu-item{
  368. float:left;
  369. }
  370. .ant-menu{
  371. background:rgba(0,0,0,0);
  372. li{
  373. display:inline-block;
  374. width:auto!important;
  375. color:#fff;
  376. padding:0 10px!important
  377. }
  378. }
  379. }
  380. </style>