You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
4.2 KiB
181 lines
4.2 KiB
<script setup lang="ts">
|
|
import { markRaw, reactive, useTemplateRef } from "vue";
|
|
import { useRouter } from "vue-router";
|
|
import { ElButton, type FormRules } from "element-plus";
|
|
import { Lock, User } from "@element-plus/icons-vue";
|
|
import { Request } from "@ease-forge/shared";
|
|
import DataForm from "../components/data-form/DataForm.vue";
|
|
import { type FormField } from "../components/data-form/DataFormTypes.ts";
|
|
import { getCurrentUser } from "@/currentUser.ts";
|
|
|
|
defineOptions({
|
|
name: 'Login',
|
|
});
|
|
|
|
// 定义 Props 类型
|
|
interface LoginProps {
|
|
}
|
|
|
|
// 读取组件 props 属性
|
|
const props = withDefaults(defineProps<LoginProps>(), {});
|
|
|
|
// 定义 State 类型
|
|
interface LoginState {
|
|
loginName?: string;
|
|
password?: string;
|
|
loading?: boolean;
|
|
errMsg?: string;
|
|
}
|
|
|
|
// state 属性
|
|
const state = reactive<LoginState>({});
|
|
|
|
// 定义 Data 类型
|
|
interface LoginData {
|
|
formFields: Array<FormField>;
|
|
rules: FormRules,
|
|
}
|
|
|
|
// 内部数据
|
|
const data: LoginData = {
|
|
formFields: [
|
|
{
|
|
dataPath: 'loginName', label: '', input: 'Input', inputRef: "loginName",
|
|
inputProps: {
|
|
placeholder: '用户名',
|
|
clearable: true,
|
|
prefixIcon: markRaw(User),
|
|
},
|
|
},
|
|
{
|
|
dataPath: 'password', label: '', input: 'Input', inputRef: "password",
|
|
inputProps: {
|
|
placeholder: '登录密码',
|
|
type: "password",
|
|
showPassword: true,
|
|
prefixIcon: markRaw(Lock),
|
|
},
|
|
},
|
|
],
|
|
rules: {
|
|
loginName: [
|
|
{ required: true, message: "用户名必填", trigger: 'blur' },
|
|
],
|
|
password: [
|
|
{ required: true, message: "登录密码必填", trigger: 'blur' },
|
|
],
|
|
},
|
|
};
|
|
const form = useTemplateRef<InstanceType<typeof DataForm>>("formRef");
|
|
const router = useRouter();
|
|
|
|
async function login() {
|
|
await form.value.data.formRef.validate(valid => {
|
|
if (!valid) return;
|
|
doLogin().finally();
|
|
});
|
|
}
|
|
|
|
async function doLogin() {
|
|
state.loading = true;
|
|
state.errMsg = "";
|
|
try {
|
|
const res = await Request.request.post("/api/login", {
|
|
loginName: state.loginName,
|
|
password: state.password,
|
|
});
|
|
const userInfo = res.userInfo;
|
|
if (userInfo) {
|
|
await getCurrentUser();
|
|
await router.push({ name: "editor" });
|
|
system.msg("登录成功");
|
|
} else {
|
|
state.errMsg = res.message ?? "登录失败,请重试!";
|
|
}
|
|
} catch (err) {
|
|
state.errMsg = "登录失败,请重试!";
|
|
} finally {
|
|
state.loading = false
|
|
}
|
|
}
|
|
|
|
interface LoginExpose {
|
|
state: LoginState;
|
|
data: LoginData;
|
|
}
|
|
|
|
const expose: LoginExpose = {
|
|
state,
|
|
data,
|
|
};
|
|
// 定义组件公开内容
|
|
defineExpose(expose);
|
|
|
|
export type {
|
|
LoginProps,
|
|
LoginState,
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="login-container content-center">
|
|
<div class="login-form-container">
|
|
<div class="login-title">登录</div>
|
|
<DataForm
|
|
ref="formRef"
|
|
class="login-form"
|
|
:size="'large'"
|
|
:data="state"
|
|
:formFields="data.formFields"
|
|
:rules="data.rules"
|
|
:showMessage="true"
|
|
:columnCount="1"
|
|
labelWidth="60px"
|
|
inputWidth=""
|
|
>
|
|
<template #submit>
|
|
<ElButton class="login-button" :loading="state.loading" type="primary" @click="login">
|
|
登录
|
|
</ElButton>
|
|
<div class="login-error">{{ state.errMsg }}</div>
|
|
</template>
|
|
</DataForm>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.login-container {
|
|
height: 100%;
|
|
background-color: #f2f5f7;
|
|
}
|
|
|
|
.login-form-container {
|
|
width: 396px;
|
|
height: 360px;
|
|
padding: 32px 48px 24px 48px;
|
|
background-color: #ffffff;
|
|
}
|
|
|
|
.login-title {
|
|
font-size: 40px;
|
|
color: #409eff;
|
|
font-weight: 500;
|
|
margin-bottom: 40px;
|
|
}
|
|
|
|
.login-form {
|
|
height: 200px;
|
|
}
|
|
|
|
.login-error {
|
|
color: #ff4d4f;
|
|
width: 100%;
|
|
height: 24px;
|
|
line-height: 24px;
|
|
}
|
|
|
|
.login-button {
|
|
width: 100%;
|
|
}
|
|
</style>
|