基于斗鱼的娱乐直播视频平台--Vue移动端页面

介绍

本次项目是移动应用网页课程的大作业,项目使用github上一开源项目学习开发而来。
https://github.com/axhello/douyu-vue
本项目基本就是斗鱼手机移动端的复刻,除了没有评论功能,以外功能都差不多,其后端也是对接的官方的api接口。
源码压缩包地址
https://download.csdn.net/download/david2000999/85656221

学习建议

  1. 本项目可以帮助初学者更好理解完整的前后端开发模式,如何进行前后端数对接,其中格外注意数据传输和展示的格式
  2. 对于想要业务功能的同学,可以直接搭建一个后端自己的数据库,承接自己新业务上的数据,比如开发自己的评论区,和一些数据统计页面,添加数据分析功能等等。

使用

  1. 首先建立空文件打开控制台克隆代码到本地
git clone https://github.com/axhello/douyu-vue.git
  1. 然后进行相关依赖安装(前提本地安装好了npm 和 node)
npm install

npm run serve
  1. 运行后就可以得到
    在这里插入图片描述
    浏览器直接访问即可
    其中第二个局域网地址,可以让电脑连接手机热点后再启动项目,就可以使用第二个的局域网地址再手机上浏览器上进行直接访问了,可以更好体验移动端的适配性。

业务分区

(1)首页:最新活动也展示和热度最高的直播间
(2)分区页:星势力,网游竞技,单机热游,手游休闲,娱乐天地,科技文化,语音互动,语音直播,正能量,赛车竞技,京斗云
(3)分类页:各个具体分区页中的再分类页
(4)推荐区:直播区和视频区下方还有类似内容推荐内容
(5)搜索区:搜索栏中进行定向内容的搜索

功能设计

(1)直播内容展示
(2)搜索相关内容
(3)直播内容分类
(4)推荐相关直播内容
(5)热点内容滚动展示
(6)获取斗鱼安装下载

软件架构

在这里插入图片描述

运行截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

核心代码

category.vue

<template>
  <div class="n-list clearfix">
    <a
      v-for="(catelist, index) in catelists"
      :key="index"
      class="n-list-item"
      @click="rooms(catelist)">
      <img class="live-feature" :src="catelist.icon">
      <p class="title">
        {
    
    {
    
     catelist.cate2Name }}
      </p>
    </a>
  </div>
</template>

<script>
import {
    
     category } from '@/api/mobile'
export default {
    
    
  name: 'Category',
  data() {
    
    
    return {
    
    
      catelists: []
    }
  },
  watch: {
    
    
    '$route.params.id'() {
    
    
      this.fetchData()
    }
  },
  created() {
    
    
    this.fetchData()
  },
  methods: {
    
    
    fetchData() {
    
    
      category({
    
     type: '' }).then(response => {
    
    
        console.log(response.data)
        const cate1Id = this.$route.params.id
        const cate2Info = response.data.cate2Info
        const result = cate2Info.filter(cate2 => cate2.cate1Id === cate1Id)
        this.catelists = result
      })
    },
    rooms(catelist) {
    
    
      this.$cookie.set('gameName', catelist.cate2Name)
      this.$router.push({
    
    
        name: 'rooms',
        params: {
    
     name: catelist.shortName }
      })
    }
  }
}
</script>

<style lang="scss">
.n-list {
    
    
  width: 100%;
  height: 100%;
  overflow-y: auto;
  background-color: #f4f4f4;
  z-index: 4;
  .n-list-item {
    
    
    margin: 0;
    padding: 0;
    float: left;
    width: 3.3rem;
    height: 3.3rem;
    border-right: 1px dashed #ddd;
    border-bottom: 1px dashed #ddd;
    text-align: center;
    font-size: 0.32rem;
    color: #000;
    margin-left: 1px;
    &:nth-child(3n) {
    
    
      border-right: none;
    }
    img {
    
    
      margin-top: 0.66666666rem;
      margin-bottom: 0.133333333rem;
      width: 1.62666666rem;
      height: 1.62666666rem;
      border-radius: 0.8133333rem;
    }
  }
}
</style>

detail.vue

<template>
  <iframe
    class="dy-inframe"
    frameborder="0"
    :src="roomId"></iframe>
</template>
<script>
export default {
    
    
  name: 'RoomDetail',
  computed: {
    
    
    roomId() {
    
    
      return '//m.douyu.com/' + this.$route.params.id
    }
  }
}
</script>
<style lang="scss">
.dy-inframe {
    
    
  width: 100%;
  height: 1050px;
  overflow-x: hidden;
  overflow-y: auto;
}
</style>

home.vue

<template>
  <section class="content">
    <div class="m-row">
      <v-swiper />
      <div class="live-list">
        <router-link
          v-for="(livelist, index) in livelists"
          :key="index"
          :to="{name: 'detail', params: { id: livelist.rid }}"
          class="live">
          <img
            class="live-feature"
            :src="livelist.roomSrc">
          <div class="live-title">
            {
    
    {
    
     livelist.roomName }}
          </div>
          <div class="live-info">
            <span class="dy-name">
              {
    
    {
    
     livelist.nickname }}
            </span>
            <span class="popularity">
              {
    
    {
    
     livelist.hn }}
            </span>
          </div>
        </router-link>
      </div>
    </div>
  </section>
</template>

<script>
import VSwiper from '@/components/v-swiper'
import {
    
     home } from '@/api/mobile'
export default {
    
    
  components: {
    
    
    VSwiper
  },
  data() {
    
    
    return {
    
    
      livelists: []
    }
  },
  created() {
    
    
    this.fetchData()
  },
  methods: {
    
    
    fetchData() {
    
    
      home().then(response => {
    
    
        console.log(response.data[0].list)
        this.livelists = response.data[0].list
        // this.livelists = response.data.data
      })
    }
  }
}
</script>

<style lang="scss">
.m-row {
    
    
  background: #fff;
}
.live-list {
    
    
  position: relative;
  box-sizing: border-box;
  padding: 0 0.13333333rem 0.13333333rem;
  width: 100%;
  &:after {
    
    
    display: block;
    content: '';
    clear: both;
  }
  .live {
    
    
    float: left;
    position: relative;
    display: block;
    margin: 0.13333333rem;
    width: 4.6rem;
    height: 3.28rem;
    color: #333;
    font-size: 12px;
    .live-feature {
    
    
      position: absolute;
      display: block;
      top: 0;
      left: 0;
      width: 100%;
      height: 2.61333333rem;
      background-color: #000;
      border-radius: 0.1rem;
    }
    .live-title {
    
    
      position: absolute;
      bottom: 0;
      left: 0.2rem;
      width: 4rem;
      color: #000;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      line-height: 0.66666667rem;
    }
    .live-info {
    
    
      position: absolute;
      bottom: 0.66666667rem;
      left: 0;
      width: 100%;
      color: #fff;
      /*padding: .1rem 0;*/
      border-bottom-left-radius: 0.2rem;
      border-bottom-right-radius: 0.2rem;
      background: linear-gradient(
        rgba(0, 0, 0, 0) 0%,
        rgba(0, 0, 0, 0.1) 30%,
        rgba(0, 0, 0, 0.8) 100%
      );
      .dy-name {
    
    
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        max-width: 2.746666666rem;
        display: inline-block;
        padding-left: 0.1rem;
      }
      .popularity {
    
    
        float: right;
        padding-right: 0.2rem;
      }
    }
  }
}
</style>

rooms.vue

<template>
  <div class="m-row">
    <div class="title">
      <svg-icon icon-class="tv" />
      <span>{
    
    {
    
     cateName }}</span>
      <strong>{
    
    {
    
     gameName }}</strong>
    </div>
    <div class="live-list clearfix">
      <router-link
        v-for="(roomlist, index) in roomlists"
        :key="index"
        :to="{name: 'detail', params: {id: roomlist.rid}}"
        class="live">
        <img class="live-feature" :src="roomlist.roomSrc">
        <div class="live-title">
          {
    
    {
    
     roomlist.roomName }}
        </div>
        <div class="live-info">
          <span class="dy-name">
            {
    
    {
    
     roomlist.nickname }}
          </span>
          <span class="popularity">
            {
    
    {
    
     roomlist.hn }}
          </span>
        </div>
      </router-link>
    </div>
    <v-more-button>
      <div v-if="!hidden" class="more-button">
        <div v-show="!loading" @click="loadMore">
          加载更多
        </div>
        <div v-show="loading" class="ball-pulse">
          <div></div>
          <div></div>
          <div></div>
        </div>
      </div>
    </v-more-button>
  </div>
</template>
<script>
import VMoreButton from '@/components/v-more-button'
import {
    
     rooms } from '@/api/mobile'
export default {
    
    
  name: 'Rooms',
  components: {
    
    
    VMoreButton
  },
  props: {
    
    
    name: {
    
    
      type: String,
      default: ''
    }
  },
  data: () => ({
    
    
    roomlists: [],
    params: {
    
    
      name: '',
      page: 1
    },
    hidden: false,
    loading: false,
    cateName: '',
    gameName: ''
  }),
  created() {
    
    
    this.fetchData()
  },
  mounted() {
    
    
    this.cateName = this.$cookie.get('cateName')
    this.gameName = this.$cookie.get('gameName')
  },
  methods: {
    
    
    fetchData() {
    
    
      rooms({
    
     page: this.params.page, type: this.name }).then(response => {
    
    
        this.loading = false
        this.roomlists = response.data.list
      })
    },
    loadMore() {
    
    
      this.loading = true
      this.params.page = ++this.params.page
      this.fetchData()
    }
  }
}
</script>
<style lang="scss" scoped>
.m-row {
    
    
  .play-icon {
    
    
    width: 0.3999999rem;
    height: 0.3999999rem;
    vertical-align: sub;
  }
  .title {
    
    
    font-size: 12px;
    margin-left: 10px;
    line-height: 0.8333333rem;
    strong {
    
    
      margin-left: 4px;
      color: #fa7122;
    }
  }
}
.live-list {
    
    
  .live {
    
    
    float: left;
    position: relative;
    display: block;
    margin: 0.13333333rem;
    width: 4.6rem;
    height: 3.28rem;
    color: #333;
    font-size: 12px;
    .live-feature {
    
    
      position: absolute;
      display: block;
      top: 0;
      left: 0;
      width: 100%;
      height: 2.61333333rem;
      background-color: #000;
      border-radius: 0.2rem;
    }
    .live-title {
    
    
      position: absolute;
      bottom: 0;
      left: 0.2rem;
      width: 4rem;
      color: #000;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      line-height: 0.66666667rem;
    }
    .live-info {
    
    
      position: absolute;
      bottom: 0.66666667rem;
      left: 0;
      width: 100%;
      color: #fff;
      /*padding: .1rem 0;*/
      border-bottom-left-radius: 0.2rem;
      border-bottom-right-radius: 0.2rem;
      background: linear-gradient(rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.1) 30%, rgba(0, 0, 0, 0.8) 100%);
      .dy-name {
    
    
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        max-width: 2.746666666rem;
        display: inline-block;
        padding-left: 0.2rem;
      }
      .popularity {
    
    
        float: right;
        padding-right: 0.2rem;
      }
    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/david2000999/article/details/125225946