Navbar.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. <template>
  2. <div class="navbar">
  3. <!-- <hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> -->
  4. <router-link
  5. key="collapse"
  6. style="display: flex; align-items: center; padding-left: 30px"
  7. to="/"
  8. >
  9. <img
  10. v-if="tenantLogo"
  11. :src="tenantLogo"
  12. class="sidebar-logo"
  13. style="width: 36px; height: 36px"
  14. />
  15. <img
  16. v-else
  17. src="@/assets/images/base/smallLogo.png"
  18. class="sidebar-logo"
  19. style="width: 36px; height: 36px"
  20. />
  21. <span class="tenantName" :title="tenantName">{{ tenantName }}</span>
  22. </router-link>
  23. <!-- <breadcrumb class="breadcrumb-container" /> -->
  24. <div class="indexlayout-top-menu">
  25. <!-- :class="{'active': getTopMenuActive === route.path}" -->
  26. <!-- el-scrollbar -->
  27. <el-scrollbar class="horizontal-scrollbar" style="overflow: hidden; height: 100%">
  28. <template v-for="route in permission_routes">
  29. <app-link
  30. v-if="!route.hidden"
  31. :to="route.path"
  32. :key="route.id"
  33. class="indexlayout-top-menu-li"
  34. :class="{ active: getTopMenuActive === route.path }"
  35. >
  36. <div
  37. style="
  38. display: flex;
  39. align-items: center;
  40. justify-content: center;
  41. flex-direction: column;
  42. height: 76px;
  43. "
  44. >
  45. <i :class="[route.meta.icon, 'menuSize']"></i>
  46. <span style="line-height: 1.2">{{ route.meta.title }}</span>
  47. </div>
  48. </app-link>
  49. </template>
  50. </el-scrollbar>
  51. </div>
  52. <div class="right-menu">
  53. <el-tooltip
  54. style="display: flex"
  55. effect="dark"
  56. v-if="tenantForm.tenantId == 1"
  57. content="点击进入商城系统"
  58. placement="bottom"
  59. >
  60. <div class="msginfo right-position" @click="gotoMall">
  61. <i class="icon_admin_mall operationSize"></i>
  62. </div>
  63. </el-tooltip>
  64. <el-tooltip
  65. style="display: flex"
  66. effect="dark"
  67. v-if="tenantForm.tenantId == 1"
  68. content="点击进入OA系统"
  69. placement="bottom"
  70. >
  71. <div class="msginfo right-position" @click="gotoOa">
  72. <i class="icon_admin_oa operationSize"></i>
  73. </div>
  74. </el-tooltip>
  75. <!-- <el-popover
  76. placement="bottom"
  77. trigger="hover"
  78. style="display: flex;"
  79. v-if="tenantForm.tenantId == 1"
  80. >
  81. <div class="popover-container" style="text-align: center">OA审批</div>
  82. <div
  83. class="msginfo right-position"
  84. @click="gotoOa"
  85. slot="reference"
  86. >
  87. <i class="icon_admin_oa operationSize"></i>
  88. </div>
  89. </el-popover> -->
  90. <!-- <el-popover
  91. v-if="isShowIns"
  92. placement="bottom"
  93. trigger="hover"
  94. style="display: flex;"
  95. >
  96. <div class="popover-container" style="text-align: center">操作手册</div>
  97. <div
  98. class="msginfo right-position"
  99. @click="openIns"
  100. slot="reference"
  101. >
  102. <i class="icon_admin_book operationSize"></i>
  103. </div>
  104. </el-popover> -->
  105. <!-- <el-popover
  106. placement="bottom"
  107. trigger="hover"
  108. style="display: flex;"
  109. >
  110. <div class="popover-container" style="text-align: center">系统日志</div>
  111. <div
  112. class="msginfo right-position"
  113. v-permission="'/journal'"
  114. @click="gotoRecode"
  115. slot="reference"
  116. >
  117. <i class="icon_admin_message operationSize"></i>
  118. </div>
  119. </el-popover> -->
  120. <el-tooltip
  121. style="display: flex"
  122. effect="dark"
  123. content="点击查看系统日志"
  124. placement="bottom"
  125. >
  126. <div class="msginfo right-position" v-permission="'/journal'" @click="gotoRecode">
  127. <i class="icon_admin_message operationSize"></i>
  128. </div>
  129. </el-tooltip>
  130. <el-tooltip
  131. style="display: flex"
  132. effect="dark"
  133. content="点击打开聊天"
  134. placement="bottom"
  135. >
  136. <el-badge :is-dot="noReadNum > 0 ? true : false" class="item">
  137. <div class="msginfo right-position" @click="gotoChart">
  138. <i class="icon_admin_chart operationSize"></i>
  139. </div>
  140. </el-badge>
  141. </el-tooltip>
  142. <div class="left-menu" v-if="organNameList && organNameList.length > 0">
  143. <el-popover
  144. placement="top-start"
  145. width="300"
  146. trigger="hover"
  147. style="display: flex"
  148. >
  149. <div class="popover-container">
  150. <el-tag
  151. class="navbar_tag"
  152. type="info"
  153. v-for="item in organNameList"
  154. :key="item"
  155. >{{ item }}</el-tag
  156. >
  157. </div>
  158. <span slot="reference" class="msginfo right-position">
  159. <i class="icon_admin_orgin operationSize"></i>
  160. </span>
  161. </el-popover>
  162. </div>
  163. <el-dropdown class="avatar-container" trigger="hover" style="margin-left: 12px">
  164. <div class="avatar-wrapper">
  165. <img
  166. v-if="$store.getters.avatar"
  167. :src="$store.getters.avatar"
  168. class="user-avatar"
  169. />
  170. <img
  171. v-else
  172. class="user-avatar"
  173. src="@/assets/images/base/placehorder-icon.png"
  174. />
  175. <span>{{ name }}</span>
  176. </div>
  177. <el-dropdown-menu slot="dropdown" class="user-dropdown">
  178. <div class="drop_userInfo">
  179. <div class="avatar-wrapper">
  180. <img
  181. v-if="$store.getters.avatar"
  182. :src="$store.getters.avatar"
  183. class="user-avatar"
  184. />
  185. <img
  186. v-else
  187. class="user-avatar"
  188. src="@/assets/images/base/placehorder-icon.png"
  189. />
  190. <div>
  191. <span>{{ name }}</span>
  192. <p class="positionName" :title="positionName">
  193. {{ positionName }}
  194. </p>
  195. </div>
  196. </div>
  197. </div>
  198. <div class="tenantService" v-if="!tenantStatus">
  199. <div class="serviceName">
  200. <p class="name">{{ tenantInfo.serverName }}</p>
  201. <div
  202. class="serviceRenew"
  203. @click="onRenew"
  204. v-if="
  205. $helpers.permission('/ productService') &&
  206. $helpers.permission('/serviceRenew')
  207. "
  208. >
  209. 立即续费
  210. </div>
  211. </div>
  212. <div class="serviceTime" v-if="tenantInfo.validRemaining > 0">
  213. 剩余{{ tenantInfo.validRemaining }}天({{ tenantInfo.expiryDateEnd }})到期
  214. </div>
  215. <div class="serviceTime" v-else>已过期</div>
  216. </div>
  217. <!-- divided -->
  218. <el-dropdown-item v-if="tenantStatus" @click.native="onTenantChange">
  219. <i class="icon_admin_tenant userSize"></i>
  220. <span class="dropdown-text">{{ tenantName }}</span>
  221. <i style="margin-left: 3px" class="icon_admin_change userSize"></i>
  222. </el-dropdown-item>
  223. <el-dropdown-item
  224. @click.native="
  225. () => {
  226. this.nocloseable = false;
  227. resetPassWord();
  228. }
  229. "
  230. >
  231. <i class="icon_admin_edit userSize"></i>
  232. <span class="dropdown-text">修改密码</span>
  233. </el-dropdown-item>
  234. <el-dropdown-item
  235. @click.native="accountStatus = true"
  236. v-if="$helpers.permission('employee/simpleUpdate')"
  237. >
  238. <i class="icon_admin_account userSize"></i>
  239. <span class="dropdown-text">账号设置</span>
  240. </el-dropdown-item>
  241. <el-dropdown-item style="border-top: 1px solid #e5e5e5" @click.native="logout">
  242. <i class="icon_admin_exit userSize"></i>
  243. <span class="dropdown-text">安全退出</span>
  244. </el-dropdown-item>
  245. </el-dropdown-menu>
  246. </el-dropdown>
  247. </div>
  248. <el-dialog
  249. title="修改密码"
  250. width="500px"
  251. append-to-body
  252. :visible.sync="resetVisible"
  253. :show-close="!nocloseable"
  254. :close-on-press-escape="false"
  255. :close-on-click-modal="false"
  256. >
  257. <el-form
  258. :model="resetForm"
  259. label-position="right"
  260. label-width="100px"
  261. ref="pwdForm"
  262. >
  263. <el-form-item label="手机号" prop="phone">
  264. <div>{{ this.$store.getters.phone }}</div>
  265. </el-form-item>
  266. <el-form-item
  267. label="新密码"
  268. :rules="[
  269. { required: true, message: '密码不能为空', trigger: 'blur' },
  270. {
  271. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  272. message: '密码为6-20位数字和字母组合',
  273. trigger: 'blur',
  274. },
  275. ]"
  276. prop="password"
  277. >
  278. <el-input
  279. v-model.trim="resetForm.password"
  280. type="password"
  281. style="width: 180px"
  282. autocomplete="off"
  283. ></el-input>
  284. </el-form-item>
  285. <el-form-item
  286. label="再次输入"
  287. :rules="[
  288. { required: true, message: '密码不能为空', trigger: 'blur' },
  289. {
  290. pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/,
  291. message: '密码为6-20位数字和字母组合',
  292. trigger: 'blur',
  293. },
  294. ]"
  295. prop="password2"
  296. >
  297. <el-input
  298. v-model.trim="resetForm.password2"
  299. type="password"
  300. style="width: 180px"
  301. autocomplete="off"
  302. ></el-input>
  303. </el-form-item>
  304. <el-form-item
  305. label="验证码"
  306. :rules="[{ required: true, message: '验证码不能为空', trigger: 'blur' }]"
  307. prop="authCode"
  308. style=""
  309. >
  310. <el-input
  311. v-model.trim="resetForm.authCode"
  312. style="width: 180px"
  313. autocomplete="off"
  314. ></el-input>
  315. <el-button :disabled="isDisable" @click="getCode">{{ btnName }}</el-button>
  316. </el-form-item>
  317. </el-form>
  318. <div slot="footer" class="dialog-footer">
  319. <el-button @click="resetVisible = false" v-if="!nocloseable">取 消</el-button>
  320. <el-button type="primary" @click="submitResetPassWord">确 定</el-button>
  321. </div>
  322. </el-dialog>
  323. <el-dialog
  324. title="切换机构"
  325. width="500px"
  326. append-to-body
  327. v-if="tenantVisible"
  328. :visible.sync="tenantVisible"
  329. >
  330. <el-form
  331. :model="tenantForm"
  332. label-position="right"
  333. label-width="100px"
  334. ref="tenantForm"
  335. >
  336. <el-form-item
  337. label="选择机构"
  338. :rules="[{ required: true, message: '请选择机构', trigger: 'change' }]"
  339. prop="tenantId"
  340. >
  341. <el-select
  342. v-model.trim="tenantForm.tenantId"
  343. filterable
  344. placeholder="请选择机构"
  345. clearable
  346. style="width: 100% !important"
  347. >
  348. <el-option
  349. v-for="(item, index) in tenantList"
  350. :key="index"
  351. :label="item.name"
  352. :value="item.id"
  353. ></el-option>
  354. </el-select>
  355. </el-form-item>
  356. </el-form>
  357. <div slot="footer" class="dialog-footer">
  358. <el-button @click="tenantVisible = false">取 消</el-button>
  359. <el-button type="primary" @click="submitTenant">确 定</el-button>
  360. </div>
  361. </el-dialog>
  362. <el-dialog
  363. title="账号设置"
  364. append-to-body
  365. :visible.sync="accountStatus"
  366. v-if="accountStatus"
  367. width="650px"
  368. >
  369. <user-model @close="accountStatus = false"></user-model>
  370. </el-dialog>
  371. <!-- <portal-target name="AppMain" ref="target">
  372. <instructions ref="instructions" @checkShow="checkShow" />
  373. </portal-target> -->
  374. </div>
  375. </template>
  376. <script>
  377. import qs from "qs";
  378. import Logo from "./Sidebar/Logo";
  379. import { mapGetters } from "vuex";
  380. // import Breadcrumb from '@/components/Breadcrumb'
  381. // import Hamburger from '@/components/Hamburger'
  382. import { resetPassword } from "@/api/buildTeam";
  383. import AppLink from "./Sidebar/Link";
  384. import { getBelongTopMenuPath } from "@/utils/permission";
  385. // import instructions from "./instructions";
  386. import { validOaUrl, validMallUrl } from "@/utils/validate";
  387. import { tenantInfoQueryPage } from "@/views/organManager/api";
  388. import Cookies from "js-cookie";
  389. import axios from "axios";
  390. import userModel from "./modal/userModal";
  391. export default {
  392. data() {
  393. let tenantConfig = sessionStorage.getItem("tenantConfig");
  394. tenantConfig = tenantConfig ? JSON.parse(tenantConfig) : {};
  395. return {
  396. accountStatus: false,
  397. organName: this.$store.getters.organName,
  398. organNameList: [],
  399. resetVisible: false,
  400. resetForm: {
  401. phone: "",
  402. authCode: "",
  403. password: "",
  404. password2: "",
  405. },
  406. isDisable: false, // 是否允许发送验证码
  407. timerCount: 60,
  408. btnName: "获取验证码",
  409. isShowIns: false,
  410. tenantVisible: false,
  411. tenantName: tenantConfig.tenantName || null,
  412. tenantForm: {
  413. tenantId: Number(tenantConfig.tenantId) || null,
  414. },
  415. tenantList: [],
  416. tenantLogo: tenantConfig.tenantLogo || null,
  417. noReadNum: 0,
  418. nocloseable: false,
  419. };
  420. },
  421. components: {
  422. AppLink,
  423. userModel,
  424. // instructions,
  425. // Breadcrumb,
  426. // Hamburger
  427. },
  428. computed: {
  429. ...mapGetters([
  430. "sidebar",
  431. "avatar",
  432. "name",
  433. "positionName",
  434. "permission_routes",
  435. "tenantInfo",
  436. ]),
  437. getTopMenuActive() {
  438. let route = this.$route;
  439. // (route, getBelongTopMenuPath(route))
  440. return getBelongTopMenuPath(route);
  441. },
  442. tenantStatus() {
  443. // 判断是否是平台账号 true 是
  444. const baseTenantId = sessionStorage.getItem("baseTenantId");
  445. return baseTenantId < 0 ? true : false;
  446. },
  447. },
  448. mounted() {
  449. // this.$bus.$on("resetPwd", () => {
  450. // this.resetPassWord();
  451. // });
  452. console.log(this.$store.getters.pwdflag, "getpwdflag");
  453. if (this.$store.getters.pwdflag) {
  454. // this.$confirm("当前账号存在安全风险是否修改密码", "提示", {
  455. // confirmButtonText: "确定",
  456. // cancelButtonText: "取消",
  457. // type: "warning",
  458. // })
  459. // .then(() => {
  460. // })
  461. // .catch(() => {});
  462. this.nocloseable = true;
  463. this.resetPassWord();
  464. }
  465. this.$bus.$on("getShowNums", (obj) => {
  466. this.noReadNum = obj;
  467. });
  468. // 手动加入
  469. this.toggleSideBar();
  470. this.organNameList = this.organName ? this.organName.split(",") : [];
  471. },
  472. methods: {
  473. toggleSideBar() {
  474. this.$store.dispatch("app/toggleSideBar");
  475. },
  476. async logout() {
  477. await this.$store.dispatch("user/logout");
  478. localStorage.removeItem("firstMenuUrl");
  479. // await this.$store.dispatch("permission/removePermission")
  480. this.$router.push(`/login`);
  481. window.location.reload();
  482. },
  483. async onTenantChange() {
  484. try {
  485. const res = await tenantInfoQueryPage({
  486. page: 1,
  487. rows: 999,
  488. payState: 1,
  489. state: 1,
  490. });
  491. this.tenantList = res.data?.rows || [];
  492. this.tenantVisible = true;
  493. } catch (e) {}
  494. },
  495. onRenew() {
  496. this.$router.push("/productService");
  497. },
  498. submitTenant() {
  499. this.$refs["tenantForm"].validate((res) => {
  500. if (res) {
  501. const tenantForm = this.tenantForm;
  502. let tenantName = null;
  503. let tenantLogo = null;
  504. this.tenantList.forEach((item) => {
  505. if (item.id == tenantForm.tenantId) {
  506. tenantName = item.name;
  507. tenantLogo = item.logo;
  508. this.tenantName = item.name;
  509. this.tenantLogo = item.logo;
  510. }
  511. });
  512. let tenantConfig = sessionStorage.getItem("tenantConfig");
  513. tenantConfig = tenantConfig ? JSON.parse(tenantConfig) : {};
  514. if (tenantConfig.tenantId != tenantForm.tenantId) {
  515. //判断是否是当前路由
  516. // if(url == this.$route.path) {
  517. tenantConfig.tenantId = tenantForm.tenantId;
  518. tenantConfig.tenantName = tenantName;
  519. tenantConfig.tenantLogo = tenantLogo;
  520. sessionStorage.setItem("tenantConfig", JSON.stringify(tenantConfig));
  521. this.$router.push({
  522. path: "/redirect",
  523. query: this.$route.fullPath,
  524. });
  525. // } else {
  526. // this.$router.push({
  527. // path: url
  528. // })
  529. // }
  530. // 需要重置数据
  531. this.$store.commit("commit_branchs", []);
  532. this.$store.commit("commit_subjects", []);
  533. this.$store.commit("commit_teachers", []);
  534. this.$store.commit("commit_schools", []);
  535. this.$store.commit("commit_vip_group_category", []);
  536. this.$store.commit("commit_educations", []);
  537. this.$store.commit("commit_technician", []);
  538. this.$store.commit("commit_roles", []);
  539. this.$store.commit("commit_employs", []);
  540. // 移除
  541. localStorage.removeItem("searchs");
  542. }
  543. }
  544. });
  545. },
  546. gotoRecode() {
  547. this.$router.push("/journal/journal");
  548. },
  549. resetPassWord() {
  550. this.resetVisible = true;
  551. },
  552. submitResetPassWord() {
  553. if (this.resetForm.password !== this.resetForm.password2) {
  554. this.$message.error("两次密码必须相同");
  555. return;
  556. }
  557. this.$refs["pwdForm"].validate((res) => {
  558. if (res) {
  559. // 发请求
  560. resetPassword({
  561. authCode: this.resetForm.authCode,
  562. mobile: this.$store.getters.phone,
  563. newPassword: this.resetForm.password,
  564. }).then((res) => {
  565. if (res.code == 200) {
  566. // 修改成功
  567. this.$message.success("修改成功");
  568. this.logout();
  569. }
  570. });
  571. }
  572. });
  573. },
  574. getCode() {
  575. // 获取验证码
  576. if (!this.$store.getters.phone) {
  577. this.$message.error("请输入正确的手机号");
  578. return;
  579. }
  580. if (!this.isDisable) {
  581. this.isDisable = true;
  582. // 发请求成功后开启定时器
  583. // 发送验证码
  584. axios
  585. .post(
  586. "/api-web/code/sendSms",
  587. qs.stringify({ mobile: this.$store.getters.phone })
  588. )
  589. .then((res) => {
  590. if (res.data.code == 200) {
  591. let timer = setInterval((res) => {
  592. if (this.timerCount <= 0) {
  593. clearInterval(timer);
  594. this.isDisable = false;
  595. this.btnName = "获取验证码";
  596. this.timerCount = 60;
  597. } else {
  598. this.timerCount--;
  599. this.btnName = `${this.timerCount}s后重试`;
  600. }
  601. }, 1000);
  602. }
  603. });
  604. }
  605. },
  606. openIns() {
  607. // this.$refs.instructions.showInstructions();
  608. },
  609. checkShow(val) {
  610. this.isShowIns = val;
  611. },
  612. gotoOa() {
  613. // console.log(validOaUrl())
  614. // const Token = Cookies.get('cross-Token')
  615. // console.log(Token, validOaUrl().split('//')[1])
  616. // Cookies.set('Admin-Token', Token, { domain: `.${validOaUrl().split('//')[1]}`, path: '/' })
  617. // document.cookie = `Adminoken=${Token};domain=oadev.dayaedu.com;`
  618. window.open(validOaUrl());
  619. },
  620. gotoMall() {
  621. window.open(validMallUrl());
  622. },
  623. gotoChart() {
  624. // 初始化未读数
  625. this.$bus.$emit("openChart", true);
  626. },
  627. },
  628. watch: {
  629. resetVisible(val) {
  630. if (!val) {
  631. this.resetForm = {
  632. phone: "",
  633. authCode: "",
  634. password: "",
  635. password2: "",
  636. };
  637. }
  638. },
  639. },
  640. };
  641. </script>
  642. <style lang="scss" scoped>
  643. .navbar_tag {
  644. margin: 0 5px 8px;
  645. }
  646. ::v-deep .el-scrollbar__thumb {
  647. background-color: rgba(255, 255, 255, 0.3);
  648. &:hover {
  649. background-color: rgba(255, 255, 255, 0.3);
  650. }
  651. }
  652. .indexlayout-top-menu {
  653. padding-left: 57px;
  654. height: 76px;
  655. line-height: 76px;
  656. flex: 1;
  657. display: flex;
  658. overflow: hidden;
  659. /* overflow-x: auto; */
  660. .indexlayout-top-menu-li {
  661. display: table-cell;
  662. padding: 0 5px;
  663. height: 76px;
  664. text-decoration: none;
  665. color: #f2f2f2;
  666. font-size: 16px;
  667. transition: all 0.3s ease;
  668. span {
  669. // display: block;
  670. transition: all 0.3s ease;
  671. // padding: 10px 20px;
  672. padding: 8px 20px 3px;
  673. }
  674. &:hover,
  675. &.active {
  676. span {
  677. font-weight: 500;
  678. // border-radius: 6px;
  679. }
  680. }
  681. // &.active span {
  682. // font-weight: bold;
  683. // }
  684. }
  685. .breadcrumb {
  686. line-height: 76px;
  687. margin-left: 10px;
  688. .el-breadcrumb__item {
  689. display: inline-block;
  690. float: none;
  691. }
  692. }
  693. }
  694. .popover-container {
  695. max-height: 350px;
  696. overflow-y: scroll;
  697. }
  698. .navbar {
  699. display: flex;
  700. flex-direction: row;
  701. justify-content: space-between;
  702. height: 76px;
  703. overflow: hidden;
  704. position: relative;
  705. z-index: 2000;
  706. box-shadow: 0px 8px 20px 0px rgba(0, 0, 0, 0.1);
  707. h2 {
  708. font-size: 18px;
  709. line-height: 76px;
  710. margin: 0 0 0 30px;
  711. display: inline-block;
  712. }
  713. .hamburger-container {
  714. line-height: 76px;
  715. height: 100%;
  716. float: left;
  717. cursor: pointer;
  718. transition: background 0.3s;
  719. -webkit-tap-highlight-color: transparent;
  720. &:hover {
  721. background: rgba(0, 0, 0, 0.025);
  722. }
  723. }
  724. .breadcrumb-container {
  725. float: left;
  726. }
  727. .left-menu {
  728. line-height: 76px;
  729. // padding-right: 22px;
  730. font-size: 16px;
  731. .topIcon {
  732. width: 20px;
  733. height: 25px;
  734. }
  735. }
  736. .right-menu {
  737. min-width: 154px;
  738. float: right;
  739. height: 100%;
  740. line-height: 76px;
  741. display: flex;
  742. flex-direction: row;
  743. justify-content: flex-start;
  744. &:focus {
  745. outline: none;
  746. }
  747. .msginfo.ins {
  748. img {
  749. width: 18px;
  750. height: 23px;
  751. }
  752. }
  753. .msginfo {
  754. display: flex;
  755. flex-direction: row;
  756. justify-content: flex-start;
  757. align-items: center;
  758. padding: 0 12px;
  759. position: relative;
  760. cursor: pointer;
  761. img {
  762. width: 24px;
  763. height: 24px;
  764. }
  765. .active {
  766. position: absolute;
  767. width: 7px;
  768. height: 7px;
  769. background-color: #f97215;
  770. border-radius: 50%;
  771. top: 20px;
  772. right: -4px;
  773. }
  774. }
  775. .right-menu-item {
  776. display: inline-block;
  777. padding: 0 8px;
  778. height: 100%;
  779. font-size: 14px;
  780. color: #5a5e66;
  781. vertical-align: text-bottom;
  782. &.hover-effect {
  783. cursor: pointer;
  784. transition: background 0.3s;
  785. &:hover {
  786. background: rgba(0, 0, 0, 0.025);
  787. }
  788. }
  789. }
  790. .avatar-container {
  791. height: 76px;
  792. margin-right: 42px;
  793. cursor: pointer;
  794. .avatar-wrapper {
  795. position: relative;
  796. display: flex;
  797. flex-direction: row;
  798. justify-content: flex-start;
  799. align-items: center;
  800. span {
  801. margin-left: 8px;
  802. font-size: 14px;
  803. font-weight: 500;
  804. // color: rgba(68, 68, 68, 1);
  805. color: #fff;
  806. }
  807. .user-avatar {
  808. cursor: pointer;
  809. width: 32px;
  810. height: 32px;
  811. border: 2px solid #f0f2f5;
  812. border-radius: 50%;
  813. }
  814. .el-icon-caret-bottom {
  815. cursor: pointer;
  816. position: absolute;
  817. right: -20px;
  818. top: 25px;
  819. font-size: 14px;
  820. }
  821. }
  822. }
  823. }
  824. }
  825. .user-dropdown {
  826. width: 258px;
  827. padding-top: 0 !important;
  828. box-shadow: 0px 2px 13px 0px rgba(0, 0, 0, 0.05);
  829. ::v-deep .popper__arrow {
  830. border-bottom-color: var(--color-primary) !important;
  831. &::after {
  832. border-bottom-color: var(--color-primary) !important;
  833. }
  834. }
  835. .drop_userInfo {
  836. background-color: var(--color-primary);
  837. height: 64px;
  838. color: #fff;
  839. padding: 0 12px;
  840. border-radius: 4px 4px 0 0;
  841. display: flex;
  842. align-items: center;
  843. .avatar-wrapper {
  844. display: flex;
  845. align-items: center;
  846. background: url("../../assets/images/user_tips.png") no-repeat right center;
  847. background-size: 45%;
  848. width: 100%;
  849. .user-avatar {
  850. width: 38px;
  851. height: 38px;
  852. border-radius: 50%;
  853. margin-right: 10px;
  854. }
  855. }
  856. }
  857. .tenantService {
  858. border-bottom: 1px solid #e5e5e5;
  859. padding: 18px 17px 12px;
  860. .serviceName {
  861. display: flex;
  862. align-items: center;
  863. justify-content: space-between;
  864. .name {
  865. font-size: 18px;
  866. font-weight: 600;
  867. color: var(--color-primary);
  868. line-height: 25px;
  869. width: 160px;
  870. overflow: hidden;
  871. text-overflow: ellipsis;
  872. white-space: nowrap;
  873. }
  874. .serviceRenew {
  875. width: 63px;
  876. height: 22px;
  877. background: linear-gradient(270deg, #ffc65e 0%, #ffe8a6 100%);
  878. border-radius: 11px;
  879. line-height: 22px;
  880. font-size: 11px;
  881. font-weight: 400;
  882. color: #981e13;
  883. text-align: center;
  884. cursor: pointer;
  885. }
  886. }
  887. .serviceTime {
  888. margin-top: 15px;
  889. font-size: 13px;
  890. font-weight: 400;
  891. color: #333333;
  892. line-height: 18px;
  893. }
  894. }
  895. .el-dropdown-menu__item {
  896. display: flex;
  897. align-items: center;
  898. // margin: 3px 17px;
  899. padding: 7px 17px;
  900. }
  901. .dropdown-text {
  902. display: block;
  903. width: 180px;
  904. overflow: hidden;
  905. text-overflow: ellipsis;
  906. white-space: nowrap;
  907. }
  908. }
  909. .right-position {
  910. display: flex;
  911. align-items: center;
  912. justify-content: center;
  913. height: 75px;
  914. }
  915. .sidebar-logo {
  916. margin-right: 8px;
  917. }
  918. .tenantName {
  919. font-size: 20px;
  920. font-family: PingFangSC-Semibold, PingFang SC;
  921. font-weight: 600;
  922. color: #ffffff;
  923. line-height: 28px;
  924. max-width: 150px;
  925. white-space: nowrap;
  926. text-overflow: ellipsis;
  927. overflow: hidden;
  928. }
  929. .positionName {
  930. padding-top: 5px;
  931. font-size: 12px;
  932. width: 145px;
  933. white-space: nowrap;
  934. overflow: hidden;
  935. text-overflow: ellipsis;
  936. }
  937. /deep/.el-badge__content.is-fixed.is-dot {
  938. top: 28px !important;
  939. }
  940. </style>