| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- <script setup>
- import { ref } from 'vue'
- import { useRouter } from 'vue-router'
- import { Form } from '@primevue/forms'
- import Card from 'primevue/card'
- import Button from 'primevue/button'
- import InputText from 'primevue/inputtext'
- import Password from 'primevue/password'
- import Message from 'primevue/message'
- import FloatLabel from 'primevue/floatlabel'
- import IconField from 'primevue/iconfield'
- import InputIcon from 'primevue/inputicon'
- import { useToast } from 'primevue/usetoast'
- import { useUserStore } from '@/stores/user'
- import { zodResolver } from '@primevue/forms/resolvers/zod'
- import { z } from 'zod'
- const toast = useToast()
- const router = useRouter()
- const loading = ref(false)
- const { login } = useUserStore()
- const loginForm = ref({
- name: '',
- password: ''
- })
- const resolver = zodResolver(
- z.object({
- name: z.string().min(1, { message: '用户名不能为空' }),
- password: z.string().min(8, { message: '密码至少8位' })
- })
- )
- const onFormSubmit = async ({ valid, values }) => {
- if (!valid) {
- return
- }
- loading.value = true
- try {
- await login(values.name, values.password)
- toast.add({ severity: 'success', summary: '成功', detail: '登录成功', life: 3000 })
- router.push('/')
- } catch (error) {
- toast.add({
- severity: 'error',
- summary: '错误',
- detail: error.message || '登录失败,请重试',
- life: 3000
- })
- } finally {
- loading.value = false
- }
- }
- </script>
- <template>
- <div class="login-page p-d-flex p-jc-center p-ai-center">
- <Card class="login-card">
- <template #title>
- <div class="text-center">
- <h2>系统登录</h2>
- </div>
- </template>
- <template #content>
- <Form v-slot="$form" :resolver="resolver" :initialValues="loginForm" @submit="onFormSubmit" class="p-fluid">
- <div class="field mt-8">
- <FloatLabel variant="on">
- <IconField>
- <InputIcon class="pi pi-user" />
- <InputText id="name" name="name" v-model="loginForm.name" autocomplete="off" fluid />
- </IconField>
- <label for="name">用户名</label>
- </FloatLabel>
- <Message v-if="$form.name?.invalid" severity="error" size="small" variant="simple">{{
- $form.name.error?.message
- }}</Message>
- </div>
- <div class="field mt-8">
- <FloatLabel variant="on">
- <IconField>
- <InputIcon class="pi pi-lock" />
- <Password
- id="password"
- name="password"
- v-model="loginForm.password"
- toggleMask
- :feedback="false"
- fluid
- />
- </IconField>
- <label for="password">密码</label>
- </FloatLabel>
- <Message v-if="$form.password?.invalid" severity="error" size="small" variant="simple">{{
- $form.password.error?.message
- }}</Message>
- </div>
- <div class="field mt-8">
- <Button label="登录" type="submit" fluid />
- </div>
- </Form>
- </template>
- </Card>
- </div>
- </template>
- <style scoped>
- .login-page {
- background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
- background-size: 400% 400%;
- animation: gradient 15s ease infinite;
- height: 100vh;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- @keyframes gradient {
- 0% {
- background-position: 0% 50%;
- }
- 50% {
- background-position: 100% 50%;
- }
- 100% {
- background-position: 0% 50%;
- }
- }
- .login-card {
- width: 30rem;
- max-width: 90%;
- border-radius: 1rem;
- box-shadow:
- 0 2px 1px -1px rgba(0, 0, 0, 0.2),
- 0 1px 1px 0 rgba(0, 0, 0, 0.14),
- 0 1px 3px 0 rgba(0, 0, 0, 0.12);
- background: rgba(255, 255, 255, 0.9);
- backdrop-filter: blur(10px);
- border: 1px solid rgba(255, 255, 255, 0.2);
- }
- .text-center {
- text-align: center;
- }
- .block {
- display: block;
- }
- .w-full {
- width: 100%;
- }
- </style>
|