This commit is contained in:
oneao committed 2025-12-12 17:27:55 +08:00
1 parent 861b529d9b
commit c4bd60d0cc
16 files changed
+689 -87

No files matched your search

@@ -9,6 +9,34 @@ function navigateTo(path: string) {
router.push(path)
}
const carouselList = [
{
title: '值得信赖',
company: '恒星科技有限公司',
content: '我们已经连续三年使用该平台,数据处理稳定高效,团队协作体验非常顺畅。',
},
{
title: '安全 · 高效',
company: '博越信息技术',
content: '平台的权限管理做得很好,操作简单清晰,极大提升了内部管理效率。',
},
{
title: '稳定可靠',
company: '远航供应链集团',
content: '系统运行非常稳定,几乎没有出现过宕机情况,客服响应速度也很快。',
},
{
title: '智能化体验',
company: '蓝海数据服务中心',
content: '智能报表和自动化功能非常实用,减少了大量人工整理数据的时间。',
},
{
title: '灵活易用',
company: '中联创投有限公司',
content: 'UI设计简洁友好,新员工上手很快,各项业务流程也能灵活配置。',
},
]
// do not use same name with ref
const form = reactive({
name: '',
@@ -35,10 +63,16 @@ function onSubmit() {
height="150px"
indicator-position="none"
>
<el-carousel-item v-for="item in 4" :key="item">
<h3 class="small justify-center" text="2xl">
{{ item }}
</h3>
<el-carousel-item v-for="(item, index) in carouselList" :key="index">
<div class="carousel-item">
<h2 class="title">
{{ item.title }}
</h2>
<span class="content">{{ item.content }}</span>
<span class="company"> - {{ item.company }}</span>
</div>
</el-carousel-item>
</el-carousel>
</div>
@@ -99,13 +133,30 @@ function onSubmit() {
.bg-content {
position: absolute;
left: 50%;
bottom: 12%;
bottom: 10%;
transform: translateX(-50%);
text-align: center;
color: #fff;
width: 600px;
.carousel-item {
display: flex;
flex-direction: column;
.title {
font-size: 28px;
line-height: 28px;
margin-bottom: 16px;
}
.content {
margin-bottom: 8px;
}
.company {
font-size: 14px;
}
}
}
}
.form-label-flex {
display: flex;
justify-content: space-between;
@@ -122,7 +173,7 @@ function onSubmit() {
flex: 1;
display: flex;
flex-direction: column;
padding: 48px 56px 24px 56px;
padding: 36px;
.logo {
height: 70px;
@@ -1,35 +1,125 @@
<script lang="ts" setup>
import { reactive } from 'vue'
import type { FormInstance } from 'element-plus'
import { ElMessage } from 'element-plus'
import { reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { loginApi } from '@/request/api/auth'
import { useUserStore } from '@/store/user'
const userStore = useUserStore()
const router = useRouter()
const carouselList = [
{
title: '值得信赖',
company: '恒星科技有限公司',
content: '我们已经连续三年使用该平台,数据处理稳定高效,团队协作体验非常顺畅。',
},
{
title: '安全 · 高效',
company: '博越信息技术',
content: '平台的权限管理做得很好,操作简单清晰,极大提升了内部管理效率。',
},
{
title: '稳定可靠',
company: '远航供应链集团',
content: '系统运行非常稳定,几乎没有出现过宕机情况,客服响应速度也很快。',
},
{
title: '智能化体验',
company: '蓝海数据服务中心',
content: '智能报表和自动化功能非常实用,减少了大量人工整理数据的时间。',
},
{
title: '灵活易用',
company: '中联创投有限公司',
content: 'UI设计简洁友好,新员工上手很快,各项业务流程也能灵活配置。',
},
]
const form = reactive<{
loginCredential: string
password: string
rememberMe: boolean
}>({
loginCredential: '',
password: '',
rememberMe: true,
})
const formRef = ref<FormInstance>()
const formRules = {
loginCredential: [
{ required: true, message: '邮箱 / 账号不能为空', trigger: 'blur' },
],
password: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
],
}
const saveLoading = ref(false)
async function submitForm(formEl: FormInstance | undefined) {
if (!formEl)
return
await formEl.validate((valid) => {
if (valid) {
saveLoading.value = true
loginApi({
loginCredential: form.loginCredential,
password: form.password,
}).then((res) => {
if (res.isSuccess) {
userStore.setUserInfo({
id: res.data.id,
account: res.data.account,
email: res.data.email,
name: res.data.name,
token: res.data.token,
avatar: res.data.avatar || '/no-avatar.png',
})
ElMessage.success('登录成功')
router.push('/')
}
else {
ElMessage.error(res.message || '登录失败,请稍后再试!')
}
}).catch((err) => {
console.log(err)
}).finally(() => {
saveLoading.value = false
})
}
})
}
function navigateTo(path: string) {
router.push(path)
}
// do not use same name with ref
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
function onSubmit() {
console.log('submit!')
}
</script>
<template>
<div class="auth-wrapper">
<div class="auth-bg">
<img src="/auth-bg.jpg">
<div class="bg-content">
<el-carousel
height="150px"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in carouselList" :key="index">
<div class="carousel-item">
<h2 class="title">
{{ item.title }}
</h2>
<span class="content">{{ item.content }}</span>
<span class="company"> - {{ item.company }}</span>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
<div class="login-form">
@@ -43,29 +133,38 @@ function onSubmit() {
输入你的 邮箱/账号 和 密码 登录账户.
</p>
<el-form
ref="formRef"
:model="form"
:rules="formRules"
label-width="auto"
label-position="top"
hide-required-asterisk
>
<el-form-item label="邮箱 / 账号">
<el-input v-model="form.name" placeholder="请输入邮箱 / 账号" size="large" />
<el-form-item label="邮箱 / 账号" prop="loginCredential">
<el-input v-model="form.loginCredential" placeholder="请输入邮箱 / 账号" size="large" />
</el-form-item>
<el-form-item>
<el-form-item prop="password">
<template #label>
<div class="form-label-flex">
<span class="form-label-flex">
<span>密码</span>
<span class="forgot" @click="navigateTo('/auth/forget')">忘记密码?</span>
</div>
</span>
</template>
<el-input v-model="form.name" placeholder="请输入密码" size="large" />
<el-input
v-model="form.password"
placeholder="请输入密码"
size="large"
@keyup.enter="submitForm(formRef)"
/>
</el-form-item>
<el-form-item>
<el-checkbox label="记住我" class="remeber" />
<el-checkbox v-model="form.rememberMe" label="记住我" class="remeber" />
</el-form-item>
<el-form-item>
<el-button type="primary" class="form-btn">
<el-button type="primary" class="form-btn" :loading="saveLoading" @click="submitForm(formRef)">
登录
</el-button>
</el-form-item>
@@ -89,12 +188,39 @@ function onSubmit() {
.auth-bg {
width: 70%;
height: 100%;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.bg-content {
position: absolute;
left: 50%;
bottom: 10%;
transform: translateX(-50%);
text-align: center;
color: #fff;
width: 600px;
.carousel-item {
display: flex;
flex-direction: column;
.title {
font-size: 28px;
line-height: 28px;
margin-bottom: 16px;
}
.content {
margin-bottom: 8px;
}
.company {
font-size: 14px;
}
}
}
}
.form-label-flex {
display: flex;
@@ -112,7 +238,7 @@ function onSubmit() {
flex: 1;
display: flex;
flex-direction: column;
padding: 48px 56px 24px 56px;
padding: 36px;
.logo {
height: 70px;
@@ -1,28 +1,128 @@
<script lang="ts" setup>
import { reactive } from 'vue'
import type { FormInstance } from 'element-plus'
import { computed, onUnmounted, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
function navigateTo(path: string) {
router.push(path)
const carouselList = [
{
title: '值得信赖',
company: '恒星科技有限公司',
content: '我们已经连续三年使用该平台,数据处理稳定高效,团队协作体验非常顺畅。',
},
{
title: '安全 · 高效',
company: '博越信息技术',
content: '平台的权限管理做得很好,操作简单清晰,极大提升了内部管理效率。',
},
{
title: '稳定可靠',
company: '远航供应链集团',
content: '系统运行非常稳定,几乎没有出现过宕机情况,客服响应速度也很快。',
},
{
title: '智能化体验',
company: '蓝海数据服务中心',
content: '智能报表和自动化功能非常实用,减少了大量人工整理数据的时间。',
},
{
title: '灵活易用',
company: '中联创投有限公司',
content: 'UI设计简洁友好,新员工上手很快,各项业务流程也能灵活配置。',
},
]
const form = reactive<{
email: string
code: string
name: string
account: string
password: string
confirmPassword: string
}>({
email: '',
code: '',
name: '',
account: '',
password: '',
confirmPassword: '',
})
const formRef = ref<FormInstance>()
const formRules = {
email: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' },
{ type: 'email', message: '请输入正确的邮箱格式', trigger: ['blur', 'change'] },
],
code: [
{ required: true, message: '验证码不能为空', trigger: 'blur' },
],
name: [
{ required: true, message: '名称不能为空', trigger: 'blur' },
{ min: 2, max: 20, message: '名称长度需在 2 到 20 个字符之间', trigger: 'blur' },
],
password: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 6, max: 20, message: '密码长度需在 6 到 20 个字符之间', trigger: 'blur' },
],
confirmPassword: [
{ required: true, message: '请再次输入密码', trigger: 'blur' },
{
validator: (rule: any, value: any, callback: any) => {
if (value !== form.password) {
callback(new Error('两次输入的密码不一致'))
}
else {
callback()
}
},
trigger: ['blur', 'change'],
},
],
}
// do not use same name with ref
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
// --- 邮箱校验(简单正则) ---
const emailRegex = /^\w+(?:[-.]\w+)*@\w+(?:[-.]\w+)*\.\w+(?:[-.]\w+)*$/
const isEmailValid = computed(() => emailRegex.test(form.email.trim()))
// --- 发送验证码状态 & 倒计时 ---
const sending = ref(false)
const countdown = ref(0)
let timer: number | undefined
function startCountdown(seconds = 60) {
countdown.value = seconds
timer = window.setInterval(() => {
countdown.value -= 1
if (countdown.value <= 0) {
clearInterval(timer)
timer = undefined
sending.value = false
}
}, 1000)
}
// 清理
onUnmounted(() => {
if (timer) {
clearInterval(timer)
timer = undefined
}
})
function onSubmit() {
console.log('submit!')
function handleSendEmailCode() {
sending.value = true
startCountdown()
}
async function submitForm() {
}
function navigateTo(path: string) {
router.push(path)
}
</script>
@@ -30,8 +130,25 @@ function onSubmit() {
<div class="auth-wrapper">
<div class="auth-bg">
<img src="/auth-bg.jpg">
</div>
<div class="bg-content">
<el-carousel
height="150px"
indicator-position="none"
>
<el-carousel-item v-for="(item, index) in carouselList" :key="index">
<div class="carousel-item">
<h2 class="title">
{{ item.title }}
</h2>
<span class="content">{{ item.content }}</span>
<span class="company"> - {{ item.company }}</span>
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
<div class="login-form">
<img src="/logo.png" class="logo" @click="navigateTo('/')">
@@ -43,25 +160,62 @@ function onSubmit() {
请填写必要的注册信息,完成账户创建。
</p>
<el-form
ref="formRef"
:model="form"
:rules="formRules"
label-width="auto"
label-position="top"
>
<el-form-item label="邮箱">
<el-input v-model="form.name" placeholder="请输入邮箱" size="large" />
<el-form-item
label="邮箱"
prop="email"
>
<el-input
v-model="form.email"
placeholder="请输入邮箱"
size="large"
/>
</el-form-item>
<el-form-item label="账号">
<el-input v-model="form.name" placeholder="请输入账号" size="large" />
<el-form-item
label="邮箱验证码"
prop="code"
>
<el-input
v-model="form.account" placeholder="请输入邮箱验证码" size="large"
class="email-code"
:class="(!isEmailValid || sending) ? 'disabled' : ''"
>
<template #append>
<el-button :disabled="!isEmailValid || sending" @click="handleSendEmailCode()">
{{ sending ? `${countdown}s` : "发送验证码" }}
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="公司名称">
<!-- <el-form-item label="账号">
<el-input v-model="form.account" placeholder="请输入账号" size="large" />
</el-form-item> -->
<el-form-item
label="公司名称"
prop="name"
>
<el-input v-model="form.name" placeholder="请输入公司名称" size="large" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.name" placeholder="请输入密码" size="large" />
<el-form-item
label="密码"
prop="password"
>
<el-input v-model="form.password" placeholder="请输入密码" size="large" />
</el-form-item>
<el-form-item
label="确认密码"
prop="confirmPassword"
>
<el-input v-model="form.confirmPassword" placeholder="请输入确认密码" size="large" />
</el-form-item>
<el-form-item>
<el-button type="primary" class="form-btn">
<el-button type="primary" class="form-btn" @click="submitForm()">
注册
</el-button>
</el-form-item>
@@ -77,6 +231,21 @@ function onSubmit() {
</template>
<style lang="scss" scoped>
.email-code {
:deep(.el-input-group__append) {
background-color: #eceffd;
color: #4041d1;
cursor: pointer;
}
&.disabled {
:deep(.el-input-group__append) {
background-color: #f5f7fa;
color: #c0c4cc;
}
}
}
.auth-wrapper {
display: flex;
height: 100vh;
@@ -85,12 +254,39 @@ function onSubmit() {
.auth-bg {
width: 70%;
height: 100%;
position: relative;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
.bg-content {
position: absolute;
left: 50%;
bottom: 10%;
transform: translateX(-50%);
text-align: center;
color: #fff;
width: 600px;
.carousel-item {
display: flex;
flex-direction: column;
.title {
font-size: 28px;
line-height: 28px;
margin-bottom: 16px;
}
.content {
margin-bottom: 8px;
}
.company {
font-size: 14px;
}
}
}
}
.form-label-flex {
display: flex;
@@ -105,16 +301,17 @@ function onSubmit() {
}
.login-form {
overflow-y: auto;
flex: 1;
display: flex;
flex-direction: column;
padding: 48px 56px 24px 56px;
padding: 36px;
.logo {
height: 70px;
width: 160px;
cursor: pointer;
margin-bottom: 48px;
margin-bottom: 24px;
}
.main {