🎈 perf: 暂存
This commit is contained in:
parent
5624d1ccd4
commit
c0e0199056
@ -23,7 +23,6 @@
|
||||
.app-header-menu--horizontal {
|
||||
flex: 1;
|
||||
margin-right: 10px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.app-header-menu :is(.el-menu-item, .el-sub-menu__title) {
|
||||
user-select: none;
|
||||
|
@ -1,17 +1,27 @@
|
||||
<template>
|
||||
<div class="gobang-header__content size-stretch flex align-center">
|
||||
<el-header class="gobang-header flex align-center">
|
||||
<router-link custom :to="{ name: 'GobangList' }" v-slot="{ navigate }">
|
||||
<div class="gobang-header__content-left flex align-center" @click="navigate">
|
||||
<div class="gobang-header__left flex align-center" @click="navigate">
|
||||
<el-icon :size="30"><icon-cs-gobang /></el-icon>
|
||||
<h2 v-show="!smLess" class="gobang-header__title">五子棋</h2>
|
||||
</div>
|
||||
</router-link>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</el-header>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
.gobang-header__content-left {
|
||||
gap: 10px;
|
||||
.gobang-header {
|
||||
--el-header-height: var(--header-height);
|
||||
background-color: white;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
position: fixed;
|
||||
top: var(--header-height);
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
user-select: none;
|
||||
&__left {
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<script setup lang="ts">
|
@ -1,15 +1,13 @@
|
||||
<template>
|
||||
<el-main class="gobang-list-page__wrapper flex">
|
||||
<el-container direction="vertical">
|
||||
<el-header class="gobang-header">
|
||||
<gobang-header-content class="justify-between">
|
||||
<div class="flex align-center">
|
||||
<el-button type="primary" :loading="loading" @click="refresh">刷新</el-button>
|
||||
<el-button @click="showDialog = true" type="success">创建房间</el-button>
|
||||
<el-button type="primary" disabled>单人游戏</el-button>
|
||||
</div>
|
||||
</gobang-header-content>
|
||||
</el-header>
|
||||
<gobang-header class="justify-between">
|
||||
<div class="flex align-center">
|
||||
<el-button type="primary" :loading="loading" @click="refresh">刷新</el-button>
|
||||
<el-button @click="showDialog = true" type="success">创建房间</el-button>
|
||||
<el-button type="primary" disabled>单人游戏</el-button>
|
||||
</div>
|
||||
</gobang-header>
|
||||
<el-main
|
||||
v-loading="loading"
|
||||
:element-loading-text="loadingText"
|
||||
@ -39,7 +37,6 @@
|
||||
</el-main>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@import url('@/assets/gobang-header.scss');
|
||||
.gobang-list-page__wrapper {
|
||||
background-color: white;
|
||||
}
|
||||
@ -85,46 +82,93 @@ export function toRoomRender(room: Room): RoomRender {
|
||||
briefId: room.id.slice(0, 8),
|
||||
});
|
||||
}
|
||||
export type Request =
|
||||
| SimplePart<'RoomList'>
|
||||
| SimplePart<'CreateRoom'>
|
||||
| Part<'PlayerJoin', { roomId: RoomId }>
|
||||
| SimplePart<'ResetRoom'>;
|
||||
export type RequestOf<T extends Request['name']> = Extract<Request, { name: T }>;
|
||||
export interface SimplePart<N extends string> {
|
||||
name: N;
|
||||
}
|
||||
export interface Part<N extends string, P extends Record<string, unknown>> extends SimplePart<N> {
|
||||
type Payload = Record<string, unknown>;
|
||||
export interface PayloadPart<N extends string, P extends Payload> extends SimplePart<N> {
|
||||
payload: P;
|
||||
}
|
||||
export type RespErrorPart = Part<'Error', { reason: string }>;
|
||||
export type Request =
|
||||
| SimplePart<'RoomList'>
|
||||
| SimplePart<'CreateRoom'>
|
||||
| PayloadPart<'PlayerJoin', { roomId: RoomId }>
|
||||
| SimplePart<'ResetRoom'>;
|
||||
export type RequestOf<T extends Request['name']> = Extract<Request, { name: T }>;
|
||||
export const relations = {
|
||||
RoomList: 'RoomList',
|
||||
RoomCreated: 'CreateRoom',
|
||||
PlayerSideAllocation: 'PlayerJoin',
|
||||
};
|
||||
const reversedRelations: Record<string, string[]> = {};
|
||||
for (const [k, v] of Object.entries(relations)) {
|
||||
(reversedRelations[v] ??= []).push(k);
|
||||
}
|
||||
export interface RelatedPart<N extends keyof typeof relations, P extends Payload>
|
||||
extends PayloadPart<N, P> {
|
||||
originalPacketName?: (typeof relations)[N];
|
||||
}
|
||||
export interface RespErrorPart extends PayloadPart<'Error', { reason: string }> {
|
||||
originalPacketName: Request['name'];
|
||||
}
|
||||
export type Resp =
|
||||
| RespErrorPart
|
||||
| Part<'UserInfo', SucceedUserInfoResponse>
|
||||
// RoomList
|
||||
| Part<'RoomList', { rooms: Room[] }>
|
||||
// CreateRoom
|
||||
| Part<'RoomCreated', { roomId: RoomId }>
|
||||
// PlayerJoin
|
||||
| Part<'PlayerSideAllocation', { isWhite: boolean }>;
|
||||
| PayloadPart<'UserInfo', SucceedUserInfoResponse>
|
||||
| RelatedPart<'RoomList', { rooms: Room[] }>
|
||||
| RelatedPart<'RoomCreated', { roomId: RoomId }>
|
||||
| RelatedPart<'PlayerSideAllocation', { isWhite: boolean }>;
|
||||
export type RespOf<T extends Resp['name']> = Extract<Resp, { name: T }>;
|
||||
export type RespHandlerMap = {
|
||||
[P in Resp['name']]?: (payload: RespOf<P>['payload']) => void;
|
||||
};
|
||||
export function useGobangSocket(respHandlers: RespHandlerMap) {
|
||||
interface UseGobangSocketOptions {
|
||||
succeed: {
|
||||
[P in Resp['name']]?: (payload: RespOf<P>['payload']) => void;
|
||||
};
|
||||
error: {
|
||||
[P in Resp['name']]?: (reason: string) => void;
|
||||
};
|
||||
finally: object;
|
||||
}
|
||||
export function useGobangSocket(options: UseGobangSocketOptions) {
|
||||
const { succeed: handlers } = options;
|
||||
const userStore = useUserStore();
|
||||
return useWebSocket<string>(`ws://wzpmc.cn:18080/chess/${userStore.token}`, {
|
||||
onMessage(_, { data }) {
|
||||
const resp: Resp = JSON.parse(data);
|
||||
console.log(resp);
|
||||
respHandlers[resp.name]?.(resp.payload as any);
|
||||
const map = new Map<string, Set<string>>();
|
||||
const { send: _send } = useWebSocket<string>(
|
||||
`ws://172.16.114.84:58080/chess/${userStore.token}`,
|
||||
{
|
||||
onMessage(_, { data }) {
|
||||
const resp: Resp = JSON.parse(data);
|
||||
const { name } = resp;
|
||||
let excFinally = true;
|
||||
if ('originalPacketName' in resp) {
|
||||
const set = map.get(name);
|
||||
if (set) {
|
||||
set.delete(name);
|
||||
if (!set.size) {
|
||||
map.delete(name);
|
||||
} else {
|
||||
excFinally = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excFinally) {
|
||||
options.finally;
|
||||
}
|
||||
console.log(resp);
|
||||
handlers[name]?.(resp.payload as any);
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
return {
|
||||
send(data: Request) {
|
||||
const respNames = reversedRelations[data.name];
|
||||
map.set(data.name, respNames && new Set(respNames));
|
||||
_send(JSON.stringify(data));
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import CreateGobangRoomDialog from '@/components/gobang/CreateGobangRoomDialog.vue';
|
||||
import GobangHeaderContent from '@/components/gobang/GobangHeaderContent.vue';
|
||||
import GobangHeader from '@/components/gobang/GobangHeader.vue';
|
||||
import router from '@/router';
|
||||
import type { SucceedUserInfoResponse } from '@/schemas';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
@ -136,17 +180,19 @@ const rooms = ref<RoomRender[]>([]);
|
||||
const loading = ref(false);
|
||||
const loadingText = ref<string>();
|
||||
const { send } = useGobangSocket({
|
||||
Error(p) {
|
||||
ElMessage.error(p.reason);
|
||||
loading.value = false;
|
||||
},
|
||||
RoomList(p) {
|
||||
rooms.value = p.rooms.map(toRoomRender);
|
||||
console.log(toRaw(rooms.value));
|
||||
loading.value = false;
|
||||
},
|
||||
RoomCreated(p) {
|
||||
play(p.roomId);
|
||||
succeed: {
|
||||
Error(p) {
|
||||
ElMessage.error(p.reason);
|
||||
loading.value = false;
|
||||
},
|
||||
RoomList(p) {
|
||||
rooms.value = p.rooms.map(toRoomRender);
|
||||
console.log(toRaw(rooms.value));
|
||||
loading.value = false;
|
||||
},
|
||||
RoomCreated(p) {
|
||||
play(p.roomId);
|
||||
},
|
||||
},
|
||||
});
|
||||
function refresh() {
|
||||
|
@ -4,17 +4,15 @@
|
||||
class="gobang-play-page__wrapper flex"
|
||||
>
|
||||
<el-container v-if="state !== 'firstLoading'">
|
||||
<el-header class="gobang-header">
|
||||
<gobang-header-content class="justify-between">
|
||||
<div class="flex align-center">
|
||||
<template v-if="roomId">
|
||||
<h2 v-show="!smLess">蓝色基因对战平台</h2>
|
||||
<h3 class="gobang-play-page__brief-id flex center">#{{ roomId.slice(0, 8) }}</h3>
|
||||
</template>
|
||||
<h2 v-else>单人游戏</h2>
|
||||
</div>
|
||||
</gobang-header-content>
|
||||
</el-header>
|
||||
<gobang-header class="justify-between">
|
||||
<div class="flex align-center">
|
||||
<template v-if="roomId">
|
||||
<h2 v-show="!smLess">蓝色基因对战平台</h2>
|
||||
<h3 class="gobang-play-page__brief-id flex center">#{{ roomId.slice(0, 8) }}</h3>
|
||||
</template>
|
||||
<h2 v-else>单人游戏</h2>
|
||||
</div>
|
||||
</gobang-header>
|
||||
<el-main class="gobang-play-page-main center flex">
|
||||
<div class="gobang-chessboard" :style="{}">
|
||||
<canvas class="gobang-chessboard__background" ref="canvas"></canvas>
|
||||
@ -41,7 +39,6 @@
|
||||
</el-main>
|
||||
</template>
|
||||
<style lang="scss" scoped>
|
||||
@import url('@/assets/gobang-header.scss');
|
||||
:deep(.gobang-header__content-left) {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
@ -91,7 +88,7 @@
|
||||
}
|
||||
</style>
|
||||
<script setup lang="ts">
|
||||
import GobangHeaderContent from '@/components/gobang/GobangHeaderContent.vue';
|
||||
import GobangHeader from '@/components/gobang/GobangHeader.vue';
|
||||
import { useMediaStore } from '@/stores/media';
|
||||
import { create2DArray } from '@/utils';
|
||||
import { type RequestOf, type RoomId, useGobangSocket } from '@/views/GobangListPage.vue';
|
||||
|
Loading…
x
Reference in New Issue
Block a user