Browse Source

对接接口

wkw 2 days ago
parent
commit
6b5149a3b4

+ 17 - 8
src/api/game.js

@@ -23,13 +23,6 @@ export const matchRank = (data) => {
       data,
     })
   }
-export const matchEnroll = (data) => {
-    return http({
-      url: '/api/game/match/enroll',
-      method: 'post',
-      data,
-    })
-  }
   // 查询用户奖金信息
 export const userPrize = (data) => {
     return http({
@@ -45,4 +38,20 @@ export const claimPrize = (data) => {
       method: 'post',
       data,
     })
-  }
+  }
+// 校验报名竞赛
+export const verifyEnroll = (data) => {
+  return http({
+    url: '/api/game/verify/enroll',
+    method: 'post',
+    data,
+  })
+}
+// 报名竞赛
+export const matchEnroll = (data) => {
+  return http({
+    url: '/api/game/match/enroll',
+    method: 'post',
+    data,
+  })
+}

+ 26 - 5
src/components/Header/index.vue

@@ -1,16 +1,16 @@
 <template>
   <view class="nav-bar">
     <view class="back-box" v-if="back"></view>
-    <view class="nav-title">
-      <slot name="title"></slot>
+    <view class="nav-title" @click="changeLinkAddress">
+      ACC <span style="padding: 0 12rpx">|</span>{{address}}
     </view>
     <view class="nav-right">
-        <view class="nav-right-network">
+        <!-- <view class="nav-right-network">
             <image
                 src="@/static/image/home/network.png"
                 mode="scaleToFill"
             />
-        </view>
+        </view> -->
         <view class="nav-right-logo">
             <image
                 src="@/static/image/home/logo.png"
@@ -21,13 +21,34 @@
   </view>
 </template>
 <script setup>
-import { defineProps } from "vue";
+import { ref,defineProps,defineEmits,onMounted } from "vue";
+import { getWalletAddress } from "@/utils/utils";
 const props = defineProps({
   back: {
     type: Boolean,
     default: () => false,
   },
 });
+const emit = defineEmits(['update:address']);
+const address = ref("");
+const getAddress = async () =>{
+  const addr = await getWalletAddress();
+  if (addr) {
+    console.log(addr);
+    emit('update:address', addr);
+    address.value = `${addr.slice(0, 4)}...${addr.slice(-4)}`;
+  } else {
+    address.value = "未连接钱包";
+  }
+}
+const changeLinkAddress = () =>{
+  if(address.value == '未连接钱包'){
+    getAddress();
+  }
+}
+onMounted(async () => {
+  getAddress();
+});
 </script>
 <style lang="scss">
 .nav-bar {

+ 5 - 23
src/pages.json

@@ -9,35 +9,35 @@
 	},
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
 		{
-			"path": "pages/home/index",
+			"path": "pages/trade/index",
 			"style": {
 				"navigationBarTitleText": "uni-app",
 				"navigationStyle": "custom"
 			}
 		},
 		{
-			"path": "pages/index/index",
+			"path": "pages/home/index",
 			"style": {
 				"navigationBarTitleText": "uni-app",
 				"navigationStyle": "custom"
 			}
 		},
 		{
-			"path": "pages/game/index",
+			"path": "pages/index/index",
 			"style": {
 				"navigationBarTitleText": "uni-app",
 				"navigationStyle": "custom"
 			}
 		},
 		{
-			"path": "pages/node/index",
+			"path": "pages/game/index",
 			"style": {
 				"navigationBarTitleText": "uni-app",
 				"navigationStyle": "custom"
 			}
 		},
 		{
-			"path": "pages/trade/index",
+			"path": "pages/node/index",
 			"style": {
 				"navigationBarTitleText": "uni-app",
 				"navigationStyle": "custom"
@@ -63,29 +63,11 @@
 				"selectedIconPath": "static/image/tabbar/home-check.png",
 				"text": "官网"
 			},
-			{
-				"pagePath": "pages/wgt/index",
-				"iconPath": "static/image/tabbar/wgt.png",
-				"selectedIconPath": "static/image/tabbar/wgt-check.png",
-				"text": "WGT"
-			},
 			{
 				"pagePath": "pages/trade/index",
 				"iconPath": "static/image/tabbar/jiaoyi.png",
 				"selectedIconPath": "static/image/tabbar/jiaoyi-check.png",
 				"text": "竞赛"
-			},
-			{
-				"pagePath": "pages/node/index",
-				"iconPath": "static/image/tabbar/money.png",
-				"selectedIconPath": "static/image/tabbar/money-check.png",
-				"text": "节点"
-			},
-			{
-				"pagePath": "pages/game/index",
-				"iconPath": "static/image/tabbar/game.png",
-				"selectedIconPath": "static/image/tabbar/game.png",
-				"text": "GameFi"
 			}
 		]
 	},

+ 2 - 28
src/pages/home/index.vue

@@ -1,11 +1,7 @@
 <template>
   <view class="home">
     <view class="content">
-      <Header>
-        <template #title
-          >ACC <span style="padding: 0 12rpx">|</span>连接钱包</template
-        >
-      </Header>
+      <Header></Header>
       <view class="home-img">
         <image src="@/static/image/home/home-banner.png" mode="widthFix" />
       </view>
@@ -86,39 +82,17 @@ import { ref, onMounted, reactive } from "vue";
 import Header from "@/components/Header";
 import { getCoinList } from "@/api/currency";
 import { matchList } from "@/api/game";
-import { getWalletAddress } from "@/utils/utils";
 import { useCounterStore } from "@/stores/counter";
-const Login = async () => {
-  let res = await getCoinList();
-  console.log(res, "测试");
-};
-Login();
-// 获取游戏列表
-const getGameList = async () => {
-  let res = await matchList();
-  console.log(res, "游戏列表");
-};
-getGameList();
 const counter = useCounterStore();
 counter.count++;
 // 自动补全! ✨
 counter.$patch({ count: counter.count + 1 });
 // 或使用 action 代替
 counter.increment();
-const title = ref("Hello");
 const star = ref(3);
 const count = ref(0);
-const address = ref("");
 const list5 = reactive([1, 2, 3]);
-onMounted(async () => {
-  const addr = await getWalletAddress();
-  if (addr) {
-    console.log(addr);
-    address.value = `${addr.slice(0, 4)}...${addr.slice(-4)}`;
-  } else {
-    address.value = "未连接钱包";
-  }
-});
+
 
 
 

+ 290 - 207
src/pages/trade/index.vue

@@ -1,12 +1,7 @@
 <template>
   <view class="home">
     <view class="content">
-      <Header>
-        <template #title
-          >ACC <text style="padding: 0 12rpx">|</text>{{ address }}</template
-        >
-      </Header>
-      <view></view>
+      <Header @update:address="handleAddressUpdate"></Header>
       <view class="home-img">
         <image src="@/static/image/trade/jinsai-icon.png" mode="widthFix" />
       </view>
@@ -17,83 +12,84 @@
         </view>
       </view>
       <view class="home-code">
-        <view class="trade-border-box"> ${{ gameList[2]?.bonus || 0 }}</view>
+        <view class="trade-border-box"> STT{{ (Number(gameList[2]?.bonus) || 0).toFixed(6) }}</view>
         <view class="trade-border-num"
-          >≈¥{{ gameList[2]?.bonus * 7.2 || 0 }}</view
+          >≈¥{{ ((Number(gameList[2]?.bonus) || 0) * 7.2).toFixed(2) }}</view
         >
       </view>
       <view class="trade-img-box">
         <image src="@/static/image/trade/money-box.png" mode="aspectFit" />
       </view>
-      <view class="trade-process">
-        <view
-          :class="
-            gameCheck == index
-              ? 'trde-process-item-active'
-              : 'trde-process-item'
-          "
-          v-for="(item, index) in gameList"
-          :key="index"
-          @click="selectGame(index, item)"
-        >
-          <view class="trade-game-name">{{ item.title }}</view>
-          <view class="trade-game-time"
-            >{{ dayjs(item.date).format("MM-DD") }}-{{
-              dayjs(item.end_date).format("MM-DD")
-            }}</view
+      <view class="card-item" style="width: 100%;">
+        <view class="trade-process" :class="bgClass">
+          <view
+            :class="
+              gameCheck == index
+                ? 'trde-process-item-active'
+                : 'trde-process-item'
+            "
+            v-for="(item, index) in gameList"
+            :key="index"
+            @click="selectGame(index, item)"
           >
-        </view>
-      </view>
-      <view class="trade-time-box">
-        <view class="time-title">
-          距离 <text>{{ gameDetail.title }}赛程 竞赛结束 </text>还有
-        </view>
-        <up-count-down
-          :time="
-            dayjs(gameDetail.end_date).valueOf() - dayjs(new Date()).valueOf()
-          "
-          format="DD:HH:mm:ss"
-          autoStart
-          millisecond
-          @change="onChange"
-        >
-          <view class="time-box-index">
-            <view class="time__item"
-              ><view class="time-box">{{ timeData.days }}</view> 天</view
-            >
-            <view class="time__item">
-              <view class="time-box">{{
-                timeData.hours > 10 ? timeData.hours : "0" + timeData.hours
-              }}</view>
-              时</view
-            >
-            <view class="time__item"
-              ><view class="time-box">
-                {{ timeData.minutes }}
-              </view>
-              分</view
-            >
-            <view class="time__item"
-              ><view class="time-box">{{ timeData.seconds }}</view
-              >秒</view
+            <view class="trade-game-name">{{ item?.title || '暂无赛程'}}</view>
+            <view class="trade-game-time" v-if="item"
+              >{{ dayjs(item?.date).format("MM/DD") }}-{{
+                dayjs(item?.end_date).format("MM/DD")
+              }}</view
             >
           </view>
-        </up-count-down>
-        <view
-          class="start-btn"
-          @click="gameCheck == 2 ? (showGameBm = true) : ''"
-          :style="{ color: gameCheck == 2 ? '#fff' : '' }"
-          >{{ gameCheck == 2 ? "报名" : "未报名" }}</view
-        >
-        <view class="num-txt" v-if="gameCheck != 2"
-          >奖池数量:<text>${{ gameDetail.bonus }}</text>
         </view>
-        <view class="num-txt-small" v-if="gameCheck != 2"
-          >≈¥{{ gameDetail.bonus * 7.2 }}</view
-        >
+        <view class="trade-time-box" v-if="gameDetail">
+          <view class="time-title">
+            距离 <text>{{ gameDetail.title }}赛程 竞赛结束 </text>还有
+          </view>
+          <up-count-down
+            :time="
+              dayjs(gameDetail.end_date).valueOf() - dayjs(new Date()).valueOf()
+            "
+            format="DD:HH:mm:ss"
+            autoStart
+            millisecond
+            @change="onChange"
+          >
+            <view class="time-box-index">
+              <view class="time__item"
+                ><view class="time-box">{{ timeData.days }}</view> 天</view
+              >
+              <view class="time__item">
+                <view class="time-box">{{
+                  timeData.hours > 10 ? timeData.hours : "0" + timeData.hours
+                }}</view>
+                时</view
+              >
+              <view class="time__item"
+                ><view class="time-box">
+                  {{ timeData.minutes }}
+                </view>
+                分</view
+              >
+              <view class="time__item"
+                ><view class="time-box">{{ timeData.seconds }}</view
+                >秒</view
+              >
+            </view>
+          </up-count-down>
+          <view
+            class="start-btn"
+            @click="changeSign"
+            :style="{ color: gameCheck == 2 || gameDetail.is_enroll? '#fff' : '' }">{{ gameCheck == 2 && !gameDetail.is_enroll ? "报名" : (gameDetail.is_enroll ? "已报名" : "未报名") }}</view
+          >
+          <view class="num-txt" v-if="gameCheck != 2"
+            >奖池数量:<text>STT{{ (Number(gameDetail.bonus) || 0).toFixed(6) }}</text>
+          </view>
+          <view class="num-txt-small" v-if="gameCheck != 2"
+            >≈¥{{ ((Number(gameDetail.bonus) || 0) * 7.2).toFixed(2) }}</view
+          >
+        </view>
       </view>
       <view class="game-play-name">赛程名次</view>
-      <view class="game-list"  v-if="gameCheck!=2">
+      <view class="game-list">
         <view class="game-list-item" v-for="(item, index) in gameRankList" :key="index">
           <view class="game-item-left">
             <view class="game-order-index">
@@ -119,46 +115,17 @@
             <view class="game-order-num">
               <view class="game-num-txt">
                 <view>{{`${item.address.slice(0, 4)}...${item.address.slice(-4)}` }}</view>
-                <view>排名赢局</view>
+                <view class="game-num-num">{{ gameDetail?.title }}</view>
               </view>
-              <view class="game-num-num">
-                <view>{{ gameDetail.title }}</view>
-                <view>{{ item.score }}</view>
+              <view class="game-num-txt" v-if="item.is_self && item.is_prize && gameCheck == 0">
+                <view class="game-item-btn" @click="awardFun(item)">{{item.is_receive?'已领取':'领取'}}</view>
+              </view>
+              <view class="game-num-txt" v-else>
+                <view>排名赢局</view>
+                <view class="game-num-num">{{ item.score }}</view>
               </view>
             </view>
           </view>
-          <!-- <view class="game-item-btn">领取</view> -->
-        </view>
-      </view>
-      <view class="game-list" v-if="gameCheck==2">
-        <view class="game-list-item" v-for="(item, index) in 10" :key="index">
-          <view class="game-item-left">
-            <view class="game-order-index">
-              <image
-                src="@/static/image/trade/one.png"
-                v-if="index == 0"
-                mode="scaleToFill"
-              />
-              <image
-                src="@/static/image/trade/two.png"
-                v-if="index == 1"
-                mode="scaleToFill"
-              />
-              <image
-                src="@/static/image/trade/three.png"
-                v-if="index == 2"
-                mode="scaleToFill"
-              />
-              <text v-if="index != 0 && index != 1 && index != 2">{{
-                index + 1
-              }}</text>
-            </view>
-            <view class="game-order-num">
-              <view class="game-num-txt">0×**001</view>
-              <view class="game-num-num">*.00</view>
-            </view>
-          </view>
-          <view class="game-item-btn" @click="awardFun">领取</view>
         </view>
       </view>
     </view>
@@ -166,7 +133,7 @@
       <view class="fix-item" @click="openGamePopup(1)">赛程规则</view>
       <view class="fix-item"  @click="openGamePopup(2)">赛程名次</view>
     </view>
-    <!-- @click="awardFun" -->
+    <!-- 规则和名次 -->
     <up-popup
       :show="showGameMsg"
       :round="10"
@@ -187,10 +154,11 @@
         <view class="show-game-title" v-if="showType==1">
           竞赛规则
         </view>
+        <!-- 名次 -->
         <view class="show-game-content" v-if="showType==2">
-          <view class="game-msg">1:赛程开始时间:{{ gameDetail.date }}</view>
+          <view class="game-msg">1:赛程开始时间:{{ gameDetail.date }} 00:00:00</view>
           <view class="game-msg"
-            >2:赛程结束时间:{{ gameDetail.end_date }}</view
+            >2:赛程结束时间:{{ gameDetail.end_date }} 23:59:59</view
           >
           <view class="game-msg"
             >3:参与场次:<text>0场;</text>输:<text>0局;</text>赢:<text
@@ -213,6 +181,7 @@
             >⑤:对于恶意刷单地址,平台将永久封禁账号;</view
           >
         </view>
+        <!-- 规则 -->
         <view class="show-game-content" v-if="showType==1">
           <view class="game-msg">1: 赛程报名截止时间:每期赛程开始前</view>
           <view class="game-msg"
@@ -227,16 +196,9 @@
           <view class="game-msg"
             >5:赛程奖励规则: 当期奖池金额</view
           >
-          <view class="dest-item" style="color: red;font-size: 24rpx;"
-            >①:第1-50
-            名平均分配20%;
+          <view class="dest-item" style="color: red;font-size: 24rpx;" v-for="(item,i) in gameDetail?.rules" :key="i">
+            <text>{{ i == 0?'①':i == 1?'②':'③' }}</text>:{{item.rule}}
           </view>
-          <view class="dest-item" style="color: red;font-size: 24rpx;"
-            >②:第51-200名平均分配30%;</view
-          >
-          <view class="dest-item" style="color: red;font-size: 24rpx;"
-            >③:第201-500名平 配50%;</view
-          >
           <view class="desc-title">注意:</view>
           <view class="dest-item">①: 如当期赛程奖励未在有效期内领取,将视为放弃;</view>
           <view class="dest-item" 
@@ -254,6 +216,7 @@
         </view>
       </view>
     </up-popup>
+    <!-- 报名 -->
     <up-popup
       :show="showGameBm"
       :round="10"
@@ -272,27 +235,27 @@
         <view class="show-game-content">
           <view class="desc-title" style="color: red">报名方式①:</view>
           <view class="game-msg" style="font-weight: 400"
-            >消耗 <text style="color: #d4ac27">0.25U</text> 等值WGT:</view
+            >消耗 <text style="color: #d4ac27">{{entry_fee}} STT</text> 等值 WGT:</view
           >
           <view class="game-msg"
-            >≈<text>0.0012</text>WGT<text
+            >≈<text>{{wgt_price}}</text>WGT<text
               style="color: #d4ac27; font-size: 20rpx"
               >(钱包扣除)</text
             ></view
           >
-          <view class="dest-item" style="color: #aaa">(WGT钱包余额0.0002)</view>
+          <view class="dest-item" style="color: #aaa">(WGT钱包余额{{ (Number(WGTbalance) || 0).toFixed(6) }})</view>
           <view class="desc-title" style="color: red">报名方式②:</view>
           <view class="game-msg"
-            >消耗0.25U
+            >消耗{{entry_fee}} STT
             <text style="color: #d4ac27; font-size: 20rpx"
               >(钱包扣除)</text
             ></view
           >
-          <view class="dest-item" style="color: #aaa">(STT钱包余额0.0002)</view>
+          <view class="dest-item" style="color: #aaa">(STT钱包余额{{ (Number(STTbalance) || 0).toFixed(6) }})</view>
         </view>
         <view class="show-game-bottom">
-          <view class="show-game-btn-wgt">WGT报名</view>
-          <view class="show-game-btn-stt">STT报名</view>
+          <view class="show-game-btn-wgt" @click="changeWGT">WGT报名</view>
+          <view class="show-game-btn-stt" @click="changeSTT">STT报名</view>
         </view>
       </view>
     </up-popup>
@@ -300,88 +263,69 @@
 </template>
   
   <script setup>
-import { ref, onMounted, reactive } from "vue";
+import { ref, onMounted,computed, reactive } from "vue";
 import Header from "@/components/Header";
-import { getWalletAddress } from "@/utils/utils";
-import { sendSingleReward } from "@/utils/web.js";
-import { matchList, matchRank, matchInfo } from "@/api/game";
+import { sendSingleReward,WGTForToken,STTForToken,getBalance } from "@/utils/web.js";
+import { matchList, matchRank, matchInfo,verifyEnroll,matchEnroll,userPrize,claimPrize } from "@/api/game";
 import dayjs from "dayjs";
 const timeData = ref({});
-const address = ref("");
-// 定义 onChange 方法
 const onChange = (e) => {
   timeData.value = e;
 };
-onMounted(async () => {
-  const addr = await getWalletAddress();
-  if (addr) {
-    console.log(addr);
-    address.value = `${addr.slice(0, 4)}...${addr.slice(-4)}`;
-  } else {
-    address.value = "未连接钱包";
-  }
+const walletAddress = ref('');
+const gameList = ref([]);
+const gameRankList = ref([]);
+const gameDetail = ref({});
+const gameCheck = ref(1);//选中tab
+const showGameBm = ref(false);
+const WGTbalance = ref(0);
+const STTbalance = ref(0);
+const entry_fee = ref(0);
+const wgt_price = ref(0);
+const privateKey = "0x4553077da5d773773dad0511c6e5d33142ae2c1bd05a3a8a4a7becbc0d23d9b5";
+
+const bgClass = computed(() => {
+  if (gameCheck.value === 0) return 'bg1';
+  if (gameCheck.value === 1) return 'bg2';
+  return 'bg3';
 });
-// 例子  调用合约
-const awardFun = async () => {
-  // const privateKey = window.android.getPrivateKey();//app
-  const privateKey =
-    "0x4553077da5d773773dad0511c6e5d33142ae2c1bd05a3a8a4a7becbc0d23d9b5"; //h5
-  try {
-    const result = await sendSingleReward(privateKey, 0.01);
-    if (result.status === "success") {
-      console.log(result);
-    }
-  } catch (error) {}
+const handleAddressUpdate = (addr) => {
+  walletAddress.value = addr;
+  getGameMatchList();
 };
-// 获取各种数据
-const gameList = ref([]);
-const getGameMatchList = async () => {
+// 获取游戏赛事列表(三个tab)
+const getGameMatchList = async (type = true) => {
   let params = {
     dapp_id: 15,
+    address:walletAddress.value
   };
-  // 获取游戏赛事列表
   let res = await matchList(params);
   if (res.status == 200) {
     gameList.value = res.data;
-    getGameInfo(res.data[0].id);
-    getGameRank(res.data[0].id);
+    if(type){
+      gameDetail.value = res.data[1];
+      getGameRank();
+    }else{
+      gameDetail.value = res.data[2];
+    }
   }
 };
-getGameMatchList();
-// 游戏赛事排行
-const gameRankList = ref([]);
 // 查询游戏赛事排名
-const getGameRank = async (id) => {
+const getGameRank = async () => {
   let params = {
     dapp_id: 15,
-    match_id: id,
+    address:walletAddress.value
   };
-  // 获取游戏赛事列表
   let res = await matchRank(params);
   if (res.status == 200) {
     gameRankList.value = res.data;
   }
 };
-// 游戏详情
-const gameDetail = ref("");
-// 获取游戏赛事详情
-const getGameInfo = async (id) => {
-  let params = {
-    dapp_id: 15,
-    match_id: id,
-  };
-  // 获取游戏赛事列表
-  let res = await matchInfo(params);
-  if (res.status == 200) {
-    gameDetail.value = res.data;
-  }
-};
-const gameCheck = ref(1);
+// 切换tab
 const selectGame = (value, item) => {
   gameCheck.value = value;
   gameDetail.value = item;
-  // getGameInfo(item.id);
-  getGameRank(item.id);
+  getGameRank();
 };
 // 游戏规则弹出框
 const showGameMsg = ref(false);
@@ -390,10 +334,137 @@ const openGamePopup = (value) => {
   showGameMsg.value = true;
   showType.value=value;
 };
-const showGameBm = ref(false);
-const openBmPopup = () => {
-  showGameBm.value = true;
+// 获取余额
+const getnum = async () =>{
+  try {
+    WGTbalance.value = await getBalance(privateKey,'wgt');
+    STTbalance.value = await getBalance(privateKey,'stt');
+  }catch(error){
+    console.log(error)
+  }
+}
+//校验报名
+const changeSign = async () =>{
+  if (gameCheck.value != 2 || gameDetail.value?.is_enroll) return;
+  let res = await verifyEnroll({dapp_id:15,match_id:gameDetail.value?.id,address:walletAddress.value});
+  if (res.status == 200) {
+    entry_fee.value = Number(res.data.entry_fee).toFixed(2);
+    wgt_price.value = Number(res.data.format?.wgt_price).toFixed(4);
+    showGameBm.value = true;
+  }
+}
+// 报名
+const getMatchEnroll = async () =>{
+  let res = await matchEnroll({dapp_id:15,match_id:gameList.value[gameCheck.value]?.id,address:walletAddress.value});
+  if (res.status == 200) {
+    uni.hideLoading()
+    uni.showToast({
+      title: '报名成功',
+      icon: 'none',
+      duration: 1000
+    })
+    getGameMatchList(false);
+  }else{
+    uni.hideLoading()
+  }
+}
+
+const changeWGT = async () => {
+  await handleTokenSignUp(WGTForToken, wgt_price.value);
 };
+
+const changeSTT = async () => {
+  await handleTokenSignUp(STTForToken, entry_fee.value);
+};
+
+const handleTokenSignUp = async (signUpFn, price) => {
+  showGameBm.value = false;
+  uni.showLoading({
+    title: '报名中...',
+    mask: true
+  });
+  try {
+    const result = await signUpFn(privateKey, price);
+    if (result.status === "success") {
+      await getMatchEnroll();
+    } else {
+      uni.hideLoading();
+      uni.showToast({
+        title: result.message || "报名失败",
+        icon: 'none',
+        duration: 1000
+      });
+    }
+  } catch (error) {
+    uni.hideLoading();
+    uni.showToast({
+      title: error.message || "报名失败",
+      icon: 'none',
+      duration: 1000
+    });
+  }
+};
+
+//查询用户奖金信息
+const awardFun = async (item) => {
+  if(item.is_receive) return;
+  let res = await userPrize({dapp_id:15,match_id:gameDetail.value?.id,address:walletAddress.value});
+  if (res.status == 200) {
+    if(!res.data.prize_money){
+      uni.showToast({
+        title: '正在结算中!',
+        icon: 'none',
+        duration: 1000
+      })
+      return;
+    };
+    getsendSingleReward(res.data.prize_money)
+  }
+};
+// 领取用户奖金
+const getClaimPrize = async () =>{
+  let res = await claimPrize({dapp_id:15,match_id:gameDetail.value?.id,address:walletAddress.value});
+  if (res.status == 200) {
+    uni.hideLoading();
+    uni.showToast({
+      title: '领取成功',
+      icon: 'none',
+      duration: 1000
+    })
+    getGameRank()
+  }
+}
+
+const getsendSingleReward = async (prize_money) =>{
+  uni.showLoading({
+    title: '领取中...',
+    mask: true
+  });
+  try {
+    const result = await sendSingleReward(privateKey,prize_money);
+    if (result.status === "success") {
+      await getClaimPrize();
+    }else{
+      uni.hideLoading();
+      uni.showToast({
+        title: result.message || "领取失败",
+        icon: 'none',
+        duration: 1000
+      });
+    }
+  } catch (error) {
+    uni.hideLoading();
+    uni.showToast({
+      title: error.message || "领取失败",
+      icon: 'none',
+      duration: 1000
+    });
+  }
+}
+
+onMounted(async () => {
+  getnum();
+});
 </script>
   
   <style lang="scss" scoped>
@@ -514,41 +585,52 @@ const openBmPopup = () => {
       height: 100%;
     }
   }
+  .bg1{
+    background-image: url("@/static/image/trade/bg1.png");
+  }
+  .bg2{
+    background-image: url("@/static/image/trade/bg2.png");
+  }
+  .bg3{
+    background-image: url("@/static/image/trade/bg3.png");
+  }
   .trade-process {
     height: 131rpx;
     width: 100%;
-    background-image: url("@/static/image/trade/process.png");
     background-position: center center;
     background-size: 100% 100%;
     background-repeat: no-repeat;
     display: flex;
     justify-content: space-between;
     align-items: center;
-    .trde-process-item {
-      width: 100%;
-      height: 100%;
-      color: #d3bdd9;
-      display: flex;
-      flex-direction: column;
-      justify-content: center;
-      align-items: center;
-      .trade-game-name {
-        font-size: 28rpx;
-        font-weight: 600;
-      }
-      .trade-game-time {
-        font-size: 24rpx;
-        margin-top: 12rpx;
-      }
-    }
+
+    // .trde-process-item {
+    //   width: 100%;
+    //   height: 100%;
+    //   color: #4C3F2E;
+    //   display: flex;
+    //   flex-direction: column;
+    //   justify-content: center;
+    //   align-items: center;
+    //   text-align: center;
+    //   .trade-game-name {
+    //     font-size: 28rpx;
+    //     font-weight: 600;
+    //   }
+    //   .trade-game-time {
+    //     font-size: 24rpx;
+    //     margin-top: 12rpx;
+    //   }
+    // }
     .trde-process-item {
       width: 100%;
       height: 100%;
       display: flex;
       flex-direction: column;
+      text-align: center;
       justify-content: center;
       align-items: center;
-      color: #d3bdd9;
+      color: #9c9c9c;
       overflow: hidden;
       padding-left: 36rpx;
       box-sizing: border-box;
@@ -571,8 +653,9 @@ const openBmPopup = () => {
       display: flex;
       flex-direction: column;
       justify-content: center;
+      text-align: center;
       align-items: center;
-      color: #4c303a;
+      color: #493D2A;
       overflow: hidden;
       padding-left: 36rpx;
       box-sizing: border-box;
@@ -657,6 +740,7 @@ const openBmPopup = () => {
   .game-play-name {
     width: 342rpx;
     height: 64rpx;
+    margin-top: 24rpx;
     background-image: url("@/static/image/trade/trade-title-bg.png");
     background-position: center center;
     background-size: 100% 100%;
@@ -701,14 +785,13 @@ const openBmPopup = () => {
         .game-order-num {
           flex: 1;
           width: 100%;
+          display: flex;
+          justify-content: space-between;
+          align-items: center;
           .game-num-txt {
-            width:100%;
             font-size: 28rpx;
             color: #f2ce9a;
             font-weight: 700;
-            display: flex;
-            justify-content: space-between;
-            align-items: center;
           }
           .game-num-num {
             margin-top: 10rpx;

+ 0 - 0
src/static/image/trade/process.png → src/static/image/trade/bg1.png


BIN
src/static/image/trade/bg2.png


BIN
src/static/image/trade/bg3.png


+ 1 - 1
src/utils/http.js

@@ -30,7 +30,7 @@ export const http = (options) => {
           resolve(res.data)
         } else {
           uni.showToast({
-            title: '请求失败',
+            title: res.data.message || '请求失败',
             icon: 'none'
           })
           reject(res)

+ 12 - 8
src/utils/web.js

@@ -27,11 +27,14 @@ async function getBalance(privateKey, type) {
         const balanceWei = await tokenContract.methods.balanceOf(address).call();
         return web3.utils.fromWei(balanceWei, 'ether');
     } catch (error) {
-        console.error("❌ 获取余额失败:", error);
-        return null;
+        return {
+            success: false,
+            message: error?.message || '未知错误'
+        };
     }
 }
 
+
 // 发放奖励
 async function sendSingleReward(privateKey, amount) {
     if (!privateKey) {
@@ -86,13 +89,12 @@ async function tokenSignUp(privateKey, amount, type) {
         const account = web3.eth.accounts.privateKeyToAccount(privateKey);
         const sender = account.address;
 
-        const [chainId, gasPriceRaw, nonce] = await Promise.all([
+        const [chainId, gasPrice, nonce] = await Promise.all([
             web3.eth.getChainId(),
             web3.eth.getGasPrice(),
             web3.eth.getTransactionCount(sender)
         ]);
 
-        const gasPrice = (BigInt(gasPriceRaw) * 10n).toString();
         const tokenContract = new web3.eth.Contract(pubData, tokenAddress);
         const exchangeContract = new web3.eth.Contract(bmabiData, MANAGER_ADDRESS);
 
@@ -115,18 +117,20 @@ async function tokenSignUp(privateKey, amount, type) {
             tokenContract.methods.allowance(sender, MANAGER_ADDRESS).call(),
             tokenContract.methods.balanceOf(sender).call()
         ]);
-
+        console.log('授权额度:',allowance)
+        console.log('账户余额:', tokenBalance)
         if (BigInt(allowance) < BigInt(tokenAmount)) return { status: "error", message: "授权额度不足" };
         if (BigInt(tokenBalance) < BigInt(tokenAmount)) return { status: "error", message: `${type.toUpperCase()} 余额不足` };
-
+        
         // gas 估算
         const receiveMethod = type.toLowerCase() === 'wgt' ? 'receiveWGT' : 'receiveSTT';
         const gasEstimate = await exchangeContract.methods[receiveMethod](tokenAmount).estimateGas({ from: sender });
         const gasLimit = Math.ceil(Number(gasEstimate) * 1.1);
         const minGasNeeded = BigInt(gasLimit) * BigInt(gasPrice);
         const ethBalance = await web3.eth.getBalance(sender);
-
-        if (BigInt(ethBalance) < minGasNeeded) return { status: "error", message: "ETH余额不足以支付Gas" };
+        console.log('估算gas:', minGasNeeded)
+        console.log('账户ACC余额:', ethBalance)
+        if (BigInt(ethBalance) < minGasNeeded) return { status: "error", message: "ACC余额不足以支付Gas" };
 
         // 发送报名交易
         const depositTx = await web3.eth.accounts.signTransaction({