adminLayout.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. <script>
  2. export default {
  3. name: "adminLayout",
  4. props: {
  5. indexPath: {
  6. default: '/'
  7. },
  8. headerHeight: {
  9. default: '35px'
  10. },
  11. sideBarWidth: {
  12. default: '270px'
  13. },
  14. sideBarHeight: {
  15. default: '35px'
  16. },
  17. bgColor: {default: '#fff'},
  18. contentBgColor: {default: '#eeeeee'},
  19. sideBarColor: {default: '#001529'},
  20. sideTextColor: {default: '#fff'},
  21. sideTextActiveColor: {default: '#ffffffa6'},
  22. headerBgColor: {default: '#014175'},
  23. // 文本颜色, 主要文本颜色 次要文本颜色
  24. textColor: {default: '#333'},
  25. mainTextColor: {default: '#333'},
  26. textColorHover: {default: '#fff'},
  27. mainTextColorHover: {default: '#fff'},
  28. btnColor: {default: '#086fb6'},
  29. btnColorHover: {default: '#086fb6'},
  30. btnTextColor: {default: '#fff'},
  31. btnTextColorHover: {default: '#fff'},
  32. sidebarMenus: {
  33. default(){
  34. return []
  35. }
  36. },
  37. interactSideBar: {
  38. default: true
  39. },
  40. logoTitle: {
  41. default: ''
  42. },
  43. headerMenus: {
  44. default(){
  45. return []
  46. }
  47. },
  48. headerMenuKey: {
  49. default: ''
  50. },
  51. userName: {
  52. default: ''
  53. },
  54. btnLink: {
  55. type: Boolean,
  56. default: false
  57. },
  58. activeKey: {
  59. default: ''
  60. },
  61. },
  62. data(){
  63. return {
  64. isShowSideBar: true,
  65. cssText: '',
  66. sideMenus: [],
  67. }
  68. },
  69. beforeMount() {
  70. this.init_computedStyle();
  71. },
  72. watch:{
  73. sidebarMenus(){
  74. this.init_comSideBar();
  75. },
  76. },
  77. mounted() {
  78. this.init_comSideBar();
  79. },
  80. methods:{
  81. init_comSideBar(){
  82. // 循环遍历菜单
  83. this.sideMenus = this.sidebarMenus.map((item)=>{
  84. let newItem = {...item};
  85. newItem.isShow = false;
  86. return newItem;
  87. });
  88. },
  89. switchHandle(){
  90. if(!this.interactSideBar){return console.log('不允许交互sidebar');}
  91. this.isShowSideBar = !this.isShowSideBar;
  92. this.init_computedStyle();
  93. },
  94. switchSideBarMenuHandle(item){
  95. item.isShow = !item.isShow;
  96. },
  97. /**
  98. * 计算dom元素样式
  99. */
  100. init_computedStyle(){
  101. let cssText = `
  102. --headerHeight: ${this.headerHeight};
  103. --sideBarWidth: ${this.isShowSideBar?this.sideBarWidth:this.sideBarHeight};
  104. --baseSideBarWidth: ${this.sideBarWidth};
  105. --sideBarHeight: ${this.sideBarHeight};
  106. --bg-color: ${this.bgColor};
  107. --content-bg-color: ${this.contentBgColor};
  108. --sideBarBgColor: ${this.sideBarColor};
  109. --sideTextColor: ${this.sideTextColor};
  110. --sideTextActiveColor: ${this.sideTextActiveColor};
  111. --header-color: ${this.headerBgColor};
  112. --text-color: ${this.textColor};
  113. --main-text-color: ${this.mainTextColor};
  114. --text-color-hover: ${this.textColorHover};
  115. --main-text-color-hover: ${this.mainTextColorHover};
  116. --btn-color: ${this.btnColor};
  117. --btn-color-hover: ${this.btnColorHover};
  118. --btn-text-color: ${this.btnTextColor};
  119. --btn-text-color-hover: ${this.btnTextColorHover};
  120. `;
  121. this.cssText = cssText;
  122. },
  123. }
  124. }
  125. </script>
  126. <template>
  127. <!-- 管理员控制台布局 永久性头部,可伸缩侧边栏-->
  128. <div class="lay-con" :style="cssText">
  129. <!-- 头部横条 -->
  130. <div class="lay-header" >
  131. <div class="lay-logo">
  132. <slot name="logo">
  133. <h1>
  134. <a :href="indexPath">
  135. {{logoTitle}}
  136. </a>
  137. </h1>
  138. </slot>
  139. </div>
  140. <div class="lay-menus">
  141. <div class="menus">
  142. <span
  143. v-for="item in headerMenus"
  144. :key="item.key"
  145. :class="`menu ${headerMenuKey===item.key?'':''}`"
  146. >
  147. <a :href="item.href">{{item.text}}</a>
  148. </span>
  149. </div>
  150. <div class="bell">
  151. <slot name="bell"> </slot>
  152. </div>
  153. <div class="user">
  154. <slot name="user">
  155. <span>{{userName}}</span>
  156. </slot>
  157. </div>
  158. </div>
  159. </div>
  160. <!-- 内容部分-->
  161. <div class="lay-box" >
  162. <div :class="`lay-sideBar ${!isShowSideBar?'lay-sideBar-hide':''}`" >
  163. <!-- 侧边按钮 -->
  164. <div class="lay-sideBar-control" @click="switchHandle">
  165. <svg-icon :icon-class="isShowSideBar?'prev':'next'"/>
  166. </div>
  167. <!-- 侧边栏,带标题,icon,下拉菜单-->
  168. <div v-for="(item,i) in sideMenus"
  169. :key="'sideBar-'+i"
  170. :class="`bar-menu-item ${item.isShow?'bar-menu-item-show':''}`"
  171. >
  172. <div class="menu-title">
  173. <span class="icon"> <svg-icon :icon-class="item.icon"/> </span>
  174. <span class="text">{{ item.title }}</span>
  175. <span class="icon option" @click="switchSideBarMenuHandle(item)">
  176. <svg-icon :icon-class="item.isShow?'arrow-up':'arrow-down'"/>
  177. </span>
  178. </div>
  179. <div class="sub-menu-box">
  180. <div v-for="sub in item.child"
  181. :key="sub.key"
  182. :class="`menu-item ${activeKey===sub.key?'menu-items-show':''}`"
  183. >
  184. <a :href="sub.path">{{sub.title}}</a>
  185. </div>
  186. </div>
  187. </div>
  188. </div>
  189. <div class="lay-content" >
  190. <slot></slot>
  191. </div>
  192. </div>
  193. </div>
  194. </template>
  195. <style scoped>
  196. .lay-con {
  197. --headerHeight: v-bind(headerHeight);
  198. --sideBarWidth: v-bind(sideBarWidth);
  199. --sideBarHeight: v-bind(sideBarHeight);
  200. --baseSideBarWidth: v-bind(sideBarWidth);
  201. --bg-color: v-bind(bgColor);
  202. --content-bg-color: v-bind(contentBgColor);
  203. --sideBarBgColor: v-bind(sideBarColor);
  204. --side-text-color: v-bind(sideTextColor);
  205. --side-text-active-color: v-bind(sideTextActiveColor);
  206. --header-color: v-bind(headerBgColor);
  207. --text-color: v-bind(textColor);
  208. --main-text-color: v-bind(mainTextColor);
  209. --text-color-hover: v-bind(textColorHover);
  210. --main-text-color-hover: v-bind(mainTextColorHover);
  211. --btn-color: v-bind(btnColor);
  212. --btn-color-hover: v-bind(btnColorHover);
  213. --btn-text-color: v-bind(btnTextColor);
  214. --btn-text-color-hover: v-bind(btnTextColorHover);
  215. width: 100vw;
  216. height: 100vh;
  217. overflow: hidden;
  218. background-color: var(--sideBarBgColor);
  219. position: relative;
  220. }
  221. .lay-header{
  222. background-color: var(--header-color);
  223. display: flex;
  224. width: 100%;
  225. height: var(--headerHeight);
  226. flex-direction: row;
  227. }
  228. .lay-header > *{
  229. width: 50%;
  230. height: 100%;
  231. display: flex;
  232. align-items: center;
  233. }
  234. .lay-logo{
  235. margin-left: 15px;
  236. margin-right: 15px;
  237. box-sizing: border-box;
  238. }
  239. .lay-menus{
  240. justify-content: end;
  241. }
  242. .lay-menus .menus{
  243. display: flex;
  244. padding: 0 5px;
  245. }
  246. .lay-menus .menus .menu{
  247. padding: 5px 15px;
  248. }
  249. .lay-menus .menus .menu:hover{
  250. color: var(--text-color-hover);
  251. }
  252. .lay-box {
  253. width: 100%;
  254. height:calc(100% - var(--headerHeight));
  255. display: flex;
  256. }
  257. .lay-box > *{
  258. transition: width .7s;
  259. height: 100%;
  260. position: relative;
  261. }
  262. .lay-sideBar{
  263. width: var(--sideBarWidth);
  264. color: var(--side-text-color);
  265. }
  266. .lay-content{
  267. width: calc(100% - var(--sideBarWidth));
  268. height: 100%;
  269. overflow: auto;
  270. background-color: var(--content-bg-color);
  271. }
  272. .lay-sideBar-control{
  273. position: relative;
  274. width: 25px;
  275. height: 25px;
  276. left: 50%;
  277. top: 0px;
  278. margin-top: 5px;
  279. transform: translate(-50%, 0);
  280. border-radius: 3px;
  281. border: 1px solid black;
  282. z-index: 999;
  283. cursor: pointer;
  284. display: flex;
  285. justify-content: center;
  286. align-items: center;
  287. background-color: var(--sideBarBgColor);
  288. }
  289. .lay-sideBar-control:hover{
  290. border-color: #f0ad4e;
  291. background-color: #f0ad4e;
  292. color: var(--side-text-active-color);
  293. }
  294. .bar-menu-item{
  295. width: 100%;
  296. height: auto;
  297. position: relative;
  298. margin-top: 5px;
  299. }
  300. .bar-menu-item .menu-title{
  301. display: flex;
  302. width: 100%;
  303. height: var(--sideBarHeight);
  304. align-items: center;
  305. box-sizing: border-box;
  306. padding-left: 5px;
  307. padding-right: 5px;
  308. cursor: default;
  309. overflow: hidden;
  310. }
  311. .bar-menu-item .menu-title:hover{
  312. color: var(--btn-text-color-hover);
  313. }
  314. .bar-menu-item .menu-title .icon{
  315. width: var(--sideBarHeight);
  316. height: var(--sideBarHeight);
  317. display: flex;
  318. justify-content: center;
  319. align-items: center;
  320. color: var(--side-text-color);
  321. flex-shrink: 0;
  322. }
  323. .bar-menu-item .menu-title .icon *{
  324. color: inherit;
  325. }
  326. .bar-menu-item .menu-title .option{
  327. cursor: pointer;
  328. color: var(--side-text-color);
  329. font-size: 1.5rem;
  330. }
  331. .bar-menu-item .menu-title .option:hover{
  332. color: var(--side-text-active-color);
  333. }
  334. .bar-menu-item .menu-title .text{
  335. width: calc(100% - var(--sideBarHeight) - var(--sideBarHeight));
  336. display: flex;
  337. align-items: center;
  338. }
  339. .bar-menu-item .sub-menu-box{
  340. width: 100%;
  341. height: 0;
  342. overflow: hidden;
  343. transition: height .7s;
  344. }
  345. .bar-menu-item .sub-menu-box .menu-item{
  346. width: 100%;
  347. height: calc(var(--sideBarHeight) - 5px);
  348. box-sizing: border-box;
  349. padding-left: calc(var(--sideBarHeight) + 5px);
  350. cursor: pointer;
  351. }
  352. .bar-menu-item .sub-menu-box .menu-item > a{
  353. width: 100%;
  354. height: 100%;
  355. display: flex;
  356. justify-content: center;
  357. align-items: center;
  358. }
  359. .bar-menu-item .sub-menu-box .menu-item:hover{
  360. color: var(--btn-text-color-hover);
  361. background-color: var(--btn-color-hover);
  362. }
  363. .bar-menu-item-show{
  364. height: auto;
  365. }
  366. .bar-menu-item-show .sub-menu-box{
  367. height: auto;
  368. }
  369. .lay-sideBar-hide .lay-sideBar{
  370. padding-top: 50px;
  371. }
  372. .lay-sideBar-hide .bar-menu-item{
  373. box-sizing: border-box;
  374. margin: 10px 0;
  375. border-top: 1px solid var(--sideBarBgColor);
  376. }
  377. .lay-sideBar-hide .bar-menu-item .menu-title {
  378. padding-left: 0;
  379. padding-right: 0;
  380. }
  381. .lay-sideBar-hide .bar-menu-item .sub-menu-box{
  382. position: absolute;
  383. display: none;
  384. top: 0;
  385. left: 100%;
  386. height: auto;
  387. width: calc(var(--baseSideBarWidth) - var(--sideBarWidth));
  388. padding: 10px 0;
  389. box-shadow: 1px 1px 3px darkgray;
  390. z-index: 9999;
  391. background-color: var(--sideBarBgColor);
  392. }
  393. .lay-sideBar-hide .bar-menu-item:hover{
  394. border-top: 1px solid var(--bg-color);
  395. }
  396. .lay-sideBar-hide .bar-menu-item:hover .sub-menu-box{
  397. display: block;
  398. }
  399. </style>