diff --git a/.gitignore b/.gitignore index 1923370..c91affc 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,7 @@ node_modules .github openspec CLAUDE.md -dosc +docs .DS_Store dist *.local diff --git a/package.json b/package.json index 090bdd0..a50c6be 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "@dcloudio/uni-quickapp-webview": "3.0.0-4060620250520001", "@dcloudio/uni-ui": "^1.5.11", "pinia": "2.0.36", + "pinia-plugin-persistedstate": "3.2.1", "vue": "^3.4.21", "vue-i18n": "^9.1.9" }, diff --git a/src/App.vue b/src/App.vue index 751b9d6..c852548 100644 --- a/src/App.vue +++ b/src/App.vue @@ -21,7 +21,8 @@ } = storeToRefs(store); const { updateUser, - updateOnline + updateOnline, + clearSessionState } = store; watch( @@ -46,6 +47,17 @@ updateUser(value); } + function onSessionKickedOut() { + const env = uni.getAccountInfoSync().miniProgram.envVersion; + uni.removeStorageSync(`${env}_token`); + clearSessionState(); + uni.showModal({ + title: "提示", + content: "账号已在其他设备登录", + showCancel: false, + }); + } + async function emitUpdateOnline() { const data = await getDeviceBatteryAPI(); updateOnline(data.online); @@ -65,6 +77,7 @@ onShow(() => { uni.$on("update-user", emitUpdateUser); uni.$on("update-online", emitUpdateOnline); + uni.$on("session-kicked-out", onSessionKickedOut); const token = uni.getStorageSync( `${uni.getAccountInfoSync().miniProgram.envVersion}_token` ); @@ -77,6 +90,7 @@ onHide(() => { uni.$off("update-user", emitUpdateUser); uni.$off("update-online", emitUpdateOnline); + uni.$off("session-kicked-out", onSessionKickedOut); websocket.closeWebSocket(); }); @@ -289,4 +303,4 @@ font-style: normal; font-display: swap; } - \ No newline at end of file + diff --git a/src/apis.js b/src/apis.js index 8431626..f980cc0 100644 --- a/src/apis.js +++ b/src/apis.js @@ -6,7 +6,7 @@ try { switch (envVersion) { case "develop": // 开发版 - // BASE_URL = "http://localhost:8000/api/shoot"; + // BASE_URL = "http://192.168.1.30:8000/api/shoot"; BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot"; break; case "trial": // 体验版 @@ -42,10 +42,13 @@ function request(method, url, data = {}) { if (code === 0) resolve(data); else if (message) { if (message.indexOf("登录身份已失效") !== -1) { + console.log('1111111111111111111,token失效') uni.removeStorageSync( `${uni.getAccountInfoSync().miniProgram.envVersion}_token` ); uni.$emit("update-user"); + reject({ type: "AUTH_INVALID", message }); + return; } if (message === "ROOM_FULL") { resolve({full: true}); diff --git a/src/audioManager.js b/src/audioManager.js index 1e7239e..a0f55bb 100644 --- a/src/audioManager.js +++ b/src/audioManager.js @@ -1,4 +1,11 @@ +export const AUDIO_INTERRUPTION_BEGIN_EVENT = "audio-interruption-begin"; +export const AUDIO_INTERRUPTION_END_EVENT = "audio-interruption-end"; + export const audioFils = { + tententen: "https://static.shelingxingqiu.com/shootmini/static/audio/tententen.mp3", + 点击按钮: "https://static.shelingxingqiu.com/shootmini/static/audio/%E7%82%B9%E5%87%BB%E6%8C%89%E9%92%AE.mp3", + "20CM全环靶": "https://static.shelingxingqiu.com/shootmini/static/audio/20CM%E5%85%A8%E7%8E%AF%E9%9D%B6-%E6%97%A0%E6%95%88.mp3", + "40CM全环靶": "https://static.shelingxingqiu.com/shootmini/static/audio/40CM%E5%85%A8%E7%8E%AF%E9%9D%B6-%E6%97%A0%E6%95%88.mp3", // 激光已校准: // "https://static.shelingxingqiu.com/attachment/2025-10-29/ddupaur1vdkyhzaqdc.mp3", 胜利: "https://static.shelingxingqiu.com/attachment/2025-09-17/dcuo9yjp0kt5msvmvd.mp3", @@ -36,7 +43,7 @@ export const audioFils = { 请开始射击: "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutzdrl5u0iromqhf.mp3", 射击无效: - "https://static.shelingxingqiu.com/attachment/2025-09-17/dcutya55ufiiw8oo55.mp3", + "https://static.shelingxingqiu.com/shootmini/static/audio/%E5%B0%84%E7%AE%AD%E6%97%A0%E6%95%88%E6%A3%80%E6%9F%A5%E8%B7%9D%E7%A6%BB%E5%92%8C%E9%9D%B6%E7%BA%B8.mp3", 未上靶: "https://static.shelingxingqiu.com/attachment/2025-11-12/de6n45o3tsm1v4unam.mp3", "1环": @@ -93,7 +100,7 @@ function debugLog(...args) { const envVersion = accountInfo.miniProgram.envVersion; // 只在体验版打印日志,正式版(release)和开发版(develop)不打印 - if (envVersion === "trial") { + if (envVersion === "trial" || envVersion === "develop") { console.log(...args); } } @@ -123,6 +130,7 @@ class AudioManager { // 防重复播放保护 this.lastPlayKey = null; this.lastPlayAt = 0; + this.isInterrupted = false; // 静音开关 this.isMuted = false; @@ -137,10 +145,41 @@ class AudioManager { this.localFileCache = uni.getStorageSync("audio_local_files") || {}; // 启动时自动清理过期的缓存文件(URL 已不在 audioFils 中的文件) this.cleanObsoleteCache(); + this.bindAudioInterruptionEvents(); this.initAudios(); } + bindAudioInterruptionEvents() { + if (this._audioInterruptionBound) return; + this._audioInterruptionBound = true; + + const begin = () => { + if (this.isInterrupted) return; + this.isInterrupted = true; + this.stopAll(); + this.isSequenceRunning = false; + this.sequenceQueue = []; + this.sequenceIndex = 0; + this.pendingPlayKey = null; + uni.$emit(AUDIO_INTERRUPTION_BEGIN_EVENT); + }; + + const end = () => { + if (!this.isInterrupted) return; + this.isInterrupted = false; + uni.$emit(AUDIO_INTERRUPTION_END_EVENT); + void this.reloadAll(); + }; + + if (typeof uni?.onAudioInterruptionBegin === "function") { + uni.onAudioInterruptionBegin(begin); + } + if (typeof uni?.onAudioInterruptionEnd === "function") { + uni.onAudioInterruptionEnd(end); + } + } + // 清理不再使用的缓存文件 cleanObsoleteCache() { const activeUrls = new Set(Object.values(audioFils)); @@ -457,6 +496,10 @@ class AudioManager { // 播放指定音频或音频数组(数组则按顺序连续播放) play(input, interrupt = true) { + if (this.isInterrupted) { + debugLog("音频处理中断状态,忽略播放请求"); + return; + } // 统一规范化为队列 let queue = []; if (Array.isArray(input)) { @@ -510,6 +553,10 @@ class AudioManager { // 内部方法:播放单个 key _playSingle(key, forceStopAll = false) { + if (this.isInterrupted) { + debugLog(`音频处理中断状态,跳过播放: ${key}`); + return; + } // 200ms 内的同 key 重复播放直接忽略,避免“比比赛开始”这类重复首音 const now = Date.now(); if (this.lastPlayKey === key && now - this.lastPlayAt < 250) { @@ -553,7 +600,13 @@ class AudioManager { // 显式授权播放并立即播放 this.allowPlayMap.set(key, true); - audio.play(); + try { + audio.play(); + } catch (err) { + this.allowPlayMap.set(key, false); + debugLog(`音频 ${key} 播放调用失败`, err?.errMsg || err); + return; + } this.currentPlayingKey = key; this.lastPlayKey = key; this.lastPlayAt = Date.now(); diff --git a/src/components/AppFooter.vue b/src/components/AppFooter.vue index 3a44260..05f2ebe 100644 --- a/src/components/AppFooter.vue +++ b/src/components/AppFooter.vue @@ -31,7 +31,7 @@ function handleTabClick(index) { v-for="(tab, index) in tabs" :key="index" class="tab-item" - @click="handleTabClick(index)" + @click="$clickSound(() => handleTabClick(index))" :style="{ width: index === 1 ? '36%' : '20%', }" diff --git a/src/components/BackToGame.vue b/src/components/BackToGame.vue index 9319c21..b5a509c 100644 --- a/src/components/BackToGame.vue +++ b/src/components/BackToGame.vue @@ -19,8 +19,12 @@ const props = defineProps({ }); const loading = ref(false); +/** 统一获取当前环境 token,用于守卫:无有效 token 时不发起接口请求 */ +const getToken = () => + uni.getStorageSync(`${uni.getAccountInfoSync().miniProgram.envVersion}_token`); + onShow(async () => { - if (user.value.id) { + if (user.value.id && getToken()) { setTimeout(async () => { const state = await getUserGameState(); updateGame(state.gaming, state.roomId); @@ -33,7 +37,8 @@ watch( async (value) => { if (!value.id) { updateGame(false, ""); - } else { + } else if (getToken()) { + // 有有效 token 时才查询在局状态,避免 token 失效时反复发起无效请求 const state = await getUserGameState(); updateGame(state.gaming, state.roomId); } @@ -49,7 +54,7 @@ const onClick = debounce(async () => { await uni.$checkAudio(); if (result.mode <= 3) { uni.navigateTo({ - url: `/pages/team-battle?battleId=${result.matchId}`, + url: `/pages/team-battle/index?battleId=${result.matchId}`, }); } else { uni.navigateTo({ diff --git a/src/components/BattleHeader.vue b/src/components/BattleHeader.vue index b7b3716..b12d84f 100644 --- a/src/components/BattleHeader.vue +++ b/src/components/BattleHeader.vue @@ -80,28 +80,35 @@ defineProps({ /> - + + + - - - {{ player.name }} + + + + {{ player.name }} + - + @@ -144,17 +151,21 @@ defineProps({ justify-content: center; } .players-melee { - display: flex; height: 80px; width: 100%; - overflow-x: auto; } .players-melee::-webkit-scrollbar { width: 0; height: 0; color: transparent; } -.players-melee > view { +/* 小程序 scroll-view 不支持直接 flex,通过内层 wrapper 承载横向排列 */ +.players-melee-inner { + display: flex; + height: 100%; + flex-wrap: nowrap; +} +.players-melee-inner > view { display: flex; flex-direction: column; align-items: center; diff --git a/src/components/BowTarget.vue b/src/components/BowTarget.vue index b1e6c5c..79ee41d 100644 --- a/src/components/BowTarget.vue +++ b/src/components/BowTarget.vue @@ -34,6 +34,18 @@ const props = defineProps({ type: Boolean, default: false, }, + targetRadius: { + type: Number, + default: 20, + }, + hitRadiusPx: { + type: Number, + default: 2, + }, + zoomHitRadiusPx: { + type: Number, + default: 5, + }, }); const pMode = ref(true); @@ -80,13 +92,79 @@ watch( } ); -function calcRealX(num, offset = 3.4) { - const len = 20.4 + num; - return `calc(${(len / 40.8) * 100 - offset / 2}%)`; +const safeTargetRadius = computed(() => { + const radius = Number(props.targetRadius); + return Number.isFinite(radius) && radius > 0 ? radius : 20; +}); + +const currentHitRadiusPx = computed(() => { + const radius = Number( + pMode.value ? props.zoomHitRadiusPx : props.hitRadiusPx + ); + return Number.isFinite(radius) && radius >= 0 ? radius : 0; +}); + +function getShotPoint(shot, fallbackCenter = false) { + const x = Number(shot?.x); + const y = Number(shot?.y); + if (Number.isFinite(x) && Number.isFinite(y)) return { x, y }; + return fallbackCenter ? { x: 0, y: 0 } : null; } -function calcRealY(num, offset = 3.4) { - const len = num < 0 ? Math.abs(num) + 20.4 : 20.4 - num; - return `calc(${(len / 40.8) * 100 - offset / 2}%)`; + +function getPointDirection(point) { + if (!point) return null; + const distance = Math.sqrt(point.x * point.x + point.y * point.y); + if (distance === 0) return null; + + return { + x: point.x / distance, + y: point.y / distance, + }; +} + +function formatPxOffset(value) { + if (!value) return ""; + const operator = value > 0 ? "+" : "-"; + return ` ${operator} ${Math.abs(value)}px`; +} + +function formatTargetPosition(percent, offset) { + const pxOffset = formatPxOffset(offset); + return pxOffset ? `calc(${percent}%${pxOffset})` : `${percent}%`; +} + +function getTargetPositionStyle(point, offsetPx = 0) { + if (!point) return { display: "none" }; + + const radius = safeTargetRadius.value; + const diameter = radius * 2; + const direction = getPointDirection(point); + const xOffset = direction ? direction.x * offsetPx : 0; + const yOffset = direction ? -direction.y * offsetPx : 0; + const leftPercent = ((point.x + radius) / diameter) * 100; + const topPercent = ((radius - point.y) / diameter) * 100; + + return { + left: formatTargetPosition(leftPercent, xOffset), + top: formatTargetPosition(topPercent, yOffset), + transform: "translate(-50%, -50%)", + }; +} + +function getHitStyle(shot) { + const radius = currentHitRadiusPx.value; + const point = getShotPoint(shot); + + return { + ...getTargetPositionStyle(point, radius), + width: `${radius * 2}px`, + height: `${radius * 2}px`, + }; +} + +function getTipStyle(shot) { + const point = getShotPoint(shot, true); + return getTargetPositionStyle(point, shot?.ring ? currentHitRadiusPx.value : 0); } const simulShoot = async () => { if (device.value.deviceId) await simulShootAPI(device.value.deviceId); @@ -169,20 +247,14 @@ onBeforeUnmount(() => { 经验 +1 {{ latestOne.ringX ? "X" : latestOne.ring || "未上靶" }} @@ -193,20 +265,14 @@ onBeforeUnmount(() => { user.id === bluelatestOne.playerId " class="e-value fade-in-out" - :style="{ - left: calcRealX(bluelatestOne.ring ? bluelatestOne.x : 0, 20), - top: calcRealY(bluelatestOne.ring ? bluelatestOne.y : 0, 40), - }" + :style="getTipStyle(bluelatestOne)" > 经验 +1 {{ bluelatestOne.ringX ? "X" : bluelatestOne.ring || "未上靶" }} @@ -217,8 +283,7 @@ onBeforeUnmount(() => { index === scores.length - 1 && latestOne ? 'pump-in' : '' }`" :style="{ - left: calcRealX(bow.x, pMode ? '3.4' : '2'), - top: calcRealY(bow.y, pMode ? '3.4' : '2'), + ...getHitStyle(bow), backgroundColor: mode === 'solo' ? '#00bf04' : '#FF0000', }" >{{ index + 1 }} { index === blueScores.length - 1 && bluelatestOne ? 'pump-in' : '' }`" :style="{ - left: calcRealX(bow.x, pMode ? '3.4' : '2'), - top: calcRealY(bow.y, pMode ? '3.4' : '2'), + ...getHitStyle(bow), backgroundColor: '#1840FF', }" > @@ -302,21 +366,11 @@ onBeforeUnmount(() => { z-index: 1; color: #fff; transition: all 0.3s ease; -} -.s-point { - width: 4px; - height: 4px; - min-width: 4px; - min-height: 4px; + box-sizing: border-box; } .b-point { - width: 10px; - height: 10px; - min-width: 10px; - min-height: 10px; border: 1px solid #fff; z-index: 1; - box-sizing: border-box; display: flex; justify-content: center; align-items: center; @@ -332,6 +386,19 @@ onBeforeUnmount(() => { transform: translate(-50%, -50%);*/ margin-top: 2rpx; } +@keyframes target-pump-in { + from { + transform: translate(-50%, -50%) scale(2); + } + + to { + transform: translate(-50%, -50%) scale(1); + } +} +.hit.pump-in { + animation: target-pump-in 0.3s ease-out forwards; + transform-origin: center center; +} .header { width: 100%; display: flex; diff --git a/src/components/Container.vue b/src/components/Container.vue index 109606a..36840f2 100644 --- a/src/components/Container.vue +++ b/src/components/Container.vue @@ -116,7 +116,7 @@ const backToGame = debounce(async () => { await checkAudioProgress(); if (result.mode <= 3) { uni.navigateTo({ - url: `/pages/team-battle?battleId=${result.matchId}`, + url: `/pages/team-battle/index?battleId=${result.matchId}`, }); } else { uni.navigateTo({ @@ -206,7 +206,7 @@ const goCalibration = async () => { - + diff --git a/src/components/CreateRoom.vue b/src/components/CreateRoom.vue index e34d7d7..e66dd22 100644 --- a/src/components/CreateRoom.vue +++ b/src/components/CreateRoom.vue @@ -17,12 +17,19 @@ const props = defineProps({ }, }); -const battleMode = ref(1); -const targetMode = ref(1); +/** 对战模式:0=未选 1=1v1 2=乱斗 3=2v2 4=3v3 */ +const battleMode = ref(0); +/** 靶纸尺寸:0=未选 1=20cm 2=40cm */ +const targetMode = ref(0); const loading = ref(false); const roomNumber = ref(""); const createRoom = debounce(async () => { + // 校验必填项:对战模式与靶纸均必须选择 + if (!battleMode.value || !targetMode.value) { + uni.showToast({ title: '请完善创建信息', icon: 'none' }); + return; + } if (game.value.inBattle) { uni.$showHint(1); return; @@ -105,7 +112,7 @@ const createRoom = debounce(async () => { 40厘米全环靶 - 创建房间 + 创建房间 diff --git a/src/components/GuideTwo.vue b/src/components/GuideTwo.vue index abe4c51..6d6cb63 100644 --- a/src/components/GuideTwo.vue +++ b/src/components/GuideTwo.vue @@ -9,12 +9,12 @@ defineProps({ @@ -134,11 +156,13 @@ onBeforeUnmount(() => { justify-content: center; font-weight: 500; } -.container > button:last-child { + +.container>button:last-child { width: 36px; height: 36px; } -.container > button:last-child > image { + +.container>button:last-child>image { width: 36px; min-height: 36px; } diff --git a/src/components/Matching.vue b/src/components/Matching.vue index c6c109a..f680c0f 100644 --- a/src/components/Matching.vue +++ b/src/components/Matching.vue @@ -123,7 +123,7 @@ onBeforeUnmount(() => { - + diff --git a/src/components/PlayerScore.vue b/src/components/PlayerScore.vue index 08931a6..54fea32 100644 --- a/src/components/PlayerScore.vue +++ b/src/components/PlayerScore.vue @@ -43,7 +43,7 @@ const rowCount = new Array(6).fill(0); {{ - scores[1] && scores[1][index] ? `${scores[0][index].ring}环` : "-" + scores[1] && scores[1][index] ? `${scores[1][index].ring}环` : "-" }} diff --git a/src/components/PlayerSeats.vue b/src/components/PlayerSeats.vue index cb4c14f..5ce4f2a 100644 --- a/src/components/PlayerSeats.vue +++ b/src/components/PlayerSeats.vue @@ -14,6 +14,11 @@ const props = defineProps({ type: Function, default: () => {}, }, + /** 当前用户是否为房主;仅房主可见踢人按钮 */ + isOwner: { + type: Boolean, + default: false, + }, }); const seats = new Array(props.total).fill(1); @@ -45,8 +50,9 @@ const seats = new Array(props.total).fill(1); mode="widthFix" class="player-bg" /> --> + @@ -384,10 +439,11 @@ onBeforeUnmount(() => { + + :removePlayer="removePlayer" :isOwner="owner.id === user.id" /> - + {{ allReady.value ? "即将进入对局..." @@ -818,4 +874,23 @@ onBeforeUnmount(() => { border: 1rpx solid #a3793f66; color: #fed847; } + +.guide-tips__target { + font-weight: 400; + font-size: 26rpx; + color: rgba(255, 217, 71, 0.8); +} + +.guide-tips__warn { + font-weight: 400; + font-size: 22rpx; + color: rgba(255, 255, 255, 0.8); + margin-top: 6rpx; +} + +.guide-tips { + display: flex; + flex-direction: column; + padding-left: 20rpx; +} diff --git a/src/pages/first-try.vue b/src/pages/first-try.vue index e33dc79..8201644 100644 --- a/src/pages/first-try.vue +++ b/src/pages/first-try.vue @@ -1,5 +1,5 @@ @@ -301,4 +375,43 @@ const onClose = async () => { width: calc(100% - 20px); margin: 0 10px; } +.calibration-container { + display: flex; + flex-direction: column; + align-items: center; +} +.calibration-guide { + display: flex; + flex-direction: column; + align-items: center; + font-size: 26rpx; + color: #ffffff; + margin-bottom: 15rpx; +} +.calibration-guide > view { + width: 100%; + margin: 25rpx 0; + display: flex; + align-items: center; +} +.calibration-guide > view > text:first-child { + font-size: 24rpx; + background: #e89024; + border-radius: 50%; + width: 32rpx; + height: 32rpx; + line-height: 32rpx; + display: block; + text-align: center; + margin-right: 15rpx; +} +.calibration-guide > image { + width: 630rpx; + height: 250rpx; +} +.calibration-container > text { + font-size: 24rpx; + color: #fff9; + margin: 30rpx; +} diff --git a/src/pages/friend-battle-result.vue b/src/pages/friend-battle-result.vue new file mode 100644 index 0000000..f231ce2 --- /dev/null +++ b/src/pages/friend-battle-result.vue @@ -0,0 +1,1101 @@ + + + + + diff --git a/src/pages/friend-battle.vue b/src/pages/friend-battle.vue index 3741aba..2cbdda1 100644 --- a/src/pages/friend-battle.vue +++ b/src/pages/friend-battle.vue @@ -98,8 +98,10 @@ onLoad(async (options) => { - 约上朋友开几局,欢乐多,不寂寞 - 一起练升级更快,早日加入全国排位赛! + + 约上朋友开几局,欢乐多,不寂寞 + 一起练升级更快,早日加入全国排位赛! + @@ -139,7 +141,7 @@ onLoad(async (options) => { - 进入房间 + 进入房间 @@ -153,7 +155,7 @@ onLoad(async (options) => { - + 创建约战房 @@ -162,7 +164,8 @@ onLoad(async (options) => { {{ warnning }} - + + @@ -170,6 +173,24 @@ onLoad(async (options) => { diff --git a/src/pages/my-device.vue b/src/pages/my-device.vue index 8ca7210..b4edcd9 100644 --- a/src/pages/my-device.vue +++ b/src/pages/my-device.vue @@ -130,7 +130,7 @@ onShow(() => { diff --git a/src/pages/point-book-edit.vue b/src/pages/point-book-edit.vue index 07a42ff..69f61aa 100644 --- a/src/pages/point-book-edit.vue +++ b/src/pages/point-book-edit.vue @@ -198,7 +198,7 @@ onLoad((options) => { diff --git a/src/pages/point-book.vue b/src/pages/point-book.vue index 7494f48..6722cb7 100644 --- a/src/pages/point-book.vue +++ b/src/pages/point-book.vue @@ -329,10 +329,10 @@ onShareTimeline(() => { - - diff --git a/src/pages/practise-one.vue b/src/pages/practise-one.vue index 9473cf6..a6cbcd3 100644 --- a/src/pages/practise-one.vue +++ b/src/pages/practise-one.vue @@ -1,5 +1,5 @@ + + + + diff --git a/src/pages/team-battle/components/Avatar.vue b/src/pages/team-battle/components/Avatar.vue new file mode 100644 index 0000000..c5ba5bb --- /dev/null +++ b/src/pages/team-battle/components/Avatar.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/src/pages/team-battle/components/BackToGame.vue b/src/pages/team-battle/components/BackToGame.vue new file mode 100644 index 0000000..748db2e --- /dev/null +++ b/src/pages/team-battle/components/BackToGame.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/src/pages/team-battle/components/BattleFooter.vue b/src/pages/team-battle/components/BattleFooter.vue new file mode 100644 index 0000000..c7c2442 --- /dev/null +++ b/src/pages/team-battle/components/BattleFooter.vue @@ -0,0 +1,203 @@ += + + + + + diff --git a/src/pages/team-battle/components/BattleHeader.vue b/src/pages/team-battle/components/BattleHeader.vue new file mode 100644 index 0000000..633d086 --- /dev/null +++ b/src/pages/team-battle/components/BattleHeader.vue @@ -0,0 +1,200 @@ + + + + + diff --git a/src/pages/team-battle/components/BowPower.vue b/src/pages/team-battle/components/BowPower.vue new file mode 100644 index 0000000..9153a2b --- /dev/null +++ b/src/pages/team-battle/components/BowPower.vue @@ -0,0 +1,40 @@ + + + + + diff --git a/src/pages/team-battle/components/BowTarget.vue b/src/pages/team-battle/components/BowTarget.vue new file mode 100644 index 0000000..c855fea --- /dev/null +++ b/src/pages/team-battle/components/BowTarget.vue @@ -0,0 +1,518 @@ + + + + + diff --git a/src/pages/team-battle/components/Container.vue b/src/pages/team-battle/components/Container.vue new file mode 100644 index 0000000..5e3ce8e --- /dev/null +++ b/src/pages/team-battle/components/Container.vue @@ -0,0 +1,353 @@ + + + + + diff --git a/src/pages/team-battle/components/Guide.vue b/src/pages/team-battle/components/Guide.vue new file mode 100644 index 0000000..0400dd6 --- /dev/null +++ b/src/pages/team-battle/components/Guide.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/src/pages/team-battle/components/Header.vue b/src/pages/team-battle/components/Header.vue new file mode 100644 index 0000000..35df1ba --- /dev/null +++ b/src/pages/team-battle/components/Header.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/pages/team-battle/components/HeaderProgress.vue b/src/pages/team-battle/components/HeaderProgress.vue new file mode 100644 index 0000000..ce1db3e --- /dev/null +++ b/src/pages/team-battle/components/HeaderProgress.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/pages/team-battle/components/IconButton.vue b/src/pages/team-battle/components/IconButton.vue new file mode 100644 index 0000000..bc466dd --- /dev/null +++ b/src/pages/team-battle/components/IconButton.vue @@ -0,0 +1,39 @@ + + + + diff --git a/src/pages/team-battle/components/PointSwitcher.vue b/src/pages/team-battle/components/PointSwitcher.vue new file mode 100644 index 0000000..1edf96e --- /dev/null +++ b/src/pages/team-battle/components/PointSwitcher.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/src/pages/team-battle/components/RoundEndTip.vue b/src/pages/team-battle/components/RoundEndTip.vue new file mode 100644 index 0000000..cc9a6f2 --- /dev/null +++ b/src/pages/team-battle/components/RoundEndTip.vue @@ -0,0 +1,172 @@ + + + + + diff --git a/src/pages/team-battle/components/SButton.vue b/src/pages/team-battle/components/SButton.vue new file mode 100644 index 0000000..a4d1bcf --- /dev/null +++ b/src/pages/team-battle/components/SButton.vue @@ -0,0 +1,96 @@ + + + + + diff --git a/src/pages/team-battle/components/SModal.vue b/src/pages/team-battle/components/SModal.vue new file mode 100644 index 0000000..3a0ba89 --- /dev/null +++ b/src/pages/team-battle/components/SModal.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/pages/team-battle/components/ScreenHint.vue b/src/pages/team-battle/components/ScreenHint.vue new file mode 100644 index 0000000..e3fb03d --- /dev/null +++ b/src/pages/team-battle/components/ScreenHint.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/pages/team-battle/components/ShootProgress2.vue b/src/pages/team-battle/components/ShootProgress2.vue new file mode 100644 index 0000000..89af288 --- /dev/null +++ b/src/pages/team-battle/components/ShootProgress2.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/src/pages/team-battle/components/TeamAvatars.vue b/src/pages/team-battle/components/TeamAvatars.vue new file mode 100644 index 0000000..3eb7a3b --- /dev/null +++ b/src/pages/team-battle/components/TeamAvatars.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/src/pages/team-battle/components/TestDistance.vue b/src/pages/team-battle/components/TestDistance.vue new file mode 100644 index 0000000..16a27e0 --- /dev/null +++ b/src/pages/team-battle/components/TestDistance.vue @@ -0,0 +1,193 @@ + + + + + diff --git a/src/pages/team-battle/index.vue b/src/pages/team-battle/index.vue new file mode 100644 index 0000000..b269f64 --- /dev/null +++ b/src/pages/team-battle/index.vue @@ -0,0 +1,1277 @@ + + + + + diff --git a/src/pages/user.vue b/src/pages/user.vue index 1a05fea..e2f2fcd 100644 --- a/src/pages/user.vue +++ b/src/pages/user.vue @@ -69,6 +69,10 @@ onMounted(() => { const envVersion = accountInfo.miniProgram.envVersion; if (envVersion !== "release") showLogout.value = true; }); + +/* global __BUILD_TIME__ */ +/** 构建时刻,由 vite.config.js define 在打包时自动注入;仅开发/体验版展示 */ +const buildVersion = typeof __BUILD_TIME__ !== 'undefined' ? __BUILD_TIME__ : '';