Navbar.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. <template>
  2. <div class="navbar">
  3. <!-- <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> -->
  4. <router-link key="collapse" style="display: flex; align-items: center; padding-left: 30px;" to="/">
  5. <img src="@/assets/images/base/logo.png"
  6. class="sidebar-logo" style="width: 129px; height: 37px" />
  7. </router-link>
  8. <!-- <breadcrumb class="breadcrumb-container" /> -->
  9. <div class="indexlayout-top-menu">
  10. <!-- :class="{'active': getTopMenuActive === route.path}" -->
  11. <!-- el-scrollbar -->
  12. <el-scrollbar class="horizontal-scrollbar" style="overflow: hidden; height: 100%;">
  13. <template v-for="route in permission_routes">
  14. <app-link v-if="!route.hidden" :to="route.path" :key="route.id" class="indexlayout-top-menu-li" :class="{'active': getTopMenuActive === route.path}">
  15. <span>{{ route.meta.title }}</span>
  16. </app-link>
  17. </template>
  18. </el-scrollbar>
  19. </div>
  20. <!-- <div class="left-menu">
  21. <i class="el-icon-location-information topIcon"></i>
  22. <el-popover placement="top-start" width="300" trigger="hover">
  23. <div class="popover-container">
  24. <el-tag
  25. class="navbar_tag"
  26. type="info"
  27. v-for="item in organNameList"
  28. :key="item"
  29. >{{ item }}</el-tag
  30. >
  31. </div>
  32. <span slot="reference">{{
  33. organName.length > 10 ? organName.substr(0, 10) + "..." : organName
  34. }}</span>
  35. </el-popover>
  36. </div> -->
  37. <div class="right-menu">
  38. <div class="msginfo" v-permission="'/journal'" @click="gotoRecode">
  39. <img src="@/assets/images/base/base-bell.svg" />
  40. <!-- <div class="active"></div> -->
  41. </div>
  42. <div class="left-menu">
  43. <el-popover placement="top-start" width="300" trigger="hover" style="display: flex;height: 89px;">
  44. <div class="popover-container">
  45. <el-tag
  46. class="navbar_tag"
  47. type="info"
  48. v-for="item in organNameList"
  49. :key="item"
  50. >{{ item }}</el-tag
  51. >
  52. </div>
  53. <span slot="reference" style="display: flex;align-items: center;justify-content: center;height: 89px;">
  54. <!-- {{ organName.length > 10 ? organName.substr(0, 10) + "..." : organName }} -->
  55. <!-- <i class="el-icon-s-home" style="font-size: 23px; color: #1A1A1A;"></i> -->
  56. <img src="@/assets/images/base/base-home.svg" style="width: 23px;">
  57. </span>
  58. </el-popover>
  59. </div>
  60. <el-dropdown class="avatar-container" trigger="click">
  61. <div class="avatar-wrapper">
  62. <img
  63. v-if="$store.getters.avatar"
  64. :src="$store.getters.avatar"
  65. class="user-avatar"
  66. />
  67. <img
  68. v-else
  69. class="user-avatar"
  70. src="@/assets/images/base/placehorder-icon.png"
  71. />
  72. <!-- <i class="el-icon-caret-bottom" /> -->
  73. <span>{{ username }}</span>
  74. </div>
  75. <el-dropdown-menu slot="dropdown" class="user-dropdown">
  76. <!-- divided -->
  77. <el-dropdown-item>
  78. <span style="display: block" @click="resetPassWord">修改密码</span>
  79. </el-dropdown-item>
  80. <el-dropdown-item>
  81. <span style="display: block" @click="logout">退出</span>
  82. </el-dropdown-item>
  83. </el-dropdown-menu>
  84. </el-dropdown>
  85. </div>
  86. <el-dialog
  87. title="修改密码"
  88. width="500px"
  89. append-to-body
  90. :visible.sync="resetVisible"
  91. >
  92. <el-form
  93. :model="resetForm"
  94. label-position="right"
  95. label-width="100px"
  96. ref="pwdForm"
  97. >
  98. <el-form-item label="手机号" prop="phone">
  99. <div>{{ this.$store.getters.phone }}</div>
  100. </el-form-item>
  101. <el-form-item
  102. label="新密码"
  103. :rules="[
  104. { required: true, message: '密码不能为空', trigger: 'blur' },
  105. {
  106. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  107. message: '密码为6-20位数字和字母组合',
  108. trigger: 'blur',
  109. },
  110. ]"
  111. prop="password"
  112. >
  113. <el-input
  114. v-model.trim="resetForm.password"
  115. type="password"
  116. style="width: 180px"
  117. autocomplete="off"
  118. ></el-input>
  119. </el-form-item>
  120. <el-form-item
  121. label="再次输入"
  122. :rules="[
  123. { required: true, message: '密码不能为空', trigger: 'blur' },
  124. {
  125. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  126. message: '密码为6-20位数字和字母组合',
  127. trigger: 'blur',
  128. },
  129. ]"
  130. prop="password2"
  131. >
  132. <el-input
  133. v-model.trim="resetForm.password2"
  134. type="password"
  135. style="width: 180px"
  136. autocomplete="off"
  137. ></el-input>
  138. </el-form-item>
  139. <el-form-item
  140. label="验证码"
  141. :rules="[
  142. { required: true, message: '验证码不能为空', trigger: 'blur' },
  143. ]"
  144. prop="authCode"
  145. style=""
  146. >
  147. <el-input
  148. v-model.trim="resetForm.authCode"
  149. style="width: 180px"
  150. autocomplete="off"
  151. ></el-input>
  152. <el-button :disabled="isDisable" @click="getCode">{{
  153. btnName
  154. }}</el-button>
  155. </el-form-item>
  156. </el-form>
  157. <div slot="footer" class="dialog-footer">
  158. <el-button @click="resetVisible = false">取 消</el-button>
  159. <el-button type="primary" @click="submitResetPassWord">确 定</el-button>
  160. </div>
  161. </el-dialog>
  162. </div>
  163. </template>
  164. <script>
  165. import qs from "qs";
  166. import Logo from './Sidebar/Logo'
  167. import { mapGetters } from "vuex";
  168. // import Breadcrumb from '@/components/Breadcrumb'
  169. // import Hamburger from '@/components/Hamburger'
  170. import { resetPassword } from "@/api/buildTeam";
  171. import AppLink from './Sidebar/Link';
  172. import { getBelongTopMenuPath } from '@/utils/permission';
  173. export default {
  174. data() {
  175. return {
  176. username: "",
  177. organName: this.$store.getters.organName,
  178. organNameList: [],
  179. resetVisible: false,
  180. resetForm: {
  181. phone: "",
  182. authCode: "",
  183. password: "",
  184. password2: "",
  185. },
  186. isDisable: false, // 是否允许发送验证码
  187. timerCount: 60,
  188. btnName: "获取验证码",
  189. };
  190. },
  191. components: {
  192. AppLink
  193. // Breadcrumb,
  194. // Hamburger
  195. },
  196. computed: {
  197. ...mapGetters(["sidebar", "avatar", "permission_routes"]),
  198. getTopMenuActive() {
  199. let route = this.$route;
  200. // console.log(route, getBelongTopMenuPath(route))
  201. return getBelongTopMenuPath(route);
  202. }
  203. },
  204. mounted() {
  205. // 手动加入
  206. this.toggleSideBar();
  207. this.username = this.$store.getters.name;
  208. this.organNameList = this.organName.split(",")||[];
  209. },
  210. methods: {
  211. toggleSideBar() {
  212. this.$store.dispatch("app/toggleSideBar");
  213. },
  214. async logout() {
  215. await this.$store.dispatch("user/logout");
  216. localStorage.removeItem('firstMenuUrl')
  217. // await this.$store.dispatch("permission/removePermission")
  218. this.$router.push(`/login`);
  219. window.location.reload();
  220. },
  221. gotoRecode() {
  222. this.$router.push("/journal/journal");
  223. },
  224. resetPassWord() {
  225. this.resetVisible = true;
  226. },
  227. submitResetPassWord() {
  228. if (this.resetForm.password !== this.resetForm.password2) {
  229. this.$message.error("两次密码必须相同");
  230. return;
  231. }
  232. this.$refs["pwdForm"].validate((res) => {
  233. if (res) {
  234. // 发请求
  235. resetPassword({
  236. authCode: this.resetForm.authCode,
  237. mobile: this.$store.getters.phone,
  238. newPassword: this.resetForm.password,
  239. }).then((res) => {
  240. if (res.code == 200) {
  241. // 修改成功
  242. this.$message.success("修改成功");
  243. this.logout();
  244. }
  245. });
  246. }
  247. });
  248. },
  249. getCode() {
  250. // 获取验证码
  251. if (!this.$store.getters.phone) {
  252. this.$message.error("请输入正确的手机号");
  253. return;
  254. }
  255. if (!this.isDisable) {
  256. this.isDisable = true;
  257. // 发请求成功后开启定时器
  258. // 发送验证码
  259. axios
  260. .post(
  261. "/api-web/code/sendSms",
  262. qs.stringify({ mobile: this.$store.getters.phone })
  263. )
  264. .then((res) => {
  265. if (res.data.code == 200) {
  266. let timer = setInterval((res) => {
  267. if (this.timerCount <= 0) {
  268. clearInterval(timer);
  269. this.isDisable = false;
  270. this.btnName = "获取验证码";
  271. this.timerCount = 60;
  272. } else {
  273. this.timerCount--;
  274. this.btnName = `${this.timerCount}s后重试`;
  275. }
  276. }, 1000);
  277. }
  278. });
  279. }
  280. },
  281. },
  282. watch: {
  283. resetVisible(val) {
  284. if (!val) {
  285. this.resetForm = {
  286. phone: "",
  287. authCode: "",
  288. password: "",
  289. password2: "",
  290. };
  291. }
  292. },
  293. },
  294. };
  295. </script>
  296. <style lang="scss" scoped>
  297. .navbar_tag {
  298. margin: 0 5px 8px;
  299. }
  300. .indexlayout-top-menu{
  301. padding-left: 57px;
  302. height: 90px;
  303. line-height: 88px;
  304. flex: 1;
  305. display: flex;
  306. overflow: hidden;
  307. /* overflow-x: auto; */
  308. .indexlayout-top-menu-li{
  309. display: inline-block;
  310. padding: 0 5px;
  311. height: 90px;
  312. text-decoration: none;
  313. color: #f2f2f2;
  314. font-size: 16px;
  315. transition: all .3s ease;
  316. span {
  317. // display: block;
  318. transition: all .3s ease;
  319. padding: 10px 20px;
  320. }
  321. &:hover,
  322. &.active{
  323. color: #fff;
  324. span {
  325. background: #14928A;
  326. border-radius: 6px;
  327. }
  328. }
  329. &.active span {
  330. font-weight: bold;
  331. }
  332. }
  333. .breadcrumb{
  334. line-height: 90px;
  335. margin-left: 10px;
  336. .el-breadcrumb__item{
  337. display: inline-block;
  338. float: none;
  339. }
  340. }
  341. }
  342. .popover-container {
  343. max-height: 350px;
  344. overflow-y: scroll;
  345. }
  346. .navbar {
  347. display: flex;
  348. flex-direction: row;
  349. justify-content: space-between;
  350. height: 90px;
  351. overflow: hidden;
  352. position: relative;
  353. background: #363D55;
  354. box-shadow: 0px 8px 20px 0px rgba(0, 0, 0, 0.1);
  355. h2 {
  356. font-size: 18px;
  357. line-height: 90px;
  358. margin: 0 0 0 30px;
  359. display: inline-block;
  360. }
  361. .hamburger-container {
  362. line-height: 90px;
  363. height: 100%;
  364. float: left;
  365. cursor: pointer;
  366. transition: background 0.3s;
  367. -webkit-tap-highlight-color: transparent;
  368. &:hover {
  369. background: rgba(0, 0, 0, 0.025);
  370. }
  371. }
  372. .breadcrumb-container {
  373. float: left;
  374. }
  375. .left-menu {
  376. line-height: 90px;
  377. padding-right: 22px;
  378. font-size: 16px;
  379. color: #fff;
  380. .topIcon {
  381. width: 20px;
  382. height: 25px;
  383. }
  384. }
  385. .right-menu {
  386. min-width: 154px;
  387. float: right;
  388. height: 100%;
  389. line-height: 90px;
  390. display: flex;
  391. flex-direction: row;
  392. justify-content: flex-start;
  393. &:focus {
  394. outline: none;
  395. }
  396. .msginfo {
  397. display: flex;
  398. flex-direction: row;
  399. justify-content: flex-start;
  400. align-items: center;
  401. margin-right: 20px;
  402. margin-left: 30px;
  403. position: relative;
  404. cursor: pointer;
  405. img {
  406. width: 23px;
  407. height: 30px;
  408. }
  409. .active {
  410. position: absolute;
  411. width: 7px;
  412. height: 7px;
  413. background-color: #f97215;
  414. border-radius: 50%;
  415. top: 20px;
  416. right: -4px;
  417. }
  418. }
  419. .right-menu-item {
  420. display: inline-block;
  421. padding: 0 8px;
  422. height: 100%;
  423. font-size: 14px;
  424. color: #5a5e66;
  425. vertical-align: text-bottom;
  426. &.hover-effect {
  427. cursor: pointer;
  428. transition: background 0.3s;
  429. &:hover {
  430. background: rgba(0, 0, 0, 0.025);
  431. }
  432. }
  433. }
  434. .avatar-container {
  435. height: 90px;
  436. margin-right: 42px;
  437. cursor: pointer;
  438. .avatar-wrapper {
  439. position: relative;
  440. display: flex;
  441. flex-direction: row;
  442. justify-content: flex-start;
  443. align-items: center;
  444. span {
  445. margin-left: 8px;
  446. font-size: 14px;
  447. font-weight: 500;
  448. // color: rgba(68, 68, 68, 1);
  449. color: #fff;
  450. }
  451. .user-avatar {
  452. cursor: pointer;
  453. width: 32px;
  454. height: 32px;
  455. border: 2px solid #f0f2f5;
  456. border-radius: 50%;
  457. }
  458. .el-icon-caret-bottom {
  459. cursor: pointer;
  460. position: absolute;
  461. right: -20px;
  462. top: 25px;
  463. font-size: 14px;
  464. }
  465. }
  466. }
  467. }
  468. }
  469. </style>