update:对接会员限制次数
This commit is contained in:
@@ -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(() => {
|
||||
</view>
|
||||
</view>
|
||||
</Container>
|
||||
<ModalDialog
|
||||
:show="showLimitModal"
|
||||
:content="'今日约战次数已经用完\n开通会员可增加次数'"
|
||||
cancelText="知道了"
|
||||
confirmText="去开通"
|
||||
:onCancel="closeLimitModal"
|
||||
:onConfirm="goVipPage"
|
||||
/>
|
||||
<!-- 踢出玩家二次确认弹窗(不传 onClose,屏蔽 X 关闭按钮) -->
|
||||
<ScreenHint :show="showKickConfirm">
|
||||
<view class="kick-confirm">
|
||||
|
||||
+14
-2
@@ -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(() => {
|
||||
|
||||
@@ -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) => {
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<view class="pp-text">
|
||||
<!-- 今日约战次数:2/2 -->
|
||||
<view v-if="challengeLimitText" class="pp-text">
|
||||
{{ challengeLimitText }}
|
||||
</view>
|
||||
<SButton width="80%" :rounded="30" :onClick="() => $clickSound(onCreateRoom)">
|
||||
创建约战房
|
||||
@@ -186,6 +223,14 @@ onLoad(async (options) => {
|
||||
<Signin :show="showSignin" :onClose="onSignin" />
|
||||
</view>
|
||||
</Container>
|
||||
<ModalDialog
|
||||
:show="showLimitModal"
|
||||
:content="'今日约战次数已经用完\n开通会员可增加次数'"
|
||||
cancelText="知道了"
|
||||
confirmText="去开通"
|
||||
:onCancel="closeLimitModal"
|
||||
:onConfirm="goVipPage"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -3,12 +3,15 @@ import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import Container from "@/components/Container.vue";
|
||||
import Matching from "@/components/Matching.vue";
|
||||
import ModalDialog from "@/components/ModalDialog.vue";
|
||||
import { matchGameAPI, getBattleAPI } from "@/apis";
|
||||
import { MESSAGETYPESV2 } from "@/constants";
|
||||
import { isLimitError } from "@/util";
|
||||
|
||||
const gameType = ref(0);
|
||||
const teamSize = ref(0);
|
||||
const onComplete = ref(null);
|
||||
const showLimitModal = ref(false);
|
||||
|
||||
/** 匹配超时计时器,用于检测 WS 消息丢失或真正超时 */
|
||||
const matchTimeoutTimer = ref(null);
|
||||
@@ -58,6 +61,18 @@ async function stopMatch() {
|
||||
uni.$showHint(3);
|
||||
}
|
||||
|
||||
const closeLimitModal = () => {
|
||||
showLimitModal.value = false;
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const goVipPage = () => {
|
||||
showLimitModal.value = false;
|
||||
uni.redirectTo({
|
||||
url: "/pages/member/be-vip",
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 取消匹配,带容错处理:
|
||||
* - 取消成功 → 返回大厅
|
||||
@@ -136,10 +151,19 @@ onBeforeUnmount(() => {
|
||||
|
||||
onShow(async () => {
|
||||
if (gameType.value && teamSize.value) {
|
||||
matchGameAPI(true, gameType.value, teamSize.value);
|
||||
// 启动超时计时器,防止 WS 消息丢失或长时间无对手导致用户卡死
|
||||
clearMatchTimeout();
|
||||
matchTimeoutTimer.value = setTimeout(handleMatchTimeout, MATCH_TIMEOUT_MS);
|
||||
try {
|
||||
await matchGameAPI(true, gameType.value, teamSize.value);
|
||||
// 启动超时计时器,防止 WS 消息丢失或长时间无对手导致用户卡死
|
||||
clearMatchTimeout();
|
||||
matchTimeoutTimer.value = setTimeout(handleMatchTimeout, MATCH_TIMEOUT_MS);
|
||||
} catch (error) {
|
||||
clearMatchTimeout();
|
||||
if (isLimitError(error)) {
|
||||
showLimitModal.value = true;
|
||||
return;
|
||||
}
|
||||
uni.navigateBack();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -154,6 +178,14 @@ onHide(() => {
|
||||
<Matching :stopMatch="stopMatch" :onComplete="onComplete" />
|
||||
</view>
|
||||
</Container>
|
||||
<ModalDialog
|
||||
:show="showLimitModal"
|
||||
:content="'今日排位赛次数已经用完\n开通会员可增加次数'"
|
||||
cancelText="知道了"
|
||||
confirmText="去开通"
|
||||
:onCancel="closeLimitModal"
|
||||
:onConfirm="goVipPage"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -81,9 +81,17 @@ const loading = ref(false);
|
||||
const shareImage = async () => {
|
||||
if (loading.value) return;
|
||||
loading.value = true;
|
||||
await generateShareImage("shareImageCanvas", record.value);
|
||||
await wxShare("shareImageCanvas");
|
||||
loading.value = false;
|
||||
try {
|
||||
await generateShareImage("shareImageCanvas", record.value);
|
||||
await wxShare("shareImageCanvas");
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: "海报生成失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onLoad(async (options) => {
|
||||
|
||||
@@ -15,11 +15,22 @@ const list = ref([]);
|
||||
const mine = ref({
|
||||
averageRing: 0,
|
||||
});
|
||||
const sharing = ref(false);
|
||||
|
||||
const shareImage = async () => {
|
||||
if (!mine.value.id) return;
|
||||
await sharePointData("shareCanvas", mine.value);
|
||||
await wxShare("shareCanvas");
|
||||
if (!mine.value.id || sharing.value) return;
|
||||
sharing.value = true;
|
||||
try {
|
||||
await sharePointData("shareCanvas", mine.value);
|
||||
await wxShare("shareCanvas");
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: "海报生成失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
} finally {
|
||||
sharing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
@@ -39,6 +39,7 @@ const practiseId = ref("");
|
||||
const showGuide = ref(false);
|
||||
const tips = ref("");
|
||||
const targetType = ref(1);
|
||||
const sharing = ref(false);
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.target) {
|
||||
@@ -112,8 +113,19 @@ async function onComplete() {
|
||||
}
|
||||
|
||||
const onClickShare = debounce(async () => {
|
||||
await sharePractiseData("shareCanvas", 2, user.value, practiseResult.value);
|
||||
await wxShare("shareCanvas");
|
||||
if (sharing.value) return;
|
||||
sharing.value = true;
|
||||
try {
|
||||
await sharePractiseData("shareCanvas", 2, user.value, practiseResult.value);
|
||||
await wxShare("shareCanvas");
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: "海报生成失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
} finally {
|
||||
sharing.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
function onAudioEnded(s) {
|
||||
|
||||
@@ -38,6 +38,7 @@ const practiseResult = ref({});
|
||||
const practiseId = ref("");
|
||||
const showGuide = ref(false);
|
||||
const targetType = ref(1);
|
||||
const sharing = ref(false);
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.target) {
|
||||
@@ -127,8 +128,19 @@ async function onComplete() {
|
||||
}
|
||||
|
||||
const onClickShare = debounce(async () => {
|
||||
await sharePractiseData("shareCanvas", 3, user.value, practiseResult.value);
|
||||
await wxShare("shareCanvas");
|
||||
if (sharing.value) return;
|
||||
sharing.value = true;
|
||||
try {
|
||||
await sharePractiseData("shareCanvas", 3, user.value, practiseResult.value);
|
||||
await wxShare("shareCanvas");
|
||||
} catch (e) {
|
||||
uni.showToast({
|
||||
title: "海报生成失败,请稍后重试",
|
||||
icon: "none",
|
||||
});
|
||||
} finally {
|
||||
sharing.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
|
||||
+51
-6
@@ -3,21 +3,23 @@ import { computed, ref } from "vue";
|
||||
import { onShow } from "@dcloudio/uni-app";
|
||||
import Container from "@/components/Container.vue";
|
||||
import Avatar from "@/components/Avatar.vue";
|
||||
import ModalDialog from "@/components/ModalDialog.vue";
|
||||
import { topThreeColors } from "@/constants";
|
||||
import {
|
||||
getDailyCountAPI,
|
||||
getSeasonList,
|
||||
getSeasonStats,
|
||||
getScoreRankList,
|
||||
getTenRingRankList,
|
||||
getMvpRankList,
|
||||
} from "@/apis";
|
||||
import { canEenter } from "@/util";
|
||||
import { canEenter, getLimitCountText, isLimitReached } from "@/util";
|
||||
import useStore from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
const store = useStore();
|
||||
const { user, device, online, game } = storeToRefs(store);
|
||||
const { getLvlName } = store;
|
||||
const { user, device, online, game, dailyCount } = storeToRefs(store);
|
||||
const { getLvlName, updateDailyCount } = store;
|
||||
|
||||
const defaultSeasonStats = {
|
||||
nickName: "",
|
||||
@@ -55,8 +57,12 @@ const rankLoading = ref(false);
|
||||
const scoreRankList = ref([]);
|
||||
const mvpRankList = ref([]);
|
||||
const tenRingRankList = ref([]);
|
||||
const showLimitModal = ref(false);
|
||||
const isSVip = computed(() => user.value.sVip === true);
|
||||
const isVip = computed(() => user.value.vip === true && !isSVip.value);
|
||||
const rankedLimitText = computed(() =>
|
||||
getLimitCountText("排位", dailyCount.value.ranked)
|
||||
);
|
||||
|
||||
const isMember = (item = {}) => item.vip === true || item.sVip === true;
|
||||
|
||||
@@ -115,12 +121,40 @@ const toMatchPage = async (gameType, teamSize) => {
|
||||
uni.$showHint(1);
|
||||
return;
|
||||
}
|
||||
const countData = await loadDailyCount();
|
||||
if (isLimitReached(countData.ranked)) {
|
||||
showLimitModal.value = true;
|
||||
return;
|
||||
}
|
||||
await uni.$checkAudio();
|
||||
uni.navigateTo({
|
||||
url: `/pages/match-page?gameType=${gameType}&teamSize=${teamSize}`,
|
||||
});
|
||||
};
|
||||
|
||||
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 toMyGrowthPage = () => {
|
||||
uni.navigateTo({
|
||||
url: "/pages/my-growth",
|
||||
@@ -246,7 +280,10 @@ const onChangeSeason = async (seasonId, name) => {
|
||||
// 页面显示时先拿赛季列表,再拉当前赛季统计和默认榜单数据。
|
||||
onShow(async () => {
|
||||
try {
|
||||
const seasonResult = await getSeasonList();
|
||||
const [seasonResult] = await Promise.all([
|
||||
getSeasonList(),
|
||||
loadDailyCount(),
|
||||
]);
|
||||
seasonData.value = seasonResult.list || [];
|
||||
|
||||
if (!seasonData.value.length) {
|
||||
@@ -283,12 +320,12 @@ onShow(async () => {
|
||||
|
||||
<template>
|
||||
<Container
|
||||
:title="'排位赛'"
|
||||
:title="rankedLimitText ? rankedLimitText : '排位赛'"
|
||||
:titleStyle="rankedLimitText ? { fontSize: '24rpx', fontWeight: 'normal' } : {}"
|
||||
:showBackToGame="true"
|
||||
:bgType="6"
|
||||
>
|
||||
<view class="battle-types-box">
|
||||
<!-- :title="'今日排位次数:2/2'" :titleStyle="{ fontSize: '24rpx', fontWeight: 'normal' }" -->
|
||||
<view class="battle-types">
|
||||
<view class="first">
|
||||
<image src="../static/rank/battle-choose.png" mode="widthFix" />
|
||||
@@ -585,6 +622,14 @@ onShow(async () => {
|
||||
</view>
|
||||
</view>
|
||||
</Container>
|
||||
<ModalDialog
|
||||
:show="showLimitModal"
|
||||
:content="'今日排位赛次数已经用完\n开通会员可增加次数'"
|
||||
cancelText="知道了"
|
||||
confirmText="去开通"
|
||||
:onCancel="closeLimitModal"
|
||||
:onConfirm="goVipPage"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user