Commit f4049020 authored by 陈冲's avatar 陈冲

feat: 图片压缩

parent 301b840f
cp.cmd cp.cmd
.vscode/launch.json
...@@ -30,6 +30,18 @@ const GAME_START_COUNTDOWN_SECS: u64 = 3; ...@@ -30,6 +30,18 @@ const GAME_START_COUNTDOWN_SECS: u64 = 3;
const GAME_RESULT_WAIT_SECS: u64 = 2; const GAME_RESULT_WAIT_SECS: u64 = 2;
const GAME_RUNNING_SECS: u64 = 60; const GAME_RUNNING_SECS: u64 = 60;
fn get_game_tilte(key: &str) -> String {
let mut GAME_MAP = HashMap::new();
GAME_MAP.insert("game1", "击鼓齐福");
GAME_MAP.insert("game2", "聚宝接福");
GAME_MAP.insert("game3", "马上有福");
GAME_MAP.insert("game4", "策马迎福");
GAME_MAP.insert("game5", "圈彩纳福");
GAME_MAP.insert("game6", "福运当头");
let str = GAME_MAP.get(key).map_or("", |v| v);
str.to_string()
}
#[derive(Clone, Default)] #[derive(Clone, Default)]
struct RoomPlayer { struct RoomPlayer {
/// 成绩分数,具体含义由前端和游戏逻辑自行定义,后端只负责存储和排序。 /// 成绩分数,具体含义由前端和游戏逻辑自行定义,后端只负责存储和排序。
...@@ -464,15 +476,26 @@ async fn handle_room_command( ...@@ -464,15 +476,26 @@ async fn handle_room_command(
} }
if let Some(index) = data.as_i64() { if let Some(index) = data.as_i64() {
if let Ok(mut state) = ROOM_STATE.lock() { if let Ok(mut state) = ROOM_STATE.lock() {
let game_id = format!("game{index}");
if cmd == "room_create" { if cmd == "room_create" {
if state.status != RoomStatus::Closed { if state.status != RoomStatus::Closed {
drop(state); drop(state);
emit_msgpack(&socket, evt, &err_resp("不能重复创建房间", None)); emit_msgpack(
&socket,
evt,
&err_resp(
&format!(
"不能重复创建游戏 - {} 房间",
get_game_tilte(&game_id)
),
None,
),
);
return; return;
} }
} }
state.reset(); state.reset();
state.current_game_id = Some(format!("game{index}")); state.current_game_id = Some(game_id);
state.status = RoomStatus::Start; state.status = RoomStatus::Start;
// let snapshot = state.snapshot(); // let snapshot = state.snapshot();
drop(state); drop(state);
...@@ -492,7 +515,6 @@ async fn handle_room_command( ...@@ -492,7 +515,6 @@ async fn handle_room_command(
//超过300人的情况 //超过300人的情况
if get_player_count() > 300 { if get_player_count() > 300 {
emit_msgpack(&socket, evt, &err_resp("本场游戏人员已满", Some(json!(3)))); emit_msgpack(&socket, evt, &err_resp("本场游戏人员已满", Some(json!(3))));
_ = socket.clone().disconnect();
return; return;
} }
let gameId = data let gameId = data
...@@ -522,57 +544,44 @@ async fn handle_room_command( ...@@ -522,57 +544,44 @@ async fn handle_room_command(
emit_msgpack( emit_msgpack(
&socket, &socket,
evt, evt,
&err_resp("当前游戏房间还未开启", Some(json!(2))), &err_resp(
&format!("当前游戏 - {} 房间还未开启", get_game_tilte(&gameId)),
Some(json!(2)),
),
);
return;
}
//游戏不是等待跟正在运行
if !matches!(state.status, RoomStatus::Start | RoomStatus::Running) {
drop(state);
emit_msgpack(
&socket,
evt,
&err_resp(
&format!(
"当前游戏 - {} 已经开始了,请在下一场游戏开始前进入",
get_game_tilte(&gameId)
),
Some(json!(2)),
),
); );
_ = socket.clone().disconnect();
return; return;
} }
let already_joined = state.players.contains_key(userid); let already_joined = state.players.contains_key(userid);
//玩家游戏过程中掉线重连
if already_joined { if already_joined {
if let Some(player) = state.players.get_mut(userid) { if let Some(player) = state.players.get_mut(userid) {
player.online = true; player.online = true;
if !nickname.is_empty() {
player.nickname = nickname.to_string(); player.nickname = nickname.to_string();
}
if !avatar.is_empty() {
player.avatar = avatar.to_string(); player.avatar = avatar.to_string();
} }
}
let reconnect_payload = state.reconnect_payload(userid); let reconnect_payload = state.reconnect_payload(userid);
let should_resume_game = state.status == RoomStatus::Running;
drop(state); drop(state);
if let Some(mut player) = CLIENT_PLAYER_MAP.get_mut(userid) { if let Some(mut player) = CLIENT_PLAYER_MAP.get_mut(userid) {
player.0 = 1; player.0 = 1;
} }
emit_msgpack(&socket, evt, &ok_resp(reconnect_payload.clone())); emit_msgpack(&socket, "room_recover_result", &ok_resp(reconnect_payload));
if should_resume_game {
if let Some(game_id) = reconnect_payload
.as_ref()
.and_then(|payload| payload.get("gameId"))
.and_then(|value| value.as_str())
{
emit_msgpack(
&socket,
"game_start_result",
&ok_resp(Some(json!(game_id))),
);
}
}
return;
}
if state.status != RoomStatus::Start {
drop(state);
emit_msgpack(
&socket,
evt,
&err_resp(
"当前游戏已经开始了,请在下一场游戏开始前进入",
Some(json!(2)),
),
);
_ = socket.clone().disconnect();
return; return;
} }
let entry_order = state.next_entry_order; let entry_order = state.next_entry_order;
...@@ -856,7 +865,7 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value ...@@ -856,7 +865,7 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
emit_msgpack( emit_msgpack(
&socket, &socket,
"login_result", "login_result",
&err_resp("当前管理员已登录,不能重复登录", Some(json!(1))), &err_resp("当前管理员账号已登录,不能重复登录", Some(json!(1))),
); );
_ = socket.disconnect(); _ = socket.disconnect();
return; return;
...@@ -870,7 +879,7 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value ...@@ -870,7 +879,7 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
emit_msgpack( emit_msgpack(
&socket, &socket,
"connect_result", "connect_result",
&err_resp("game is not open", None), &err_resp("游戏管理员暂未开启该房间", None),
); );
_ = socket.disconnect(); _ = socket.disconnect();
return; return;
...@@ -942,10 +951,10 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value ...@@ -942,10 +951,10 @@ pub async fn on_connect(_io: SocketIo, socket: SocketRef, Data(data): Data<Value
let count = state.players.len(); let count = state.players.len();
let ranking = state.current_ranking_payload(); let ranking = state.current_ranking_payload();
drop(state); drop(state);
broadcast_msgpack_all_admin( // broadcast_msgpack_all_admin(
"room_join_result", // "room_join_result",
&ok_resp(Some(json!({"list":ranking,"count":count}))), // &ok_resp(Some(json!({"list":ranking,"count":count}))),
); // );
} }
} }
} }
...@@ -1001,7 +1010,7 @@ pub async fn login(req: &mut Request, res: &mut Response) { ...@@ -1001,7 +1010,7 @@ pub async fn login(req: &mut Request, res: &mut Response) {
let passphrase = utils::get_aes_passphrase(); let passphrase = utils::get_aes_passphrase();
if passphrase.is_none() { if passphrase.is_none() {
res.render(Json(err_resp("username 和 password 不能为空", None))); res.render(Json(err_resp("用户名或密码不能为空", None)));
return; return;
} }
//当前管理员已登录,不能重复登录 //当前管理员已登录,不能重复登录
......
import game1MusicUrl from '@/assets/images/game1.mp3' import game1MusicUrl from '@/assets/images/game1.mp3'
import game6Music1Url from '@/assets/images/game6_1.mp3' import game6Music1Url from '@/assets/images/game6_1.mp3'
import game6Music2Url from '@/assets/images/game6_2.mp3' import game6Music2Url from '@/assets/images/game6_2.mp3'
import game6Music3Url from '@/assets/images/game6_3.mp3'
import go321 from '@/assets/images/321go.mp3' import go321 from '@/assets/images/321go.mp3'
...@@ -17,7 +16,7 @@ function getEffectTemplate(music: string) { ...@@ -17,7 +16,7 @@ function getEffectTemplate(music: string) {
template = new Audio(music) template = new Audio(music)
template.loop = false template.loop = false
template.preload = 'auto' template.preload = 'auto'
template.volume = 0.6 template.volume = 1
template.load() template.load()
effectTemplates.set(music, template) effectTemplates.set(music, template)
} }
...@@ -52,7 +51,7 @@ function setPendingRetry(retry: () => void) { ...@@ -52,7 +51,7 @@ function setPendingRetry(retry: () => void) {
async function playEffect(music: string, retry: () => void) { async function playEffect(music: string, retry: () => void) {
const audio = getEffectTemplate(music).cloneNode(true) as HTMLAudioElement const audio = getEffectTemplate(music).cloneNode(true) as HTMLAudioElement
audio.loop = false audio.loop = false
audio.volume = 0.6 audio.volume = 1
playingEffects.add(audio) playingEffects.add(audio)
const release = () => releaseEffect(audio) const release = () => releaseEffect(audio)
...@@ -105,10 +104,9 @@ export function stopCountdownMusic() { ...@@ -105,10 +104,9 @@ export function stopCountdownMusic() {
/* /*
打地鼠击中爆炸6-1 打地鼠击中爆炸6-1
打小白兔眩晕6-2 打小白兔眩晕6-2
没打中6-3
*/ */
export async function playGame6Music(index: number) { export async function playGame6Music(index: number) {
let arr: [string, string, string, string] = ['', game6Music1Url, game6Music2Url, game6Music3Url]; let arr: [string, string, string] = ['', game6Music1Url, game6Music2Url];
const music = arr[index] const music = arr[index]
if (!music) { if (!music) {
......
...@@ -18,12 +18,11 @@ type GameSocketOptions = { ...@@ -18,12 +18,11 @@ type GameSocketOptions = {
onScoreSubmitted?: (is_save: boolean, data: any) => void onScoreSubmitted?: (is_save: boolean, data: any) => void
onRescoreSubmitted?: (recount: number) => void onRescoreSubmitted?: (recount: number) => void
onRoomClosed?: (data: any) => void onRoomClosed?: (data: any) => void
onGameRecover?: (data: any) => void
onEvent?: (evt: string, payload: SocketPayload) => void onEvent?: (evt: string, payload: SocketPayload) => void
onRoomBack?: (data: any) => void onRoomBack?: (data: any) => void
} }
let gameId = '';
function getGameIndex(data: any) { function getGameIndex(data: any) {
if (typeof data === 'object' && data !== null) { if (typeof data === 'object' && data !== null) {
return Number(data.game ?? data.game_id ?? data.gameId ?? data.id) return Number(data.game ?? data.game_id ?? data.gameId ?? data.id)
...@@ -42,7 +41,7 @@ function getGameHomePath(data: any) { ...@@ -42,7 +41,7 @@ function getGameHomePath(data: any) {
return `/game${gameIndex}` return `/game${gameIndex}`
} }
export function joinSharedRoom(nickname: string, token: string, avatar: string) { export function joinSharedRoom(nickname: string, token: string, avatar: string, gameId: string) {
return sendSocketMessage('room_join', { nickname: nickname, token, avatar, gameId: gameId }) return sendSocketMessage('room_join', { nickname: nickname, token, avatar, gameId: gameId })
} }
...@@ -52,7 +51,6 @@ export function sendGameMessage(cmd: string, data: any = {}) { ...@@ -52,7 +51,6 @@ export function sendGameMessage(cmd: string, data: any = {}) {
export const userJoinStatus = ref(false) export const userJoinStatus = ref(false)
export function useGameSocket(options: GameSocketOptions) { export function useGameSocket(options: GameSocketOptions) {
gameId = options.gameId;
const router = useRouter() const router = useRouter()
let socket: Socket | null = null let socket: Socket | null = null
let offSocketMessage: (() => void) | undefined let offSocketMessage: (() => void) | undefined
...@@ -68,7 +66,7 @@ export function useGameSocket(options: GameSocketOptions) { ...@@ -68,7 +66,7 @@ export function useGameSocket(options: GameSocketOptions) {
}, },
onDisconnect: (_reason: string) => { }, onDisconnect: (_reason: string) => { },
onError: (error: any) => { onError: (error: any) => {
console.error('socket.io connect_error:', error) // console.error('socket.io connect_error:', error)
}, },
}) })
...@@ -103,6 +101,10 @@ export function useGameSocket(options: GameSocketOptions) { ...@@ -103,6 +101,10 @@ export function useGameSocket(options: GameSocketOptions) {
} }
switch (evt) { switch (evt) {
case 'connect_result':{
debugger
break;
}
case 'room_create_result': { case 'room_create_result': {
const nextPath = getGameHomePath(data) const nextPath = getGameHomePath(data)
...@@ -113,12 +115,30 @@ export function useGameSocket(options: GameSocketOptions) { ...@@ -113,12 +115,30 @@ export function useGameSocket(options: GameSocketOptions) {
} }
case 'room_join_result': { case 'room_join_result': {
if (data != options.gameId) { if (data != options.gameId) {
alert('当前游戏房间还未开启');
return; return;
} }
userJoinStatus.value = true userJoinStatus.value = true
break break
} }
case 'room_recover_result': {
/*{
"gameId": "game6",
"rank": 1,
"reconnect": true,
"remainingSeconds": 56,
"score": 0,
"status": "running"
}*/
//游戏进行中玩家掉线重连时
if (data.gameId != options.gameId) {
return;
}
userJoinStatus.value = true
let { rank, remainingSeconds, score } = data;
//返回的时间可能会慢一秒
options.onGameRecover?.({ rank, remainingSeconds, score });
break
}
case 'game_start_result': { case 'game_start_result': {
if (data === options.gameId) { if (data === options.gameId) {
options.onGameStart?.(data) options.onGameStart?.(data)
......
...@@ -106,12 +106,6 @@ function startGameCountdown(seconds = 60) { ...@@ -106,12 +106,6 @@ function startGameCountdown(seconds = 60) {
gameCountdownTimer = window.setTimeout(tickCountdown, 1000) gameCountdownTimer = window.setTimeout(tickCountdown, 1000)
} }
function showLoadingView() {
stopGameCountdown()
currentView.value = 'loading'
setDivDescVisible(false)
}
function resetToLoadingView() { function resetToLoadingView() {
stopGameCountdown() stopGameCountdown()
if (guFrameTimer) { if (guFrameTimer) {
...@@ -142,14 +136,6 @@ function showScoreView() { ...@@ -142,14 +136,6 @@ function showScoreView() {
currentView.value = 'score' currentView.value = 'score'
} }
function handleRoomBack() {
resetToLoadingView()
window.setTimeout(() => {
joinSharedRoom(nickname.value, token.value, avatar.value)
}, 200)
}
const touchHandler = () => { const touchHandler = () => {
if (isGuPlaying.value) { if (isGuPlaying.value) {
return return
...@@ -181,14 +167,15 @@ const touchHandler = () => { ...@@ -181,14 +167,15 @@ const touchHandler = () => {
} }
if (wechat) { if (wechat) {
const gameId = 'game1';
const { offSocketMessage } = useGameSocket({ const { offSocketMessage } = useGameSocket({
gameId: 'game1', gameId,
auth: { auth: {
userid: wechat.token, userid: wechat.token,
}, },
onConnect: () => { onConnect: () => {
window.setTimeout(() => { window.setTimeout(() => {
const joined = joinSharedRoom(nickname.value, token.value, avatar.value) const joined = joinSharedRoom(nickname.value, token.value, avatar.value, gameId)
}, 200) }, 200)
}, },
onGameStart: async () => { onGameStart: async () => {
...@@ -207,8 +194,32 @@ if (wechat) { ...@@ -207,8 +194,32 @@ if (wechat) {
onRescoreSubmitted: (_recount) => { onRescoreSubmitted: (_recount) => {
submitScore(true); submitScore(true);
}, },
onRoomClosed: showLoadingView, onGameRecover: (data) => {
onRoomBack: handleRoomBack, const recoveredRank = Number(data?.rank)
const recoveredScore = Number(data?.score)
const recoveredSeconds = Number(data?.remainingSeconds)
rank.value = Number.isFinite(recoveredRank) && recoveredRank > 0 ? recoveredRank : 0
tick.value = Number.isFinite(recoveredScore) && recoveredScore > 0 ? recoveredScore : 0
showGameRule.value = false
// showGameRank.value = false
currentView.value = 'playing'
startGameCountdown(
Number.isFinite(recoveredSeconds) && recoveredSeconds > 0 ? recoveredSeconds : 0,
)
},
onRoomClosed: () => {
stopGameCountdown()
currentView.value = 'loading'
setDivDescVisible(false)
alert('管理员关闭了该房间')
},
onRoomBack: () => {
resetToLoadingView()
window.setTimeout(() => {
joinSharedRoom(nickname.value, token.value, avatar.value, gameId)
}, 200)
},
}) })
_offSocketMessage.value = offSocketMessage _offSocketMessage.value = offSocketMessage
} }
......
...@@ -128,12 +128,6 @@ function startGameCountdown(seconds = 60) { ...@@ -128,12 +128,6 @@ function startGameCountdown(seconds = 60) {
gameCountdownTimer = window.setTimeout(tickCountdown, 1000) gameCountdownTimer = window.setTimeout(tickCountdown, 1000)
} }
function showLoadingView() {
stopGameCountdown()
currentView.value = 'loading'
setDivDescVisible(false)
}
function resetToLoadingView() { function resetToLoadingView() {
stopGameCountdown() stopGameCountdown()
if (guFrameTimer) { if (guFrameTimer) {
...@@ -168,37 +162,31 @@ function showGameOverRank() { ...@@ -168,37 +162,31 @@ function showGameOverRank() {
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'loading'
showGameRank.value = true showGameRank.value = true
userJoinStatus.value = false;
} }
function handleRoomBack() { const touchHandler = (mole: boolean) => {
resetToLoadingView() let scoreDelta = mole ? 5 : 0;
window.setTimeout(() => { let nextTick = score.value + scoreDelta
joinSharedRoom(nickname.value, token.value, avatar.value)
}, 200)
}
const touchHandler = (scoreDelta: number) => {
const nextTick = score.value + scoreDelta
score.value = nextTick score.value = nextTick
submitScore(false, nextTick) if (mole) {
if (scoreDelta == 5) {
playGame6Music(1); playGame6Music(1);
} else if (scoreDelta == -3) { submitScore(false, nextTick)
playGame6Music(2);
} else { } else {
playGame6Music(3); playGame6Music(2);
} }
} }
if (wechat) { if (wechat) {
const gameId = 'game6';
const { offSocketMessage } = useGameSocket({ const { offSocketMessage } = useGameSocket({
gameId: 'game6', gameId,
auth: { auth: {
userid: wechat.token, userid: wechat.token,
}, },
onConnect: () => { onConnect: () => {
window.setTimeout(() => { window.setTimeout(() => {
const joined = joinSharedRoom(nickname.value, token.value, avatar.value) const joined = joinSharedRoom(nickname.value, token.value, avatar.value, gameId)
}, 200) }, 200)
}, },
onGameStart: async () => { onGameStart: async () => {
...@@ -231,8 +219,32 @@ if (wechat) { ...@@ -231,8 +219,32 @@ if (wechat) {
onRescoreSubmitted: (_recount) => { onRescoreSubmitted: (_recount) => {
submitScore(true); submitScore(true);
}, },
onRoomClosed: showLoadingView, onGameRecover: (data) => {
onRoomBack: handleRoomBack, const recoveredRank = Number(data?.rank)
const recoveredScore = Number(data?.score)
const recoveredSeconds = Number(data?.remainingSeconds)
rank.value = Number.isFinite(recoveredRank) && recoveredRank > 0 ? recoveredRank : 0
score.value = Number.isFinite(recoveredScore) && recoveredScore > 0 ? recoveredScore : 0
showGameRule.value = false
showGameRank.value = false
currentView.value = 'playing'
startGameCountdown(
Number.isFinite(recoveredSeconds) && recoveredSeconds > 0 ? recoveredSeconds : 0,
)
},
onRoomClosed: () => {
stopGameCountdown()
currentView.value = 'loading'
setDivDescVisible(false)
alert('管理员关闭了该房间')
},
onRoomBack: () => {
resetToLoadingView()
window.setTimeout(() => {
joinSharedRoom(nickname.value, token.value, avatar.value, gameId)
}, 200)
},
}) })
_offSocketMessage.value = offSocketMessage _offSocketMessage.value = offSocketMessage
} }
...@@ -279,7 +291,7 @@ const rankCloseHandler = () => { ...@@ -279,7 +291,7 @@ const rankCloseHandler = () => {
<div class="rule-txt-container"> <div class="rule-txt-container">
<div class="rule-title">游戏规则</div> <div class="rule-title">游戏规则</div>
<div class="rule-txt"> <div class="rule-txt">
1. 主持人开赛点击敲击,打中地鼠 + 5 分、误击白兔-3分;<br /> 1. 主持人开赛点击敲击,打中地鼠 + 5 分、打中白兔不得分;<br />
2. 限时比拼反应速度,结束后按积分排名;<br /> 2. 限时比拼反应速度,结束后按积分排名;<br />
3. 高分用户有机会领取新疆福彩定制周边;<br /> 3. 高分用户有机会领取新疆福彩定制周边;<br />
4. 禁止外挂作弊,违规账号取消成绩与领奖资格;<br /><br /> 4. 禁止外挂作弊,违规账号取消成绩与领奖资格;<br /><br />
......
...@@ -11,7 +11,7 @@ defineProps<{ ...@@ -11,7 +11,7 @@ defineProps<{
}>() }>()
const emit = defineEmits<{ const emit = defineEmits<{
touch: [scoreDelta: number] touch: [mole: boolean]
}>() }>()
type TargetKind = 'mole' | 'rabbit' type TargetKind = 'mole' | 'rabbit'
...@@ -91,7 +91,7 @@ function playTargetLifecycle(index: number, kind: TargetKind, duration = 1000) { ...@@ -91,7 +91,7 @@ function playTargetLifecycle(index: number, kind: TargetKind, duration = 1000) {
} }
function randomTargetKind(): TargetKind { function randomTargetKind(): TargetKind {
return Math.random() < 0.65 ? 'mole' : 'rabbit' return Math.random() < 0.75 ? 'mole' : 'rabbit'
} }
function randomCount(min = 1, max = 3) { function randomCount(min = 1, max = 3) {
...@@ -120,9 +120,7 @@ function handleTargetTouch(index: number) { ...@@ -120,9 +120,7 @@ function handleTargetTouch(index: number) {
if (!item || item.state === 'idle' || item.state === 'hit') { if (!item || item.state === 'idle' || item.state === 'hit') {
return return
} }
emit('touch', item.kind === 'mole')
const scoreDelta = item.kind === 'mole' ? 5 : -3
emit('touch', scoreDelta)
clearTargetTimer(item) clearTargetTimer(item)
item.state = 'hit' item.state = 'hit'
item.timer = window.setTimeout(() => { item.timer = window.setTimeout(() => {
......
...@@ -87,7 +87,7 @@ function clearCountdownRetry() { ...@@ -87,7 +87,7 @@ function clearCountdownRetry() {
export async function playCountdownMusic() { export async function playCountdownMusic() {
const audio = getCountdownTemplate().cloneNode(true) as HTMLAudioElement const audio = getCountdownTemplate().cloneNode(true) as HTMLAudioElement
audio.loop = false audio.loop = false
audio.volume = 0.8 audio.volume = 1
countdownAudios.add(audio) countdownAudios.add(audio)
const release = () => releaseCountdownAudio(audio) const release = () => releaseCountdownAudio(audio)
......
...@@ -77,7 +77,9 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean { ...@@ -77,7 +77,9 @@ export function sendSocketMessage(cmd: string, data: any = {}): boolean {
if (!socket?.connected) { if (!socket?.connected) {
return false; return false;
} }
if ($is_run_local()) {
console.log('===================>send', cmd, data);
}
socket.send(encode({ cmd, data })); socket.send(encode({ cmd, data }));
return true; return true;
} }
......
...@@ -167,7 +167,7 @@ onBeforeUnmount(() => { ...@@ -167,7 +167,7 @@ onBeforeUnmount(() => {
height: 84px; height: 84px;
padding: 0 40px; padding: 0 40px;
background: rgba(0, 0, 0, 0.42); background: rgba(0, 0, 0, 0.42);
border: 1px dashed #ccc; /* border: 1px solid #ccc; */
color: #fff; color: #fff;
font-size: 42px; font-size: 42px;
line-height: 84px; line-height: 84px;
......
...@@ -41,6 +41,10 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) { ...@@ -41,6 +41,10 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
return sendSocketMessage(cmd, data) return sendSocketMessage(cmd, data)
} }
function closeRoom(){
return sendSocketMessage('room_close', {})
}
onMounted(() => { onMounted(() => {
const { passphrase, token, socket_path, client_ns, domain } = $read_socket_storge() const { passphrase, token, socket_path, client_ns, domain } = $read_socket_storge()
initSocket({ initSocket({
...@@ -103,5 +107,6 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) { ...@@ -103,5 +107,6 @@ export function useAdminGameSocket(options: AdminGameSocketOptions) {
backRoom, backRoom,
startGame, startGame,
sendAdminMessage, sendAdminMessage,
closeRoom,
} }
} }
...@@ -40,6 +40,7 @@ const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null) ...@@ -40,6 +40,7 @@ const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null)
let isPlayingStartAnimation = false let isPlayingStartAnimation = false
const confirmRefresh = (event: BeforeUnloadEvent) => { const confirmRefresh = (event: BeforeUnloadEvent) => {
// closeRoom();
event.preventDefault() event.preventDefault()
event.returnValue = '' event.returnValue = ''
} }
...@@ -136,7 +137,7 @@ function handleRoomState(data: any) { ...@@ -136,7 +137,7 @@ function handleRoomState(data: any) {
} }
} }
const { startGame, createRoom, backRoom } = useAdminGameSocket({ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gameId: 'game1', gameId: 'game1',
onRoomState: handleRoomState, onRoomState: handleRoomState,
onRoomJoin: (data) => { onRoomJoin: (data) => {
...@@ -169,6 +170,14 @@ const nextRoundWithMusic = () => { ...@@ -169,6 +170,14 @@ const nextRoundWithMusic = () => {
nextRound() nextRound()
} }
const backHandler = () => {
if (confirm('是否关闭当前房间回到首页')) {
closeRoom();
stopGame1Music()
router.replace('/main');
}
}
onMounted(() => { onMounted(() => {
window.addEventListener('beforeunload', confirmRefresh) window.addEventListener('beforeunload', confirmRefresh)
playGame1Music() playGame1Music()
...@@ -182,7 +191,7 @@ onUnmounted(() => { ...@@ -182,7 +191,7 @@ onUnmounted(() => {
<template> <template>
<Loading v-if="screen === 'loading'" :players="loadingPlayers" :player-count="playerCount" <Loading v-if="screen === 'loading'" :players="loadingPlayers" :player-count="playerCount"
@start="startGameWithMusic" /> @start="startGameWithMusic" @back="backHandler" />
<Rank1 v-else-if="screen === 'rank1'" ref="rank1Ref" :rank-list="rankPlayers" @start="startGameWithMusic" /> <Rank1 v-else-if="screen === 'rank1'" ref="rank1Ref" :rank-list="rankPlayers" @start="startGameWithMusic" />
<Rank2 v-else :rank-list="rankPlayers" @next="nextRoundWithMusic" /> <Rank2 v-else :rank-list="rankPlayers" @next="nextRoundWithMusic" @back="backHandler" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import router from '@/router';
import { $format_str } from '@/commons/utils.ts'; import { $format_str } from '@/commons/utils.ts';
import DesignStage from '@/components/DesignStage.vue' import DesignStage from '@/components/DesignStage.vue'
import { assetUrl, cssAssetUrl } from '@/commons/assets.ts'; import { assetUrl, cssAssetUrl } from '@/commons/assets.ts';
...@@ -11,6 +12,7 @@ defineProps<{ ...@@ -11,6 +12,7 @@ defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
start: []; start: [];
back: [];
}>(); }>();
const imageUrls = { const imageUrls = {
...@@ -24,8 +26,10 @@ const imageUrls = { ...@@ -24,8 +26,10 @@ const imageUrls = {
avatarAnimation: cssAssetUrl('avatar_animation.png'), avatarAnimation: cssAssetUrl('avatar_animation.png'),
avatar: cssAssetUrl('avatar.png'), avatar: cssAssetUrl('avatar.png'),
line: cssAssetUrl('game1/line.png'), line: cssAssetUrl('game1/line.png'),
start1: cssAssetUrl('game1/start-1.png'), start: cssAssetUrl('game1/start.png'),
start2: cssAssetUrl('game1/start-2.png'), back: cssAssetUrl('game1/back.png'),
// start1: cssAssetUrl('game1/start-1.png'),
// start2: cssAssetUrl('game1/start-2.png'),
}; };
const isStartPressed = ref(false); const isStartPressed = ref(false);
...@@ -72,14 +76,11 @@ const renderAvatar = (item: any | null) => { ...@@ -72,14 +76,11 @@ const renderAvatar = (item: any | null) => {
</div> </div>
<div class="list-container-line"></div> <div class="list-container-line"></div>
<div class="list-container-right"> <div class="list-container-right">
<div <!-- <div class="btn-start" :class="{ pressed: isStartPressed }" @pointerdown="pressStartButton"
class="btn-start" @pointerup="releaseStartButton" @pointerleave="releaseStartButton"
:class="{ pressed: isStartPressed }" @pointercancel="releaseStartButton"></div> -->
@pointerdown="pressStartButton" <div class="btn-start" @click="pressStartButton"></div>
@pointerup="releaseStartButton" <div class="btn-back" @click="emit('back')"></div>
@pointerleave="releaseStartButton"
@pointercancel="releaseStartButton"
></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -237,13 +238,22 @@ const renderAvatar = (item: any | null) => { ...@@ -237,13 +238,22 @@ const renderAvatar = (item: any | null) => {
width: 316px; width: 316px;
height: 105px; height: 105px;
margin-left: 60px; margin-left: 60px;
margin-top: 80px; margin-top: 10px;
background: v-bind('imageUrls.start1'); background: v-bind('imageUrls.start');
cursor: pointer; cursor: pointer;
} }
.btn-start.pressed { /* .btn-start.pressed {
background: v-bind('imageUrls.start2'); background: v-bind('imageUrls.start2');
} */
.btn-back {
width: 316px;
height: 105px;
margin-left: 60px;
margin-top: 30px;
background: v-bind('imageUrls.back');
cursor: pointer;
} }
} }
} }
......
...@@ -10,6 +10,7 @@ const props = defineProps<{ ...@@ -10,6 +10,7 @@ const props = defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
next: []; next: [];
back: [];
}>(); }>();
const FINAL_RANK_LIMIT = 10; const FINAL_RANK_LIMIT = 10;
...@@ -29,7 +30,9 @@ const imageUrls = { ...@@ -29,7 +30,9 @@ const imageUrls = {
pai3: cssAssetUrl('game1/pai3.png'), pai3: cssAssetUrl('game1/pai3.png'),
rankIcon: cssAssetUrl('game1/no-icon.png'), rankIcon: cssAssetUrl('game1/no-icon.png'),
avatarAnimation: cssAssetUrl('avatar_animation.png'), avatarAnimation: cssAssetUrl('avatar_animation.png'),
next: cssAssetUrl('game1/next-1.png'), next: cssAssetUrl('game1/next.png'),
back: cssAssetUrl('game1/back.png'),
vip: cssAssetUrl('game1/vip.png'),
}; };
const emptyPlayer = (index: number): Player => ({ const emptyPlayer = (index: number): Player => ({
...@@ -59,7 +62,7 @@ const renderAvatar = (item: any | null) => { ...@@ -59,7 +62,7 @@ const renderAvatar = (item: any | null) => {
if (item && item.avatar) { if (item && item.avatar) {
return `background: url('${item.avatar}') center / cover no-repeat;` return `background: url('${item.avatar}') center / cover no-repeat;`
} }
return `background: v-bind('imageUrls.avatar') center / cover no-repeat;` return `background: ${imageUrls.avatar} center / cover no-repeat;`
} }
</script> </script>
...@@ -71,29 +74,24 @@ const renderAvatar = (item: any | null) => { ...@@ -71,29 +74,24 @@ const renderAvatar = (item: any | null) => {
<div class="img-title2"></div> <div class="img-title2"></div>
<div class="podium"> <div class="podium">
<div class="rank-vip"></div>
<div class="rank-no1"> <div class="rank-no1">
<div class="gu-burst"></div> <div class="gu-burst"></div>
<div class="avatar" :style="`${renderAvatar(list[0])}`"> <div class="avatar" :style="`${renderAvatar(list[0])}`">
</div> </div>
<div class="nickname">{{ list[0]?.nickname }}</div> <div class="nickname">{{ list[0]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
<div class="rank-no2"> <div class="rank-no2">
<div class="gu-burst"></div> <div class="gu-burst"></div>
<div class="avatar" :style="`${renderAvatar(list[1])}`"> <div class="avatar" :style="`${renderAvatar(list[1])}`">
</div> </div>
<div class="nickname">{{ list[1]?.nickname }}</div> <div class="nickname">{{ list[1]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
<div class="rank-no3"> <div class="rank-no3">
<div class="gu-burst"></div> <div class="gu-burst"></div>
<div class="avatar" :style="`${renderAvatar(list[2])}`"> <div class="avatar" :style="`${renderAvatar(list[2])}`">
</div> </div>
<div class="nickname">{{ list[2]?.nickname }}</div> <div class="nickname">{{ list[2]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
</div> </div>
...@@ -102,7 +100,7 @@ const renderAvatar = (item: any | null) => { ...@@ -102,7 +100,7 @@ const renderAvatar = (item: any | null) => {
<div class="no-icon">{{ index + 4 }}</div> <div class="no-icon">{{ index + 4 }}</div>
<div> <div>
<div class="img-avatar-container"> <div class="img-avatar-container">
<div class="img-avatar"></div> <div class="img-avatar" :style="`${renderAvatar(list[index + 3])}`"></div>
</div> </div>
<div class="txt-nickname">{{ item.nickname }}</div> <div class="txt-nickname">{{ item.nickname }}</div>
</div> </div>
...@@ -110,6 +108,7 @@ const renderAvatar = (item: any | null) => { ...@@ -110,6 +108,7 @@ const renderAvatar = (item: any | null) => {
</div> </div>
<div class="btn-next" @click="emit('next')"></div> <div class="btn-next" @click="emit('next')"></div>
<div class="btn-back" @click="emit('back')"></div>
</div> </div>
</DesignStage> </DesignStage>
</template> </template>
...@@ -182,46 +181,28 @@ const renderAvatar = (item: any | null) => { ...@@ -182,46 +181,28 @@ const renderAvatar = (item: any | null) => {
} }
.avatar { .avatar {
/* background: v-bind('imageUrls.avatar') center / cover no-repeat; */ width: 160px;
width: 120px; height: 160px;
height: 120px; border-radius: 80px;
border-radius: 60px;
position: absolute; position: absolute;
left: 610px; left: 575px;
top: -136px; top: -146px;
} }
.nickname { .nickname {
width: 167px; width: 167px;
height: 46px; height: 46px;
background: #FFCF44; background: linear-gradient(0deg, #FFBF5A 0%, #FFE47A 100%);
color: white; border: 1px solid #FFF9DC;
color: #4B1A14;
text-align: center; text-align: center;
line-height: 46px; line-height: 46px;
position: absolute; position: absolute;
left: 590px; left: 570px;
top: -25px; top: -25px;
z-index: 1; z-index: 1;
border-radius: 23px; border-radius: 23px;
} }
.guan {
background: v-bind('imageUrls.guan1');
width: 64px;
height: 64px;
position: absolute;
left: 580px;
top: -153px
}
.pai {
background: v-bind('imageUrls.pai1');
width: 212px;
height: 200px;
position: absolute;
left: 570px;
top: 40px;
}
} }
.rank-no2 { .rank-no2 {
...@@ -233,20 +214,21 @@ const renderAvatar = (item: any | null) => { ...@@ -233,20 +214,21 @@ const renderAvatar = (item: any | null) => {
} }
.avatar { .avatar {
background: v-bind('imageUrls.avatar') center / cover no-repeat; width: 144px;
width: 120px; height: 144px;
height: 120px; border-radius: 72px;
border-radius: 60px;
position: absolute; position: absolute;
left: 180px; left: 180px;
top: -110px; top: -113px;
} }
.nickname { .nickname {
width: 167px; width: 167px;
height: 46px; height: 46px;
background: #CA9600; background: linear-gradient(0deg, #AEA6A7 0%, #EAE4DF 100%);
color: white; border: 1px solid white;
color: #383636;
text-align: center; text-align: center;
line-height: 46px; line-height: 46px;
position: absolute; position: absolute;
...@@ -255,24 +237,6 @@ const renderAvatar = (item: any | null) => { ...@@ -255,24 +237,6 @@ const renderAvatar = (item: any | null) => {
z-index: 1; z-index: 1;
border-radius: 23px; border-radius: 23px;
} }
.guan {
background: v-bind('imageUrls.guan2') no-repeat center;
width: 96px;
height: 96px;
position: absolute;
left: 134px;
top: -144px;
}
.pai {
background: v-bind('imageUrls.pai2') no-repeat center;
width: 212px;
height: 200px;
position: absolute;
left: 140px;
top: 50px;
}
} }
.rank-no3 { .rank-no3 {
...@@ -284,47 +248,40 @@ const renderAvatar = (item: any | null) => { ...@@ -284,47 +248,40 @@ const renderAvatar = (item: any | null) => {
} }
.avatar { .avatar {
background: v-bind('imageUrls.avatar') center / cover no-repeat; width: 144px;
width: 120px; height: 144px;
height: 120px; border-radius: 72px;
border-radius: 60px;
position: absolute; position: absolute;
left: 1046px; left: 987px;
top: -110px; top: -116px;
} }
.nickname { .nickname {
width: 167px; width: 167px;
height: 46px; height: 46px;
background: #E2E2E2; background: linear-gradient(0deg, #F3AE76 0%, #F9CDA3 100%);
color: #AFAFAF; color: #6F3A0E;
border: 1px solid #FEFEFD;
text-align: center; text-align: center;
line-height: 46px; line-height: 46px;
position: absolute; position: absolute;
left: 1028px; left: 977px;
top: 2px; top: 2px;
z-index: 1; z-index: 1;
border-radius: 23px; border-radius: 23px;
} }
.guan {
background: v-bind('imageUrls.guan3') no-repeat center;
width: 96px;
height: 96px;
position: absolute;
left: 1003px;
top: -146px;
} }
}
.pai { .rank-vip {
background: v-bind('imageUrls.pai3') no-repeat center; width: 969px;
width: 212px; height: 238px;
height: 200px; background: v-bind('imageUrls.vip');
position: absolute; position: absolute;
right: 130px; left: 171px;
top: 50px; top: -200px;
}
}
} }
.rank-container { .rank-container {
...@@ -393,10 +350,20 @@ const renderAvatar = (item: any | null) => { ...@@ -393,10 +350,20 @@ const renderAvatar = (item: any | null) => {
.btn-next { .btn-next {
position: absolute; position: absolute;
bottom: 100px; bottom: 100px;
left: 820px; left: 620px;
width: 316px; width: 316px;
height: 105px; height: 105px;
cursor: pointer; cursor: pointer;
background: v-bind('imageUrls.next') center / cover no-repeat; background: v-bind('imageUrls.next') center / cover no-repeat;
} }
.btn-back {
position: absolute;
bottom: 100px;
left: 1020px;
width: 316px;
height: 105px;
cursor: pointer;
background: v-bind('imageUrls.back') center / cover no-repeat;
}
</style> </style>
...@@ -136,7 +136,7 @@ function handleRoomState(data: any) { ...@@ -136,7 +136,7 @@ function handleRoomState(data: any) {
} }
} }
const { startGame, createRoom, backRoom } = useAdminGameSocket({ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
gameId: 'game6', gameId: 'game6',
onRoomState: handleRoomState, onRoomState: handleRoomState,
onRoomJoin: (data) => { onRoomJoin: (data) => {
...@@ -169,6 +169,14 @@ const nextRoundWithMusic = () => { ...@@ -169,6 +169,14 @@ const nextRoundWithMusic = () => {
nextRound() nextRound()
} }
const backHandler = () => {
if (confirm('是否关闭当前房间回到首页')) {
closeRoom();
stopGame6Music()
router.replace('/main');
}
}
onMounted(() => { onMounted(() => {
window.addEventListener('beforeunload', confirmRefresh) window.addEventListener('beforeunload', confirmRefresh)
playGame6Music() playGame6Music()
...@@ -181,12 +189,8 @@ onUnmounted(() => { ...@@ -181,12 +189,8 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<!-- <Loading :players="loadingPlayers" :player-count="playerCount"
@start="startGameWithMusic" /> -->
<!-- <Rank1 ref="rank1Ref" :rank-list="rankPlayers" @start="startGameWithMusic" /> -->
<!-- <Rank2 :rank-list="rankPlayers" @next="nextRoundWithMusic" /> -->
<Loading v-if="screen === 'loading'" :players="loadingPlayers" :player-count="playerCount" <Loading v-if="screen === 'loading'" :players="loadingPlayers" :player-count="playerCount"
@start="startGameWithMusic" /> @start="startGameWithMusic" @back="backHandler" />
<Rank1 v-else-if="screen === 'rank1'" ref="rank1Ref" :rank-list="rankPlayers" @start="startGameWithMusic" /> <Rank1 v-else-if="screen === 'rank1'" ref="rank1Ref" :rank-list="rankPlayers" @start="startGameWithMusic" />
<Rank2 v-else :rank-list="rankPlayers" @next="nextRoundWithMusic" /> <Rank2 v-else :rank-list="rankPlayers" @next="nextRoundWithMusic" @back="backHandler" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import router from '@/router';
import { $format_str } from '@/commons/utils.ts'; import { $format_str } from '@/commons/utils.ts';
import DesignStage from '@/components/DesignStage.vue' import DesignStage from '@/components/DesignStage.vue'
import { assetUrl, cssAssetUrl } from '@/commons/assets.ts'; import { assetUrl, cssAssetUrl } from '@/commons/assets.ts';
...@@ -11,6 +12,7 @@ defineProps<{ ...@@ -11,6 +12,7 @@ defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
start: []; start: [];
back:[];
}>(); }>();
const imageUrls = { const imageUrls = {
...@@ -34,8 +36,11 @@ const imageUrls = { ...@@ -34,8 +36,11 @@ const imageUrls = {
avatarAnimation: cssAssetUrl('avatar-red_animation.png'), avatarAnimation: cssAssetUrl('avatar-red_animation.png'),
avatar: cssAssetUrl('avatar-red.png'), avatar: cssAssetUrl('avatar-red.png'),
line: cssAssetUrl('game1/line.png'), line: cssAssetUrl('game1/line.png'),
start1: cssAssetUrl('game1/start-1.png'), // start1: cssAssetUrl('game1/start-1.png'),
start2: cssAssetUrl('game1/start-2.png'), // start2: cssAssetUrl('game1/start-2.png'),
start: cssAssetUrl('game1/start.png'),
back: cssAssetUrl('game1/back.png'),
}; };
const isStartPressed = ref(false); const isStartPressed = ref(false);
...@@ -83,9 +88,11 @@ const renderAvatar = (item: any | null) => { ...@@ -83,9 +88,11 @@ const renderAvatar = (item: any | null) => {
</div> </div>
<div class="list-container-line"></div> <div class="list-container-line"></div>
<div class="list-container-right"> <div class="list-container-right">
<div class="btn-start" :class="{ pressed: isStartPressed }" @pointerdown="pressStartButton" <!-- <div class="btn-start" :class="{ pressed: isStartPressed }" @pointerdown="pressStartButton"
@pointerup="releaseStartButton" @pointerleave="releaseStartButton" @pointerup="releaseStartButton" @pointerleave="releaseStartButton"
@pointercancel="releaseStartButton"></div> @pointercancel="releaseStartButton"></div> -->
<div class="btn-start" @click="pressStartButton"></div>
<div class="btn-back" @click="emit('back')"></div>
</div> </div>
</div> </div>
</div> </div>
...@@ -254,13 +261,22 @@ const renderAvatar = (item: any | null) => { ...@@ -254,13 +261,22 @@ const renderAvatar = (item: any | null) => {
width: 316px; width: 316px;
height: 105px; height: 105px;
margin-left: 60px; margin-left: 60px;
margin-top: 80px; margin-top: 10px;
background: v-bind('imageUrls.start1'); background: v-bind('imageUrls.start');
cursor: pointer; cursor: pointer;
} }
.btn-start.pressed { /* .btn-start.pressed {
background: v-bind('imageUrls.start2'); background: v-bind('imageUrls.start2');
} */
.btn-back {
width: 316px;
height: 105px;
margin-left: 60px;
margin-top: 30px;
background: v-bind('imageUrls.back');
cursor: pointer;
} }
} }
} }
......
...@@ -10,6 +10,7 @@ const props = defineProps<{ ...@@ -10,6 +10,7 @@ const props = defineProps<{
const emit = defineEmits<{ const emit = defineEmits<{
next: []; next: [];
back: [];
}>(); }>();
const FINAL_RANK_LIMIT = 10; const FINAL_RANK_LIMIT = 10;
...@@ -22,7 +23,8 @@ const imageUrls = { ...@@ -22,7 +23,8 @@ const imageUrls = {
avatar: cssAssetUrl('avatar-yellow.png'), avatar: cssAssetUrl('avatar-yellow.png'),
avatarAnimation: cssAssetUrl('avatar-yellow_animation.png'), avatarAnimation: cssAssetUrl('avatar-yellow_animation.png'),
rankIcon: cssAssetUrl('game6/no4.png'), rankIcon: cssAssetUrl('game6/no4.png'),
next: cssAssetUrl('game6/next-1.png'), next: cssAssetUrl('game1/next.png'),
back: cssAssetUrl('game1/back.png'),
}; };
const emptyPlayer = (index: number): Player => ({ const emptyPlayer = (index: number): Player => ({
...@@ -69,22 +71,16 @@ const renderAvatar = (item: any | null) => { ...@@ -69,22 +71,16 @@ const renderAvatar = (item: any | null) => {
<div class="avatar" :style="`${renderAvatar(list[0])}`"> <div class="avatar" :style="`${renderAvatar(list[0])}`">
</div> </div>
<div class="nickname">{{ list[0]?.nickname }}</div> <div class="nickname">{{ list[0]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
<div class="rank-no2"> <div class="rank-no2">
<div class="avatar" :style="`${renderAvatar(list[1])}`"> <div class="avatar" :style="`${renderAvatar(list[1])}`">
</div> </div>
<div class="nickname">{{ list[1]?.nickname }}</div> <div class="nickname">{{ list[1]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
<div class="rank-no3"> <div class="rank-no3">
<div class="avatar" :style="`${renderAvatar(list[2])}`"> <div class="avatar" :style="`${renderAvatar(list[2])}`">
</div> </div>
<div class="nickname">{{ list[2]?.nickname }}</div> <div class="nickname">{{ list[2]?.nickname }}</div>
<div class="guan"></div>
<div class="pai"></div>
</div> </div>
</div> </div>
...@@ -101,6 +97,7 @@ const renderAvatar = (item: any | null) => { ...@@ -101,6 +97,7 @@ const renderAvatar = (item: any | null) => {
</div> </div>
<div class="btn-next" @click="emit('next')"></div> <div class="btn-next" @click="emit('next')"></div>
<div class="btn-back" @click="emit('back')"></div>
</div> </div>
</DesignStage> </DesignStage>
</template> </template>
...@@ -322,10 +319,19 @@ const renderAvatar = (item: any | null) => { ...@@ -322,10 +319,19 @@ const renderAvatar = (item: any | null) => {
.btn-next { .btn-next {
position: absolute; position: absolute;
bottom: 50px; bottom: 50px;
left: 820px; left: 620px;
width: 318px; width: 316px;
height: 95px; height: 105px;
cursor: pointer; cursor: pointer;
background: v-bind('imageUrls.next') center / cover no-repeat; background: v-bind('imageUrls.next') center / cover no-repeat;
} }
.btn-back {
position: absolute;
bottom: 50px;
left: 1020px;
width: 316px;
height: 105px;
cursor: pointer;
background: v-bind('imageUrls.back') center / cover no-repeat;
}
</style> </style>
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