From 4c32bbfb137215aa2ae30c14dc4bd3134a5b1acc Mon Sep 17 00:00:00 2001
From: zhangyibo95 <690096405@qq.com>
Date: Thu, 25 Jun 2026 18:16:13 +0800
Subject: [PATCH] =?UTF-8?q?update:=E5=AF=B9=E6=8E=A5=E4=BC=9A=E5=91=98?=
=?UTF-8?q?=E9=99=90=E5=88=B6=E6=AC=A1=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/apis.js | 19 ++++++--
src/canvas.js | 16 +++++--
src/pages/battle-room.vue | 32 ++++++++++++-
src/pages/first-try.vue | 16 ++++++-
src/pages/friend-battle.vue | 57 +++++++++++++++++++---
src/pages/match-page.vue | 40 ++++++++++++++--
src/pages/point-book-detail.vue | 14 ++++--
src/pages/point-book-rank.vue | 17 +++++--
src/pages/practise-one.vue | 16 ++++++-
src/pages/practise-two.vue | 16 ++++++-
src/pages/ranking.vue | 57 +++++++++++++++++++---
src/store.js | 19 ++++++++
src/util.js | 84 ++++++++++++++++++++++++++-------
13 files changed, 351 insertions(+), 52 deletions(-)
diff --git a/src/apis.js b/src/apis.js
index 590d837..c515e0e 100644
--- a/src/apis.js
+++ b/src/apis.js
@@ -23,7 +23,9 @@ try {
console.error("获取环境信息失败,使用默认正式环境", e);
}
-function request(method, url, data = {}) {
+const ADDONS_BASE_URL = BASE_URL.replace(/\/api\/shoot$/, "/api/shoot");
+
+function request(method, url, data = {}, baseUrl = BASE_URL) {
const token = uni.getStorageSync(
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`
);
@@ -31,7 +33,7 @@ function request(method, url, data = {}) {
if (token) header.Authorization = `Bearer ${token || ""}`;
return new Promise((resolve, reject) => {
uni.request({
- url: `${BASE_URL}${url}`,
+ url: `${baseUrl}${url}`,
method,
header,
data,
@@ -41,6 +43,7 @@ function request(method, url, data = {}) {
const {code, data, message} = res.data;
if (code === 0) resolve(data);
else if (message) {
+ const error = {code, data, message};
if (message.indexOf("登录身份已失效") !== -1) {
console.log('1111111111111111111,token失效')
uni.removeStorageSync(
@@ -50,6 +53,10 @@ function request(method, url, data = {}) {
reject({ type: "AUTH_INVALID", message });
return;
}
+ if (message.indexOf("已达上限") !== -1) {
+ reject(error);
+ return;
+ }
if (message === "ROOM_FULL") {
resolve({full: true});
return;
@@ -88,8 +95,10 @@ function request(method, url, data = {}) {
title: message,
icon: "none",
});
+ reject(error);
+ return;
}
- reject("");
+ reject({code, data, message});
}
},
fail: (err) => {
@@ -158,6 +167,10 @@ export const getAppConfig = () => {
return request("GET", "/index/appConfig");
};
+export const getDailyCountAPI = () => {
+ return request("GET", "/index/dailyCount", {}, ADDONS_BASE_URL);
+};
+
export const getHomeData = (seasonId) => {
return request("GET", `/user/myHome?seasonId=${seasonId}`);
};
diff --git a/src/canvas.js b/src/canvas.js
index e5e41f4..7c5b66b 100644
--- a/src/canvas.js
+++ b/src/canvas.js
@@ -456,23 +456,29 @@ export const generateShareImage = async (canvasId, data) => {
// 2D 即时绘制,无需 ctx.draw()
} catch (e) {
console.error("generateShareImage 绘制失败:", e);
+ throw e;
}
};
// 顶部导入与工具方法
async function getCanvas2DContext(canvasId, targetWidth, targetHeight) {
- return new Promise((resolve) => {
+ return new Promise((resolve, reject) => {
const query = uni.createSelectorQuery();
query
.select(`#${canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
- const { node: canvas } = res[0] || {};
+ const canvasInfo = res && res[0];
+ const { node: canvas } = canvasInfo || {};
+ if (!canvas || typeof canvas.getContext !== "function") {
+ reject(new Error(`canvas ${canvasId} not found`));
+ return;
+ }
const ctx = canvas.getContext("2d");
const dpr = uni.getSystemInfoSync().pixelRatio || 1;
- const w = targetWidth || res[0].width;
- const h = targetHeight || res[0].height;
+ const w = targetWidth || canvasInfo.width;
+ const h = targetHeight || canvasInfo.height;
canvas.width = w * dpr;
canvas.height = h * dpr;
@@ -561,6 +567,7 @@ export const sharePointData = async (canvasId, data) => {
// 2D 即时绘制,无需 ctx.draw()
} catch (e) {
console.error("generateShareImage 绘制失败:", e);
+ throw e;
}
};
@@ -778,6 +785,7 @@ export async function sharePractiseData(canvasId, type, user, data) {
// 2D 模式下无需 ctx.draw()
} catch (err) {
console.log(err);
+ throw err;
}
}
diff --git a/src/pages/battle-room.vue b/src/pages/battle-room.vue
index 0449663..2ae2dc3 100644
--- a/src/pages/battle-room.vue
+++ b/src/pages/battle-room.vue
@@ -7,6 +7,7 @@ import GuideTwo from "@/components/GuideTwo.vue";
import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue";
import ScreenHint from "@/components/ScreenHint.vue";
+import ModalDialog from "@/components/ModalDialog.vue";
import {
getRoomAPI,
exitRoomAPI,
@@ -14,6 +15,7 @@ import {
getReadyAPI,
kickPlayerAPI,
} from "@/apis";
+import { isLimitError } from "@/util";
import { MESSAGETYPES, MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
@@ -56,6 +58,7 @@ const ready = ref(false);
const allReady = ref(false);
const timer = ref(null);
const goBattle = ref(false);
+const showLimitModal = ref(false);
/** 从结算页返回时为 true,跳过进场靶纸语音 */
const skipTargetAudio = ref(false);
@@ -137,7 +140,26 @@ async function refreshRoomData() {
}
const getReady = async () => {
- await getReadyAPI(roomNumber.value);
+ try {
+ await getReadyAPI(roomNumber.value);
+ } catch (error) {
+ if (isLimitError(error)) {
+ showLimitModal.value = true;
+ return;
+ }
+ console.log("room ready error", error);
+ }
+};
+
+const closeLimitModal = () => {
+ showLimitModal.value = false;
+};
+
+const goVipPage = () => {
+ showLimitModal.value = false;
+ uni.navigateTo({
+ url: "/pages/member/be-vip",
+ });
};
const refreshMembers = (members = []) => {
@@ -456,6 +478,14 @@ onBeforeUnmount(() => {
+
diff --git a/src/pages/first-try.vue b/src/pages/first-try.vue
index 8201644..cc40e37 100644
--- a/src/pages/first-try.vue
+++ b/src/pages/first-try.vue
@@ -48,6 +48,7 @@ const practiseId = ref("");
const showGuide = ref(false);
const laserActive = ref(false);
const guideSwiperIndex = ref(0);
+const sharing = ref(false);
const guideImages = [
"https://static.shelingxingqiu.com/shootmini/static/target.png",
@@ -139,8 +140,19 @@ async function onReceiveMessage(msg) {
}
const onClickShare = debounce(async () => {
- await sharePractiseData("shareCanvas", 1, user.value, practiseResult.value);
- await wxShare("shareCanvas");
+ if (sharing.value) return;
+ sharing.value = true;
+ try {
+ await sharePractiseData("shareCanvas", 1, user.value, practiseResult.value);
+ await wxShare("shareCanvas");
+ } catch (e) {
+ uni.showToast({
+ title: "海报生成失败,请稍后重试",
+ icon: "none",
+ });
+ } finally {
+ sharing.value = false;
+ }
});
onMounted(() => {
diff --git a/src/pages/friend-battle.vue b/src/pages/friend-battle.vue
index de326a8..fd53ad6 100644
--- a/src/pages/friend-battle.vue
+++ b/src/pages/friend-battle.vue
@@ -8,14 +8,16 @@ import SModal from "@/components/SModal.vue";
import Signin from "@/components/Signin.vue";
import CreateRoom from "@/components/CreateRoom.vue";
import Avatar from "@/components/Avatar.vue";
+import ModalDialog from "@/components/ModalDialog.vue";
-import { getRoomAPI, joinRoomAPI, getBattleDataAPI } from "@/apis";
-import { debounce, canEenter } from "@/util";
+import { getRoomAPI, joinRoomAPI, getBattleDataAPI, getDailyCountAPI } from "@/apis";
+import { debounce, canEenter, getLimitCountText, isLimitReached } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
-const { user, device, online, game } = storeToRefs(store);
+const { user, device, online, game, dailyCount } = storeToRefs(store);
+const { updateDailyCount } = store;
const showModal = ref(false);
const showSignin = ref(false);
@@ -24,8 +26,12 @@ const roomNumber = ref("");
const data = ref({});
const roomID = ref("");
const loading = ref(false);
+const showLimitModal = ref(false);
const isSVip = computed(() => user.value.sVip === true);
const isVip = computed(() => user.value.vip === true && !isSVip.value);
+const challengeLimitText = computed(() =>
+ getLimitCountText("约战", dailyCount.value.challenge)
+);
const enterRoom = debounce(async (number) => {
if (loading.value) return;
@@ -67,9 +73,37 @@ const enterRoom = debounce(async (number) => {
});
const onCreateRoom = async () => {
if (!canEenter(user.value, device.value, online.value)) return;
+ const countData = await loadDailyCount();
+ if (isLimitReached(countData.challenge)) {
+ showLimitModal.value = true;
+ return;
+ }
warnning.value = "";
showModal.value = true;
};
+
+const closeLimitModal = () => {
+ showLimitModal.value = false;
+};
+
+const goVipPage = () => {
+ showLimitModal.value = false;
+ uni.navigateTo({
+ url: "/pages/member/be-vip",
+ });
+};
+
+const loadDailyCount = async () => {
+ if (!user.value.id) return dailyCount.value;
+ try {
+ const result = await getDailyCountAPI();
+ updateDailyCount(result);
+ return result || dailyCount.value;
+ } catch (error) {
+ console.log("load daily count error", error);
+ return dailyCount.value;
+ }
+};
const onSignin = () => {
if (roomID.value && user.value.id) enterRoom(roomID.value);
showSignin.value = false;
@@ -83,7 +117,10 @@ const goMyRecord = () => {
};
onShow(async () => {
if (user.value.id) {
- const result = await getBattleDataAPI();
+ const [result] = await Promise.all([
+ getBattleDataAPI(),
+ loadDailyCount(),
+ ]);
data.value = result;
}
});
@@ -168,8 +205,8 @@ onLoad(async (options) => {
-
-
+
+ {{ challengeLimitText }}
创建约战房
@@ -186,6 +223,14 @@ onLoad(async (options) => {
+