Commit 2499dbb9 authored by 董政锦's avatar 董政锦

style: game4 h5端样式修改;

parent cb2dbddf
......@@ -4,6 +4,7 @@ declare module 'crypto-js';
declare module 'crypto-js/sha256';
declare const __APP_DOMAIN__: string;
declare const __DEBUG__: boolean;
interface ImportMetaEnv {
readonly VITE_ASSET_BASE_URL?: string;
......
......@@ -15,12 +15,14 @@
"crypto-js": "^4.2.0",
"msgpack": "^1.0.3",
"socket.io-client": "^4.8.3",
"vconsole": "^3.15.1",
"vue": "^3.5.32",
"vue-router": "^4.6.4"
},
"devDependencies": {
"@tsconfig/node24": "^24.0.4",
"@types/node": "^24.12.2",
"@vitejs/plugin-basic-ssl": "^2.3.0",
"@vitejs/plugin-vue": "^6.0.6",
"@vue/tsconfig": "^0.9.1",
"npm-run-all2": "^8.0.4",
......
......@@ -20,6 +20,9 @@ importers:
socket.io-client:
specifier: ^4.8.3
version: 4.8.3
vconsole:
specifier: ^3.15.1
version: 3.15.1
vue:
specifier: ^3.5.32
version: 3.5.35(typescript@6.0.3)
......@@ -33,6 +36,9 @@ importers:
'@types/node':
specifier: ^24.12.2
version: 24.12.4
'@vitejs/plugin-basic-ssl':
specifier: ^2.3.0
version: 2.3.0(vite@8.0.16(@types/node@24.12.4))
'@vitejs/plugin-vue':
specifier: ^6.0.6
version: 6.0.7(vite@8.0.16(@types/node@24.12.4))(vue@3.5.35(typescript@6.0.3))
......@@ -185,6 +191,10 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0-0
'@babel/runtime@7.29.7':
resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==}
engines: {node: '>=6.9.0'}
'@babel/template@7.29.7':
resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==}
engines: {node: '>=6.9.0'}
......@@ -348,6 +358,12 @@ packages:
'@types/node@24.12.4':
resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==}
'@vitejs/plugin-basic-ssl@2.3.0':
resolution: {integrity: sha512-bdyo8rB3NnQbikdMpHaML9Z1OZPBu6fFOBo+OtxsBlvMJtysWskmBcnbIDhUqgC8tcxNv/a+BcV5U+2nQMm1OQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
peerDependencies:
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
'@vitejs/plugin-vue@6.0.7':
resolution: {integrity: sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==}
engines: {node: ^20.19.0 || >=22.12.0}
......@@ -474,6 +490,13 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
copy-text-to-clipboard@3.2.2:
resolution: {integrity: sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==}
engines: {node: '>=12'}
core-js@3.49.0:
resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==}
cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
......@@ -698,6 +721,9 @@ packages:
muggle-string@0.4.1:
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
mutation-observer@1.0.3:
resolution: {integrity: sha512-M/O/4rF2h776hV7qGMZUH3utZLO/jK7p8rnNgGkjKUw8zCGjRQPxB8z6+5l8+VjRUQ3dNYu4vjqXYLr+U8ZVNA==}
nan@2.27.0:
resolution: {integrity: sha512-hC+0LidcL3XE4rp1C4H54KujgXKzbfyTngZTwBByQxsOxCEKZT0MPQ4hOKUH2jU1OYstqdDH4onyHPDzcV0XdQ==}
......@@ -836,6 +862,9 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
vconsole@3.15.1:
resolution: {integrity: sha512-KH8XLdrq9T5YHJO/ixrjivHfmF2PC2CdVoK6RWZB4yftMykYIaXY1mxZYAic70vADM54kpMQF+dYmvl5NRNy1g==}
vite-dev-rpc@2.0.0:
resolution: {integrity: sha512-yKwbTwdHKSD2k/aGqyWpPHepo45OQc8lH3/6IfT4ZqeKE26ooKvi4WIEKzqWav8v+9Is8u1k8q54hvOmqASazA==}
peerDependencies:
......@@ -1135,6 +1164,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@babel/runtime@7.29.7': {}
'@babel/template@7.29.7':
dependencies:
'@babel/code-frame': 7.29.7
......@@ -1270,6 +1301,10 @@ snapshots:
dependencies:
undici-types: 7.16.0
'@vitejs/plugin-basic-ssl@2.3.0(vite@8.0.16(@types/node@24.12.4))':
dependencies:
vite: 8.0.16(@types/node@24.12.4)
'@vitejs/plugin-vue@6.0.7(vite@8.0.16(@types/node@24.12.4))(vue@3.5.35(typescript@6.0.3))':
dependencies:
'@rolldown/pluginutils': 1.0.1
......@@ -1431,6 +1466,10 @@ snapshots:
convert-source-map@2.0.0: {}
copy-text-to-clipboard@3.2.2: {}
core-js@3.49.0: {}
cross-spawn@7.0.6:
dependencies:
path-key: 3.1.1
......@@ -1586,6 +1625,8 @@ snapshots:
muggle-string@0.4.1: {}
mutation-observer@1.0.3: {}
nan@2.27.0: {}
nanoid@3.3.12: {}
......@@ -1729,6 +1770,13 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
vconsole@3.15.1:
dependencies:
'@babel/runtime': 7.29.7
copy-text-to-clipboard: 3.2.2
core-js: 3.49.0
mutation-observer: 1.0.3
vite-dev-rpc@2.0.0(vite@8.0.16(@types/node@24.12.4)):
dependencies:
birpc: 4.0.0
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
<svg width="447" height="288" viewBox="0 0 447 288" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 9.99999C0 4.47715 4.47715 0 10 0H437C442.523 0 447 4.47715 447 10V287.5L224 234.5L0 287.5V9.99999Z" fill="url(#paint0_linear_99_884)"/>
<defs>
<linearGradient id="paint0_linear_99_884" x1="223.5" y1="0" x2="223.5" y2="287.5" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFE897"/>
<stop offset="1" stop-color="white"/>
</linearGradient>
</defs>
</svg>
import SHA256 from 'crypto-js/sha256'
/**
* 是否开启 vconsole 调试面板
* - 开发模式(__DEBUG__=true)下自动开启
* - 生产模式下可通过 URL 参数 ?vc 或 ?debug 手动开启
*
* 关闭方式:将 vite.config.ts 中 __DEBUG__ 改为 false,且访问时不带 ?vc 参数
*/
function shouldEnableVConsole(): boolean {
if (__DEBUG__) return true
const params = new URLSearchParams(location.search)
return params.has('vc') || params.has('debug')
}
/**
* 是否使用模拟微信数据
* - 开发模式下如果 URL 没有真实 token 参数,自动启用模拟数据
* - 生产模式下可通过 URL 参数 ?mock 手动启用
*/
export function shouldMockWechat(): boolean {
const params = new URLSearchParams(location.search)
if (params.get('token')) return false // 有真实 token 就不 mock
if (__DEBUG__) return true
return params.has('mock')
}
/** 模拟的微信用户数据 */
export function getMockWechat() {
const mockToken = 'debug_mock_token_' + Date.now()
return {
token: SHA256(mockToken).toString(),
token_origin: mockToken,
nickname: '测试用户',
avatar: 'https://picsum.photos/200',
}
}
/**
* 初始化 vconsole(动态导入,生产环境未触发时不会打包)
*/
export async function initVConsole() {
if (!shouldEnableVConsole()) return
try {
const { default: VConsole } = await import('vconsole')
const vc = new VConsole()
console.log('[debug] vconsole 已启动')
return vc
} catch (e) {
console.warn('[debug] vconsole 加载失败:', e)
}
}
......@@ -89,5 +89,17 @@ export function $getWechat(): any | null {
avatar: q[2],
};
}
// 调试模式:无真实微信参数时使用模拟数据
if (__DEBUG__) {
const mockToken = 'debug_mock_token_' + Date.now()
return {
token: SHA256(mockToken).toString(),
token_origin: mockToken,
nickname: '测试用户',
avatar: 'https://picsum.photos/200',
}
}
return null;
}
\ No newline at end of file
......@@ -186,7 +186,7 @@ defineExpose({
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.2);
background-color: rgba(0, 0, 0, 0.6);
/* pointer-events: none; */
}
......
......@@ -3,7 +3,9 @@ import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { initVConsole } from './commons/debug'
localStorage.setItem('domain', __APP_DOMAIN__)
initVConsole()
createApp(App).use(router).mount('#app')
<script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { cssAssetUrl } from '@/commons/assets.ts'
import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus } from '@/composables/useGameSocket'
......@@ -14,11 +14,13 @@ const imageUrls = {
bg: cssAssetUrl('game4/h5-game4-bg.svg'),
bg2: cssAssetUrl('game1/bg2.png'),
playBg: cssAssetUrl('game4/h5-game4-bg2.svg'),
logo: cssAssetUrl('game1/logo.png'),
logo: cssAssetUrl('game4/logo.svg'),
time: cssAssetUrl('game4/h5-game4-clock.svg'),
title: cssAssetUrl('game4/h5-game4-title1.svg'),
title2: cssAssetUrl('game4/h5-game4-title2.svg'),
avatarBg: cssAssetUrl('game4/h5-game4-join.svg'),
// avatarBg: cssAssetUrl('game4/h5-game4-join.svg'),
userBg: cssAssetUrl('game4/user-bg.svg'),
startBg: cssAssetUrl('game4/start-bg.svg'),
gift: cssAssetUrl('game4/h5-game4-gift.svg'),
avatar: cssAssetUrl('game1/avatar.png'),
gu: cssAssetUrl('game4/h5-game4-horse.svg'),
......@@ -33,6 +35,13 @@ const imageUrls = {
const wechat = $getWechat()
const currentView = ref<GameView>('loading')
const stageBackground = computed(() => {
if (currentView.value === 'playing') {
return `${imageUrls.playBg} center/cover`
}
return `${imageUrls.bg} center/cover`
})
const countdownInterval = ref(60)
const isDivDescVisible = ref(false)
const tick = ref(0) // 点击次数/摇动次数
......@@ -216,7 +225,7 @@ onBeforeUnmount(() => {
<template>
<MobileStage v-if="token" :showGameRule="showGameRule" ref="mobileStageRef"
:background="`${imageUrls.bg} center/cover`">
:background="stageBackground">
<template #gameRule>
<div class="rule-container">
<div class="rule-txt-container">
......@@ -250,9 +259,10 @@ onBeforeUnmount(() => {
<style scoped>
.rule-container {
.rule-txt-container {
background: #FFF9E4;
width: 62vw;
margin: 0 40px;
border-radius: 5px;
background: #FFF9E4;
padding-top: 20px;
padding-bottom: 10px;
......
<script setup lang="ts">
import { $getWechat } from '@/commons/utils.ts'
import { onMounted, ref } from 'vue';
defineProps<{
imageUrls: Record<string, string>
userJoinStatus: boolean
......@@ -7,6 +10,14 @@ defineProps<{
defineEmits<{
touchGameRule: []
}>()
const nickname = ref('');
const avatar = ref('');
onMounted(() => {
const wechat = $getWechat();
nickname.value = wechat.nickname;
avatar.value = wechat.avatar;
});
</script>
<template>
......@@ -16,8 +27,14 @@ defineEmits<{
<div class="img-title"></div>
<div class="img-title2"></div>
<div class="img-gift"></div>
<div class="img-avatar-bg"></div>
<div class="img-avatar"></div>
<div class="img-user-bg"></div>
<div class="img-avatar" :style="`background: url(${avatar});border-radius:66px;width:132px;height:132px;`"></div>
<div class="txt-nickname">{{ nickname }}</div>
<div class="txt-loading">
<label v-if="userJoinStatus">您已成功加入游戏等待主持人开始</label>
<label v-else>正在加入游戏...</label>
</div>
<div class="img-start-bg"></div>
</div>
</template>
......@@ -99,28 +116,24 @@ defineEmits<{
background: v-bind('imageUrls.gift') center/cover;
}
.img-avatar-bg {
.img-user-bg {
position: absolute;
top: 568px;
left: calc(50% + 12px);
width: 500px;
height: 821px;
background: v-bind('imageUrls.avatarBg') center/cover;
top: 634px;
left: 50%;
width: 447px;
height: 287.5px;
background: v-bind('imageUrls.userBg') center/cover no-repeat;
transform: translateX(-50%);
}
.img-avatar {
position: absolute;
top: 564px;
top: 524px;
left: 50%;
width: 156px;
height: 156px;
background: v-bind('imageUrls.avatar') center/cover;
transform: translateX(-50%);
}
.txt-nickname {
position: absolute;
top: 650px;
top: 668px;
left: 50%;
color: #E00000;
font-size: 25pt;
......@@ -130,7 +143,7 @@ defineEmits<{
.txt-loading {
position: absolute;
top: 710px;
top: 743px;
left: 50%;
width: 288px;
color: #E00000;
......@@ -140,6 +153,16 @@ defineEmits<{
transform: translateX(-50%);
}
.img-start-bg {
position: absolute;
bottom: 291px;
left: 50%;
width: 500px;
height: 90px;
background: v-bind('imageUrls.startBg') center/cover no-repeat;
transform: translateX(-50%);
}
.txt-loading label {
display: inline-block;
transform-origin: center;
......
......@@ -2,7 +2,7 @@
import { onBeforeUnmount, onMounted } from 'vue'
import shakeSound from '@/assets/images/game4/yaoyiyao.mp3'
defineProps<{
const props = defineProps<{
imageUrls: Record<string, string>
countdownInterval: number
isDivDescVisible: boolean
......@@ -83,6 +83,13 @@ const handleDeviceMotion = (ev: DeviceMotionEvent) => {
lastShakeTime = now
playShakeSound()
// 摇晃时打印日志:输出将要通过 websocket 提交的数据
console.log('[摇一摇] 检测到摇晃,即将提交数据:', {
type: 'submit_score',
data: { score: props.tick + 1 },
})
emit('touch')
}
......
......@@ -20,16 +20,16 @@ defineEmits<{
<div class="score-content">
<div>张小明</div>
<div>您的成绩</div>
<div>策马跑道</div>
<div></div>
<div>{{ tick }}</div>
<div>最终排名</div>
<div><label>{{ level }}</label></div>
</div>
</div>
<div class="btn-group">
<!-- <div class="btn-group">
<div class="btn-replay" @click="$emit('replay')"></div>
<div class="btn-back" @click="$emit('back')"></div>
</div>
</div> -->
</div>
</template>
......
import { fileURLToPath, URL } from 'node:url'
import { cpSync, existsSync, rmSync } from 'node:fs'
import { resolve } from 'node:path'
import basicSsl from '@vitejs/plugin-basic-ssl'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueDevTools from 'vite-plugin-vue-devtools'
......@@ -29,10 +29,12 @@ export default defineConfig(({ command }) => ({
base: command === 'build' ? '/cc/h5/' : '/',
define: {
__APP_DOMAIN__: JSON.stringify(command === 'build' ? buildDomain : ''),
__DEBUG__: JSON.stringify(command === 'serve'),
},
plugins: [
vue(),
vueDevTools(),
basicSsl(),
copyImageAssets(),
],
server: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment