shuisheng пре 2 година
родитељ
комит
2a4dee8b5c

+ 6 - 0
src/api/area.ts

@@ -1,5 +1,11 @@
 import request from '@/utils/request';
 
+export function fetchAreaList() {
+  return request.instance({
+    url: '/area/list',
+    method: 'get',
+  });
+}
 export function fetchAreaLiveRoomList(params: {
   orderName: string;
   orderBy: string;

BIN
src/assets/img/pay.png


BIN
src/assets/img/rank.png


BIN
src/assets/img/shop.png


+ 23 - 27
src/layout/pc/head/index.vue

@@ -20,26 +20,18 @@
           首页
         </a>
         <a
+          v-for="(item, index) in areaList"
+          :key="index"
           class="item"
           :class="{
-            active: router.currentRoute.value.name === routerName.shop,
-          }"
-          href="/shop"
-          @click.prevent="router.push({ name: routerName.shop })"
-        >
-          商店
-        </a>
-        <a
-          class="item"
-          :class="{
-            active: router.currentRoute.value.name === routerName.order,
+            active: router.currentRoute.value.name === routerName.ad,
           }"
-          href="/order"
-          @click.prevent="router.push({ name: routerName.order })"
+          href="/ad"
+          @click.prevent="changeArea(item)"
         >
-          订单
+          {{ item.name }}
         </a>
-        <a
+        <!-- <a
           class="item"
           :class="{
             active: router.currentRoute.value.name === routerName.ad,
@@ -48,17 +40,7 @@
           @click.prevent="router.push({ name: routerName.ad })"
         >
           广告
-        </a>
-        <a
-          class="item"
-          :class="{
-            active: router.currentRoute.value.name === routerName.rank,
-          }"
-          href="/rank"
-          @click.prevent="router.push({ name: routerName.rank })"
-        >
-          排行榜
-        </a>
+        </a> -->
       </div>
     </div>
     <div class="right">
@@ -253,12 +235,13 @@ import { openToTarget, windowReload } from 'billd-utils';
 import { onMounted, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
+import { fetchAreaList } from '@/api/area';
 import Dropdown from '@/components/Dropdown/index.vue';
 import VPIconChevronDown from '@/components/icons/VPIconChevronDown.vue';
 import VPIconExternalLink from '@/components/icons/VPIconExternalLink.vue';
 import { APIFOX_URL } from '@/constant';
 import { loginTip, useQQLogin } from '@/hooks/use-login';
-import { liveTypeEnum } from '@/interface';
+import { IArea, liveTypeEnum } from '@/interface';
 import { routerName } from '@/router';
 import { useUserStore } from '@/store/user';
 
@@ -268,6 +251,7 @@ const githubStar = ref('');
 const dropdownDoc = ref(false);
 const dropdownSys = ref(false);
 const dropdownAbout = ref(false);
+const areaList = ref<IArea[]>([]);
 
 const about = ref([
   {
@@ -330,6 +314,17 @@ function handleLogout() {
   }, 500);
 }
 
+async function getAreaList() {
+  const res = await fetchAreaList();
+  if (res.code === 200) {
+    areaList.value = res.data.rows;
+  }
+}
+
+function changeArea(item: IArea) {
+  router.push({ name: routerName.area, params: { id: item.id } });
+}
+
 function handleJump(item) {
   if (item.url) {
     openToTarget(item.url);
@@ -341,6 +336,7 @@ function handleJump(item) {
 onMounted(() => {
   githubStar.value =
     'https://img.shields.io/github/stars/galaxy-s10/billd-live?label=Star&logo=GitHub&labelColor=white&logoColor=black&style=social&cacheSeconds=3600';
+  getAreaList();
 });
 
 function quickStart() {

+ 2 - 0
src/layout/pc/index.vue

@@ -5,12 +5,14 @@
       <component :is="Component"></component>
     </router-view>
     <ModalCpt></ModalCpt>
+    <SidebarCpt></SidebarCpt>
   </div>
 </template>
 
 <script lang="ts" setup>
 import HeadCpt from './head/index.vue';
 import ModalCpt from './modal/index.vue';
+import SidebarCpt from './sidebar/index.vue';
 </script>
 
 <style lang="scss" scoped>

+ 71 - 0
src/layout/pc/sidebar/index.vue

@@ -0,0 +1,71 @@
+<template>
+  <aside class="sidebar-wrap">
+    <div
+      class="item"
+      @click="router.push({ name: routerName.rank })"
+    >
+      <div class="ico rank"></div>
+      <div class="txt">排行榜</div>
+    </div>
+    <div
+      class="item"
+      @click="router.push({ name: routerName.shop })"
+    >
+      <div class="ico shop"></div>
+      <div class="txt">商店</div>
+    </div>
+    <div
+      class="item"
+      @click="router.push({ name: routerName.order })"
+    >
+      <div class="ico pay"></div>
+      <div class="txt">订单</div>
+    </div>
+  </aside>
+</template>
+
+<script lang="ts" setup>
+import router, { routerName } from '@/router';
+</script>
+
+<style lang="scss" scoped>
+.sidebar-wrap {
+  position: fixed;
+  top: 50%;
+  right: 0;
+  padding: 15px 10px;
+  width: 40px;
+  border-radius: 20px 0 0 20px;
+  background-color: white;
+  box-shadow: 0 0 20px 1px rgba($theme-color-gold, 0.15);
+  color: $theme-color-gold;
+  text-align: center;
+  transform: translateY(-50%);
+  .item {
+    &:not(:last-child) {
+      margin-bottom: 10px;
+    }
+    cursor: pointer;
+    .ico {
+      margin: 0 auto;
+      width: 20px;
+      height: 20px;
+      opacity: 0.9;
+
+      @extend %containBg;
+      &.rank {
+        @include setBackground('@/assets/img/rank.png');
+      }
+      &.shop {
+        @include setBackground('@/assets/img/shop.png');
+      }
+      &.pay {
+        @include setBackground('@/assets/img/pay.png');
+      }
+    }
+    .txt {
+      font-size: 13px;
+    }
+  }
+}
+</style>

+ 7 - 1
src/router/index.ts

@@ -17,6 +17,7 @@ export const mobileRouterName = {
 export const routerName = {
   home: 'home',
   about: 'about',
+  area: 'area',
   account: 'account',
   rank: 'rank',
   sponsors: 'sponsors',
@@ -81,6 +82,11 @@ export const defaultRoutes: RouteRecordRaw[] = [
           },
         ],
       },
+      {
+        name: routerName.area,
+        path: '/area/:id',
+        component: () => import('@/views/area/index.vue'),
+      },
       {
         name: routerName.rank,
         path: '/rank',
@@ -145,7 +151,7 @@ export const defaultRoutes: RouteRecordRaw[] = [
       },
       {
         name: mobileRouterName.h5Area,
-        path: 'area/:areaId',
+        path: 'area/:id',
         component: () => import('@/views/h5/area/index.vue'),
       },
       {

+ 146 - 0
src/views/area/index.vue

@@ -0,0 +1,146 @@
+<template>
+  <div class="area-wrap">
+    <div
+      v-loading="loading"
+      class="live-room-list"
+    >
+      <div
+        v-for="(iten, indey) in liveRoomList"
+        :key="indey"
+        class="live-room"
+        @click="goRoom(iten)"
+      >
+        <div
+          class="cover"
+          :style="{
+            backgroundImage: `url('${
+              iten?.cover_img || iten?.users?.[0].avatar
+            }')`,
+          }"
+        >
+          <div class="txt">{{ iten?.users?.[0].username }}</div>
+        </div>
+        <div class="desc">{{ iten?.name }}</div>
+      </div>
+      <div
+        v-if="!liveRoomList.length"
+        class="null"
+      >
+        暂无数据
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, ref, watch } from 'vue';
+import { useRoute } from 'vue-router';
+
+import { fetchLiveRoomList } from '@/api/area';
+import { ILiveRoom, liveTypeEnum } from '@/interface';
+import router, { routerName } from '@/router';
+
+const liveRoomList = ref<ILiveRoom[]>([]);
+
+const route = useRoute();
+
+const loading = ref(false);
+
+watch(
+  () => route.params.id,
+  (newVal) => {
+    if (!newVal) return;
+    getData();
+  }
+);
+
+function goRoom(item: ILiveRoom) {
+  if (!item.live) {
+    window.$message.info('该直播间没在直播~');
+    return;
+  }
+  router.push({
+    name: routerName.pull,
+    params: { roomId: item.id },
+    query: {
+      liveType: liveTypeEnum.srsFlvPull,
+    },
+  });
+}
+
+onMounted(() => {
+  getData();
+});
+
+async function getData() {
+  try {
+    loading.value = true;
+    const res = await fetchLiveRoomList({
+      id: Number(route.params.id),
+    });
+    if (res.code === 200) {
+      liveRoomList.value = res.data.rows;
+    }
+  } catch (error) {
+    console.log(error);
+  } finally {
+    loading.value = false;
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.area-wrap {
+  padding: 20px;
+  .title {
+    margin-bottom: 10px;
+  }
+  .live-room-list {
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    .live-room {
+      display: inline-block;
+      margin-right: 35px;
+      margin-bottom: 10px;
+      width: 300px;
+      cursor: pointer;
+      .cover {
+        position: relative;
+        overflow: hidden;
+        width: 100%;
+        height: 150px;
+        border-radius: 8px;
+        background-position: center center;
+        background-size: cover;
+
+        .txt {
+          position: absolute;
+          bottom: 0;
+          left: 0;
+          box-sizing: border-box;
+          padding: 4px 8px;
+          width: 100%;
+          border-radius: 0 0 4px 4px;
+          background-image: linear-gradient(
+            -180deg,
+            rgba(0, 0, 0, 0),
+            rgba(0, 0, 0, 0.6)
+          );
+          color: white;
+          text-align: initial;
+          font-size: 13px;
+
+          @extend %singleEllipsis;
+        }
+      }
+      .desc {
+        margin-top: 4px;
+        font-size: 14px;
+
+        @extend %singleEllipsis;
+      }
+    }
+  }
+}
+</style>

+ 1 - 1
src/views/h5/area/index.vue

@@ -61,7 +61,7 @@ onMounted(() => {
 
 async function getData() {
   const res = await fetchLiveRoomList({
-    id: Number(route.params.areaId),
+    id: Number(route.params.id),
   });
   if (res.code === 200) {
     liveRoomList.value = res.data.rows;

+ 1 - 1
src/views/h5/index.vue

@@ -101,7 +101,7 @@ async function getLiveRoomList() {
 function showAll(item: IArea) {
   router.push({
     name: mobileRouterName.h5Area,
-    params: { areaId: item.id },
+    params: { id: item.id },
     query: { name: item.name },
   });
 }