adminLayout.vue 9.1 KB

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