DESKTOP-7E9LH09\admin 5 дней назад
Родитель
Сommit
00ee6ccaa8

+ 1 - 0
components.d.ts

@@ -57,6 +57,7 @@ declare module 'vue' {
     ElTag: typeof import('element-plus/es')['ElTag']
     ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
+    HomeSidebar: typeof import('./src/components/Layout/components/HomeSidebar.vue')['default']
     HotList: typeof import('./src/components/Layout/components/leftDraw/components/hotList.vue')['default']
     Layout: typeof import('./src/components/Layout/index.vue')['default']
     LeagueList: typeof import('./src/components/Layout/components/leftDraw/components/leagueList.vue')['default']

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/assets/index-BoEA_nBp.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
dist/assets/index-DVrKOkmg.css


+ 2 - 2
dist/config.js

@@ -5,7 +5,7 @@ window.global = {
   wsURL: "wss://sportapi.sp2509.cc:9501",
   botURL: "https://bot-api.f1bet888.com/api/",
   // botURL: "https://bot28api.sp2509.cc/api/",
-  // serviceURL: 'https://service.8xbet001.com',
-  serviceURL: "https://bot28webkefu.sp2509.cc",
+  serviceURL: 'https://service.askgoing.com',
+  // serviceURL: "https://bot28webkefu.sp2509.cc",
   openAPPURL: "https://m.F1bet888.com",
 };

+ 3 - 3
dist/index.html

@@ -12,10 +12,10 @@
       </script>
     <script src="https://cdn.jsdelivr.net/npm/pako@2.1.0/dist/pako.min.js"></script>
     <title>Vite App</title>
-    <script type="module" crossorigin src="/assets/index-sHosDoqZ.js"></script>
+    <script type="module" crossorigin src="/assets/index-CNaoJewN.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/vue-vendor-ByaAFEoM.js">
-    <link rel="modulepreload" crossorigin href="/assets/element-plus-CX7swo72.js">
-    <link rel="stylesheet" crossorigin href="/assets/index-jrrBtnUf.css">
+    <link rel="modulepreload" crossorigin href="/assets/element-plus-B30z60mc.js">
+    <link rel="stylesheet" crossorigin href="/assets/index-CYbZ5Ul4.css">
   </head>
   <body>
     <div id="app"></div>


+ 431 - 0
src/components/Layout/components/HomeSidebar.vue

@@ -0,0 +1,431 @@
+<template>
+  <aside class="home-sidebar" :class="{ 'is-collapsed': !sidebarStore.isOpen }">
+    <div class="sidebar-menu">
+      <div v-for="item in primaryItems" :key="item.key" class="sidebar-group">
+        <button class="sidebar-item" :class="{ active: isActive(item) }" type="button"
+          :title="sidebarStore.isOpen ? '' : getItemLabel(item)" @click="handleItemClick(item)">
+          <el-icon class="sidebar-icon">
+            <component :is="item.icon" />
+          </el-icon>
+          <span v-if="sidebarStore.isOpen" class="sidebar-label">{{ getItemLabel(item) }}</span>
+          <el-icon v-if="sidebarStore.isOpen && item.children?.length" class="sidebar-arrow"
+            :class="{ rotated: isExpanded(item.key) }" @click.stop="toggleSection(item.key)">
+            <ArrowDown />
+          </el-icon>
+        </button>
+
+        <div v-if="sidebarStore.isOpen && item.children?.length && isExpanded(item.key)" class="sidebar-submenu">
+          <button v-for="child in item.children" :key="child.key" class="sidebar-subitem"
+            :class="{ active: isActive(child) }" type="button" :title="getItemLabel(child)"
+            @click="handleItemClick(child)">
+            <span class="sidebar-sub-label">{{ getItemLabel(child) }}</span>
+          </button>
+        </div>
+      </div>
+
+
+    </div>
+
+
+    <button class="sidebar-toggle" type="button" :aria-label="sidebarStore.isOpen ? t('收起') : t('展开')"
+      @click="sidebarStore.setSheetOpen(!sidebarStore.isOpen)">
+      <el-icon>
+        <component :is="sidebarStore.isOpen ? ArrowLeft : ArrowRight" />
+      </el-icon>
+    </button>
+  </aside>
+</template>
+
+<script setup>
+import { computed, onMounted, ref, watch } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
+import { useI18n } from 'vue-i18n';
+import {
+  ArrowDown,
+  ArrowLeft,
+  ArrowRight,
+  Collection,
+  Discount,
+  Document,
+  Football,
+  House,
+  Monitor,
+  Money,
+  Ship,
+  Ticket,
+  Trophy,
+  User,
+  Wallet,
+} from '@element-plus/icons-vue';
+import { useHomeLeftDrawStore } from '@/store/homeLeftDraw';
+import { useGameIframeStore } from '@/store/gameIframe';
+import { useUserStore } from '@/store/user/index.js';
+import { getBalance, getDeomUrl, getGameUrl, getPlatforms } from '@/request/api.js';
+
+const route = useRoute();
+const router = useRouter();
+const sidebarStore = useHomeLeftDrawStore();
+const gameIframeStore = useGameIframeStore();
+const userStore = useUserStore();
+const { t } = useI18n();
+
+const platformGroups = ref([]);
+
+const primaryItems = computed(() => {
+  const sports = getPlatformsByType(4);
+  const live = getPlatformsByType(1);
+  const casino = getPlatformsByType(7);
+
+  return [
+    { key: 'home', labelKey: '首页', icon: House, route: 'Home' },
+    {
+      key: 'sports',
+      labelKey: '体育',
+      icon: Football,
+      route: 'SportsBetting',
+      children: [
+        { key: 'f1-sports', label: 'f1bet体育', route: 'SportsBetting', query: { category: 'f1' } },
+        ...sports.map(platform => createPlatformItem(platform, 4)),
+      ],
+    },
+    {
+      key: 'live',
+      labelKey: '真人',
+      icon: User,
+      route: 'videoGames',
+      query: { type: 1 },
+      children: live.map(platform => createPlatformItem(platform, 1)),
+    },
+    { key: 'fishing', labelKey: '捕鱼', icon: Ship, route: 'videoGames', query: { type: 6 } },
+    {
+      key: 'casino',
+      labelKey: '棋牌',
+      icon: Trophy,
+      children: casino.map(platform => createPlatformItem(platform, 7)),
+    },
+    { key: 'lottery', labelKey: '彩票', icon: Ticket, route: 'EntertainmentList' },
+    { key: 'games', labelKey: '电子', icon: Monitor, route: 'videoGames', query: { type: 2 } },
+    { key: 'promotion', labelKey: '优惠活动', icon: Discount, route: 'Promotion' },
+    { key: 'profile', labelKey: '我的', icon: User, route: 'My' },
+    { key: 'history', labelKey: '记录', icon: Document, route: 'rechargeRecord' },
+  ];
+});
+
+
+
+const expandedMenus = ref(['sports']);
+const sportsRouteNames = ['SportsBetting', 'SportDetail', 'WorldCup', 'TotalSoccerAdvance'];
+const lotteryRouteNames = [
+  'EntertainmentList',
+  'Entertainment',
+  'ExtremeSpeed28',
+  'Digital',
+  'NewDigital',
+  'SpeedDigital',
+  'HKDigital',
+  'JisuGame',
+  'EntertainmentHistory',
+  'DigitalOrderList',
+  'DigitalOrderDetail',
+  'EntertainmentDetail',
+  'LotteryOrderDetail',
+];
+
+onMounted(async () => {
+  try {
+    const res = await getPlatforms({ device: 'pc' });
+    platformGroups.value = res?.data?.list || [];
+
+    ['sports'].forEach(key => {
+      if (primaryItems.value.find(item => item.key === key)?.children?.length) {
+        expandedMenus.value = Array.from(new Set([...expandedMenus.value, key]));
+      }
+    });
+  } catch (error) {
+    console.error('获取侧边栏游戏平台失败:', error);
+  }
+});
+
+watch(
+  () => route.name,
+  (name) => {
+    if (sportsRouteNames.includes(name)) {
+      expandedMenus.value = Array.from(new Set([...expandedMenus.value, 'sports']));
+    }
+  },
+  { immediate: true },
+);
+
+function isExpanded(key) {
+  return expandedMenus.value.includes(key);
+}
+
+function toggleSection(key) {
+  expandedMenus.value = isExpanded(key)
+    ? expandedMenus.value.filter((item) => item !== key)
+    : [...expandedMenus.value, key];
+}
+
+function getPlatformsByType(gameType) {
+  return platformGroups.value.find(item => Number(item.gameType) === gameType)?.platforms || [];
+}
+
+function createPlatformItem(platform, gameType) {
+  return {
+    key: `${gameType}-${platform.platType}`,
+    label: platform.name,
+    external: true,
+    platform,
+    gameType,
+  };
+}
+
+function getItemLabel(item) {
+  return item.label || t(item.labelKey);
+}
+
+function refreshBalance() {
+  return getBalance()
+    .then(res => {
+      if (res?.data?.money !== undefined) {
+        userStore.balance = res.data.money;
+      }
+    })
+    .catch(error => {
+      console.error('获取游戏平台余额失败:', error);
+    });
+}
+
+function isActive(item) {
+  if (item.key === 'lottery') return lotteryRouteNames.includes(route.name);
+  if (item.key === 'sports') {
+    return sportsRouteNames.includes(route.name)
+      || route.query.category === 'f1'
+      || (route.name === 'videoGames' && String(route.query.type) === '4');
+  }
+  if (item.key === 'casino') {
+    return route.name === 'videoGames' && String(route.query.type) === '7';
+  }
+  if (item.external) {
+    return gameIframeStore.platformKey === item.key;
+  }
+  if (item.query?.category) return route.name === item.route && route.query.category === item.query.category;
+  if (item.route === 'videoGames' && item.query?.type !== undefined) {
+    return route.name === item.route && String(route.query.type) === String(item.query.type);
+  }
+  if (item.route === 'Home') return route.name === 'Home';
+  return route.name === item.route || route.path.toLowerCase().includes(String(item.route).toLowerCase());
+}
+
+function handleItemClick(item) {
+  if (item.key === 'sports') {
+    return toggleSection(item.key);
+  }
+  if (item.key === 'live') {
+    return toggleSection(item.key);
+  }
+  if (item.key === 'casino') {
+    return toggleSection(item.key);
+  }
+
+  if (item.external) {
+    const params = {
+      platType: item.platform.platType,
+      gameType: item.gameType,
+      device: 'pc',
+    };
+    const request = localStorage.getItem('youke_token')
+      ? getDeomUrl(params)
+      : getGameUrl(params);
+
+    request.then(res => {
+      const url = res?.data?.url || res?.data?.data?.url || res?.url;
+      if (!url) return;
+
+      refreshBalance();
+      gameIframeStore.open(url, getItemLabel(item), item.key, item.gameType);
+      router.push({ name: 'videoGames', query: { type: item.gameType } });
+    }).catch(error => {
+      console.error('打开游戏平台失败:', error);
+    });
+    return;
+  }
+  if (item.route === 'recharge') return router.push({ name: 'rechargeRecord' });
+  if (item.route === 'withdraw') return router.push({ name: 'withdrawalHistory' });
+  if (item.route === 'language') return;
+  if (item.route) router.push(item.query ? { name: item.route, query: item.query } : { name: item.route });
+}
+</script>
+
+<style scoped lang="scss">
+.home-sidebar {
+  z-index: 12;
+  display: flex;
+  flex: 0 0 258px;
+  width: 258px;
+  flex-direction: column;
+  height: 100%;
+  padding: 16px;
+  box-sizing: border-box;
+  background: #1e1e1e;
+  border: 1px solid rgba(255, 255, 255, 0.08);
+  transition: flex-basis 0.25s ease, width 0.25s ease;
+  box-shadow: 2px 0 12px rgba(0, 0, 0, 0.35);
+  border-radius: 16px;
+  position: relative;
+}
+
+.home-sidebar.is-collapsed {
+  flex-basis: 72px;
+  width: 72px;
+  align-items: center;
+  padding-inline: 8px;
+}
+
+.sidebar-menu,
+.sidebar-footer {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+
+.sidebar-menu {
+  flex: 1;
+  overflow-y: auto;
+}
+
+.sidebar-footer {
+  padding-top: 10px;
+  border-top: 1px solid rgba(255, 255, 255, 0.08);
+}
+
+.home-sidebar.is-collapsed .sidebar-menu,
+.home-sidebar.is-collapsed .sidebar-footer {
+  width: 100%;
+  align-items: center;
+}
+
+.home-sidebar.is-collapsed .sidebar-item {
+  justify-content: center;
+  width: 54px;
+}
+
+.sidebar-group {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+
+.sidebar-item,
+.sidebar-subitem {
+  display: flex;
+  align-items: center;
+  width: 200px;
+  min-height: 46px;
+  padding: 0 16px;
+  box-sizing: border-box;
+  border: 0;
+  border-radius: 10px;
+  background: transparent;
+  color: #e5e5e5;
+  cursor: pointer;
+  font-size: 14px;
+  text-align: left;
+  transition: background 0.2s ease, color 0.2s ease;
+}
+
+.sidebar-item:hover,
+.sidebar-subitem:hover {
+  background: #2a2a2a;
+  color: #f8b932;
+}
+
+.sidebar-item.active,
+.sidebar-subitem.active {
+  background: rgba(248, 185, 50, 0.14);
+  color: #f8b932;
+}
+
+.sidebar-icon {
+  flex: 0 0 22px;
+  justify-content: center;
+  font-size: 20px;
+}
+
+.sidebar-label {
+  margin-left: 12px;
+  white-space: nowrap;
+}
+
+.sidebar-arrow {
+  margin-left: auto;
+  font-size: 14px;
+  transition: transform 0.2s ease;
+}
+
+.sidebar-arrow.rotated {
+  transform: rotate(-180deg);
+}
+
+.sidebar-divider {
+  height: 1px;
+  margin: 8px;
+  background: rgba(255, 255, 255, 0.08);
+}
+
+.sidebar-submenu {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+  padding: 2px 0 4px 14px;
+  margin-left: 10px;
+  border-left: 1px solid rgba(255, 255, 255, 0.08);
+}
+
+.sidebar-subitem {
+  width: 182px;
+  min-height: 40px;
+  padding-left: 18px;
+  font-size: 13px;
+}
+
+.sidebar-sub-label {
+  white-space: nowrap;
+}
+
+.sidebar-toggle {
+  position: absolute;
+  top: 50%;
+  right: -12px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  width: 24px;
+  height: 48px;
+  padding: 0;
+  border: 1px solid rgba(255, 255, 255, 0.12);
+  border-radius: 0 8px 8px 0;
+  background: #1e1e1e;
+  color: #999;
+  cursor: pointer;
+  transform: translateY(-50%);
+  box-shadow: 2px 2px 8px rgba(0, 0, 0, 0.35);
+}
+
+.sidebar-toggle:hover {
+  color: #f8b932;
+}
+
+@media screen and (max-width: 800px) {
+  .home-sidebar {
+    flex-basis: 72px;
+    width: 72px;
+  }
+
+  .home-sidebar:not(.is-collapsed) {
+    position: relative;
+    width: 258px;
+    flex-basis: 258px;
+  }
+}
+</style>

Разница между файлами не показана из-за своего большого размера
+ 368 - 194
src/components/Layout/index.vue


+ 8 - 1
src/lang/en.js

@@ -26,6 +26,12 @@ export default {
 	"投注历史": "Betting History",
 	"我的": "My",
 	"首页": "Home",
+	"娱乐": "Entertainment",
+	"真人": "Live Casino",
+	"电竞": "Esports",
+	"棋牌": "Board Games",
+	"电子": "Games",
+	"简体中文": "Simplified Chinese",
 	"安全": "Security",
 	"注册并登录": "Register and login",
 	"请输入有效的充值数量": "Please enter a valid deposit amount",
@@ -254,6 +260,7 @@ export default {
 	"已取消": "Cancelled",
 	"彩票": "Lottery",
 	"体育": "Sports",
+	"f1bet体育": "F1 Sports Betting",
 	"是否中奖": "Win status",
 	"结算状态": "Settlement status",
 	"返回": "Back",
@@ -660,4 +667,4 @@ export default {
 	"退款被驳回": "Refund rejected",
 	"统计项": "Statistics item",
 	"在线客服": "Online customer service",
-}
+}

+ 7 - 0
src/lang/vi.js

@@ -27,6 +27,12 @@ export default {
   投注历史: "Lịch sử đặt cược",
   我的: "Của tôi",
   首页: "Trang chủ",
+  "娱乐": "Gi岷i tr铆",
+  "真人": "Casino tr峄峜 tuy岷璸",
+  "电竞": "Th峄?thao 膽i峄噉 t峄?",
+  "棋牌": "Tr貌 ch啤i b岷",
+  "电子": "Tr貌 ch啤i 膽i峄噉 t峄?",
+  "简体中文": "Ti岷g Trung gi岷n th峄?",
   安全: "An toàn",
   注册并登录: "Đăng ký và đăng nhập",
   请输入有效的充值数量: "Vui lòng nhập số tiền nạp hợp lệ",
@@ -257,6 +263,7 @@ export default {
   已取消: "Đã hủy",
   彩票: "Giải trí",
   体育: "Thể thao",
+  f1bet体育: "Cá cược thể thao F1",
   是否中奖: "Có trúng thưởng không",
   结算状态: "Trạng thái thanh toán",
   返回: "Quay lại",

+ 7 - 0
src/lang/zh.js

@@ -26,6 +26,12 @@ export default {
 	"投注历史": "投注历史",
 	"我的": "我的",
 	"首页": "首页",
+	"娱乐": "娱乐",
+	"真人": "真人",
+	"电竞": "电竞",
+	"棋牌": "棋牌",
+	"电子": "电子",
+	"简体中文": "简体中文",
 	"安全": "安全",
 	"注册并登录": "注册并登录",
 	"请输入有效的充值数量": "请输入有效的充值数量",
@@ -254,6 +260,7 @@ export default {
 	"已取消": "已取消",
 	"彩票": "彩票",
 	"体育": "体育",
+	"f1bet体育": "f1bet体育",
 	"是否中奖": "是否中奖",
 	"结算状态": "结算状态",
 	"返回": "返回",

+ 32 - 0
src/store/gameIframe.js

@@ -0,0 +1,32 @@
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
+
+export const useGameIframeStore = defineStore('gameIframe', () => {
+  const url = ref('');
+  const platformName = ref('');
+  const platformKey = ref('');
+  const gameType = ref('');
+
+  const open = (value, name = '', key = '', type = '') => {
+    url.value = value || '';
+    platformName.value = name || '';
+    platformKey.value = key || '';
+    gameType.value = type === undefined || type === null ? '' : String(type);
+  };
+
+  const clear = () => {
+    url.value = '';
+    platformName.value = '';
+    platformKey.value = '';
+    gameType.value = '';
+  };
+
+  return {
+    url,
+    platformName,
+    platformKey,
+    gameType,
+    open,
+    clear,
+  };
+});

+ 20 - 9
src/views/Home/index.vue

@@ -38,7 +38,7 @@
           <span class="url-text animated-text">{{ animatedUrl }}</span>
         </div>
       </div>
-
+      <!-- 
       <div class="game-category-container">
         <div class="category-scroll pc-scroll-view">
           <div class="category-flex">
@@ -49,7 +49,7 @@
             </div>
           </div>
         </div>
-      </div>
+      </div> -->
 
       <div class="roll-ball-section">
         <div class="roll-ball-header">
@@ -527,7 +527,7 @@ const handleOtherGameClick = (path) => {
 };
 
 const categoryList = ref([
-  { name: '彩票', icon: iconCp1, path: '/EntertainmentList' },
+  { name: '彩票', icon: iconCp1, route: { name: 'EntertainmentList' } },
   { name: '电子', icon: iconDz, path: '' },
   { name: '视讯', icon: iconSx, path: '' },
   { name: '体育', icon: iconTy, path: '/SportsBetting' },
@@ -537,8 +537,8 @@ const categoryList = ref([
 ]);
 
 const handleCategoryClick = (item) => {
-  if (item.path) {
-    router.push({ path: item.path });
+  if (item.route) {
+    router.push(item.route);
   }
 };
 
@@ -640,7 +640,7 @@ const getDiceDots = (num) => {
 };
 
 const toLottery = () => {
-  router.push({ path: '/EntertainmentList' });
+  router.push({ name: 'EntertainmentList' });
 };
 
 const goToLotteryDetail = (item) => {
@@ -933,16 +933,27 @@ onQuery();
 
 <style scoped lang="scss">
 .page-scroll-container {
-  width: 1200px;
+  // width: 1200px;
   height: 100%;
   overflow-y: auto;
-  margin: 0 auto;
+  margin: 0 20px;
+  scrollbar-width: none;
+  -ms-overflow-style: none;
+
+  &::-webkit-scrollbar {
+    display: none;
+  }
 }
 
 .pc-scroll-view {
   width: 100%;
   white-space: nowrap;
   overflow-x: auto;
+  padding: 10px;
+  box-sizing: border-box;
+  border-radius: 12px;
+  background: #1e1e1e;
+  border: 1px solid rgba(255, 255, 255, 0.08);
 }
 
 .pc-scroll-view::-webkit-scrollbar {
@@ -1770,4 +1781,4 @@ onQuery();
   height: 140px;
   cursor: pointer;
 }
-</style>
+</style>

+ 94 - 58
src/views/LotteryDraw/index.vue

@@ -4,17 +4,14 @@
       <div class="page-header">
         <h2 class="title">{{ t('开奖历史') }}</h2>
         <el-button type="primary" circle @click="onQuery" :loading="loading">
-          <el-icon><Refresh /></el-icon>
+          <el-icon>
+            <Refresh />
+          </el-icon>
         </el-button>
       </div>
 
       <div class="lottery-grid">
-        <div
-            class="lottery-item"
-            v-for="(item, index) in dataList"
-            :key="index"
-            @click="goToDetail(item)"
-        >
+        <div class="lottery-item" v-for="(item, index) in dataList" :key="index" @click="goToDetail(item)">
           <div class="item-header">
             <div class="header-left">
               <span class="lottery-name">{{ item.name }}</span>
@@ -35,12 +32,8 @@
               <div class="red-sum-ball">{{ getSum(getNumbers(item.lottery)) }}</div>
             </div>
             <div class="tags-row">
-              <div
-                  class="combo-tag"
-                  v-for="(tag, tagIdx) in getComboTags(item.lottery.combo)"
-                  :key="tagIdx"
-                  :class="getTagClass(tag)"
-              >
+              <div class="combo-tag" v-for="(tag, tagIdx) in getComboTags(item.lottery.combo)" :key="tagIdx"
+                :class="getTagClass(tag)">
                 {{ tag }}
               </div>
             </div>
@@ -62,17 +55,14 @@
 
           <div v-else-if="[7, 9, 11].includes(item.type)" class="play-container">
             <div class="blocks-row">
-              <div
-                  class="square-block"
-                  v-for="(num, idx) in getNumbers(item.lottery)"
-                  :key="idx"
-                  :style="{ backgroundColor: getNumColor(num) }"
-              >
+              <div class="square-block" v-for="(num, idx) in getNumbers(item.lottery)" :key="idx"
+                :style="{ backgroundColor: getNumColor(num) }">
                 {{ num }}
               </div>
             </div>
             <div class="tags-row mt-tags" v-if="item.lottery.open_code_other">
-              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)" :key="tagIdx">
+              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)"
+                :key="tagIdx">
                 {{ tag }}
               </div>
             </div>
@@ -80,16 +70,13 @@
 
           <div v-else-if="[8, 10].includes(item.type)" class="play-container">
             <div class="balls-row">
-              <div
-                  class="ball"
-                  v-for="(num, idx) in getNumbers(item.lottery)"
-                  :key="idx"
-              >
+              <div class="ball" v-for="(num, idx) in getNumbers(item.lottery)" :key="idx">
                 {{ num }}
               </div>
             </div>
             <div class="tags-row mt-tags" v-if="item.lottery.open_code_other">
-              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)" :key="tagIdx">
+              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)"
+                :key="tagIdx">
                 {{ tag }}
               </div>
             </div>
@@ -97,21 +84,14 @@
 
           <div v-else-if="[12, 13].includes(item.type)" class="play-container">
             <div class="dice-row">
-              <div
-                  class="dice"
-                  v-for="(num, idx) in getNumbers(item.lottery)"
-                  :key="idx"
-              >
-                <div
-                    v-for="(show, dotIdx) in getDiceDots(num)"
-                    :key="dotIdx"
-                    class="dot"
-                    :class="{ 'visible': show, 'red-dot': Number(num) === 1 || Number(num) === 4 }"
-                ></div>
+              <div class="dice" v-for="(num, idx) in getNumbers(item.lottery)" :key="idx">
+                <div v-for="(show, dotIdx) in getDiceDots(num)" :key="dotIdx" class="dot"
+                  :class="{ 'visible': show, 'red-dot': Number(num) === 1 || Number(num) === 4 }"></div>
               </div>
             </div>
             <div class="tags-row mt-tags" v-if="item.lottery.open_code_other">
-              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)" :key="tagIdx">
+              <div class="combo-tag tag-blue" v-for="(tag, tagIdx) in getOtherTags(item.lottery.open_code_other)"
+                :key="tagIdx">
                 {{ tag }}
               </div>
             </div>
@@ -206,12 +186,12 @@ const getNumColor = (num) => {
 
 const getDiceDots = (num) => {
   const layouts = {
-    1: [0, 0, 0,  0, 1, 0,  0, 0, 0],
-    2: [1, 0, 0,  0, 0, 0,  0, 0, 1],
-    3: [1, 0, 0,  0, 1, 0,  0, 0, 1],
-    4: [1, 0, 1,  0, 0, 0,  1, 0, 1],
-    5: [1, 0, 1,  0, 1, 0,  1, 0, 1],
-    6: [1, 0, 1,  1, 0, 1,  1, 0, 1]
+    1: [0, 0, 0, 0, 1, 0, 0, 0, 0],
+    2: [1, 0, 0, 0, 0, 0, 0, 0, 1],
+    3: [1, 0, 0, 0, 1, 0, 0, 0, 1],
+    4: [1, 0, 1, 0, 0, 0, 1, 0, 1],
+    5: [1, 0, 1, 0, 1, 0, 1, 0, 1],
+    6: [1, 0, 1, 1, 0, 1, 1, 0, 1]
   };
   return layouts[Number(num)] || layouts[1];
 };
@@ -245,6 +225,7 @@ const goToDetail = (item) => {
   justify-content: space-between;
   align-items: center;
   margin-bottom: 25px;
+
   .title {
     color: #ffffff;
     font-size: 26px;
@@ -268,7 +249,7 @@ const goToDetail = (item) => {
 
   &:hover {
     transform: translateY(-5px);
-    box-shadow: 0 10px 20px rgba(0,0,0,0.5);
+    box-shadow: 0 10px 20px rgba(0, 0, 0, 0.5);
     border-color: #f8b932;
   }
 
@@ -282,17 +263,20 @@ const goToDetail = (item) => {
       display: flex;
       align-items: center;
       gap: 12px;
+
       .lottery-name {
         font-size: 18px;
         font-weight: bold;
         color: #ffffff;
       }
+
       .lottery-issue {
         font-size: 14px;
         color: #f8b932;
         font-weight: 500;
       }
     }
+
     .header-right {
       .lottery-time {
         font-size: 13px;
@@ -302,11 +286,13 @@ const goToDetail = (item) => {
   }
 
   .play-container {
+
     // ======== PC28 ========
     .equation-row {
       display: flex;
       align-items: center;
       margin-bottom: 15px;
+
       .grey-ball {
         width: 36px;
         height: 36px;
@@ -319,6 +305,7 @@ const goToDetail = (item) => {
         font-size: 16px;
         font-weight: bold;
       }
+
       .red-sum-ball {
         width: 36px;
         height: 36px;
@@ -339,11 +326,13 @@ const goToDetail = (item) => {
       align-items: center;
       flex-wrap: wrap;
       gap: 6px;
+
       .lhc-col {
         display: flex;
         flex-direction: column;
         align-items: center;
         gap: 4px;
+
         .lhc-ball {
           width: 34px;
           height: 34px;
@@ -357,20 +346,38 @@ const goToDetail = (item) => {
           font-weight: bold;
           border: 2px solid transparent;
         }
-        .color-red { border-color: #f75b5b; }
-        .color-blue { border-color: #49b3ff; }
-        .color-green { border-color: #40b17b; }
-        .lhc-zodiac { font-size: 12px; color: #aaa; }
+
+        .color-red {
+          border-color: #f75b5b;
+        }
+
+        .color-blue {
+          border-color: #49b3ff;
+        }
+
+        .color-green {
+          border-color: #40b17b;
+        }
+
+        .lhc-zodiac {
+          font-size: 12px;
+          color: #aaa;
+        }
       }
     }
 
-    .operator { color: #888; font-size: 20px; margin: 0 5px; }
+    .operator {
+      color: #888;
+      font-size: 20px;
+      margin: 0 5px;
+    }
 
     // ======== 时时彩等球类 ========
     .balls-row {
       display: flex;
       flex-wrap: wrap;
       gap: 10px;
+
       .ball {
         width: 34px;
         height: 34px;
@@ -389,6 +396,7 @@ const goToDetail = (item) => {
       display: flex;
       flex-wrap: wrap;
       gap: 6px;
+
       .square-block {
         width: 30px;
         height: 30px;
@@ -406,6 +414,7 @@ const goToDetail = (item) => {
     .dice-row {
       display: flex;
       gap: 15px;
+
       .dice {
         display: grid;
         grid-template-columns: repeat(3, 1fr);
@@ -415,10 +424,21 @@ const goToDetail = (item) => {
         background-color: #eee;
         border-radius: 8px;
         padding: 4px;
+
         .dot {
-          width: 8px; height: 8px; border-radius: 50%; background-color: transparent; place-self: center;
-          &.visible { background-color: #222; }
-          &.visible.red-dot { background-color: #e54d42; }
+          width: 8px;
+          height: 8px;
+          border-radius: 50%;
+          background-color: transparent;
+          place-self: center;
+
+          &.visible {
+            background-color: #222;
+          }
+
+          &.visible.red-dot {
+            background-color: #e54d42;
+          }
         }
       }
     }
@@ -428,6 +448,7 @@ const goToDetail = (item) => {
       flex-wrap: wrap;
       gap: 8px;
       margin-top: 15px;
+
       .combo-tag {
         padding: 3px 10px;
         border-radius: 4px;
@@ -435,11 +456,26 @@ const goToDetail = (item) => {
         font-weight: bold;
         color: #fff;
       }
-      .tag-red { background-color: #f07474; }
-      .tag-green { background-color: #79c55b; }
-      .tag-yellow { background-color: #eebb4d; }
-      .tag-blue { background-color: #5b9cf7; }
-      .tag-default { background-color: #444; }
+
+      .tag-red {
+        background-color: #f07474;
+      }
+
+      .tag-green {
+        background-color: #79c55b;
+      }
+
+      .tag-yellow {
+        background-color: #eebb4d;
+      }
+
+      .tag-blue {
+        background-color: #5b9cf7;
+      }
+
+      .tag-default {
+        background-color: #444;
+      }
     }
   }
 }

+ 2 - 2
src/views/SportsBetting/index.vue

@@ -356,7 +356,7 @@ import pcFooter from '@/businessComponents/pcFooter/index.vue'
 // })
 
 import { ref, watch, computed, onMounted, onActivated, onUnmounted, nextTick } from "vue"
-import { useRouter } from "vue-router"
+import { useRoute, useRouter } from "vue-router"
 import { useI18n } from "vue-i18n"
 import { getSportSchedule, getBanner,getActivity, getUserInfo } from "@/request/api.js"
 import { useOrderStore } from "@/store/bettingSheet.js"
@@ -1807,4 +1807,4 @@ $hover-bg: var(--el-fill-color-light);
     :deep(.el-carousel) { height: 100%; }
     :deep(.el-carousel__container) { height: 100% !important; }
   }
-</style>
+</style>

+ 39 - 21
src/views/dzGames/index.vue

@@ -20,7 +20,8 @@
                 <div class="other-games-scroll pc-scroll-view">
                     <div class="other-games-flex">
                         <div class="other-game-item" v-for="(item, itemIndex) in dzGames.platforms[tabIndex].games"
-                            :key="itemIndex" @click="goGame1(dzGames[tabIndex].platType, dzGameType, item.gameCode)">
+                            :key="itemIndex"
+                            @click="goGame1(dzGames.platforms[tabIndex].platType, dzGameType, item.gameCode, dzGames.platforms[tabIndex].name, item.name)">
                             <img :src="item.logo"
                                 style="width: 140px; height: 140px; border-radius: 8px; object-fit: cover;" />
                         </div>
@@ -38,11 +39,15 @@ import { ref, watch, onMounted, computed, onUnmounted, onActivated } from "vue";
 import { useRouter, useRoute } from 'vue-router';
 import { useI18n } from "vue-i18n";
 import pcFooter from '@/businessComponents/pcFooter/index.vue'
-import { getGameUrl, getDeomUrl, dzList } from "@/request/api.js";
+import { getBalance, getGameUrl, getDeomUrl, dzList } from "@/request/api.js";
+import { useGameIframeStore } from '@/store/gameIframe.js';
+import { useUserStore } from '@/store/user/index.js';
 import iconDz from '@/assets/images/Home/dz.png'
 const { t, locale } = useI18n();
 const router = useRouter();
 const route = useRoute();
+const gameIframeStore = useGameIframeStore();
+const userStore = useUserStore();
 const dzGames = ref([])
 const dzGameType = ref("")
 const tabIndex = ref(0)
@@ -62,29 +67,42 @@ const getDzList = async () => {
             dzGames.value = item
         }
     });
-    dzGameType = route.query.type
+    dzGameType.value = route.query.type
+    console.log(dzGameType)
     console.log(res.data.list)
 }
-const goGame1 = (game, gameType, gameCode) => {
+const refreshBalance = () => {
+    return getBalance().then(res => {
+        if (res?.data?.money !== undefined) {
+            userStore.balance = res.data.money;
+        }
+    }).catch(error => {
+        console.error('获取游戏平台余额失败:', error);
+    });
+}
+
+const goGame1 = (game, gameType, gameCode, platformName, gameName) => {
     let params = {
         platType: game,
         gameType: gameType,
         gameCode: gameCode,
         device: "pc"
     }
-    if (localStorage.getItem('youke_token')) {
-        getDeomUrl(params).then(res => {
-            console.log(res.data)
-            window.location.href = res.data.url
-        })
-        // return ElMessage.warning(t('试玩账户不可进入'))
-    } else {
-
-        getGameUrl(params).then(res => {
-            console.log(res.data)
-            window.location.href = res.data.url
-        })
-    }
+    const request = localStorage.getItem('youke_token')
+        ? getDeomUrl(params)
+        : getGameUrl(params);
+
+    request.then(res => {
+        const url = res?.data?.url || res?.data?.data?.url || res?.url;
+        if (!url) return;
+
+        refreshBalance();
+        const label = gameName ? `${platformName} - ${gameName}` : platformName;
+        gameIframeStore.open(url, label, `${gameType}-${game}-${gameCode}`, gameType);
+        router.push({ name: 'videoGames', query: { type: gameType } });
+    }).catch(error => {
+        console.error('打开游戏失败:', error);
+    });
 }
 </script>
 <style lang="scss" scoped>
@@ -93,8 +111,8 @@ $card-bg: #1e1e1e;
 $border-color: #333;
 
 .entertainment-list {
-    width: 90%;
-    max-width: 1200px;
+    width: 95%;
+    // max-width: 1200px;
     margin: 0 auto;
     border: 1px solid transparent; // 替换为你原本的 border: 1px solid;
     box-sizing: border-box;
@@ -215,7 +233,7 @@ $border-color: #333;
     // flex-direction: row;
     // justify-content: space-between;
     flex-wrap: wrap;
-    gap: 16px;
+    gap: 26px;
     padding-bottom: 4px;
 }
 
@@ -227,4 +245,4 @@ $border-color: #333;
     height: 140px;
     cursor: pointer;
 }
-</style>
+</style>

Некоторые файлы не были показаны из-за большого количества измененных файлов