index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. <template>
  2. <header class="header">
  3. <div class="container clearfix">
  4. <div class="logo logo--no" v-if="header.companyLogo">
  5. <img
  6. style="cursor: pointer; width: 162px; height: 33px"
  7. :src="$tools.splitImgHost(header.companyLogo)"
  8. alt=""
  9. @click="go('/')"
  10. />
  11. </div>
  12. <h1 class="logo" v-else @click="go('/')"></h1>
  13. <nav class="nav">
  14. <ul class="list">
  15. <li v-for="(item, index) in showNav(header.Nav)" :key="index">
  16. <a v-if="item.name == '首页'" @click="go('/index')">首页</a>
  17. <a v-if="item.name == '走进祥粤'" @click="go('/about')">走进祥粤</a>
  18. <a v-if="item.name == '课程'" @click="go('/course-list')">课程</a>
  19. <a v-if="item.name == '直播'" @click="go('/live-list')">直播</a>
  20. <a v-if="item.name == '题库'" @click="go('/bank-list')">题库</a>
  21. </li>
  22. </ul>
  23. </nav>
  24. <div class="userinfo" v-if="userInfo">
  25. <!-- <a class="msg" @click="go('/person-center/my-message')">
  26. <i class="pi" v-if="msgCount > 0"></i>
  27. <i class="el-icon-message-solid icon"></i>
  28. <div @click.stop="" class="popover_style">
  29. {{ msgData.text }} <el-button style="float:right;" type="text">立即学习</el-button>
  30. </div>
  31. </a> -->
  32. <el-tooltip
  33. placement="bottom"
  34. effect="light"
  35. v-model="msgShow"
  36. :hide-after="0"
  37. manual
  38. >
  39. <el-badge :is-dot="msgCount > 0 ? true : false" class="item">
  40. <el-button
  41. style="font-size: 18px; padding: 0px"
  42. icon="el-icon-message-solid"
  43. type="text"
  44. @click="go('/person-center/my-message')"
  45. ></el-button>
  46. </el-badge>
  47. <div slot="content">
  48. {{ msgData.text }}
  49. <div>
  50. <el-button type="text" @click="newGoToStudy">立即学习</el-button
  51. ><el-button type="text" @click="clearMsg">关闭</el-button>
  52. </div>
  53. </div>
  54. </el-tooltip>
  55. <el-dropdown @command="handleCommand">
  56. <span
  57. class="el-dropdown-link"
  58. @click="go('/person-center/my-course')"
  59. style="margin-left: 10px; cursor: pointer"
  60. >
  61. <img
  62. style="width: 24px; vertical-align: middle"
  63. :src="
  64. userInfo
  65. ? userInfo.avatar
  66. ? $tools.splitImgHost(userInfo.avatar, true)
  67. : '@/assets/qrcode.png'
  68. : ''
  69. "
  70. alt=""
  71. />
  72. <span>{{ userInfo && userInfo.realname }}</span>
  73. </span>
  74. <el-dropdown-menu slot="dropdown">
  75. <el-dropdown-item command="1">我的课程</el-dropdown-item>
  76. <el-dropdown-item command="2">我的题库</el-dropdown-item>
  77. <el-dropdown-item command="3">个人中心</el-dropdown-item>
  78. <el-dropdown-item command="4">退出登录</el-dropdown-item>
  79. </el-dropdown-menu>
  80. </el-dropdown>
  81. </div>
  82. <div class="userinfo" v-else>
  83. <div class="text-list" v-if="!userInfo">
  84. <a @click="go('/login', { state: 1 })">登录</a>
  85. <a @click="go('/login', { state: 2 })">注册</a>
  86. </div>
  87. </div>
  88. <div class="search">
  89. <div class="search__select">
  90. <select v-model="type">
  91. <option value="1">课程</option>
  92. <option value="2">题库</option>
  93. <option value="6">直播</option>
  94. </select>
  95. </div>
  96. <div class="search__input">
  97. <input type="text" v-model="searchKey" autocomplete="off" />
  98. <input
  99. type="password"
  100. autocomplete="new-password"
  101. style="display: none"
  102. />
  103. </div>
  104. <el-button type="primary" @click="search" class="search__btn"
  105. >搜索</el-button
  106. >
  107. </div>
  108. </div>
  109. <RebuildModal
  110. ref="rebuildModal"
  111. @rebuildSubmit="rebuildSubmit($event)"
  112. ></RebuildModal>
  113. </header>
  114. </template>
  115. <script>
  116. import RebuildModal from "@/components/rebuildModal";
  117. import { mapGetters, mapMutations } from "vuex";
  118. export default {
  119. name: "Header",
  120. components: {
  121. RebuildModal,
  122. },
  123. data() {
  124. return {
  125. searchKey: "",
  126. type: "1",
  127. showBox: false,
  128. timer: null,
  129. msgData: {},
  130. sysTime: 0,
  131. msgShow: false,
  132. };
  133. },
  134. computed: {
  135. ...mapGetters(["header", "userInfo", "msgCount"]),
  136. showNav: function () {
  137. return function (list) {
  138. var newList = [];
  139. if (list) {
  140. newList = list.filter((item) => {
  141. return item.status === 1;
  142. });
  143. }
  144. return newList;
  145. };
  146. },
  147. },
  148. mounted() {
  149. if (this.$tools.isLogin()) {
  150. this.$request.informUserselectLastUnStudyMsg().then((res) => {
  151. if (res.data && res.data.id) {
  152. let today = new Date(new Date().toLocaleDateString()).getTime();
  153. if (localStorage.getItem("msg")) {
  154. let ary = JSON.parse(localStorage.getItem("msg"));
  155. if (ary.updateTime === today) {
  156. this.msgShow = false;
  157. return;
  158. }
  159. }
  160. this.$nextTick(() => {
  161. this.msgData = res.data;
  162. this.msgShow = true;
  163. });
  164. } else {
  165. this.msgShow = false;
  166. }
  167. });
  168. this.getMsgCount();
  169. }
  170. },
  171. methods: {
  172. ...mapMutations(["getMsgCount"]),
  173. rebuildSubmit(item) {
  174. this.$router.push({
  175. path: `/my-course-detail/${item.goodsId}`,
  176. query: {
  177. gradeId: item.gradeId,
  178. orderGoodsId: item.orderGoodsId,
  179. rebuild: 1,
  180. },
  181. });
  182. },
  183. getGoodsData() {
  184. return new Promise((resolve, reject) => {
  185. this.$request.goodsDetail(this.msgData.goodsId).then((res) => {
  186. resolve(res.data);
  187. });
  188. });
  189. },
  190. /**
  191. * 关闭消息
  192. */
  193. clearMsg() {
  194. let ary = {
  195. userId: this.msgData.userId,
  196. msgId: this.msgData.id,
  197. updateTime: new Date(new Date().toLocaleDateString()).getTime(),
  198. };
  199. localStorage.setItem("msg", JSON.stringify(ary));
  200. this.msgShow = false;
  201. },
  202. /**
  203. * 前往学习
  204. */
  205. async newGoToStudy() {
  206. let item = await this.getGoodsData();
  207. if (item.goodsType == 1) {
  208. this.sysTime = this.$tools.timest();
  209. item.orderGoodsId = this.msgData.orderGoodsId;
  210. this.canJump(item).then((res) => {
  211. this.clearMsg();
  212. this.$router.push({
  213. path: `/my-course-detail/${item.goodsId}`,
  214. query: {
  215. gradeId: item.gradeId,
  216. orderGoodsId: item.orderGoodsId,
  217. courseId: res.rows[0].courseId || "",
  218. },
  219. });
  220. });
  221. // arsty = '立刻学习';
  222. //题库
  223. } else if (item.goodsType == 2) {
  224. this.clearMsg();
  225. this.$router.push({
  226. path: "/person-center/my-bank/bank-detail/" + item.goodsId,
  227. query: {
  228. orderGoodsId: item.orderGoodsId,
  229. },
  230. });
  231. }
  232. },
  233. canJump(item) {
  234. return new Promise((resolve) => {
  235. this.$request
  236. .orderInfo({
  237. orderGoodsId: item.orderGoodsId,
  238. })
  239. .then(async (res) => {
  240. let items = res.data;
  241. let currentTime = this.$tools.timest();
  242. if (items.interfaceAccountId > 0) {
  243. //学习账号已开通
  244. if (items.learnStatus == 1) {
  245. //跳转第三方h5
  246. const confirmText = [
  247. "您的学习账号已经开通,请按照步骤操作,进行学习。",
  248. "1.点击【跳转学习网址】按钮",
  249. "2.打开学习网址后,选择【个人用户】进行登录",
  250. "(1)账号:您个人的身份证号码",
  251. "(2)密码:身份证号码,再加111111",
  252. ];
  253. const newDatas = [];
  254. const h = this.$createElement;
  255. for (const i in confirmText) {
  256. newDatas.push(h("p", null, confirmText[i]));
  257. }
  258. this.$confirm(h("div", null, newDatas), "温馨提示", {
  259. confirmButtonText: "跳转学习网址",
  260. cancelButtonText: "关闭",
  261. closeOnClickModal: false,
  262. closeOnPressEscape: false,
  263. distinguishCancelAndClose: false,
  264. showClose: false,
  265. })
  266. .then((_) => {
  267. window.open("http://admin.zhujianpeixun.com/", "_blank");
  268. })
  269. .catch((_) => {});
  270. return;
  271. } else {
  272. this.$message({
  273. type: "warning",
  274. message:
  275. "您的学习账号未开通,请稍后再尝试,有疑问,请联系020-87085982!",
  276. });
  277. return;
  278. }
  279. }
  280. // //内部系统
  281. // if (items.interfacePushId > 0 && items.officialStatus != 1) {
  282. // this.$message({
  283. // type: "warning",
  284. // message:
  285. // "机构正在为您报名中,请耐心等待,有疑问请联系020-87085982!",
  286. // });
  287. // return;
  288. // }
  289. if (
  290. this.sysTime <= items.serviceStartTime ||
  291. this.sysTime >= items.serviceEndTime
  292. ) {
  293. this.$message({
  294. type: "warning",
  295. message: "不在学习服务期,不能进入学习",
  296. });
  297. return;
  298. }
  299. if (
  300. (items.classStartTime && this.sysTime <= items.classStartTime) ||
  301. (items.classEndTime && this.sysTime >= items.classEndTime)
  302. ) {
  303. this.$message({
  304. type: "warning",
  305. message: "不在班级有效期,不能进入学习",
  306. });
  307. return;
  308. }
  309. if (items.learningStatus == 2) {
  310. this.$message({
  311. type: "warning",
  312. message: "开放学习时间待定,不能进入学习",
  313. });
  314. return;
  315. }
  316. if (items.classStatus == 0) {
  317. this.$message({
  318. type: "warning",
  319. message: "尚未开班,不能进入学习",
  320. });
  321. return;
  322. }
  323. if (
  324. items.learningStatus == 3 &&
  325. this.sysTime < items.learningTimeStart
  326. ) {
  327. this.$message({
  328. type: "warning",
  329. message: "不在开放学习时间,不能进入学习",
  330. });
  331. return;
  332. }
  333. let rebuildStatus = await this.courseGoodsRebuildStatus(
  334. items.goodsId,
  335. items.gradeId
  336. );
  337. if (rebuildStatus == 0) {
  338. this.$refs.rebuildModal.showModal(items);
  339. return;
  340. }
  341. // if (item.educationName == "继续教育") {
  342. this.$request
  343. .lockLockStatus({
  344. action: "jxjy",
  345. })
  346. .then((res) => {
  347. //有其他端在操作,不能学习
  348. this.$message({
  349. type: "warning",
  350. message: res.msg,
  351. });
  352. })
  353. .catch((err) => {
  354. //可以学习
  355. this.$request
  356. .courseCourseList({
  357. pageNum: 1,
  358. pageSize: 1,
  359. goodsId: items.goodsId,
  360. gradeId: items.gradeId,
  361. })
  362. .then((res) => {
  363. if (res.rows.length) {
  364. resolve(res);
  365. } else {
  366. this.$message({
  367. type: "warning",
  368. message: "课程内暂无可以学习的科目",
  369. });
  370. }
  371. });
  372. });
  373. // } else {
  374. // this.$request
  375. // .courseCourseList({
  376. // pageNum: 1,
  377. // pageSize: 1,
  378. // goodsId: items.goodsId,
  379. // gradeId: items.gradeId,
  380. // })
  381. // .then((res) => {
  382. // if (res.rows.length) {
  383. // resolve(res);
  384. // } else {
  385. // this.$message({
  386. // type: "warning",
  387. // message: "课程内暂无可以学习的科目",
  388. // });
  389. // }
  390. // });
  391. // }
  392. });
  393. });
  394. },
  395. /**
  396. * @param {Object} goodsId 商品id
  397. * 查询商品重修状态
  398. */
  399. courseGoodsRebuildStatus(goodsId, gradeId) {
  400. return new Promise((resolve) => {
  401. this.$request
  402. .courseGoodsRebuildStatus({
  403. goodsId: goodsId,
  404. gradeId: gradeId,
  405. })
  406. .then((res) => {
  407. resolve(res.data);
  408. });
  409. });
  410. },
  411. handleCommand(command) {
  412. switch (command) {
  413. case "1":
  414. this.go("/person-center/my-course");
  415. break;
  416. case "2":
  417. this.go("/person-center/my-bank");
  418. break;
  419. case "3":
  420. this.go("/person-center/my-info");
  421. break;
  422. case "4":
  423. this.$tools.exit();
  424. break;
  425. default:
  426. break;
  427. }
  428. },
  429. go(path, query) {
  430. this.$router.push({
  431. path,
  432. query,
  433. });
  434. },
  435. search() {
  436. if (!this.searchKey.trim()) {
  437. this.$message({
  438. type: "warning",
  439. duration: 2000,
  440. message: "请输入搜索内容",
  441. });
  442. return;
  443. }
  444. let type = this.type;
  445. let path = this.$route.path;
  446. if (path == "/bank-list") {
  447. //在题库列表页面直接传参
  448. if (type == "2") {
  449. this.$emit("search", this.searchKey);
  450. } else if (type == "6") {
  451. this.$router.push({
  452. path: "/live-list",
  453. query: {
  454. searchKey: this.searchKey,
  455. },
  456. });
  457. } else {
  458. this.$router.push({
  459. path: "/course-list",
  460. query: {
  461. searchKey: this.searchKey,
  462. },
  463. });
  464. }
  465. } else if (path == "/course-list") {
  466. //在课程列表页面直接传参
  467. if (type == "1") {
  468. this.$emit("search", this.searchKey);
  469. } else if (type == "6") {
  470. this.$router.push({
  471. path: "/live-list",
  472. query: {
  473. searchKey: this.searchKey,
  474. },
  475. });
  476. } else {
  477. this.$router.push({
  478. path: "/bank-list",
  479. query: {
  480. searchKey: this.searchKey,
  481. },
  482. });
  483. }
  484. } else if (path == "/live-list") {
  485. //在课程列表页面直接传参
  486. if (type == "6") {
  487. this.$emit("search", this.searchKey);
  488. } else if (type == "1") {
  489. this.$router.push({
  490. path: "/course-list",
  491. query: {
  492. searchKey: this.searchKey,
  493. },
  494. });
  495. } else {
  496. this.$router.push({
  497. path: "/bank-list",
  498. query: {
  499. searchKey: this.searchKey,
  500. },
  501. });
  502. }
  503. } else {
  504. //根据类型跳转题库或者列表页面
  505. console.log(type);
  506. if (type == "1") {
  507. this.$router.push({
  508. path: "/course-list",
  509. query: {
  510. searchKey: this.searchKey,
  511. },
  512. });
  513. } else if (type == "6") {
  514. this.$router.push({
  515. path: "/live-list",
  516. query: {
  517. searchKey: this.searchKey,
  518. },
  519. });
  520. } else {
  521. this.$router.push({
  522. path: "/bank-list",
  523. query: {
  524. searchKey: this.searchKey,
  525. },
  526. });
  527. }
  528. }
  529. },
  530. mouseover() {
  531. clearTimeout(this.timer);
  532. this.showBox = true;
  533. },
  534. mouseLeave() {
  535. clearTimeout(this.timer);
  536. this.timer = setTimeout(() => {
  537. this.showBox = false;
  538. }, 500);
  539. },
  540. },
  541. };
  542. </script>
  543. <!-- Add "scoped" attribute to limit CSS to this component only -->
  544. <style scoped lang="scss">
  545. .header {
  546. position: relative;
  547. background: #fff;
  548. box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.04);
  549. .container {
  550. height: 80px;
  551. .logo {
  552. margin-top: 23px;
  553. float: left;
  554. cursor: pointer;
  555. width: 162px;
  556. height: 33px;
  557. background: url("~@/assets/logo.png") no-repeat center;
  558. &--no {
  559. background: none;
  560. }
  561. }
  562. .nav {
  563. float: left;
  564. margin-top: 30px;
  565. .list {
  566. margin-left: 146px;
  567. display: flex;
  568. li {
  569. margin: 0 20px;
  570. a {
  571. color: #333;
  572. }
  573. a:hover {
  574. color: #3f8dfd;
  575. }
  576. }
  577. }
  578. }
  579. .search {
  580. float: right;
  581. margin-right: 12px;
  582. margin-top: 20px;
  583. width: 324px;
  584. background: #fafbfc;
  585. border: 1px solid #3f8dfd;
  586. border-radius: 8px;
  587. display: flex;
  588. overflow: hidden;
  589. &__select {
  590. width: 76px;
  591. border-right: 1px solid #fff;
  592. select {
  593. text-align: center;
  594. width: 100%;
  595. height: 100%;
  596. border: 0;
  597. outline: none;
  598. }
  599. }
  600. &__input {
  601. flex: 1;
  602. input {
  603. width: 100%;
  604. height: 100%;
  605. }
  606. }
  607. &__btn {
  608. padding: 0;
  609. text-align: center;
  610. width: 80px;
  611. height: 40px;
  612. line-height: 40px;
  613. font-size: 14px;
  614. border-radius: 0;
  615. }
  616. }
  617. .userinfo {
  618. margin-top: 30px;
  619. float: right;
  620. white-space: nowrap;
  621. a {
  622. display: inline-block;
  623. margin-left: 20px;
  624. vertical-align: middle;
  625. &.msg {
  626. position: relative;
  627. margin-top: 2px;
  628. .icon {
  629. font-size: 20px;
  630. color: #3f8dfd;
  631. }
  632. .pi {
  633. display: inline-block;
  634. width: 10px;
  635. height: 10px;
  636. background: #ff3b30;
  637. border: 1px solid #ffffff;
  638. border-radius: 10px;
  639. position: absolute;
  640. top: 0;
  641. right: 0;
  642. }
  643. .popover_style {
  644. position: absolute;
  645. top: 150%;
  646. left: -100px;
  647. border-radius: 8px;
  648. background-color: #fff;
  649. border: 1px solid #333;
  650. padding: 0px 6px;
  651. width: 300px;
  652. white-space: normal;
  653. }
  654. }
  655. &.name {
  656. position: relative;
  657. z-index: 99;
  658. img {
  659. width: 24px;
  660. vertical-align: middle;
  661. }
  662. .modal-box {
  663. width: 162px;
  664. background: #ffffff;
  665. box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1);
  666. border-radius: 8px;
  667. position: absolute;
  668. top: 55px;
  669. left: -40px;
  670. li {
  671. margin-left: 10px;
  672. border-bottom: 1px solid #eeeeee;
  673. height: 40px;
  674. line-height: 40px;
  675. cursor: pointer;
  676. padding-left: 5px;
  677. &:hover {
  678. background: #eeeeee;
  679. color: #3f8dfd;
  680. }
  681. &:nth-last-of-type(1) {
  682. border: 0;
  683. }
  684. }
  685. }
  686. }
  687. }
  688. }
  689. .text-list {
  690. text-align: right;
  691. font-size: 0;
  692. a {
  693. display: inline-block;
  694. margin: 0;
  695. color: #3f8dfd;
  696. font-size: 14px;
  697. padding: 0 14px;
  698. &:nth-last-of-type(1) {
  699. padding-right: 0;
  700. border-left: 1px solid #3f8dfd;
  701. }
  702. }
  703. }
  704. }
  705. }
  706. .fade-enter,
  707. .fade-leave-to {
  708. opacity: 0;
  709. height: 0;
  710. }
  711. .fade-enter-to,
  712. .fade-leave {
  713. opacity: 1;
  714. height: 122px;
  715. }
  716. .fade-enter-active,
  717. .fade-leave-active {
  718. transition: all 0.3s;
  719. }
  720. </style>