feat(component): 新增CuteFormProDialog组件并重构搜索表单
- 新增CuteFormProDialog表单弹窗组件,支持多种输入类型 - 重命名CuteSearchFormPro为CuteSearchProForm并优化组件结构 - 更新组件演示页面,添加表单对话框Pro功能演示 - 为新组件添加完整的属性定义和事件处理机制 - 优化表单验证规则和数据绑定逻辑 - 添加日期和时间范围选择器支持
This commit is contained in:
@@ -0,0 +1,262 @@
|
|||||||
|
<!--
|
||||||
|
* 表单弹窗Pro
|
||||||
|
* @author odboy
|
||||||
|
* @email tianjun@odboy.cn
|
||||||
|
* @created 2026-02-01
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:title="title"
|
||||||
|
:visible.sync="visible"
|
||||||
|
:width="width"
|
||||||
|
:fullscreen="fullscreen"
|
||||||
|
:before-close="beforeClose"
|
||||||
|
:modal="false"
|
||||||
|
>
|
||||||
|
<div class="container-form">
|
||||||
|
<el-form ref="form" :model="model" :rule="dynamicRules" :inline="false" size="small" label-position="left" label-width="100px">
|
||||||
|
<el-form-item v-for="item in schema" :key="item.name" :prop="item.name" :label="item.title" :required="item.required === true">
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<el-input
|
||||||
|
v-if="item.type === 'input'"
|
||||||
|
v-model="model[item.name]"
|
||||||
|
:placeholder="`请输入${item.title}`"
|
||||||
|
clearable
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
<!-- 选择框 -->
|
||||||
|
<el-select
|
||||||
|
v-if="item.type === 'select'"
|
||||||
|
v-model="model[item.name]"
|
||||||
|
clearable
|
||||||
|
:placeholder="`请选择${item.title}`"
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="option in (item.dataSource || [])"
|
||||||
|
:key="option.value"
|
||||||
|
:label="option.label"
|
||||||
|
:value="option.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<!-- 日期选择 -->
|
||||||
|
<el-date-picker
|
||||||
|
v-if="item.type === 'date'"
|
||||||
|
v-model="model[item.name]"
|
||||||
|
type="daterange"
|
||||||
|
align="right"
|
||||||
|
unlink-panels
|
||||||
|
clearable
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
:picker-options="pickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
<!-- 日期时间选择 -->
|
||||||
|
<el-date-picker
|
||||||
|
v-if="item.type === 'datetime'"
|
||||||
|
v-model="model[item.name]"
|
||||||
|
type="datetimerange"
|
||||||
|
align="right"
|
||||||
|
clearable
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
:picker-options="pickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
<el-divider />
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button type="danger" @click="hidden">取 消</el-button>
|
||||||
|
<!--<el-button @click="resetForm('form')">重 置</el-button>-->
|
||||||
|
<el-button v-prevent-re-click type="primary" @click="submitForm('form')">提 交</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CuteFormProDialog',
|
||||||
|
props: {
|
||||||
|
/**
|
||||||
|
* 弹窗标题
|
||||||
|
*/
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
default: '默认标题'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 弹窗宽度
|
||||||
|
*/
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '40%'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否全屏
|
||||||
|
*/
|
||||||
|
fullscreen: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 表单定义
|
||||||
|
*/
|
||||||
|
schema: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: function() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 绑定值
|
||||||
|
*/
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
rules: {},
|
||||||
|
pickerOptions: {
|
||||||
|
shortcuts: [{
|
||||||
|
text: '最近一周',
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
|
||||||
|
picker.$emit('pick', [start, end])
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: '最近一个月',
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
|
||||||
|
picker.$emit('pick', [start, end])
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
text: '最近三个月',
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
|
||||||
|
picker.$emit('pick', [start, end])
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dynamicRules() {
|
||||||
|
const schema = this.schema
|
||||||
|
const formRules = {}
|
||||||
|
let trigger = 'blur'
|
||||||
|
for (const element of schema) {
|
||||||
|
if (element.type === 'input') {
|
||||||
|
trigger = 'blur'
|
||||||
|
} else {
|
||||||
|
trigger = 'change'
|
||||||
|
}
|
||||||
|
formRules[element.name] = [
|
||||||
|
{ required: element.required === true, message: '请输入' + element.title, trigger: trigger }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return formRules
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
show() {
|
||||||
|
this.visible = true
|
||||||
|
},
|
||||||
|
hidden() {
|
||||||
|
this.resetForm('form')
|
||||||
|
this.visible = false
|
||||||
|
},
|
||||||
|
submitForm(formName) {
|
||||||
|
this.$refs[formName].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$emit('submit', this.model)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
resetForm(formName) {
|
||||||
|
// 调用默认的重置
|
||||||
|
this.$refs[formName].resetFields()
|
||||||
|
// 根据schema配置重置顽固选项
|
||||||
|
const schema = this.schema
|
||||||
|
const model = this.model
|
||||||
|
for (const element of schema) {
|
||||||
|
if (element.type === 'input' || element.type === 'select') {
|
||||||
|
model[element.name] = null
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (element.type === 'date' || element.type === 'datetime') {
|
||||||
|
model[element.name] = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.model = { ...model }
|
||||||
|
},
|
||||||
|
beforeClose() {
|
||||||
|
this.hidden()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.container-form {
|
||||||
|
overflow-y: scroll; /* 启用滚动 */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
padding-right: 20px;
|
||||||
|
-ms-overflow-style: none; /* Internet Explorer 10+ */
|
||||||
|
max-height: calc(100vh - 200px); /* 调整高度以适应页头和底部按钮 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-form::-webkit-scrollbar {
|
||||||
|
display: none; /* Chrome, Safari, Opera*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
padding: 16px 0 0 0;
|
||||||
|
background-color: white;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep(.el-dialog__body) {
|
||||||
|
padding: 20px 20px !important;
|
||||||
|
height: 90%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep(.el-divider--horizontal) {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
+10
-19
@@ -14,7 +14,6 @@
|
|||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
size="small"
|
size="small"
|
||||||
>
|
>
|
||||||
<!-- <el-form-item v-for="item in schema" :key="item.name" :prop="item.name" :label="item.title" :required="item.required === true">-->
|
|
||||||
<el-form-item v-for="item in schema" :key="item.name" :prop="item.name" :label="item.title">
|
<el-form-item v-for="item in schema" :key="item.name" :prop="item.name" :label="item.title">
|
||||||
<!-- 输入框 -->
|
<!-- 输入框 -->
|
||||||
<el-input
|
<el-input
|
||||||
@@ -81,9 +80,12 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CuteSearchFormPro',
|
name: 'CuteSearchProForm',
|
||||||
components: {},
|
components: {},
|
||||||
props: {
|
props: {
|
||||||
|
/**
|
||||||
|
* 表单定义
|
||||||
|
*/
|
||||||
schema: {
|
schema: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -91,10 +93,16 @@ export default {
|
|||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 绑定值
|
||||||
|
*/
|
||||||
model: {
|
model: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 是否禁用
|
||||||
|
*/
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -103,7 +111,6 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// formRules: {},
|
|
||||||
pickerOptions: {
|
pickerOptions: {
|
||||||
shortcuts: [{
|
shortcuts: [{
|
||||||
text: '最近一周',
|
text: '最近一周',
|
||||||
@@ -133,22 +140,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// mounted() {
|
|
||||||
// const schema = this.schema
|
|
||||||
// const formRules = this.formRules
|
|
||||||
// let trigger = 'blur'
|
|
||||||
// for (const element of schema) {
|
|
||||||
// if (element.type === 'input') {
|
|
||||||
// trigger = 'blur'
|
|
||||||
// } else {
|
|
||||||
// trigger = 'change'
|
|
||||||
// }
|
|
||||||
// formRules[element.name] = [
|
|
||||||
// { required: element.required === true, message: '请输入' + element.title, trigger: trigger }
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// this.formRules = formRules
|
|
||||||
// },
|
|
||||||
methods: {
|
methods: {
|
||||||
onFormSubmit(formName) {
|
onFormSubmit(formName) {
|
||||||
const that = this
|
const that = this
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
<el-button type="primary">查询后置按钮</el-button>
|
<el-button type="primary">查询后置按钮</el-button>
|
||||||
</template>
|
</template>
|
||||||
</cute-search-form>
|
</cute-search-form>
|
||||||
<cute-section-title title="高级搜索Pro版 CuteSearchFormPro" />
|
<cute-section-title title="高级搜索Pro版 CuteSearchProForm" />
|
||||||
<cute-search-form-pro :model="searchFormProValues" :schema="searchFormProSchema" />
|
<cute-search-pro-form :model="searchFormProValues" :schema="searchFormProSchema" />
|
||||||
<cute-section-title title="横向滚动 CuteHorizontalScrollBar" />
|
<cute-section-title title="横向滚动 CuteHorizontalScrollBar" />
|
||||||
<cute-horizontal-scroll-bar>
|
<cute-horizontal-scroll-bar>
|
||||||
<div style="width: 3000px;min-width: 3000px">模拟超长内容</div>
|
<div style="width: 3000px;min-width: 3000px">模拟超长内容</div>
|
||||||
@@ -75,12 +75,12 @@ import CuteSectionTitle from '@/views/components/dev/CuteSectionTitle.vue'
|
|||||||
import CuteButton from '@/views/components/dev/CuteButton.vue'
|
import CuteButton from '@/views/components/dev/CuteButton.vue'
|
||||||
import CuteTransfer from '@/views/components/dev/CuteTransfer.vue'
|
import CuteTransfer from '@/views/components/dev/CuteTransfer.vue'
|
||||||
import CuteTextAreaInput from '@/views/components/dev/CuteTextAreaInput.vue'
|
import CuteTextAreaInput from '@/views/components/dev/CuteTextAreaInput.vue'
|
||||||
import CuteSearchFormPro from '@/views/components/dev/CuteSearchFormPro.vue'
|
import CuteSearchProForm from '@/views/components/dev/CuteSearchProForm.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CuteOtherDemo',
|
name: 'CuteOtherDemo',
|
||||||
components: {
|
components: {
|
||||||
CuteSearchFormPro,
|
CuteSearchProForm,
|
||||||
CuteTextAreaInput,
|
CuteTextAreaInput,
|
||||||
CuteTransfer,
|
CuteTransfer,
|
||||||
CuteButton,
|
CuteButton,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="onDialogClick">演示:表单对话框</el-button>
|
<el-button type="primary" @click="onDialogClick">演示:表单对话框</el-button>
|
||||||
|
<el-button type="primary" @click="onDialogProClick">演示:表单对话框Pro</el-button>
|
||||||
<el-button type="primary" @click="onDrawerClick">演示:表单抽屉</el-button>
|
<el-button type="primary" @click="onDrawerClick">演示:表单抽屉</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -103,6 +104,13 @@
|
|||||||
<cute-edit-table v-model="editTableDataSource" primary-key="id" :schema="editTableSchema" />
|
<cute-edit-table v-model="editTableDataSource" primary-key="id" :schema="editTableSchema" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</cute-form-drawer>
|
</cute-form-drawer>
|
||||||
|
<cute-form-pro-dialog
|
||||||
|
ref="dialogProForm"
|
||||||
|
:model="createFormProModel"
|
||||||
|
:schema="createFormProSchema"
|
||||||
|
title="演示:表单对话框Pro"
|
||||||
|
@submit="onDialogFormSubmit"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -115,10 +123,11 @@ import { FormatRowDateTimeStr } from '@/utils/KitUtil'
|
|||||||
import CuteButton from '@/views/components/dev/CuteButton.vue'
|
import CuteButton from '@/views/components/dev/CuteButton.vue'
|
||||||
import CuteTransfer from '@/views/components/dev/CuteTransfer.vue'
|
import CuteTransfer from '@/views/components/dev/CuteTransfer.vue'
|
||||||
import CuteEditTable from '@/views/components/dev/CuteEditTable.vue'
|
import CuteEditTable from '@/views/components/dev/CuteEditTable.vue'
|
||||||
|
import CuteFormProDialog from '@/views/components/dev/CuteFormProDialog.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CuteSimpleTableDemo',
|
name: 'CuteSimpleTableDemo',
|
||||||
components: { CuteEditTable, CuteTransfer, CuteButton, CuteFormDrawer, CuteFormDialog, CuteSimpleTable },
|
components: { CuteFormProDialog, CuteEditTable, CuteTransfer, CuteButton, CuteFormDrawer, CuteFormDialog, CuteSimpleTable },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
modeDataSource: [
|
modeDataSource: [
|
||||||
@@ -190,6 +199,7 @@ export default {
|
|||||||
total: 0
|
total: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// CuteFormDialog
|
||||||
createFormModel: {
|
createFormModel: {
|
||||||
name: '',
|
name: '',
|
||||||
region: '',
|
region: '',
|
||||||
@@ -203,7 +213,15 @@ export default {
|
|||||||
region: [
|
region: [
|
||||||
{ required: true, message: '请选择活动区域', trigger: 'change' }
|
{ required: true, message: '请选择活动区域', trigger: 'change' }
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
// CuteFormProDialog
|
||||||
|
createFormProModel: {},
|
||||||
|
createFormProSchema: [
|
||||||
|
{ name: 'name', title: '姓名', type: 'input', required: true },
|
||||||
|
{ name: 'sex', title: '性别', type: 'select', required: true, dataSource: [{ label: '男', value: 'nn' }, { label: '女', value: 'mm' }] },
|
||||||
|
{ name: 'createDate', title: '创建日期', type: 'date', required: false },
|
||||||
|
{ name: 'createTime', title: '创建时间', type: 'datetime', required: false }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -234,6 +252,9 @@ export default {
|
|||||||
onDialogClick() {
|
onDialogClick() {
|
||||||
this.$refs.dialogForm.show()
|
this.$refs.dialogForm.show()
|
||||||
},
|
},
|
||||||
|
onDialogProClick() {
|
||||||
|
this.$refs.dialogProForm.show()
|
||||||
|
},
|
||||||
onDialogFormSubmit(values) {
|
onDialogFormSubmit(values) {
|
||||||
console.log('onDialogFormSubmit', values)
|
console.log('onDialogFormSubmit', values)
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user