Head.vue 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <template>
  2. <div class="head-wrapper">
  3. <div class="head-logo">
  4. <svg-icon icon-class="zhihui-logo" @click="topHome()" />
  5. </div>
  6. <div v-for="item in headList" :key="item.path" class="nav-tag" :class="{'active-nav-tag':activeNavTag === item.name}" @click="changeNavTag(item)">
  7. <div v-if="item.icon" class="icon">
  8. <div v-show="notice && item.name.search(/个人工作台/)>=0" class="if-notice" />
  9. <svg-icon :icon-class="item.icon" />
  10. </div>
  11. <div class="name">{{ item.name }}</div>
  12. </div>
  13. <div @mouseleave="target = true">
  14. <div :class="[target ? 'nav-div1' : 'nav-div2']">
  15. <el-tooltip v-if="!target" class="item" effect="dark" content="工具集合" placement="right">
  16. <div class="div-child" @click="goto('Interface')"><svg-icon icon-class="b_工具集合" /></div>
  17. </el-tooltip>
  18. <el-tooltip v-if="!target" class="item" effect="dark" content="环境平台" placement="right">
  19. <div class="div-child" @click="goto('env')"><svg-icon icon-class="b_环境平台" /></div>
  20. </el-tooltip>
  21. </div>
  22. <div class="nav-div3 nav-circular" />
  23. <div class="nav-div4 nav-circular" @mouseenter="target = false" />
  24. </div>
  25. <!-- <div v-show="navTagType === 2" class="nav-tag-type" @click="setNavTagType(1)">
  26. <i class="el-icon-notebook-2" style="transform: rotate(90deg);" />
  27. </div>
  28. <div v-show="navTagType === 1" class="nav-tag-type" @click="setNavTagType(2)">
  29. <i class="el-icon-notebook-2" />
  30. </div> -->
  31. <el-tooltip class="item" effect="dark" content="用户指导手册" placement="right">
  32. <el-link class="user-tip" href="https://base3.xiaojukeji.com/docs/zhihui/" target="_blank">
  33. <svg-icon style="width: 24px; height: 24px;" icon-class="question" />
  34. </el-link>
  35. </el-tooltip>
  36. <div v-if="userInfo" class="user-info">
  37. <a-popover placement="rightBottom" overlay-class-name="head-popover">
  38. <template #content>
  39. <div :class="memberCheck ? 'user-admin-one' : 'user-admin'">
  40. <div class="user-name">{{ userInfo.name }}</div>
  41. <div class="line" />
  42. <div class="user-logout">
  43. <el-button v-if="navTagType === 1" type="primary" plain size="small" @click="setNavTagType(2)">顶部导航</el-button>
  44. <el-button v-if="navTagType === 2" type="primary" plain size="small" @click="setNavTagType(1)">侧边导航</el-button>
  45. </div>
  46. <div class="line" />
  47. <div v-if="memberCheck" class="user-logout">
  48. <el-button type="primary" plain size="small" @click="administratorsJump()"> 管 理 员 </el-button>
  49. </div>
  50. <div v-if="memberCheck" class="line" />
  51. <div class="user-logout">
  52. <el-button type="primary" plain size="small" @click="layout()">退出登录</el-button>
  53. </div>
  54. </div>
  55. </template>
  56. <img :src="userInfo.phoneUrl">
  57. </a-popover>
  58. </div>
  59. </div>
  60. </template>
  61. <script>
  62. import { mapGetters } from 'vuex'
  63. import routes from '@/router/newRouter'
  64. import websocket from '@/views/workbench/mixins/websocket'
  65. import { memberGetLoginInMemberInfoByLdap } from '@/api/projectIndex'
  66. import { logoutUrl } from '@/apiConfig/requestIP.js'
  67. import { log } from '@/utils/global'
  68. import { verifyIsAdmin } from '@/api/configure.js'
  69. export default {
  70. mixins: [websocket],
  71. data() {
  72. return {
  73. headList: routes.filter(item => item.name !== '业务线'),
  74. userInfo: null,
  75. memberCheck: false,
  76. target: true
  77. }
  78. },
  79. computed: {
  80. ...mapGetters(['activeNavTag', 'navTagType', 'notice'])
  81. },
  82. watch: {
  83. $route: {
  84. handler(to) {
  85. this.findRoute(to.name)
  86. },
  87. immediate: true
  88. }
  89. },
  90. created() {
  91. this.getLoginUser()
  92. this.verifyIsAdmin()
  93. },
  94. methods: {
  95. goto(name) {
  96. log({ c: 'project', d: `goto_${name}` })
  97. this.$router.push({ name })
  98. },
  99. getTarget() {
  100. this.target = !this.target
  101. },
  102. findRoute(routeName) {
  103. for (const element of routes) {
  104. if (element.name === routeName) {
  105. // 先对父元素进行查找
  106. this.$store.dispatch('global/setActiveNavTag', element.name)
  107. } else if (element.children) {
  108. const child = element.children.find(item => item.name === routeName) // 对子元素进行查找
  109. child ? this.$store.dispatch('global/setActiveNavTag', element.name) : '' // 父元素的名字设为路径
  110. }
  111. }
  112. },
  113. // 切换二级导航
  114. changeNavTag(nav) {
  115. this.$store.dispatch('global/setActiveNavTag', nav.name) // 设置二级导航的类别
  116. this.$router.push({ name: nav.name }) // 跳转
  117. },
  118. // 设置二级导航类型
  119. setNavTagType(type) {
  120. if (type === 2) {
  121. log({ c: 'sys_setting', d: 'change_nav_bar_top' })
  122. } else {
  123. log({ c: 'sys_setting', d: 'change_nav_bar_side' })
  124. }
  125. this.$store.dispatch('global/setNavTagType', type)
  126. localStorage.setItem('navTagType', type)
  127. },
  128. // 获取登录人员信息
  129. async getLoginUser() {
  130. const res = await memberGetLoginInMemberInfoByLdap()
  131. if (res && res.data) this.userInfo = res.data || null
  132. },
  133. // 查看是否为管理员
  134. async verifyIsAdmin() {
  135. const res = await verifyIsAdmin()
  136. if (res.code === 200) this.memberCheck = res.data
  137. },
  138. // 退出登录
  139. layout() {
  140. window.location.href = logoutUrl
  141. },
  142. topHome() {
  143. this.$router.push({ path: '/' })
  144. },
  145. administratorsJump() {
  146. this.$router.push({ name: '管理员' })
  147. },
  148. // websocket数据接收
  149. websocketonmessage(e) {
  150. const { hasReminding } = JSON.parse(e.data)
  151. if (hasReminding) {
  152. this.$store.dispatch('data/setNotice', true)
  153. const link = document.querySelector('link')
  154. link.href = link.href.replace(/favicon.ico/, 'favicon-tips.ico')
  155. } else {
  156. this.$store.dispatch('data/setNotice', false)
  157. const link = document.querySelector('link')
  158. link.href = link.href.replace(/favicon-tips.ico/, 'favicon.ico')
  159. }
  160. }
  161. }
  162. }
  163. </script>
  164. <style lang="scss" scoped>
  165. .head-wrapper {
  166. display: flex;
  167. flex-direction: column;
  168. flex-shrink: 0;
  169. z-index: 99;
  170. width: 80px;
  171. align-items: center;
  172. background: #409eff;
  173. font-size: 20px;
  174. color: #333;
  175. padding-top: 17px;
  176. }
  177. .head-logo {
  178. height: 40px;
  179. width: 40px;
  180. margin-bottom: 42px;
  181. .svg-icon {
  182. cursor: pointer;
  183. width: 100%;
  184. height: 100%;
  185. }
  186. }
  187. .nav-tag {
  188. width: 100%;
  189. font-size: 14px;
  190. color: #ffffff;
  191. text-align: center;
  192. margin-bottom: 20px;
  193. padding: 5px 0 9px 0;
  194. cursor: pointer;
  195. .icon {
  196. position: relative;
  197. color: #ffffff;
  198. height: 27px;
  199. width: 33px;
  200. margin: 7px auto;
  201. font-size: 32px;
  202. }
  203. .svg-icon {
  204. position: absolute;
  205. top: 0;
  206. left: 0;
  207. width: 100%;
  208. height: 100%;
  209. }
  210. .if-notice {
  211. position: absolute;
  212. z-index: 1;
  213. height: 8px;
  214. width: 8px;
  215. background-color: #E02020;
  216. border-radius: 50%;
  217. top: 0;
  218. right: 0;
  219. transform: translateY(-50%);
  220. }
  221. }
  222. .active-nav-tag {
  223. background-color: #1E89F7;
  224. }
  225. .nav-tag-type {
  226. margin-top: auto;
  227. color: #ffffff;
  228. cursor: pointer;
  229. }
  230. .user-tip {
  231. margin-top: auto;
  232. margin-bottom: 20px;
  233. }
  234. .user-info {
  235. height: 30px;
  236. width: 30px;
  237. display: flex;
  238. justify-content: center;
  239. align-items: center;
  240. background-color: #fff;
  241. border-radius: 50%;
  242. overflow: hidden;
  243. // margin-top: auto;
  244. margin-bottom: 30px;
  245. img {
  246. height: 30px;
  247. }
  248. }
  249. .user-admin {
  250. height: 143px;
  251. width: 95px;
  252. display: flex;
  253. flex-direction: column;
  254. display: grid;
  255. grid-template-rows: 47px 1px 47px 1px 47px;
  256. justify-items: center;
  257. align-items: center;
  258. .line {
  259. width: 100%;
  260. height: 1px;
  261. background-color: rgba(112, 112, 112, 0.2);
  262. }
  263. }
  264. .user-admin-one {
  265. height: 190px;
  266. width: 95px;
  267. display: flex;
  268. flex-direction: column;
  269. display: grid;
  270. grid-template-rows: 47px 1px 47px 1px 47px;
  271. justify-items: center;
  272. align-items: center;
  273. .line {
  274. width: 100%;
  275. height: 1px;
  276. background-color: rgba(112, 112, 112, 0.2);
  277. }
  278. }
  279. // .user-control {
  280. // width: 95px;
  281. // display: flex;
  282. // flex-direction: column;
  283. // display: grid;
  284. // grid-template-rows: 47px 1px 47px 1px 47px;
  285. // justify-items: center;
  286. // align-items: center;
  287. // .line {
  288. // width: 100%;
  289. // height: 1px;
  290. // background-color: rgba(112, 112, 112, 0.2);
  291. // }
  292. // }
  293. </style>
  294. <style lang="scss" scoped>
  295. .head-popover {
  296. box-shadow: 10px 0px 11px #dedede;
  297. /deep/ .ant-popover-inner-content {
  298. padding: 0;
  299. }
  300. }
  301. .nav-div1 {
  302. width:25px;height:50px;border-radius: 0 50px 50px 0;line-height:50px;background: #6cb5ff; position: absolute; bottom: 172px; left: 0;border: 1px solid #6cb5ff;animation:myfirsts 0.5s;
  303. }
  304. .nav-div2 {
  305. bottom: 137px; width:60px; height:120px; line-height:120px;border-radius: 0 80px 80px 0;;background: #6cb5ff; position: absolute; left: 0;animation:myfirst 1s;
  306. }
  307. @keyframes myfirst
  308. {
  309. from {bottom: 172px; width:25px; height:50px; line-height:50px;}
  310. to {bottom: 137px; width:60px; height:120px; line-height:120px;}
  311. }
  312. @keyframes myfirsts
  313. {
  314. from {bottom: 137px; width:60px; height:120px; line-height:120px;}
  315. to {bottom: 172px; width:25px; height:50px; line-height:50px;}
  316. }
  317. .nav-div3 {
  318. width:25px;
  319. height:50px;
  320. line-height:50px;
  321. background: #FFF;
  322. bottom: 172px;
  323. border: 1px solid #FFF;
  324. opacity: 0.63;
  325. }
  326. .nav-div4 {
  327. width:20px;
  328. height:40px;
  329. line-height:45px;
  330. background: #FFF;
  331. bottom: 177px;
  332. border: 1px solid #FFF;
  333. }
  334. .div-child {
  335. text-align: right;
  336. margin-right: 19px;
  337. line-height: 61px;
  338. cursor: pointer;
  339. opacity: 1;
  340. animation:myfirs 3s;
  341. }
  342. @keyframes myfirs
  343. {
  344. from {opacity: 0}
  345. to {opacity: 1}
  346. }
  347. .nav-circular {
  348. position: absolute;
  349. left: 0;
  350. border-radius: 0 50px 50px 0;
  351. cursor: pointer;
  352. }
  353. </style>