Pre Merge pull request !787 from puhui999/master-fix1
commit
e55e2a011c
|
|
@ -0,0 +1,177 @@
|
||||||
|
# FormCreate 组件联动示例
|
||||||
|
|
||||||
|
这个示例页面演示了 FormCreate 中各种组件联动的使用方法,参考了官方文档 https://form-create.com/v3/guide/control
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
### 1. 基础联动 (Basic Control)
|
||||||
|
|
||||||
|
- **显示/隐藏控制**:根据用户类型选择显示不同的表单字段
|
||||||
|
- **条件逻辑**:个人用户显示身份证号,企业用户显示公司信息
|
||||||
|
- **实时响应**:选择变化时立即更新表单结构
|
||||||
|
|
||||||
|
### 2. 禁用联动 (Disabled Control)
|
||||||
|
|
||||||
|
- **启用/禁用控制**:通过开关控制表单字段的可编辑状态
|
||||||
|
- **批量操作**:一次性控制多个字段的禁用状态
|
||||||
|
- **状态保持**:禁用时保持原有数据不变
|
||||||
|
|
||||||
|
### 3. 选项联动 (Options Control)
|
||||||
|
|
||||||
|
- **三级联动**:省市区三级下拉选择联动
|
||||||
|
- **动态选项**:根据上级选择动态更新下级选项
|
||||||
|
- **选项替换**:使用 `replaceOptions` 方法更新选项列表
|
||||||
|
|
||||||
|
### 4. 复杂联动 (Complex Control)
|
||||||
|
|
||||||
|
- **多条件控制**:根据订单类型显示不同的业务字段
|
||||||
|
- **业务场景**:模拟真实的订单管理场景
|
||||||
|
- **混合控制**:同时使用显示/隐藏和选项联动
|
||||||
|
|
||||||
|
### 5. 动态规则 (Dynamic Rules)
|
||||||
|
|
||||||
|
- **动态添加**:运行时动态添加表单字段
|
||||||
|
- **动态删除**:运行时删除已添加的字段
|
||||||
|
- **API操作**:使用 FormCreate API 进行动态操作
|
||||||
|
|
||||||
|
## 技术要点
|
||||||
|
|
||||||
|
### Control 配置结构
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: '触发值', // 触发联动的值
|
||||||
|
condition: '==', // 条件操作符 (==, !=, >, <, >=, <=, in, !in)
|
||||||
|
method: '联动方法', // 联动方法 (hidden, display, disabled, enabled, replaceOptions)
|
||||||
|
rule: ['字段名'], // 受影响的字段
|
||||||
|
options: [] // 新选项 (仅 replaceOptions 方法使用)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 联动方法说明
|
||||||
|
|
||||||
|
- **hidden**: 隐藏字段
|
||||||
|
- **display**: 显示字段
|
||||||
|
- **disabled**: 禁用字段
|
||||||
|
- **enabled**: 启用字段
|
||||||
|
- **replaceOptions**: 替换选项
|
||||||
|
|
||||||
|
### 条件操作符
|
||||||
|
|
||||||
|
- **==**: 等于
|
||||||
|
- **!=**: 不等于
|
||||||
|
- **>**: 大于
|
||||||
|
- **<**: 小于
|
||||||
|
- **>=**: 大于等于
|
||||||
|
- **<=**: 小于等于
|
||||||
|
- **in**: 包含在数组中
|
||||||
|
- **!in**: 不包含在数组中
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 基础显示/隐藏联动
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
field: 'userType',
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'personal',
|
||||||
|
condition: '==',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: ['companyName', 'businessLicense']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 选项联动
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'province',
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'guangdong',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['city'],
|
||||||
|
options: [
|
||||||
|
{ label: '广州市', value: 'guangzhou' },
|
||||||
|
{ label: '深圳市', value: 'shenzhen' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 动态操作
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 添加字段
|
||||||
|
formApi.append({
|
||||||
|
type: 'input',
|
||||||
|
field: 'newField',
|
||||||
|
title: '新字段'
|
||||||
|
})
|
||||||
|
|
||||||
|
// 删除字段
|
||||||
|
formApi.removeField('fieldName')
|
||||||
|
|
||||||
|
// 更新字段属性
|
||||||
|
formApi.updateRule('fieldName', {
|
||||||
|
props: { disabled: true }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
1. **合理使用联动**:避免过于复杂的联动逻辑,保持用户体验流畅
|
||||||
|
2. **性能考虑**:大量字段联动时注意性能影响
|
||||||
|
3. **用户体验**:联动变化要有明确的视觉反馈
|
||||||
|
4. **数据一致性**:隐藏字段时考虑是否需要清空数据
|
||||||
|
5. **错误处理**:联动失败时要有合适的错误处理机制
|
||||||
|
|
||||||
|
## 扩展功能
|
||||||
|
|
||||||
|
- 支持自定义联动方法
|
||||||
|
- 支持异步联动(如远程获取选项)
|
||||||
|
- 支持复杂条件表达式
|
||||||
|
- 支持联动动画效果
|
||||||
|
- 支持联动历史记录
|
||||||
|
|
||||||
|
## 访问方式
|
||||||
|
|
||||||
|
### 开发环境访问
|
||||||
|
|
||||||
|
直接在浏览器中访问:
|
||||||
|
|
||||||
|
```url
|
||||||
|
http://localhost:3000/#/infra/demo/formCreateControl
|
||||||
|
```
|
||||||
|
|
||||||
|
### 路由配置
|
||||||
|
|
||||||
|
如果需要在菜单中显示,可以在后台管理系统中添加菜单项:
|
||||||
|
|
||||||
|
- **菜单名称**: FormCreate联动示例
|
||||||
|
- **路由地址**: `demo/formCreateControl`
|
||||||
|
- **组件路径**: `infra/demo/formCreateControl/index`
|
||||||
|
|
||||||
|
### 文件结构
|
||||||
|
|
||||||
|
```text
|
||||||
|
src/views/infra/demo/formCreateControl/
|
||||||
|
├── index.vue # 主页面组件
|
||||||
|
└── README.md # 说明文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 相关文档
|
||||||
|
|
||||||
|
- [FormCreate 官方文档](https://form-create.com/v3/)
|
||||||
|
- [Control 联动控制](https://form-create.com/v3/guide/control)
|
||||||
|
- [API 参考](https://form-create.com/v3/guide/api)
|
||||||
|
|
@ -0,0 +1,590 @@
|
||||||
|
<template>
|
||||||
|
<ContentWrap>
|
||||||
|
<div class="mb-20px">
|
||||||
|
<el-alert
|
||||||
|
title="FormCreate 组件联动示例"
|
||||||
|
type="info"
|
||||||
|
description="演示 FormCreate 中各种组件联动的使用方法,包括显示/隐藏、禁用/启用、选项联动等"
|
||||||
|
show-icon
|
||||||
|
:closable="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-tabs v-model="activeTab" type="border-card">
|
||||||
|
<!-- 基础联动示例 -->
|
||||||
|
<el-tab-pane label="基础联动" name="basic">
|
||||||
|
<div class="demo-container">
|
||||||
|
<h3>基础显示/隐藏联动</h3>
|
||||||
|
<p class="demo-desc">根据选择的值控制其他组件的显示和隐藏</p>
|
||||||
|
|
||||||
|
<form-create
|
||||||
|
v-model="basicForm.value"
|
||||||
|
v-model:api="basicForm.api"
|
||||||
|
:rule="basicForm.rule"
|
||||||
|
:option="basicForm.option"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="form-data">
|
||||||
|
<h4>表单数据:</h4>
|
||||||
|
<pre>{{ JSON.stringify(basicForm.value, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 禁用联动示例 -->
|
||||||
|
<el-tab-pane label="禁用联动" name="disabled">
|
||||||
|
<div class="demo-container">
|
||||||
|
<h3>组件禁用/启用联动</h3>
|
||||||
|
<p class="demo-desc">根据条件动态禁用或启用表单组件</p>
|
||||||
|
|
||||||
|
<form-create
|
||||||
|
v-model="disabledForm.value"
|
||||||
|
v-model:api="disabledForm.api"
|
||||||
|
:rule="disabledForm.rule"
|
||||||
|
:option="disabledForm.option"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="form-data">
|
||||||
|
<h4>表单数据:</h4>
|
||||||
|
<pre>{{ JSON.stringify(disabledForm.value, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 选项联动示例 -->
|
||||||
|
<el-tab-pane label="选项联动" name="options">
|
||||||
|
<div class="demo-container">
|
||||||
|
<h3>下拉选项联动</h3>
|
||||||
|
<p class="demo-desc">省市区三级联动,根据上级选择动态更新下级选项</p>
|
||||||
|
|
||||||
|
<form-create
|
||||||
|
v-model="optionsForm.value"
|
||||||
|
v-model:api="optionsForm.api"
|
||||||
|
:rule="optionsForm.rule"
|
||||||
|
:option="optionsForm.option"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="form-data">
|
||||||
|
<h4>表单数据:</h4>
|
||||||
|
<pre>{{ JSON.stringify(optionsForm.value, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 复杂联动示例 -->
|
||||||
|
<el-tab-pane label="复杂联动" name="complex">
|
||||||
|
<div class="demo-container">
|
||||||
|
<h3>复杂业务联动</h3>
|
||||||
|
<p class="demo-desc">模拟真实业务场景的复杂联动逻辑</p>
|
||||||
|
|
||||||
|
<form-create
|
||||||
|
v-model="complexForm.value"
|
||||||
|
v-model:api="complexForm.api"
|
||||||
|
:rule="complexForm.rule"
|
||||||
|
:option="complexForm.option"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="form-data">
|
||||||
|
<h4>表单数据:</h4>
|
||||||
|
<pre>{{ JSON.stringify(complexForm.value, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
|
||||||
|
<!-- 动态规则示例 -->
|
||||||
|
<el-tab-pane label="动态规则" name="dynamic">
|
||||||
|
<div class="demo-container">
|
||||||
|
<h3>动态添加/删除组件</h3>
|
||||||
|
<p class="demo-desc">根据用户操作动态添加或删除表单组件</p>
|
||||||
|
|
||||||
|
<form-create
|
||||||
|
v-model="dynamicForm.value"
|
||||||
|
v-model:api="dynamicForm.api"
|
||||||
|
:rule="dynamicForm.rule"
|
||||||
|
:option="dynamicForm.option"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="mt-20px">
|
||||||
|
<el-button type="primary" @click="addField">添加字段</el-button>
|
||||||
|
<el-button type="danger" @click="removeField">删除字段</el-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-data">
|
||||||
|
<h4>表单数据:</h4>
|
||||||
|
<pre>{{ JSON.stringify(dynamicForm.value, null, 2) }}</pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</ContentWrap>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
defineOptions({ name: 'FormCreateControlDemo' })
|
||||||
|
|
||||||
|
const activeTab = ref('basic')
|
||||||
|
|
||||||
|
// 基础联动表单
|
||||||
|
const basicForm = reactive({
|
||||||
|
value: {},
|
||||||
|
api: null,
|
||||||
|
option: {
|
||||||
|
form: {
|
||||||
|
labelWidth: '120px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'radio',
|
||||||
|
field: 'userType',
|
||||||
|
title: '用户类型',
|
||||||
|
value: 'personal',
|
||||||
|
options: [
|
||||||
|
{ label: '个人用户', value: 'personal' },
|
||||||
|
{ label: '企业用户', value: 'enterprise' }
|
||||||
|
],
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'personal',
|
||||||
|
condition: '==',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: ['companyName', 'businessLicense']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'enterprise',
|
||||||
|
condition: '==',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: ['idCard']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'userName',
|
||||||
|
title: '用户名',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入用户名'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'idCard',
|
||||||
|
title: '身份证号',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入身份证号'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'companyName',
|
||||||
|
title: '公司名称',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入公司名称'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'businessLicense',
|
||||||
|
title: '营业执照号',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入营业执照号'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 禁用联动表单
|
||||||
|
const disabledForm = reactive({
|
||||||
|
value: {},
|
||||||
|
api: null,
|
||||||
|
option: {
|
||||||
|
form: {
|
||||||
|
labelWidth: '120px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'switch',
|
||||||
|
field: 'enableEdit',
|
||||||
|
title: '启用编辑',
|
||||||
|
value: false,
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: false,
|
||||||
|
condition: '==',
|
||||||
|
method: 'disabled',
|
||||||
|
rule: ['name', 'email', 'phone']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'name',
|
||||||
|
title: '姓名',
|
||||||
|
value: '张三',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入姓名'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'email',
|
||||||
|
title: '邮箱',
|
||||||
|
value: 'zhangsan@example.com',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入邮箱'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'phone',
|
||||||
|
title: '手机号',
|
||||||
|
value: '13800138000',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入手机号'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 选项联动表单
|
||||||
|
const optionsForm = reactive({
|
||||||
|
value: {},
|
||||||
|
api: null,
|
||||||
|
option: {
|
||||||
|
form: {
|
||||||
|
labelWidth: '120px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'province',
|
||||||
|
title: '省份',
|
||||||
|
options: [
|
||||||
|
{ label: '广东省', value: 'guangdong' },
|
||||||
|
{ label: '江苏省', value: 'jiangsu' },
|
||||||
|
{ label: '浙江省', value: 'zhejiang' }
|
||||||
|
],
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'guangdong',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['city'],
|
||||||
|
options: [
|
||||||
|
{ label: '广州市', value: 'guangzhou' },
|
||||||
|
{ label: '深圳市', value: 'shenzhen' },
|
||||||
|
{ label: '珠海市', value: 'zhuhai' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'jiangsu',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['city'],
|
||||||
|
options: [
|
||||||
|
{ label: '南京市', value: 'nanjing' },
|
||||||
|
{ label: '苏州市', value: 'suzhou' },
|
||||||
|
{ label: '无锡市', value: 'wuxi' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'zhejiang',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['city'],
|
||||||
|
options: [
|
||||||
|
{ label: '杭州市', value: 'hangzhou' },
|
||||||
|
{ label: '宁波市', value: 'ningbo' },
|
||||||
|
{ label: '温州市', value: 'wenzhou' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'city',
|
||||||
|
title: '城市',
|
||||||
|
options: [],
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'guangzhou',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['district'],
|
||||||
|
options: [
|
||||||
|
{ label: '天河区', value: 'tianhe' },
|
||||||
|
{ label: '越秀区', value: 'yuexiu' },
|
||||||
|
{ label: '海珠区', value: 'haizhu' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'shenzhen',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['district'],
|
||||||
|
options: [
|
||||||
|
{ label: '南山区', value: 'nanshan' },
|
||||||
|
{ label: '福田区', value: 'futian' },
|
||||||
|
{ label: '罗湖区', value: 'luohu' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'hangzhou',
|
||||||
|
condition: '==',
|
||||||
|
method: 'replaceOptions',
|
||||||
|
rule: ['district'],
|
||||||
|
options: [
|
||||||
|
{ label: '西湖区', value: 'xihu' },
|
||||||
|
{ label: '拱墅区', value: 'gongshu' },
|
||||||
|
{ label: '江干区', value: 'jianggan' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'district',
|
||||||
|
title: '区县',
|
||||||
|
options: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 复杂联动表单
|
||||||
|
const complexForm = reactive({
|
||||||
|
value: {},
|
||||||
|
api: null,
|
||||||
|
option: {
|
||||||
|
form: {
|
||||||
|
labelWidth: '120px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
field: 'orderType',
|
||||||
|
title: '订单类型',
|
||||||
|
options: [
|
||||||
|
{ label: '普通订单', value: 'normal' },
|
||||||
|
{ label: '预售订单', value: 'presale' },
|
||||||
|
{ label: '定制订单', value: 'custom' }
|
||||||
|
],
|
||||||
|
control: [
|
||||||
|
{
|
||||||
|
value: 'presale',
|
||||||
|
condition: '==',
|
||||||
|
method: 'display',
|
||||||
|
rule: ['presaleDate', 'deposit']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'custom',
|
||||||
|
condition: '==',
|
||||||
|
method: 'display',
|
||||||
|
rule: ['customRequirement', 'designFee']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'normal',
|
||||||
|
condition: '==',
|
||||||
|
method: 'hidden',
|
||||||
|
rule: ['presaleDate', 'deposit', 'customRequirement', 'designFee']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'productName',
|
||||||
|
title: '产品名称',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入产品名称'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'quantity',
|
||||||
|
title: '数量',
|
||||||
|
value: 1,
|
||||||
|
props: {
|
||||||
|
min: 1,
|
||||||
|
max: 999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'price',
|
||||||
|
title: '单价',
|
||||||
|
props: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
field: 'presaleDate',
|
||||||
|
title: '预售日期',
|
||||||
|
props: {
|
||||||
|
type: 'date',
|
||||||
|
placeholder: '请选择预售日期'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'deposit',
|
||||||
|
title: '定金',
|
||||||
|
props: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'customRequirement',
|
||||||
|
title: '定制需求',
|
||||||
|
props: {
|
||||||
|
type: 'textarea',
|
||||||
|
rows: 3,
|
||||||
|
placeholder: '请描述定制需求'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'inputNumber',
|
||||||
|
field: 'designFee',
|
||||||
|
title: '设计费',
|
||||||
|
props: {
|
||||||
|
min: 0,
|
||||||
|
precision: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 动态表单
|
||||||
|
const dynamicForm = reactive({
|
||||||
|
value: {},
|
||||||
|
api: null,
|
||||||
|
option: {
|
||||||
|
form: {
|
||||||
|
labelWidth: '120px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rule: [
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'name',
|
||||||
|
title: '姓名',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入姓名'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
field: 'email',
|
||||||
|
title: '邮箱',
|
||||||
|
props: {
|
||||||
|
placeholder: '请输入邮箱'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 动态字段计数器
|
||||||
|
let fieldCounter = 0
|
||||||
|
|
||||||
|
// 添加字段
|
||||||
|
const addField = () => {
|
||||||
|
fieldCounter++
|
||||||
|
const newField = {
|
||||||
|
type: 'input',
|
||||||
|
field: `dynamicField${fieldCounter}`,
|
||||||
|
title: `动态字段${fieldCounter}`,
|
||||||
|
props: {
|
||||||
|
placeholder: `请输入动态字段${fieldCounter}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dynamicForm.api) {
|
||||||
|
dynamicForm.api.append(newField)
|
||||||
|
} else {
|
||||||
|
dynamicForm.rule.push(newField)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除字段
|
||||||
|
const removeField = () => {
|
||||||
|
if (fieldCounter > 0) {
|
||||||
|
const fieldToRemove = `dynamicField${fieldCounter}`
|
||||||
|
|
||||||
|
if (dynamicForm.api) {
|
||||||
|
dynamicForm.api.removeField(fieldToRemove)
|
||||||
|
} else {
|
||||||
|
const index = dynamicForm.rule.findIndex((item) => item.field === fieldToRemove)
|
||||||
|
if (index > -1) {
|
||||||
|
dynamicForm.rule.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldCounter--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.demo-container {
|
||||||
|
padding: 20px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-container h3 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.demo-desc {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
color: #606266;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-data {
|
||||||
|
margin-top: 30px;
|
||||||
|
padding: 15px;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e4e7ed;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-data h4 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #303133;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-data pre {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px;
|
||||||
|
background: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #606266;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-tabs__content) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-tab-pane) {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue