feat: add VbenForm component (#4352)

* feat: add form component

* fix: build error

* feat: add form adapter

* feat: add some component

* feat: add some component

* feat: add example

* feat: suppoer custom action button

* chore: update

* feat: add example

* feat: add formModel,formDrawer demo

* fix: build error

* fix: typo

* fix: ci error

---------

Co-authored-by: jinmao <jinmao88@qq.com>
Co-authored-by: likui628 <90845831+likui628@users.noreply.github.com>
This commit is contained in:
Vben
2024-09-10 21:48:51 +08:00
committed by GitHub
parent 86ed732ca8
commit 524b9badf2
271 changed files with 5974 additions and 1247 deletions

View File

@@ -1,20 +1,19 @@
<script setup lang="ts">
import type { VbenFormSchema } from '@vben-core/form-ui';
import type { RegisterEmits } from './types';
import { computed, reactive } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import {
VbenButton,
VbenCheckbox,
VbenInput,
VbenInputPassword,
} from '@vben-core/shadcn-ui';
import { useVbenForm } from '@vben-core/form-ui';
import { VbenButton } from '@vben-core/shadcn-ui';
import Title from './auth-title.vue';
interface Props {
formSchema: VbenFormSchema[];
/**
* @zh_CN 是否处于加载处理状态
*/
@@ -30,6 +29,7 @@ defineOptions({
});
const props = withDefaults(defineProps<Props>(), {
formSchema: () => [],
loading: false,
loginPath: '/auth/login',
});
@@ -38,43 +38,24 @@ const emit = defineEmits<{
submit: RegisterEmits['submit'];
}>();
const [Form, { validate }] = useVbenForm(
reactive({
commonConfig: {
hideLabel: true,
hideRequiredMark: true,
},
schema: computed(() => props.formSchema),
showDefaultActions: false,
}),
);
const router = useRouter();
const formState = reactive({
agreePolicy: false,
confirmPassword: '',
password: '',
submitted: false,
username: '',
});
const usernameStatus = computed(() => {
return formState.submitted && !formState.username ? 'error' : 'default';
});
const passwordStatus = computed(() => {
return formState.submitted && !formState.password ? 'error' : 'default';
});
const confirmPasswordStatus = computed(() => {
return formState.submitted && formState.password !== formState.confirmPassword
? 'error'
: 'default';
});
function handleSubmit() {
formState.submitted = true;
if (
usernameStatus.value !== 'default' ||
passwordStatus.value !== 'default'
) {
return;
async function handleSubmit() {
const { valid, values } = await validate();
if (valid) {
emit('submit', values as { password: string; username: string });
}
emit('submit', {
password: formState.password,
username: formState.username,
});
}
function goToLogin() {
@@ -88,73 +69,11 @@ function goToLogin() {
{{ $t('authentication.createAnAccount') }} 🚀
<template #desc> {{ $t('authentication.signUpSubtitle') }} </template>
</Title>
<VbenInput
v-model="formState.username"
:error-tip="$t('authentication.usernameTip')"
:label="$t('authentication.username')"
:placeholder="$t('authentication.username')"
:status="usernameStatus"
name="username"
type="text"
/>
<!-- Use 8 or more characters with a mix of letters, numbers & symbols. -->
<VbenInputPassword
v-model="formState.password"
:error-tip="$t('authentication.passwordTip')"
:label="$t('authentication.password')"
:password-strength="true"
:placeholder="$t('authentication.password')"
:status="passwordStatus"
name="password"
required
type="password"
>
<template #strengthText>
{{ $t('authentication.passwordStrength') }}
</template>
</VbenInputPassword>
<Form />
<VbenInputPassword
v-model="formState.confirmPassword"
:error-tip="$t('authentication.confirmPasswordTip')"
:label="$t('authentication.confirmPassword')"
:placeholder="$t('authentication.confirmPassword')"
:status="confirmPasswordStatus"
name="confirmPassword"
required
type="password"
/>
<div class="relative mt-4 flex pb-6">
<div class="flex-center">
<VbenCheckbox
v-model:checked="formState.agreePolicy"
name="agreePolicy"
>
{{ $t('authentication.agree') }}
<span class="text-primary hover:text-primary-hover">{{
$t('authentication.privacyPolicy')
}}</span>
&
<span class="text-primary hover:text-primary-hover">
{{ $t('authentication.terms') }}
</span>
</VbenCheckbox>
</div>
<Transition name="slide-up">
<p
v-show="formState.submitted && !formState.agreePolicy"
class="text-destructive absolute bottom-1 left-0 text-xs"
>
{{ $t('authentication.agreeTip') }}
</p>
</Transition>
</div>
<div>
<VbenButton :loading="loading" class="w-full" @click="handleSubmit">
{{ $t('authentication.signUp') }}
</VbenButton>
</div>
<VbenButton :loading="loading" class="mt-2 w-full" @click="handleSubmit">
{{ $t('authentication.signUp') }}
</VbenButton>
<div class="mt-4 text-center text-sm">
{{ $t('authentication.alreadyHaveAccount') }}
<span