feat: 添加五子棋主页

This commit is contained in:
Litrix 2024-12-13 13:00:56 +08:00
parent 008290e3fd
commit 9ede5bdef9
5 changed files with 73 additions and 27 deletions

View File

@ -12,21 +12,24 @@
:router="true"
>
<el-menu-item index="/">首页</el-menu-item>
<el-sub-menu v-if="userStore.logined" class="festival-menu" index="festival">
<el-sub-menu class="festival-menu" index="festival">
<template #title>社团文化节</template>
<festival-menu-item src="/2048.png" title="2048" to="/2048" />
<festival-menu-item src="/gobang.svg" title="五子棋" to="/gobang" />
<festival-menu-item
v-if="userStore.logined"
src="/gobang.svg"
title="五子棋"
to="/gobang"
/>
</el-sub-menu>
</el-menu>
<div class="app-header-user flex center" v-loading="userStore.initializing">
<template v-if="!userStore.initializing">
<template v-if="userInfo && userInfo.id !== -1">
<!-- 仅收紧类型 -->
<template v-if="userInfo && userStore.logined">
<el-dropdown>
<div class="app-header-user__inner flex align-center">
<el-avatar :icon="userInfo.avatar ?? undefined"></el-avatar>
<div class="app-header-user__username">
{{ userInfo.name }}
</div>
</div>
<template #dropdown>
<el-dropdown-menu>
@ -34,6 +37,9 @@
</el-dropdown-menu>
</template>
</el-dropdown>
<div class="app-header-user__username">
{{ userInfo.name }}
</div>
</template>
<el-button type="primary" v-else @click="showLoginRegisterDialog = true">登录</el-button>
</template>
@ -56,7 +62,6 @@
min-height: 100vh;
}
.app-header {
--header-height: 50px;
--el-header-height: var(--header-height);
--el-loading-spinner-size: 30px;
background-color: white;
@ -75,7 +80,6 @@
}
.app-main {
padding: 0;
flex: 1;
display: flex;
}
.app-header-user {
@ -94,15 +98,13 @@
.app-router-view-leave-to {
opacity: 0;
}
.app-router-component__wrapper {
flex: 1;
}
</style>
<script setup lang="ts">
import { CloseBold } from '@element-plus/icons-vue';
import type { AxiosError } from 'axios';
import { ElMessage } from 'element-plus';
import { onMounted, provide, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { provide, ref } from 'vue';
import axiosInstance, { type RawResp } from './api/index';
import FestivalMenuItem from './components/FestivalMenuItem.vue';
import LoginRegisterDialog, {
@ -112,7 +114,6 @@ import LoginRegisterDialog, {
import { loginResponseSchema, registerResponseSchema } from './schemas/response';
import { usePageStore } from './stores/page.js';
import { useUserStore } from './stores/user';
import { storeToRefs } from 'pinia';
const userStore = useUserStore();
const { userInfo } = storeToRefs(userStore);
const pageStore = usePageStore();
@ -151,8 +152,8 @@ async function logout() {
userStore.token = null;
await userStore.updateSelfUserInfo(true);
}
onMounted(() => {
userStore.token = null;
userStore.updateSelfUserInfo(true);
});
// onMounted(() => {
// userStore.token = null;
// userStore.updateSelfUserInfo(true);
// });
</script>

View File

@ -3,14 +3,16 @@
padding: 0;
box-sizing: border-box;
}
:root {
--header-height: 50px;
}
body {
background-color: rgb(244, 246, 249);
}
#app {
width: 100vw;
height: 100vh;
min-width: 100vw;
min-height: 100vh;
}
.flex {
display: flex !important;
@ -31,3 +33,7 @@ body {
@extend .justify-center;
@extend .align-center;
}
.el-main {
padding: 0 !important;
}

View File

@ -10,6 +10,7 @@ declare module 'vue-router' {
interface RouteMeta {
permissionId?: RoutePermissionId;
shouldLogin?: boolean;
routeId?: number;
}
}
const routes: RouteRecordRaw[] = [
@ -31,13 +32,10 @@ const routes: RouteRecordRaw[] = [
{
path: '/2048',
component: () => import('@/views/Game2048Page.vue'),
meta: {
shouldLogin: true,
},
},
{
path: '/gobang',
component: () => import('@/views/Game2048Page.vue'),
component: () => import('@/views/GobangPage.vue'),
meta: {
shouldLogin: true,
},
@ -66,7 +64,7 @@ router.beforeEach(async (to) => {
const succeed = await userStore.updateSelfUserInfo(true);
if (!succeed) {
if (permissionId === undefined) {
return;
return true;
}
return pageStore.createTempErrorRoute(
{
@ -89,6 +87,7 @@ router.beforeEach(async (to) => {
} finally {
pageStore.removeRouteId(to);
}
return true;
});
router.afterEach((to) => {
const pageStore = usePageStore();

View File

@ -23,14 +23,15 @@ export const useUserStore = defineStore('user', () => {
const logined = computed(() => userInfo.value && userInfo.value.id !== -1);
watch(
userInfo,
(info) => {
initializing.value = !!info;
() => {
router.push({ path: router.currentRoute.value.fullPath, force: true });
},
{ flush: 'sync' },
);
async function updateSelfUserInfo(showErrorMessage: boolean): Promise<boolean> {
initializing.value = true;
console.log('called');
try {
const raw = await axiosInstance
.get<RawResp>('/api/user/info')

39
src/views/GobangPage.vue Normal file
View File

@ -0,0 +1,39 @@
<template>
<el-main class="gobang-page__wrapper">
<el-container>
<el-header class="gobang-page-header flex align-center">
<div class="gobang-page-header__title">五子棋</div>
<el-button type="primary">单人游戏</el-button>
</el-header>
<el-main class="gobang-page-main"></el-main>
</el-container>
</el-main>
</template>
<style lang="scss" scoped>
.gobang-page__wrapper {
background-color: white;
}
.gobang-page-header__title {
font-size: 25px;
font-weight: bold;
margin-right: auto;
}
.gobang-page-header {
--el-header-height: var(--header-height);
background-color: white;
gap: 10px;
border-bottom: 1px solid var(--el-border-color);
}
</style>
<script lang="ts" setup>
import { useWebSocket } from '@vueuse/core';
import { ref } from 'vue';
interface Room {}
interface GobangRespPart<N extends string, P extends object> {
name: N;
payload: P;
}
type GobangResp = GobangRespPart<'RoomInfo', { roomId: string; rooms: Room[] }>;
const rooms = ref<Room[]>();
// const { data } = useWebSocket<GobangResp>(`ws://127.0.0.1:58080/chess/${token}`);
</script>