<template>
<zk-theme type="page" :is-navbar="true" navbar-title="表单演示" :show-back="true">
<!-- 基础表单 -->
<zk-theme type="card" :margin="20" :padding="20">
<view class="demo-title">
<zk-text text="基础表单" type="primary" :size="32" :bold="true" />
</view>
<zk-form ref="form" :model="formData" :rules="rules" @submit="onSubmit">
<!-- 用户名 -->
<zk-form-item :labelWidth="80" label="用户名" prop="username" required>
<zk-input v-model="formData.username" placeholder="请输入用户名" />
</zk-form-item>
<!-- 手机号 -->
<zk-form-item required :labelWidth="80" label="手机号" prop="phone"
:rules="{ required: true, message: '请输入手机号' }">
<zk-input v-model="formData.phone" type="number" :maxlength="11" placeholder="请输入手机号" />
</zk-form-item>
<!-- 密码 -->
<zk-form-item :labelWidth="80" label="密码" prop="password" required>
<zk-input v-model="formData.password" type="password" placeholder="请输入密码" />
</zk-form-item>
<!-- 确认密码 -->
<zk-form-item :labelWidth="80" label="确认密码" prop="confirmPassword" required>
<zk-input v-model="formData.confirmPassword" type="password" placeholder="请再次输入密码" />
</zk-form-item>
<!-- 提交按钮 -->
<view class="form-actions">
<zk-button text="提交" type="primary" @click="$refs.form.submitForm()" block />
</view>
</zk-form>
</zk-theme>
<!-- 高级表单 -->
<zk-theme type="card" :margin="20" :padding="20">
<view class="demo-title">
<zk-text text="高级表单" type="primary" :size="32" :bold="true" />
</view>
<zk-text text="请填写详细的个人信息" type="secondary" margin="0 0 20rpx 0" />
<zk-form ref="advancedForm" :model="advancedForm" :rules="advancedRules" label-width="200"
@submit="onAdvancedSubmit">
<!-- 姓名 -->
<zk-form-item label="姓名" prop="name" required>
<zk-input v-model="advancedForm.name" placeholder="请输入姓名" />
</zk-form-item>
<!-- 性别 -->
<zk-form-item label="性别" prop="gender" required>
<view class="radio-group" style="align-items: center;">
<view class="" style="margin-left: 20rpx;" v-for="item in genderOptions">
<zk-radio :key="item.value" :name="item.value" :label="item.label"
v-model="advancedForm.gender" />
</view>
</view>
</zk-form-item>
<!-- 是否接受协议 -->
<zk-form-item prop="agreement">
<view class="agreement-label">
<zk-checkbox v-model="advancedForm.agreement" name="agreement" />
<zk-text text="我已阅读并同意" :size="28" align="center" />
<zk-text text="《用户协议》" type="primary" :size="28" decoration="underline"
@click="showAgreement" />
</view>
</zk-form-item>
<!-- 提交按钮 -->
<view class="form-actions">
<zk-button text="重置" type="info" @click="resetAdvancedForm" width="100" />
<zk-button text="提交" type="primary" @click="$refs.advancedForm.submitForm()" width="100" />
</view>
</zk-form>
</zk-theme>
<!-- 垂直布局表单 -->
<zk-theme type="card" :margin="20" :padding="20">
<view class="demo-title">
<zk-text text="垂直布局表单" type="primary" :size="32" :bold="true" />
</view>
<zk-form ref="verticalForm" :model="verticalForm" :rules="verticalRules" label-position="top">
<!-- 标题 -->
<zk-form-item label="标题" prop="title" required>
<zk-input border="bottom" v-model="verticalForm.title" placeholder="请输入标题" />
</zk-form-item>
<!-- 描述 -->
<zk-form-item label="描述" prop="description" required>
<zk-input border="bottom" v-model="verticalForm.description" type="textarea" :rows="3"
placeholder="请输入描述内容" />
</zk-form-item>
<!-- 分类 -->
<zk-form-item label="分类" prop="category" required>
<zk-input border="bottom" v-model="verticalForm.category" placeholder="请选择分类" />
</zk-form-item>
<!-- 提交按钮 -->
<view class="form-actions">
<zk-button text="提交" type="primary" @click="$refs.verticalForm.submitForm()" block />
</view>
</zk-form>
</zk-theme>
</zk-theme>
</template>
<script>
export default {
data() {
// 密码验证器
const validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'))
} else if (value.length < 6) {
callback(new Error('密码不能少于6个字符'))
} else {
if (this.formData.confirmPassword !== '') {
this.$refs.form.validateField('confirmPassword')
}
callback()
}
}
// 确认密码验证器
const validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== this.formData.password) {
callback(new Error('两次输入密码不一致!'))
} else {
callback()
}
}
return {
// 基础表单数据
formData: {
username: '',
phone: '',
password: '',
confirmPassword: ''
},
// 基础表单验证规则
rules: {
username: [{
required: true,
message: '请输入用户名'
},
{
min: 3,
max: 20,
message: '用户名长度在 3 到 20 个字符'
}
],
phone: [{
required: true,
message: '请输入手机号'
},
{
validator: (rule, value, callback) => {
if (!/^1[3-9]d{9}$/.test(value)) {
callback(new Error('请输入正确的手机号'))
} else {
callback()
}
}
}
],
password: [{
validator: validatePass,
trigger: 'blur'
}],
confirmPassword: [{
validator: validatePass2,
trigger: 'blur'
}]
},
// 高级表单数据
advancedForm: {
name: '',
gender: 'male',
age: '',
birthday: '',
education: '',
hobbies: [],
region: [],
address: '',
introduction: '',
agreement: false
},
// 高级表单验证规则
advancedRules: {
name: [{
required: true,
message: '请输入姓名'
}],
gender: [{
required: true,
message: '请选择性别'
}],
age: [{
required: true,
message: '请输入年龄'
},
{
validator: (rule, value, callback) => {
if (value < 0 || value > 120) {
callback(new Error('请输入合理的年龄'))
} else {
callback()
}
}
}
],
birthday: [{
required: true,
message: '请选择出生日期'
}],
education: [{
required: true,
message: '请选择学历'
}],
hobbies: [{
required: true,
message: '请选择兴趣爱好'
},
{
validator: (rule, value, callback) => {
if (value.length < 1) {
callback(new Error('至少选择一个兴趣爱好'))
} else {
callback()
}
}
}
],
region: [{
required: true,
message: '请选择所在地区'
}],
address: [{
required: true,
message: '请输入详细地址'
}],
agreement: [{
validator: (rule, value, callback) => {
if (!value) {
callback(new Error('请同意用户协议'))
} else {
callback()
}
}
}]
},
// 选项数据
genderOptions: [{
label: '男',
value: 'male'
},
{
label: '女',
value: 'female'
}
],
educationIndex: 0,
// 垂直布局表单数据
verticalForm: {
title: '',
description: '',
category: ''
},
// 垂直布局表单验证规则
verticalRules: {
title: [{
required: true,
message: '请输入标题'
}],
description: [{
required: true,
message: '请输入描述'
}],
category: [{
required: true,
message: '请选择分类'
}]
}
}
},
methods: {
// 基础表单提交
onSubmit(formData) {
console.log('基础表单提交:', formData)
uni.showToast({
title: '提交成功',
icon: 'success'
})
},
// 高级表单提交
onAdvancedSubmit(formData) {
console.log('高级表单提交:', formData)
uni.showToast({
title: '提交成功',
icon: 'success'
})
},
// 重置高级表单
resetAdvancedForm() {
// 只重置表单数据
this.advancedForm = {
name: '',
gender: 'male',
age: '',
birthday: '',
education: '',
hobbies: [],
region: [],
address: '',
introduction: '',
agreement: false
}
},
// 日期选择改变
onBirthdayChange(e) {
this.advancedForm.birthday = e.detail.value
},
// 学历选择改变
onEducationChange(e) {
const index = e.detail.value
this.educationIndex = index
this.advancedForm.education = this.educationOptions[index].label
},
// 兴趣爱好改变
onHobbiesChange(e) {
this.advancedForm.hobbies = e.detail.value
},
// 地区选择改变
onRegionChange(e) {
this.advancedForm.region = e.detail.value
},
// 显示协议
showAgreement() {
uni.showModal({
title: '用户协议',
content: '这是一份示例用户协议...',
showCancel: false
})
}
}
}
</script>
<style lang="scss">
.form-input {
height: 60rpx;
font-size: 28rpx;
color: #323233;
}
.form-textarea {
width: 100%;
height: 160rpx;
font-size: 28rpx;
color: #323233;
}
.radio-group {
/* #ifdef APP-NVUE */
flex-direction: row;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
flex-direction: row;
/* #endif */
flex-wrap: wrap;
}
.checkbox-group {
/* #ifdef APP-NVUE */
flex-direction: row;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
flex-direction: row;
/* #endif */
flex-wrap: wrap;
}
.radio-label,
.checkbox-label {
margin-right: 32rpx;
margin-bottom: 16rpx;
font-size: 28rpx;
color: #323233;
}
.picker-value {
height: 60rpx;
line-height: 60rpx;
font-size: 28rpx;
color: #323233;
}
.agreement-label {
font-size: 28rpx;
/* #ifdef APP-NVUE */
flex-direction: row;
align-items: center;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
flex-direction: row;
align-items: center;
/* #endif */
color: #323233;
}
.form-actions {
padding: 40rpx;
width: 600rpx;
/* #ifdef APP-NVUE */
flex-direction: row;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
flex-direction: row;
/* #endif */
justify-content: space-between;
}
.demo-title {
/* #ifdef APP-NVUE */
flex-direction: row;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
flex-direction: row;
/* #endif */
margin-bottom: 20rpx;
}
</style>