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

<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>