Dubbo 分布式架构搭建教育 PC 站 - 前端:Vue 代码

src\router\index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Vuex from 'vuex'
import Index from '../components/Index.vue'
import Course from '../components/Course.vue'


Vue.use(VueRouter)
Vue.use(Vuex)

const videoDetail = () => import('../components/videoDetail.vue');

const routes = [
  {
    path: '/',
    name: 'Index',
    component: Index,
    meta: {
      title: '首页'
    }
  },
  {
    path: '/Course',
    name: 'Course',
    component: Course,
    meta: {
      title: '课程简介页'
    }
  },
  {
    path: '/videoDetail',
    name: 'videoDetail',
    component: videoDetail,
    meta: {
      title: '视频播放页'
    }
  }
]

const router = new VueRouter({
  routes
})

export default router

首页显示全部课程和已购课程

src\components\Index.vue

<script>
import Header from "./Header/Header"; //顶部登录条
import Footer from "./Footer/index"; //顶部登录条
export default {
  name: "Index",
  components: {
    Header,
    Footer,
  },
  data() {
    return {
      activeName: "allLesson",
      courseList: [], // 课程集合
      myCourseList: [], // 我购买过的课程列表
      isLogin: false, //登录状态
      user: null, // 已登录的用户对象信息
    };
  },
  created() {
    this.user = JSON.parse(localStorage.getItem("user"));
    if (this.user != null) {
      this.isLogin = true; //已登录
      this.getMyCourseList(); // 调用查询我购买的课程方法
    }

    this.getCourseList(); //当组件创建完毕,就调用获取所有课程的方法
  },
  methods: {
    changeCourseTab(tabName) {
      this.classSelect = tabName;
      sessionStorage && sessionStorage.setItem("courseTab", tabName);
    },
    gotoDetail(item) {
      this.$router.push({ name: "Course", params: { course: item } });
    },
    getCourseList() {
      // 去dubbo服务获取全部课程的数据
      return this.axios
        .get("http://localhost:80/course/getAllCourse")
        .then((result) => {
          console.log(result);
          this.courseList = result.data;
        })
        .catch((error) => {
          this.$message.error("获取课程信息失败!");
        });
    },
    getMyCourseList() {
      return this.axios
        .get(
          "http://localhost:80/course/getCourseByUserId/" + this.user.content.id
        )
        .then((result) => {
          console.log(result);
          this.myCourseList = result.data;
        })
        .catch((error) => {
          this.$message.error("获取课程信息失败!");
        });
    },
  },
};
</script>
<!-- 课程信息展示开始 -->
<li
    class="course-li"
    v-for="(item, index) in courseList"
    :key="index"
    >
    <!-- 课程封面图 -->
    <img
         :src="item.courseImgUrl"
         class="teacher-portrait hover-pointer"
         />
    <!-- 课程文字信息 -->
    <div class="content-main">
        <!-- 课程标题 -->
        <div class="content-title hover-pointer">
            <div
                 class="p-title"
                 style="text-align: left"
                 @click="gotoDetail(item)"
                 >
                <span>
                    {{ item.courseName }}
                </span>
            </div>
            <!-- 作者和职称 -->
            <p class="p-title-buy text-overflow">
                <span class="p-author-span">
                    {{ item.teacher.teacherName }}
                </span>
                <span class="p-author-line" />
                <span class="p-author-span">
                    {{ item.teacher.position }}
                </span>
            </p>
            <p></p>
            <!-- 课程简单描述 -->
            <p class="p-describe" style="text-align: left">
                {{ item.brief }}
            </p>
        </div>
        <!-- 课程前两个章节信息 -->
        <ul class="content-course" style="text-align: left">
            <!-- 章节1 : 免费试看,通常是第一章的前两节课 -->
            <li
                class="content-course-lesson text-overflow"
                style="width: 300px"
                v-for="(lesson,
                       index) in item.courseSections[0].courseLessons.slice(0, 2)"
                :key="index"
                >
                <!-- 免费试看图标 -->
                <img
                     src="@/assets/course-list/free-course.png"
                     class="free-label hover-pointer"
                     />
                <span class="theme-span hover-pointer">
                    {{ lesson.theme }}
                </span>
            </li>
        </ul>
        <!-- 价格信息 -->
        <div class="content-price" style="text-align: left">
            <p class="content-price-p">
                <span class="content-price-orange-sm">¥</span>
                <span class="content-price-orange">{{
                    item.discounts
                    }}</span>
                <span class="current-price">
                    <span class="current-price-unite">¥</span>
                    {{ item.price }}
                </span>
                <span class="activity-name">成就自己</span>
                <span class="content-price-buy"
                      >{{ item.sales }}人购买</span
                    >
            </p>
            <div class="btn btn-green btn-offset">立即购买</div>
        </div>
    </div>
</li>
<!-- 课程信息结束 -->

登录

src\components\Header\Header.vue

<script>
// import wxlogin from 'vue-wxlogin'; // 引入

export default {
  name: "Header",
  components: {
    // wxlogin  // 声明引用的组件
  },
  props: {},
  data() {
    return {
      isLogin: false, // 登录状态,true:已登录,false:未登录
      userDTO: null, // 用来保存登录的用户信息
      isHasNewMessage: false, // 是否有新的推送消息
      dialogFormVisible: false, // 是否显示登录框,true:显示,false:隐藏
      phone: "", // 双向绑定表单 手机号
      password: "", // 双向绑定表单 密码
      // appid:"wxd99431bbff8305a0", // 应用唯一标识,在微信开放平台提交应用审核通过后获得
      // scope:"snsapi_login", // 应用授权作用域,网页应用目前仅填写snsapi_login即可
      // redirect_uri:"http://www.pinzhi365.com/user/wxlogin",  //重定向地址,(回调地址)
      x: null,
    };
  },
  computed: {},
  watch: {},
  mounted() {},
  created() {
    // 当刷新页面,组件创建成功之后,立刻检测本地储存中是否存在用户对象
    this.userDTO = JSON.parse(localStorage.getItem("user"));
    if (this.userDTO != null) {
      this.isLogin = true; // 已登录
    } else {
      // 去检测微信是否登录过
      this.axios
        .get("http://localhost:80/user/checkWxStatus")
        .then((result) => {
          this.userDTO = result.data;
          this.phone = this.userDTO.content.phone;
          this.password = this.userDTO.content.password;
          this.login(); // 走普通登录
        })
        .catch((error) => {
          //this.$message.error("登录失败!");
        });
    }

    !(function (a, b, c) {
      function d(a) {
        var c = "default";
        a.self_redirect === !0
          ? (c = "true")
          : a.self_redirect === !1 && (c = "false");
        var d = b.createElement("iframe"),
          e =
            "https://open.weixin.qq.com/connect/qrconnect?appid=" +
            a.appid +
            "&scope=" +
            a.scope +
            "&redirect_uri=" +
            a.redirect_uri +
            "&state=" +
            a.state +
            "&login_type=jssdk&self_redirect=" +
            c +
            "&styletype=" +
            (a.styletype || "") +
            "&sizetype=" +
            (a.sizetype || "") +
            "&bgcolor=" +
            (a.bgcolor || "") +
            "&rst=" +
            (a.rst || "");
        (e += a.style ? "&style=" + a.style : ""),
          (e += a.href ? "&href=" + a.href : ""),
          (d.src = e),
          (d.frameBorder = "0"),
          (d.allowTransparency = "true"),
          (d.sandbox = "allow-scripts allow-top-navigation allow-same-origin"), // 允许多种请求
          (d.scrolling = "no"),
          (d.width = "300px"),
          (d.height = "400px");
        var f = b.getElementById(a.id);
        (f.innerHTML = ""), f.appendChild(d);
      }
      a.WxLogin = d;
    })(window, document);
  },
  methods: {
    goToSetting() {
      this.$router.push("/setting"); // 跳转个人设置页面
    },
    goToLogin() {
      this.dialogFormVisible = true; // 显示登录框
    },
    login() {
      // 前去登录
      return this.axios
        .get("http://localhost:80/user/login", {
          params: {
            phone: this.phone,
            password: this.password,
            nickname: "",
            headimg: "",
          },
        })
        .then((result) => {
          console.log(result);
          this.dialogFormVisible = false; //关闭登录框
          this.userDTO = result.data; // 保存返回数据中的用户对象信息
          this.isLogin = true; // 更新登录状态
          localStorage.setItem("user", JSON.stringify(this.userDTO)); // 将登录成功的对象信息保存到本地储存中
        })
        .catch((error) => {
          this.$message.error("登录失败!");
        });
    },
    // 微信登录
    goToLoginWX() {
      // 普通的登录表单隐藏
      document.getElementById("loginForm").style.display = "none";
      // 显示二维码的容器
      document.getElementById("wxLoginForm").style.display = "block";

      // 生成二维码
      // 待dom更新之后再用二维码渲染其内容
      this.$nextTick(function () {
        this.createCode(); // 直接调用会报错:TypeError: Cannot read property 'appendChild' of null
      });
    },
    // 生成二维码
    createCode() {
      var obj = new WxLogin({
        id: "wxLoginForm", // 挂载点,二维码的容器
        appid: "wxd99431bbff8305a0", // 应用唯一标识,在微信开放平台提交应用审核通过后获得
        scope: "snsapi_login", // 应用授权作用域,网页应用目前仅填写snsapi_login即可
        redirect_uri: "http://www.pinzhi365.com/user/wxlogin", //重定向地址,(回调地址)
        href:
          "data:text/css;base64,LmltcG93ZXJCb3ggLnFyY29kZSB7d2lkdGg6IDIwMHB4O30NCi5pbXBvd2VyQm94IC50aXRsZSB7ZGlzcGxheTogbm9uZTt9DQouaW1wb3dlckJveCAuaW5mbyB7d2lkdGg6IDIwMHB4O30NCi5zdGF0dXNfaWNvbiB7ZGlzcGxheTogbm9uZX1jcw0KLmltcG93ZXJCb3ggLnN0YXR1cyB7dGV4dC1hbGlnbjogY2VudGVyO30=", // 加载修饰二维码的css样式
      });
    },
    toToIndex() {
      this.$router.push("/"); //回到首页
    },
    toToNotic() {},
    //登出
    logout() {
      localStorage.setItem("user", null); // 将登录成功的对象信息保存到本地储存中
      this.isLogin = false; // 更新登录状态
      // alert("谢谢使用,再见");
      // 去检测微信是否登录过
      this.axios
        .get("http://localhost:80/user/logout")
        .then((result) => {})
        .catch((error) => {
          //this.$message.error("登录失败!");
        });
    },
  },
};
</script>

课程详情和留言

src\components\Course.vue

<!-- 课程详情 -->
<div class="container">
  <div style="height: 100%">
    <div class="weui-tab content-wrapper">
      <div
        id="vux_view_box_body"
        class="weui-tab__panel vux-fix-safari-overflow-scrolling"
      >
        <div style="position: relative">
          <div class="intro">
            <div class="intro-content">
              <img
                class="course-img"
                :src="course.courseImgUrl"
                alt="课程图片"
              />
              <div class="conent-wrap">
                <div class="name" style="text-align: left">
                  {{ course.courseName }}
                </div>
                <div class="des text-omit" style="text-align: left">
                  {{ course.brief }}
                </div>
                <div class="title">
                  <div class="teacher-name text-omit">
                    讲师:{{ course.teacher.teacherName }}
                    <span class="line"></span>
                    {{ course.teacher.position }}
                  </div>
                </div>
                <div class="lesson-info">
                  <div class="boook-icon backgroun-img-set"></div>
                  <div class="time">
                    {{ totalLessons }} 讲 /
                    {{ course.totalDuration }} 课时
                  </div>
                  <div class="person-icon backgroun-img-set"></div>
                  <div class="person">{{ course.sales }}人已购买</div>
                </div>
              </div>

              <div class="content-right">
                <div class="button-wrap" @click="watchCourse(1)">
                  免费试看
                  <div class="small-arrows"></div>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="public-class-container is-pc">
          <el-tabs v-model="activeName">
            <el-tab-pane label="课程信息" name="intro">
              <div
                v-html="course.courseDescription"
                class="content-p pc-background"
              ></div>

              <!-- 留言板 开始-->
              <div class="message">
                <div class="message-topic">
                  <div class="message-topic-title normal-font">
                    精选留言
                  </div>
                </div>
                <div>
                  <div class="message-edit">
                    <textarea
                      rows="20"
                      style="border: none; resize: none"
                      contenteditable="true"
                      placeholder="分享学习心得、思考感悟或者给自己一个小鼓励吧!"
                      class="edit-div pcStyle"
                      v-model="comment"
                    ></textarea>
                  </div>
                  <div class="message-edit-footer flex">
                    <button
                      class="message-edit-btn disableBg"
                      @click="saveComment"
                    >
                      发表留言
                    </button>
                  </div>
                </div>

                <!-- 留言 开始 -->
                <div
                  class="message-list"
                  v-for="(comment, index) in commentList"
                  :key="index"
                >
                  <div class="message-list-title">
                    <div class="message-list-title-left">
                      <div class="message-list-title-left-name">
                        {{ comment.userName }}
                      </div>
                      <div class="message-list-title-left-tag"></div>
                    </div>
                    <!-- 已赞 https://img-blog.csdnimg.cn/2022010709524139259.png -->
                    <div
                      @click="cancelzan(comment)"
                      v-if="
                        JSON.stringify(comment.favoriteRecords).indexOf(
                          user.content.id
                        ) >= 0
                      "
                      class="message-list-title-right"
                    >
                      <img
                        class="message-list-title-right-icon"
                        src="https://img-blog.csdnimg.cn/2022010709524139259.png"
                        alt=""
                      />
                      <div class="message-list-title-right-praise">
                        {{ comment.likeCount }}
                      </div>
                    </div>
                    <!-- 没点过赞 -->
                    <div
                      @click="zan(comment)"
                      v-else
                      class="message-list-title-right"
                    >
                      <img
                        class="message-list-title-right-icon"
                        src="https://img-blog.csdnimg.cn/2022010709524176679.png"
                        alt=""
                      />
                      <div class="message-list-title-right-praise">
                        {{ comment.likeCount }}
                      </div>
                    </div>
                  </div>
                  <div class="message-list-content">
                    {{ comment.comment }}
                  </div>
                  <!--删除留言(必须登录才能删除自己的)-->
                  <!--
                  <div class="message-delete pointer">
                    <img class="message-delete-icon" src="https://img-blog.csdnimg.cn/2022010709524145287.png" alt="">删除
                  </div>
                  -->
                </div>
                <!-- 留言 结束 -->
              </div>
              <!-- 留言板 结束-->
            </el-tab-pane>
            <el-tab-pane label="目录" name="directory">
              <div
                class="class-menu-contaniner list-page-container more-sections more-sections-padding"
              >
                <!-- 第一章 开始 -->
                <div v-for="section in course.courseSections.slice(0, 1)">
                  <div class="section-name single-line">
                    {{ section.sectionName }}
                  </div>
                  <div class="class-menu-block">
                    <!-- 每节课 开始 -->
                    <div
                      class="class-level-one over-ellipsis"
                      @click="
                        watchCourse(
                          1,
                          lesson.id,
                          index,
                          lesson.courseMedia
                        )
                      "
                      v-for="(lesson, index) in section.courseLessons"
                      :key="index"
                    >
                      <div class="text-wrap">
                        <div class="content">{{ lesson.theme }}</div>
                        <div
                          class="item-status-wrap item-status-wrap-list"
                        >
                          <!-- 第一章,前两节 -->
                          <div v-if="index < 2">
                            <!-- 未登录 => 试看 -->
                            <div
                              v-if="!isLogin"
                              class="item-status test-watch"
                            >
                              试看
                            </div>
                            <!-- 已登录,未购买 => 试看 -->
                            <div
                              v-else-if="isLogin && !isBuy"
                              class="item-status test-watch"
                            >
                              试看
                            </div>
                            <!-- 已登录,已购买 => 播放 -->
                            <div v-else class="item-status test-watch">
                              播放
                            </div>
                          </div>

                          <!-- 第一章,除了前两节的 -->
                          <div v-if="index > 1">
                            <!-- 未登录 => 锁 -->
                            <div
                              v-if="!isLogin"
                              class="item-status lock"
                            ></div>
                            <!-- 已登录,未购买 => 锁 -->
                            <div
                              v-else-if="isLogin && !isBuy"
                              class="item-status lock"
                            ></div>
                            <!-- 已登录,已购买 => 播放 -->
                            <div v-else class="item-status test-watch">
                              播放
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                    <!-- 每节课 结束 -->
                  </div>
                </div>
                <!-- 第一章 结束 -->

                <!-- 其余章 开始 -->
                <div
                  v-for="section in course.courseSections.slice(
                    1,
                    course.courseSections.length
                  )"
                >
                  <div class="section-name single-line">
                    {{ section.sectionName }}
                  </div>
                  <div class="class-menu-block">
                    <!-- 每节课 开始 -->
                    <div
                      class="class-level-one over-ellipsis"
                      @click="
                        watchCourse(
                          2,
                          lesson.id,
                          index,
                          lesson.courseMedia
                        )
                      "
                      v-for="(lesson, index) in section.courseLessons"
                      :key="index"
                    >
                      <div class="text-wrap">
                        <div class="content">{{ lesson.theme }}</div>
                        <div
                          class="item-status-wrap item-status-wrap-list"
                        >
                          <!-- 未登录 => 锁 -->
                          <div
                            v-if="!isLogin"
                            class="item-status lock"
                          ></div>
                          <!-- 已登录,未购买 => 锁 -->
                          <div
                            v-else-if="isLogin && !isBuy"
                            class="item-status lock"
                          ></div>
                          <!-- 已登录,已购买 => 播放 -->
                          <div v-else class="item-status test-watch">
                            播放
                          </div>
                        </div>
                      </div>
                    </div>
                    <!-- 每节课 结束 -->
                  </div>
                </div>
                <!-- 其余章 结束 -->
              </div>
            </el-tab-pane>
          </el-tabs>

          <div class="tab-fix-wrap"></div>
          <div></div>
        </div>
      </div>
    </div>
  </div>

  <!-- 微信支付二维码-->
  <el-dialog
    :visible.sync="dialogFormVisible"
    style="width: 800px; margin: 0px auto"
  >
    <h1 style="font-size: 30px; color: #00b38a">微信扫一扫支付</h1>
    <div id="qrcode" style="width: 210px; margin: 20px auto"></div>
    <h2 id="statusText"></h2>
    <p id="closeText"></p>
  </el-dialog>

  <!-- 底部购买 -->
  <div
    class="public-class-footer"
    slot="bottom"
    style="border: 1px solid #eee; height: 60px; text-align: left"
  >
    <span class="product-descript" style="font-size: 0.347rem"
      >成就自己</span
    >
    <span class="current-price" style="font-size: 28px">
      <span class="current-price-unite" style="font-size: 0.347rem">
        ¥</span
      >{{ course.discounts }}
    </span>
    <span class="current-price price">
      <span class="current-price-unite">¥</span>
      {{ course.price }}
    </span>
    <button
      @click="buy(7)"
      type="button"
      class="weui-btn purchase-button weui-btn_mini weui-btn_primary"
      style="width: 155px; height: 45px; font-size: 17px"
    >
      立即购买
      <!-- ::after -->
    </button>
  </div>
</div>
<script>
import Header from "./Header/Header"; //顶部登录条
import Footer from "./Footer/index"; //顶部登录条
import QRCode from "qrcodejs2"; // 引入qrcodejs

export default {
  name: "Course",
  components: {
    Header,
    Footer,
    QRCode, // 声明组件
  },
  data() {
    return {
      activeName: "intro",
      course: null,
      totalLessons: 0, // 本门课程的总节数
      commentList: null, // 所有留言
      isLogin: false, // false 未登录
      isBuy: false, // false 未购买
      user: null, // 当前用户
      myCourseList: [], // 当前用户购买过的所有课程
      comment: null, // 待发表的留言内容
      dialogFormVisible: false, //默认false:隐藏,true:显示
      time: null, // 计时对象
      orderNo: "", // 订单编号
    };
  },
  created() {
    this.course = this.$route.params.course; // 从路由中获得参数对象赋值给本组件的参数

    // 检测是否登陆
    this.user = JSON.parse(localStorage.getItem("user"));
    if (this.user != null) {
      this.isLogin = true; // 已登录
      this.getMyCourseList(); // 查询登录用户购买的所有课程
    }

    // 计算多少节课要讲
    let x = 0;
    for (let i = 0; i < this.course.courseSections.length; i++) {
      let section = this.course.courseSections[i]; //每一章
      for (let j = 0; j < section.courseLessons.length; j++) {
        x++;
      }
    }
    this.totalLessons = x;

    // 获得所有留言
    this.getComment();
  },
  methods: {
    //播放视频 ( 章节,小节课编号,每节课的索引,每节课的视频对象)
    watchCourse(status, lessonid, index, media) {
      if (media == null || media == "") {
        this.$message.error("播放失败,暂无视频!");
      } else {
        // 试看的可以跳转播放页面
        if (status == 1 && index < 2) {
          this.$message.success("观看第【" + lessonid + "】节课程视频!");
          this.$router.push({
            name: "videoDetail",
            params: {
              course: this.course,
              lessonid: lessonid,
              isBuy: this.isBuy,
            },
          });
        } else {
          // 锁上的,先验证是否登录
          if (!this.isLogin) {
            this.$message.success("请先登录!");
          } else {
            // 登录后,再验证是否购买过
            if (!this.isBuy) {
              this.$message.warning("请购买并解锁,才能观看本视频!");
            } else {
              this.$message.success("观看第【" + lessonid + "】节课程视频!");
              this.$router.push({
                name: "videoDetail",
                params: {
                  course: this.course,
                  lessonid: lessonid,
                  isBuy: this.isBuy,
                },
              });
            }
          }
        }
      }
    },
    // 购买课程
    buy(courseid) {
      //alert("购买第【" + courseid + "】门课程成功,加油!");
      this.dialogFormVisible = true; //显示提示框

      // 待dom更新之后再用二维码渲染其内容
      this.$nextTick(function () {
        this.createCode(); // 直接调用会报错:TypeError: Cannot read property 'appendChild' of null
      });
    },
    // 生成二维码
    createCode() {
      // 去获取支付连接
      this.axios
        .get("http://localhost:80/order/createCode", {
          params: {
            courseid: this.course.id,
            coursename: this.course.courseName,
            price: 1, //测试支付金额固定为1分钱,真实上线环境再改回此真实价钱:this.course.discounts
          },
        })
        .then((result) => {
          console.log(result);
          // QRCode(存放二维码的dom元素id,二维码的属性参数)
          let qrcode = new QRCode("qrcode", {
            width: 200,
            height: 200,
            text: result.data.code_url, // 将返回的数据嵌入到二维码中
          });

          this.orderNo = result.data.orderId;

          // 保存订单, 状态为:已创建 0
          this.saveOrder();

          // 检查支付状态
          this.axios
            .get("http://localhost:80/order/checkOrderStatus", {
              params: {
                orderId: result.data.orderId, // 传递 订单编号 进行查询
              },
            })
            .then((result) => {
              if (result.data.trade_state == "SUCCESS") {
                document.getElementById("statusText").innerHTML =
                  "<i style='color:#00B38A' class='el-icon-success'></i> 支付成功!";
                // 支付成功
                this.updateOrder(20);
              }
              /*
              else if(result.data.trade_state=="NOTPAY"){
                document.getElementById("statusText").innerHTML = "<i style='color:#00B38A' class='el-icon-success'></i> 未支付!";
                this.updateOrder(10);
              }
              */

              // 3秒后关闭二维码窗口
              let s = 3;
              this.closeQRForm(s);
            })
            .catch((error) => {
              this.$message.error("查询订单失败!");
            });
        })
        .catch((error) => {
          this.$message.error("生成二维码失败!");
        });
    },
    // 倒计时关闭二维码窗口
    closeQRForm(s) {
      let that = this;
      that.time = setInterval(function () {
        document.getElementById("closeText").innerHTML =
          "( " + s-- + " ) 秒后关闭本窗口";
        if (s == 0) {
          clearInterval(that.time); // 停止计时器
          that.dialogFormVisible = false; // 二维码窗口隐藏
          that.isBuy = true; // 修改购买状态(已购买)
        }
      }, 1000);
    },
    // 保存订单
    saveOrder() {
      return this.axios
        .get("http://localhost:80/order/saveOrder", {
          params: {
            orderNo: this.orderNo,
            user_id: this.user.content.id,
            course_id: this.course.id,
            activity_course_id: this.course.id,
            source_type: 1,
          },
        })
        .then((result) => {
          // console.log(result);
          console.log("保存订单");
        })
        .catch((error) => {
          this.$message.error("保存订单失败!");
        });
    },
    // 更新订单的状态
    updateOrder(statusCode) {
      return this.axios
        .get("http://localhost:80/order/updateOrder", {
          params: {
            orderNo: this.orderNo,
            status: statusCode,
          },
        })
        .then((result) => {
          console.log("更新订单【" + this.orderNo + "】状态:" + statusCode);
        })
        .catch((error) => {
          this.$message.error("更新订单失败!");
        });
    },
    // 获取本课程的全部留言
    getComment() {
      return this.axios
        .get(
          "http://localhost:80/course/comment/getCourseCommentList/" +
            this.course.id +
            "/1/20"
        )
        .then((result) => {
          this.commentList = result.data;
          console.log("获取留言:");
          console.log(this.commentList);
        })
        .catch((error) => {
          this.$message.error("获取留言信息失败!");
        });
    },
    // 发表留言
    saveComment() {
      return this.axios
        .get("http://localhost:80/course/comment/saveCourseComment", {
          params: {
            courseid: this.course.id,
            userid: this.user.content.id,
            username: this.user.content.name,
            comment: this.comment,
          },
        })
        .then((result) => {
          // console.log(result);
          // 重新获取本门课的全部留言信息
          this.getComment();
        })
        .catch((error) => {
          this.$message.error("发表留言失败!");
        });
    },
    // 查询当前用户购买过的全部课程
    getMyCourseList() {
      return this.axios
        .get(
          "http://localhost:80/course/getCourseByUserId/" + this.user.content.id
        )
        .then((result) => {
          console.log(result);
          this.myCourseList = result.data;

          // 检测当前的课程是否购买过
          for (let i = 0; i < this.myCourseList.length; i++) {
            if (this.myCourseList[i].id == this.course.id) {
              this.isBuy = true; // 标记购买过本课程
              break;
            }
          }
        })
        .catch((error) => {
          this.$message.error("获取课程信息失败!");
        });
    },
    // 点赞
    zan(comment) {
      return this.axios
        .get(
          "http://localhost:80/course/comment/saveFavorite/" +
            comment.id +
            "/" +
            this.user.content.id
        )
        .then((result) => {
          // console.log(result);
          // 重新获取本门课的全部留言信息
          this.getComment();
        })
        .catch((error) => {
          this.$message.error("点赞失败!");
        });
    },
    // 取消赞
    cancelzan(comment) {
      return this.axios
        .get(
          "http://localhost:80/course/comment/cancelFavorite/" +
            comment.id +
            "/" +
            this.user.content.id
        )
        .then((result) => {
          // console.log(result);
          // 重新获取本门课的全部留言信息
          this.getComment();
        })
        .catch((error) => {
          this.$message.error("取消赞失败!");
        });
    },
  },
};
</script>

播放页

src\components\videoDetail.vue

<div id="videoDetail">
  <div class="detail-container">
    <div class="left-container top-container">
      <nav class="nav">
        <div class="nav-back" @click="goBack">
          <span class="kw-icon-back"> &lt; </span>
          <span style="">&nbsp;返回</span>
        </div>
        <span style="position:absolute;left:80px;">
          {{course.courseName}} > {{lessonName}}</span
        >
      </nav>
      <div class="video-content calc">
        <div class="video-container" >
          <div
            id="player-video-vontainer"
            class="player-container video-container" 
          >
            <div
              style="min-width:750px;min-height:550px; max-height:940px"
              class="video"
              
            >
              <video
                style="width: 100%; height: 100%;max-height:920px"
                id="myvideo"
                src=""
                @canplay="getInit"
                @timeupdate="handlerNowTime"
                
                @click="play"
              />
              <div class="controls">
                <div class="con_left">
                  <!-- 播放 -->
                  <i
                    :class="{
                      'el-icon-video-play': !isplay,
                      'el-icon-video-pause': isplay,
                    }"
                    @click="play"
                    style="font-size:40px"
                  ></i>
                  <span>{{ nowTime }}/{{ totalTime }}</span>
                </div>
                <div class="con_right">
                  <!-- 音量 -->
                  <i
                    class="el-icon-headset"
                    @click="play"
                    style="font-size:40px"
                  ></i>
                  <!-- 全屏 -->
                  <i
                    class="el-icon-monitor"
                    @click="play"
                    style="font-size:40px"
                  ></i>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="right-container bottom-container">
      <div style="height: 100%;">
        <div class="detail-part-content-title">课程目录</div>
        <div class="study-percent-tip">
          <div class="week-progress">
            <img
              class="video-book"
              src="https://img-blog.csdnimg.cn/2022010709524217657.png"
              alt=""
            />
            <span class="progress-label">--</span>
          </div>
        </div>
        <div class="detail-part-content-pc calc detail-part-content">
          <div class="content-fold">
            <div class="content-fold-img"></div>
          </div>
          <div class="content-container">

            <!-- 第一章 开始 -->
            <div v-for="section in course.courseSections.slice(0,1)">
              <div class="content-label">
                <div class="content-label-title single-line">{{section.sectionName}}</div>
                <img
                  class="arrow-icon"
                  src="https://img-blog.csdnimg.cn/2022010709524233510.png"
                  alt=""
                />
              </div>

              <!-- 第一章 开始 -->
              <div class="content-sections">
                <div :class="{ 
                  'content-section': lesson.id != lessonid, 
                  'content-section content-section-choose': lesson.id == lessonid, 
                  }"    
                    v-for="(lesson , index) in section.courseLessons" :key="index"
                    @click="playLesson(1,index,lesson)"
                    >
                  <!-- 第一章,前两节 -->
                  <div v-if="index<2">
                    <div class="section-item clearfix">
                      <span :class="{ 
                        'kw-icon-video section-type-icon': lesson.id != lessonid, 
                        'kw-icon-video section-type-icon lv': lesson.id == lessonid, 
                        }"><i class="el-icon-video-play"></i></span>
                      <span :class="{ 
                        'section-dec': lesson.id != lessonid, 
                        'section-dec lv': lesson.id == lessonid, 
                        }">{{lesson.theme}}</span>
                      <span v-if="lesson.id != lessonid" class="section-status-icon pause-play">试看</span>
                      <span v-else class="section-status-icon pause-play"></span>
                    </div>
                    <div class="section-duration">
                      <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
                      <span v-else>时长:无媒体文件</span>
                    </div>
                  </div>
                  <div v-if="index>1">
                    <div class="section-item clearfix">
                      <span :class="{ 
                        'kw-icon-video section-type-icon': lesson.id != lessonid, 
                        'kw-icon-video section-type-icon lv': lesson.id == lessonid, 
                        }"><i class="el-icon-video-play"></i></span>
                      <span :class="{ 
                        'section-dec': lesson.id != lessonid, 
                        'section-dec lv': lesson.id == lessonid, 
                        }">{{lesson.theme}}</span>
                      <!-- 未登录 => 锁 -->
                      <span  v-if="!isLogin" class="section-status-icon pause-play">未解锁</span>
                      <!-- 已登录,未购买 => 锁 -->
                      <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁</span>
                      <!-- 已登录,已购买 => 播放 -->
                      <span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放</span>
                      <span v-else-if="lesson.id == lessonid" class="section-status-icon pause-play"></span>
                    </div>
                    <div class="section-duration">
                      <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
                      <span v-else>时长:无媒体文件</span>
                    </div>
                  </div>
                </div>
                <!-- 正在播放的视频 
                <div class="content-section content-section-choose"
                  style=" color: #00b38a;" >
                  <div class="section-item clearfix">
                    <span class="kw-icon-video section-type-icon lv"><i class="el-icon-video-play"></i></span>
                    <span class="section-dec lv">2.起步</span>
                    <span class="section-status-icon pause-play"></span>
                  </div>
                  <div class="section-duration">
                    <span>时长:0</span>
                  </div>
                </div>
                -->
              </div>

            </div>
            <!-- 第一章 结束 -->
            <!-- 其余章 开始 -->
            <div v-for="section in course.courseSections.slice(1,course.courseSections.length)">
              <div class="content-label">
                <div class="content-label-title single-line">{{section.sectionName}}</div>
                <img
                  class="arrow-icon"
                  src="https://img-blog.csdnimg.cn/2022010709524233510.png"
                  alt=""
                />
              </div>
              <div class="content-sections">
                <div :class="{ 
                    'content-section': lesson.id != lessonid, 
                    'content-section content-section-choose': lesson.id == lessonid, 
                    }"  
                    v-for="(lesson , index) in section.courseLessons" 
                    :key="index"
                    @click="playLesson(2,index,lesson)"
                  >
                  <div>
                    <div class="section-item clearfix">
                      <span :class="{ 
                        'kw-icon-video section-type-icon': lesson.id != lessonid, 
                        'kw-icon-video section-type-icon lv': lesson.id == lessonid, 
                        }"><i class="el-icon-video-play"></i></span>
                      <span :class="{ 
                        'section-dec': lesson.id != lessonid, 
                        'section-dec lv': lesson.id == lessonid, 
                        }">{{lesson.theme}}</span>
                      <!-- 未登录 => 锁 -->
                      <span  v-if="!isLogin" class="section-status-icon pause-play">未解锁</span>
                      <!-- 已登录,未购买 => 锁 -->
                      <span v-else-if="isLogin && !isBuy" class="section-status-icon pause-play">未解锁</span>
                      <!-- 已登录,已购买 => 播放 -->
                      <span v-else-if="lesson.id != lessonid" class="section-status-icon pause-play">播放</span>
                      <span v-else-if="lesson.id == lessonid" class="section-status-icon pause-play"></span>
                    </div>
                    <div class="section-duration">
                      <span v-if="lesson.courseMedia != null">时长:{{lesson.courseMedia.duration}}</span>
                      <span v-else>时长:无媒体文件</span>
                    </div>
                  </div>
                </div>
              </div>

            </div>
            <!-- 其余章 结束 -->

          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<script>
export default {
  name: "videoDetail",
  components: {},
  data() {
    return {
      myvideo: null, // 播放器对象
      isplay: false, //是否在播放
      nowTime: "00:00", //当前播放时间
      totalTime: "00:00", //总时长
      course:null, // 课程
      lessonid:0, // 当前播放视频的课节id
      lessonName:null, // 当前播放的视频名称
      isLogin:false, // false 未登录
      isBuy:false, // false 未购买
    };
  },
  computed: {},
  created() { 
    // 判断登录(暂无)
    this.user = JSON.parse(localStorage.getItem("user"));
    if(this.user != null){
       this.isLogin = true; // 已登录 
    }

    // 从上一级页面的请求中获得课程对象和小节编号
    this.course = this.$route.params.course;
    this.lessonid = this.$route.params.lessonid;
    this.isBuy = this.$route.params.isBuy;
  },
  mounted() {
    this.myvideo = document.getElementById("myvideo");
    this.myvideo.controls = true; // 显示播放器的控制面板
    this.initplay(); // 初始化播放的视频
  },
  methods: {
    play() {
      this.isplay = !this.isplay;
      if (this.isplay) {
        this.myvideo.play();
      } else {
        this.myvideo.pause();
      }
    },
    // 获取视频的时间是秒为单位,格式化城00:00的格式
    formatTime(time) {
      let mm = Math.floor((time % 3600) / 60);
      let ss = Math.floor(time % 60);
      mm = mm < 10 ? "0" + mm : mm;
      ss = ss < 10 ? "0" + ss : ss;
      return `${mm}:${ss}`;
    },
    //获取初始化信息
    getInit() {
      if (!this.myvideo) {
        //获取失败,显示0
        this.totalTime = this.formatTime(0);
      } else {
        //获取视频总时长
        this.totalTime = this.formatTime(this.myvideo.duration);
      }
    },
    //播放时显示当前播放时间和总时长
    handlerNowTime() {
      if (!this.myvideo) {
        this.nowTime = `${this.formatTime(0)}`;
      }
      this.nowTime = this.formatTime(this.myvideo.currentTime || 0);
    },
    //返回
    goBack() {
      this.$router.push({ name: "Course", params: { course: this.course } });
    },
    //播放课程
    playLesson(status,index,lesson) {

      if(lesson.courseMedia == null){ 
          this.$message.error("播放失败,暂无视频!");
      }else{
        // 试看的可以跳转播放页面
        if(status == 1 && index < 2){
           this.playNow(lesson);
        }else{ // 锁上的,先验证是否登录
          if(!this.isLogin){
              this.$message.success("请先登录!");
          }else{ // 登录后,再验证是否购买过
            if(!this.isBuy){
              this.$message.warning("请购买并解锁,才能观看本视频!");
            }else{
              this.playNow(lesson);
            }
          }
        }
      }
    },
    playNow(lesson){
      this.lessonid = lesson.id; // 当前播放的视频,就是我点击的课
      this.myvideo.src = lesson.courseMedia.fileEdk; // 切换播放器的播放地址
      this.myvideo.play(); // 立刻播放
      this.isplay = true; // 按钮呈现为播放状态
    },
    // 初始化时播放的视频
    initplay(){
      //1.在课程信息中查找即将播放的小节视频的编号
      for( let i = 0 ; i< this.course.courseSections.length;i++ ){
          let section = this.course.courseSections[i];
          for(let j = 0; j<section.courseLessons.length ; j++){
              let lesson = section.courseLessons[j]; // 每节课
              if(lesson.courseMedia!=null){
                if(this.lessonid == lesson.courseMedia.lessonId){
                  console.log("视频地址:" + lesson.courseMedia.fileEdk);
                  this.lessonName = lesson.theme;
                  //2.将小节视频的地址 赋值 给播放器,进行播放
                  this.myvideo.src = lesson.courseMedia.fileEdk;
                  return;
                }
              }
          }
      }
    }
  },
};
</script>

想了解更多,欢迎关注我的微信公众号:Renda_Zhang

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值