2024-04-08 18:00:04 +08:00
|
|
|
<template>
|
2024-07-11 22:33:48 +08:00
|
|
|
<el-container class="app-root" direction="vertical">
|
|
|
|
<el-header class="app-header" height="50px">
|
|
|
|
<div class="app-header-inner">
|
|
|
|
<router-link v-slot="{ navigate }" :to="{ path: '/', force: true }" custom>
|
|
|
|
<div class="header-title" @click="navigate()">社团展示系统</div>
|
|
|
|
</router-link>
|
|
|
|
<transition name="header-content-container">
|
|
|
|
<template v-if="arrayIncludes(['initialized', 'failed'], userStore.userInfoStatus)">
|
|
|
|
<nav class="header-content-container">
|
|
|
|
<el-menu
|
|
|
|
:default-active="route.fullPath"
|
|
|
|
:ellipsis="false"
|
|
|
|
:router="true"
|
|
|
|
mode="horizontal"
|
|
|
|
>
|
|
|
|
<div style="flex: 1"></div>
|
|
|
|
<el-menu-item index="/2048">
|
|
|
|
<img alt="2048" class="header-menu-image" src="@/assets/2048.png" />
|
|
|
|
</el-menu-item>
|
|
|
|
</el-menu>
|
2024-12-09 20:43:08 +08:00
|
|
|
<template v-if="userStore.userInfo && userStore.userInfo.id !== -1">
|
2024-07-11 22:33:48 +08:00
|
|
|
<div class="username">
|
|
|
|
{{ userStore.userInfo.name }}
|
|
|
|
</div>
|
|
|
|
<el-dropdown ref="dropdownRef">
|
|
|
|
<el-avatar :icon="userStore.userInfo.avatar || Avatar" :size="40"></el-avatar>
|
|
|
|
<template #dropdown>
|
|
|
|
<el-dropdown-menu>
|
2024-12-09 20:43:08 +08:00
|
|
|
<!-- <router-link v-slot="{ navigate }" custom to="/user">
|
2024-07-11 22:33:48 +08:00
|
|
|
<el-dropdown-item :icon="UserFilled" @click="navigate()">
|
|
|
|
个人主页
|
|
|
|
</el-dropdown-item>
|
2024-12-09 20:43:08 +08:00
|
|
|
</router-link> -->
|
2024-07-11 22:33:48 +08:00
|
|
|
<el-dropdown-item :icon="CloseBold" @click="logout">
|
|
|
|
退出登录
|
|
|
|
</el-dropdown-item>
|
|
|
|
</el-dropdown-menu>
|
|
|
|
</template>
|
|
|
|
</el-dropdown>
|
2024-06-13 18:00:41 +08:00
|
|
|
</template>
|
2024-07-11 22:33:48 +08:00
|
|
|
<el-avatar
|
|
|
|
v-else
|
|
|
|
:size="40"
|
|
|
|
style="color: black; user-select: none; cursor: pointer"
|
|
|
|
@click="showLoginRegisterDialog = true"
|
|
|
|
>
|
|
|
|
登录
|
|
|
|
</el-avatar>
|
|
|
|
</nav>
|
2024-06-13 18:00:41 +08:00
|
|
|
</template>
|
2024-07-11 22:33:48 +08:00
|
|
|
<div v-else class="header-content-container">
|
|
|
|
<el-icon class="loading-icon is-loading" color="dimgrey" size="25">
|
|
|
|
<icon-cs-loading />
|
|
|
|
</el-icon>
|
|
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</div>
|
2024-04-09 17:57:51 +08:00
|
|
|
</el-header>
|
2024-12-09 20:43:08 +08:00
|
|
|
<el-main v-loading="!!pageStore.pageLoadingCount">
|
2024-07-11 22:33:48 +08:00
|
|
|
<router-view v-slot="{ Component: comp }">
|
|
|
|
<transition appear mode="out-in" name="page-root">
|
|
|
|
<component :is="comp" />
|
|
|
|
</transition>
|
|
|
|
</router-view>
|
|
|
|
<transition name="page-root"></transition>
|
2024-12-09 20:43:08 +08:00
|
|
|
<!-- <div
|
2024-07-11 22:33:48 +08:00
|
|
|
:style="
|
|
|
|
pageStore.pageLoadingCount
|
|
|
|
? {
|
|
|
|
opacity: 1,
|
|
|
|
transition: 'opacity 0.75s 0.15s',
|
|
|
|
zIndex: 99
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
opacity: 0,
|
|
|
|
transition: 'opacity 0.3s',
|
|
|
|
zIndex: -1
|
|
|
|
}
|
|
|
|
"
|
|
|
|
class="page-loading-mask"
|
|
|
|
>
|
|
|
|
<div class="page-loading-icon-container">
|
|
|
|
<el-icon class="loading-icon is-loading" color="white" size="60">
|
|
|
|
<icon-cs-loading />
|
|
|
|
</el-icon>
|
|
|
|
</div>
|
2024-12-09 20:43:08 +08:00
|
|
|
</div> -->
|
2024-07-11 22:33:48 +08:00
|
|
|
</el-main>
|
2024-04-09 17:57:51 +08:00
|
|
|
</el-container>
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-dialog
|
|
|
|
v-model="showLoginRegisterDialog"
|
|
|
|
:align-center="true"
|
2024-07-08 21:31:47 +08:00
|
|
|
class="login-dialog"
|
|
|
|
width="400"
|
2024-04-14 14:40:34 +08:00
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<el-tabs v-model="loginRegisterDialogActiveName">
|
|
|
|
<el-tab-pane label="登录" name="login">
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-form ref="loginFormRef" :model="loginFormData" :rules="loginFormRules" @submit.prevent>
|
2024-04-10 17:51:13 +08:00
|
|
|
<el-form-item prop="username">
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-input
|
|
|
|
v-model="loginFormData.username"
|
|
|
|
:disabled="logining"
|
2024-07-08 21:31:47 +08:00
|
|
|
placeholder="请输入用户名"
|
2024-04-14 14:40:34 +08:00
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<template #prepend>
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-icon>
|
|
|
|
<icon-ep-user-filled />
|
|
|
|
</el-icon>
|
2024-04-10 17:51:13 +08:00
|
|
|
</template>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item prop="password">
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-input
|
|
|
|
v-model="loginFormData.password"
|
|
|
|
:disabled="logining"
|
2024-07-08 21:31:47 +08:00
|
|
|
placeholder="请输入密码"
|
|
|
|
type="password"
|
2024-04-14 14:40:34 +08:00
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<template #prepend>
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-icon>
|
|
|
|
<icon-cs-lock />
|
|
|
|
</el-icon>
|
2024-04-10 17:51:13 +08:00
|
|
|
</template>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
2024-04-19 20:52:42 +08:00
|
|
|
<el-form-item prop="verifyCode">
|
|
|
|
<verify-input v-model="loginFormData" :disabled="logining" />
|
|
|
|
</el-form-item>
|
2024-04-18 18:02:43 +08:00
|
|
|
<el-form-item style="margin-bottom: 0">
|
|
|
|
<el-button
|
2024-07-08 21:31:47 +08:00
|
|
|
:loading="logining"
|
2024-05-10 17:59:25 +08:00
|
|
|
native-type="submit"
|
2024-04-18 18:02:43 +08:00
|
|
|
style="width: 100%"
|
2024-07-08 21:31:47 +08:00
|
|
|
type="primary"
|
2024-04-19 20:52:42 +08:00
|
|
|
@click="submitLoginForm"
|
2024-04-18 18:02:43 +08:00
|
|
|
>
|
|
|
|
登录
|
|
|
|
</el-button>
|
|
|
|
</el-form-item>
|
2024-04-10 17:51:13 +08:00
|
|
|
</el-form>
|
|
|
|
</el-tab-pane>
|
|
|
|
<el-tab-pane label="注册" name="register">
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-form
|
|
|
|
ref="registerFormRef"
|
|
|
|
:model="registerFormData"
|
|
|
|
:rules="registerFormRules"
|
|
|
|
@submit.prevent
|
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<el-form-item prop="username">
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-input
|
|
|
|
v-model="registerFormData.username"
|
|
|
|
:disabled="registering"
|
2024-07-08 21:31:47 +08:00
|
|
|
placeholder="请输入注册用户名"
|
2024-04-14 14:40:34 +08:00
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<template #prepend>
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-icon>
|
|
|
|
<icon-cs-user />
|
|
|
|
</el-icon>
|
2024-04-10 17:51:13 +08:00
|
|
|
</template>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item prop="password">
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-input
|
|
|
|
v-model="registerFormData.password"
|
|
|
|
:disabled="registering"
|
2024-07-08 21:31:47 +08:00
|
|
|
placeholder="请输入密码"
|
|
|
|
type="password"
|
2024-04-14 14:40:34 +08:00
|
|
|
>
|
2024-04-10 17:51:13 +08:00
|
|
|
<template #prepend>
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-icon>
|
|
|
|
<icon-cs-lock />
|
|
|
|
</el-icon>
|
2024-04-10 17:51:13 +08:00
|
|
|
</template>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
|
|
|
<el-form-item prop="confirmPassword">
|
|
|
|
<el-input
|
2024-04-14 14:40:34 +08:00
|
|
|
v-model="registerFormData.confirmPassword"
|
|
|
|
:disabled="registering"
|
2024-07-08 21:31:47 +08:00
|
|
|
placeholder="请确认密码"
|
|
|
|
type="password"
|
2024-04-10 17:51:13 +08:00
|
|
|
>
|
|
|
|
<template #prepend>
|
2024-05-10 17:59:25 +08:00
|
|
|
<el-icon>
|
|
|
|
<icon-cs-lock />
|
|
|
|
</el-icon>
|
2024-04-10 17:51:13 +08:00
|
|
|
</template>
|
|
|
|
</el-input>
|
|
|
|
</el-form-item>
|
2024-04-19 20:52:42 +08:00
|
|
|
<el-form-item prop="verifyCode">
|
|
|
|
<verify-input v-model="registerFormData" :disabled="registering" />
|
|
|
|
</el-form-item>
|
2024-04-10 17:51:13 +08:00
|
|
|
<el-form-item style="margin-bottom: 0">
|
2024-04-14 14:40:34 +08:00
|
|
|
<el-button
|
2024-07-08 21:31:47 +08:00
|
|
|
:loading="registering"
|
2024-05-10 17:59:25 +08:00
|
|
|
native-type="submit"
|
2024-04-14 14:40:34 +08:00
|
|
|
style="width: 100%"
|
2024-07-08 21:31:47 +08:00
|
|
|
type="primary"
|
2024-04-14 14:40:34 +08:00
|
|
|
@click="submitRegisterForm"
|
|
|
|
>
|
|
|
|
注册
|
|
|
|
</el-button>
|
2024-04-10 17:51:13 +08:00
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
</el-tab-pane>
|
|
|
|
</el-tabs>
|
|
|
|
</el-dialog>
|
2024-04-08 18:00:04 +08:00
|
|
|
</template>
|
2024-07-08 21:31:47 +08:00
|
|
|
<style lang="scss" scoped>
|
2024-07-11 22:33:48 +08:00
|
|
|
.app-root {
|
|
|
|
min-height: 100vh;
|
|
|
|
}
|
|
|
|
|
|
|
|
.app-header {
|
|
|
|
--el-header-padding: 0;
|
|
|
|
--el-menu-horizontal-height: 50px;
|
|
|
|
--el-menu-base-level-padding: 10px;
|
|
|
|
position: sticky;
|
|
|
|
top: 0;
|
2024-04-09 17:57:51 +08:00
|
|
|
display: flex;
|
2024-07-11 22:33:48 +08:00
|
|
|
justify-content: center;
|
2024-04-09 17:57:51 +08:00
|
|
|
border-bottom: 1px solid var(--el-border-color);
|
2024-06-13 18:00:41 +08:00
|
|
|
box-shadow: 0 1px 5px rgba(black, 0.1);
|
2024-05-10 17:59:25 +08:00
|
|
|
background-color: white;
|
2024-06-13 18:00:41 +08:00
|
|
|
z-index: 100;
|
2024-07-11 22:33:48 +08:00
|
|
|
overflow: hidden;
|
2024-04-09 17:57:51 +08:00
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-07-11 22:33:48 +08:00
|
|
|
.app-header-inner {
|
|
|
|
position: relative;
|
|
|
|
width: var(--page-content-width);
|
2024-05-10 17:59:25 +08:00
|
|
|
height: 100%;
|
2024-07-11 22:33:48 +08:00
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: stretch;
|
|
|
|
margin: 0 15px;
|
2024-05-10 17:59:25 +08:00
|
|
|
}
|
|
|
|
|
2024-07-11 22:33:48 +08:00
|
|
|
.header-content-container {
|
|
|
|
height: 50px;
|
|
|
|
flex: 1;
|
2024-04-14 14:40:34 +08:00
|
|
|
display: flex;
|
2024-07-11 22:33:48 +08:00
|
|
|
justify-content: flex-end;
|
2024-04-14 14:40:34 +08:00
|
|
|
align-items: center;
|
2024-07-11 22:33:48 +08:00
|
|
|
transition-property: opacity;
|
|
|
|
transition-duration: 0.3s;
|
|
|
|
|
|
|
|
&:has(.loading-icon) {
|
|
|
|
position: absolute;
|
|
|
|
top: 0;
|
|
|
|
right: 0;
|
|
|
|
}
|
2024-04-14 14:40:34 +08:00
|
|
|
}
|
2024-04-18 17:57:35 +08:00
|
|
|
|
2024-07-11 22:33:48 +08:00
|
|
|
.header-content-container .el-menu {
|
|
|
|
flex: 1;
|
2024-06-05 18:02:15 +08:00
|
|
|
margin-right: 10px;
|
|
|
|
}
|
|
|
|
|
2024-07-11 22:33:48 +08:00
|
|
|
.header-content-container .header-menu-image {
|
|
|
|
width: 40px;
|
|
|
|
display: flex;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.header-content-container-enter-from,
|
|
|
|
.header-content-container-leave-to {
|
|
|
|
opacity: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.el-main {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
position: relative;
|
|
|
|
padding: 0;
|
|
|
|
|
|
|
|
&:has(.page-root-enter-active, .page-root-leave-active) {
|
|
|
|
overflow-x: hidden;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.page-root {
|
|
|
|
transition-property: opacity, transform;
|
|
|
|
transition-duration: 0.3s;
|
|
|
|
|
|
|
|
&:not(.page-max-width) {
|
|
|
|
width: var(--page-content-width);
|
|
|
|
margin: 0 15px;
|
|
|
|
}
|
|
|
|
|
|
|
|
&.page-max-width {
|
|
|
|
width: 100vw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.page-root-enter-from {
|
|
|
|
opacity: 0;
|
|
|
|
|
|
|
|
&:not(.page-max-width) {
|
|
|
|
transform: translateX(-30px);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.page-root-leave-to {
|
|
|
|
opacity: 0;
|
|
|
|
|
|
|
|
&:not(.page-max-width) {
|
|
|
|
transform: translateX(30px);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
.page-loading-mask {
|
|
|
|
position: absolute;
|
|
|
|
inset: 0;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
transition-property: opacity;
|
|
|
|
background-color: rgb(black, 0.3);
|
|
|
|
z-index: 99;
|
|
|
|
}
|
|
|
|
|
|
|
|
.page-loading-icon-container {
|
|
|
|
width: 100px;
|
|
|
|
height: 100px;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
border-radius: 6px;
|
|
|
|
background-color: rgb(black, 0.5);
|
2024-06-05 18:02:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.nav-img-items {
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.nav-img-items img {
|
|
|
|
width: 40px;
|
|
|
|
height: 40px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.game-2048 {
|
|
|
|
margin-right: 20px;
|
|
|
|
}
|
|
|
|
|
2024-05-10 17:59:25 +08:00
|
|
|
.header-title {
|
2024-07-11 22:33:48 +08:00
|
|
|
font-size: 20px;
|
|
|
|
line-height: 50px;
|
|
|
|
user-select: none;
|
|
|
|
cursor: pointer;
|
2024-04-09 17:57:51 +08:00
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
.username {
|
|
|
|
margin-right: 10px;
|
|
|
|
}
|
2024-04-09 17:57:51 +08:00
|
|
|
</style>
|
2024-07-08 21:31:47 +08:00
|
|
|
<script lang="ts" setup>
|
2024-12-09 20:43:08 +08:00
|
|
|
import axiosInstance, { type RawResp } from '@/api';
|
2024-04-18 18:02:43 +08:00
|
|
|
import { type VerifyImagePath } from '@/components/VerifyInput.vue';
|
2024-05-10 17:59:25 +08:00
|
|
|
import { loginResponseSchema, registerResponseSchema } from '@/schemas';
|
2024-04-14 14:40:34 +08:00
|
|
|
import { useUserStore } from '@/stores';
|
2024-07-11 22:33:48 +08:00
|
|
|
import { usePageStore } from '@/stores/page';
|
|
|
|
import { arrayIncludes, errorMessage } from '@/utils';
|
2024-12-10 11:38:40 +08:00
|
|
|
import { Avatar, CloseBold } from '@element-plus/icons-vue';
|
2024-04-14 14:40:34 +08:00
|
|
|
import { AxiosError } from 'axios';
|
2024-04-18 17:57:35 +08:00
|
|
|
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
|
2024-04-19 20:52:42 +08:00
|
|
|
import { partial } from 'lodash-es';
|
2024-05-10 17:59:25 +08:00
|
|
|
import { reactive, ref, watch } from 'vue';
|
2024-07-11 22:33:48 +08:00
|
|
|
import { RouterView, useRoute, useRouter } from 'vue-router';
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-08 18:00:04 +08:00
|
|
|
const router = useRouter();
|
2024-07-11 22:33:48 +08:00
|
|
|
const route = useRoute();
|
2024-04-14 14:40:34 +08:00
|
|
|
const userStore = useUserStore();
|
2024-07-11 22:33:48 +08:00
|
|
|
const pageStore = usePageStore();
|
2024-05-10 17:59:25 +08:00
|
|
|
watch(
|
2024-07-11 22:33:48 +08:00
|
|
|
() => userStore.userInfoStatus,
|
2024-05-10 17:59:25 +08:00
|
|
|
(value) => {
|
2024-07-11 22:33:48 +08:00
|
|
|
if (value === 'initialized' && userStore.token === null) {
|
2024-05-10 17:59:25 +08:00
|
|
|
showLoginRegisterDialog.value = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
2024-04-14 14:40:34 +08:00
|
|
|
const showLoginRegisterDialog = ref(false);
|
|
|
|
watch(showLoginRegisterDialog, (value) => {
|
|
|
|
if (value) {
|
|
|
|
logining.value = false;
|
2024-04-19 20:52:42 +08:00
|
|
|
loginFormData.verifyImage = 'none';
|
2024-04-14 14:40:34 +08:00
|
|
|
loginFormRef.value?.resetFields();
|
|
|
|
registering.value = false;
|
2024-04-19 20:52:42 +08:00
|
|
|
registerFormData.verifyImage = 'none';
|
2024-04-14 14:40:34 +08:00
|
|
|
registerFormRef.value?.resetFields();
|
|
|
|
}
|
|
|
|
});
|
2024-04-10 17:51:13 +08:00
|
|
|
const loginRegisterDialogActiveName = ref('login');
|
|
|
|
const loginFormRef = ref<FormInstance>();
|
2024-12-10 11:38:40 +08:00
|
|
|
let loginFormData = reactive({
|
2024-04-14 14:40:34 +08:00
|
|
|
username: 'wubaopu2',
|
2024-04-18 17:57:35 +08:00
|
|
|
password: '123456',
|
|
|
|
verifyImage: 'none' as VerifyImagePath,
|
2024-04-19 20:52:42 +08:00
|
|
|
verifyCode: ''
|
2024-04-10 17:51:13 +08:00
|
|
|
});
|
|
|
|
const loginFormRules = reactive<FormRules<typeof loginFormData>>({
|
2024-04-14 14:40:34 +08:00
|
|
|
username: [
|
2024-04-19 20:52:42 +08:00
|
|
|
{ required: true, message: '请输入用户名' },
|
|
|
|
{ min: 6, message: '用户名长度不能小于3位' }
|
2024-04-14 14:40:34 +08:00
|
|
|
],
|
|
|
|
password: [
|
2024-04-19 20:52:42 +08:00
|
|
|
{ required: true, message: '请输入密码' },
|
|
|
|
{ min: 6, message: '密码长度不能小于6位' }
|
|
|
|
],
|
|
|
|
verifyCode: [
|
|
|
|
{ required: true, message: '请输入验证码' },
|
|
|
|
{ pattern: /[0-9A-Za-z]{4}/, message: '验证码不符合格式' }
|
2024-04-14 14:40:34 +08:00
|
|
|
]
|
2024-04-10 17:51:13 +08:00
|
|
|
});
|
2024-04-14 14:40:34 +08:00
|
|
|
const logining = ref(false);
|
2024-04-10 17:51:13 +08:00
|
|
|
const registerFormRef = ref<FormInstance>();
|
2024-12-10 11:38:40 +08:00
|
|
|
let registerFormData = reactive({
|
2024-04-10 17:51:13 +08:00
|
|
|
username: '',
|
|
|
|
password: '',
|
2024-04-18 17:57:35 +08:00
|
|
|
confirmPassword: '',
|
|
|
|
verifyImage: 'none' as VerifyImagePath,
|
2024-04-19 20:52:42 +08:00
|
|
|
verifyCode: ''
|
2024-04-10 17:51:13 +08:00
|
|
|
});
|
|
|
|
const registerFormRules = reactive<FormRules<typeof registerFormData>>({
|
2024-04-14 14:40:34 +08:00
|
|
|
...loginFormRules,
|
2024-04-10 17:58:10 +08:00
|
|
|
confirmPassword: [
|
|
|
|
{
|
2024-05-10 17:59:25 +08:00
|
|
|
validator(_, value, callback) {
|
2024-04-14 14:40:34 +08:00
|
|
|
if (value === '') {
|
|
|
|
callback('请输入密码');
|
|
|
|
} else if (value !== registerFormData.password) {
|
|
|
|
callback('密码不一致');
|
|
|
|
} else if (value.length < 6) {
|
|
|
|
callback('密码长度不能小于6位');
|
2024-04-10 17:58:10 +08:00
|
|
|
} else {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
2024-04-10 17:51:13 +08:00
|
|
|
});
|
2024-04-14 14:40:34 +08:00
|
|
|
const registering = ref(false);
|
|
|
|
const loginErrorMessage = partial(errorMessage, '登录');
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
interface LoginParams {
|
|
|
|
username: string;
|
|
|
|
password: string;
|
2024-04-18 18:02:43 +08:00
|
|
|
key: string;
|
|
|
|
code: string;
|
2024-04-14 14:40:34 +08:00
|
|
|
}
|
2024-04-18 17:57:35 +08:00
|
|
|
|
2024-12-09 20:43:08 +08:00
|
|
|
async function login(params: LoginParams): Promise<boolean> {
|
|
|
|
const loginRespRaw = await axiosInstance
|
|
|
|
.post<RawResp>('/api/user/login', params)
|
|
|
|
.then((r) => r.data)
|
|
|
|
.catch((e: AxiosError) => {
|
2024-04-14 14:40:34 +08:00
|
|
|
ElMessage.error(loginErrorMessage(e.code, e.message));
|
2024-12-09 20:43:08 +08:00
|
|
|
});
|
|
|
|
if (!loginRespRaw) return false;
|
|
|
|
const loginResp = loginResponseSchema.parse(loginRespRaw);
|
|
|
|
if (loginResp.type === 'error') {
|
|
|
|
ElMessage.error(loginErrorMessage(loginResp.code, loginResp.msg));
|
2024-04-14 14:40:34 +08:00
|
|
|
return false;
|
|
|
|
}
|
2024-12-09 20:43:08 +08:00
|
|
|
await userStore.updateSelfUserInfo(true);
|
|
|
|
return true;
|
2024-04-14 14:40:34 +08:00
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
async function submitLoginForm() {
|
|
|
|
let succeed = false;
|
|
|
|
logining.value = true;
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
await loginFormRef.value?.validate();
|
|
|
|
} catch (e) {
|
|
|
|
return;
|
|
|
|
}
|
2024-12-10 11:38:40 +08:00
|
|
|
if (typeof loginFormData.verifyImage !== 'object') {
|
2024-04-19 20:52:42 +08:00
|
|
|
ElMessage.error('请获取验证码');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const {
|
|
|
|
username,
|
|
|
|
password,
|
|
|
|
verifyImage: { key },
|
|
|
|
verifyCode: code
|
|
|
|
} = loginFormData;
|
|
|
|
succeed = await login({
|
|
|
|
username,
|
|
|
|
password,
|
|
|
|
key,
|
|
|
|
code
|
|
|
|
});
|
2024-04-14 14:40:34 +08:00
|
|
|
} finally {
|
|
|
|
if (succeed) {
|
2024-12-09 20:43:08 +08:00
|
|
|
showLoginRegisterDialog.value = false;
|
2024-04-14 14:40:34 +08:00
|
|
|
} else {
|
2024-05-10 17:59:25 +08:00
|
|
|
loginFormData.verifyImage = 'none';
|
|
|
|
loginFormRef.value?.resetFields('verifyCode');
|
2024-04-14 14:40:34 +08:00
|
|
|
logining.value = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
const registerErrorMessage = partial(errorMessage, '注册');
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-19 20:52:42 +08:00
|
|
|
interface RegisterParams extends LoginParams {
|
|
|
|
auth: number;
|
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-19 20:52:42 +08:00
|
|
|
async function register(params: RegisterParams) {
|
2024-04-14 14:40:34 +08:00
|
|
|
try {
|
|
|
|
const registerResp = registerResponseSchema.parse(
|
2024-04-19 20:52:42 +08:00
|
|
|
(await axiosInstance.put('/api/user/create', params)).data
|
2024-04-14 14:40:34 +08:00
|
|
|
);
|
|
|
|
if (registerResp.type === 'error') {
|
|
|
|
ElMessage.error({
|
|
|
|
message: registerErrorMessage(registerResp.code, registerResp.msg)
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} catch (e) {
|
|
|
|
if (e instanceof AxiosError) {
|
|
|
|
ElMessage.error(registerErrorMessage(e.code, e.message));
|
2024-04-18 17:57:35 +08:00
|
|
|
} else {
|
|
|
|
ElMessage.error('error');
|
2024-04-14 14:40:34 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
async function submitRegisterForm() {
|
|
|
|
let succeed = false;
|
|
|
|
registering.value = true;
|
2024-04-10 17:51:13 +08:00
|
|
|
try {
|
2024-04-14 14:40:34 +08:00
|
|
|
try {
|
|
|
|
await registerFormRef.value?.validate();
|
|
|
|
} catch {
|
|
|
|
return;
|
|
|
|
}
|
2024-12-10 11:38:40 +08:00
|
|
|
if (typeof registerFormData.verifyImage !== 'object') {
|
2024-04-19 20:52:42 +08:00
|
|
|
ElMessage.error('请输入验证码');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const {
|
|
|
|
username,
|
|
|
|
password,
|
|
|
|
verifyImage: { key },
|
|
|
|
verifyCode: code
|
|
|
|
} = registerFormData;
|
|
|
|
succeed = await register({ username, password, key, code, auth: 1 });
|
2024-04-14 14:40:34 +08:00
|
|
|
} finally {
|
|
|
|
if (succeed) {
|
2024-12-09 20:43:08 +08:00
|
|
|
userStore.userInfoStatus = 'uninitialized';
|
2024-12-10 11:38:40 +08:00
|
|
|
await router.push({ path: route.fullPath, force: true });
|
2024-04-14 14:40:34 +08:00
|
|
|
} else {
|
2024-05-10 17:59:25 +08:00
|
|
|
registerFormData.verifyImage = 'none';
|
|
|
|
registerFormRef.value?.resetFields('verifyCode');
|
2024-04-14 14:40:34 +08:00
|
|
|
registering.value = false;
|
|
|
|
}
|
2024-04-10 17:51:13 +08:00
|
|
|
}
|
|
|
|
}
|
2024-05-10 17:59:25 +08:00
|
|
|
|
2024-04-14 14:40:34 +08:00
|
|
|
async function logout() {
|
|
|
|
userStore.$reset();
|
2024-12-09 20:43:08 +08:00
|
|
|
await userStore.updateSelfUserInfo(true);
|
2024-04-14 14:40:34 +08:00
|
|
|
}
|
2024-04-08 18:00:04 +08:00
|
|
|
</script>
|