基于Vue和Quasar的前端SPA项目实战之拖拽表单定制(十六)
基于Vue和Quasar的前端SPA项目实战之拖拽表单定制(十六)
回顾
通过前一篇文章 基于Vue和Quasar的前端SPA项目实战之动态表单(五)的介绍,实现了元数据中动态表单设计功能,支持常见的数据类型和索引,然后实现了动态表单的crud增删改查功能,所有的表单页面都是默认的风格。本文主要介绍拖拽表单定制功能,通过拖拽的方式定制表单录入和编辑页面,满足了个性化需求。
简介
针对元数据表的每个字段,通过拖拽方式决定是否显示或者隐藏,然后还可以配置显示的宽度。最终以json格式保存到后台数据库,运行时根据配置动态渲染录入和编辑表单form页面。针对不同的设备(电脑,平板,手机)都可以单独定制。
UI界面
![]()
页面构建
![]()
运行时
代码
说明
采用开源框架vuesortable,基于vue的实现排序,支持拖拽。页面构建分为左中右三个部分,左边为候选字段,中间为需要显示的字段,右边可以针对每个字段单独设置一些属性,比如宽度等。
数据表
创建表单tableFormBuilder,用于存储页面构建json数据,包括类型type、设备device、内容body等字段, 充分利用crudapi功能,API部分零代码实现。
![]()
tableFormBuilder
核心代码
页面构建
class="dragArea list-group row"
:list="selectedList"
group="people"
@change="log"
>
v-for="formElement in selectedList"
:key="formElement.columnId"
:class="formElement | classFormat(currentElement)"
@click="selectForEdit(formElement)"
>
v-bind:class="{ 'required': !formElement.column.nullable}">
{{formElement.column.caption}}:
readonly
:placeholder="formElement.column.description"
:type="formElement.isPwd ? 'password' : 'text'"
v-model="formElement.column.value" >
:name="formElement.isPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="formElement.isPwd = !formElement.isPwd"
/>
v-model="textValue"
:placeholder="formElement.column.description" >
mask="YYYY-MM-DD HH:mm:ss"
@input="hideRefPopProxyAction('qDateProxy')" />
format24h with-seconds
@input="hideRefPopProxyAction('qTimeProxy')" />
mask="YYYY-MM-DD"
@input="hideRefPopProxyAction('qDateProxy')" />
format24h with-seconds
@input="hideRefPopProxyAction('qTimeProxy')" />
v-model="formElement.column.value">
v-else-if="isNumberType(formElement)"
:placeholder="formElement.column.description"
type="number"
v-model="formElement.column.value" >
v-model="formElement.column.value" >
readonly
:placeholder="formElement.column.description"
:type="formElement.isPwd ? 'password' : 'text'"
v-model="formElement.column.value" >
:name="formElement.isPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="formElement.isPwd = !formElement.isPwd"
/>
通过draggable标签实现
运行时渲染
v-for="formElement in selectedList"
:key="formElement.columnId"
:class="formElement | classFormat">
v-bind:class="{ 'required': !formElement.column.nullable}">
{{formElement.column.caption}}:
style="border-bottom: 1px solid rgba(0,0,0,0.12)"
v-if="formElement.column.relationTableName">
{{ formElement.column.value | relationDataFormat(formElement.column) }}
@click="openDialogClickAction(formElement.column)" />
v-model="formElement.column.value"
:placeholder="formElement.column.description"
:type="formElement.isPwd ? 'password' : 'text'" >
:name="formElement.isPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="formElement.isPwd = !formElement.isPwd"
/>
v-model="formElement.column.value"
:placeholder="formElement.column.description" >
v-model="formElement.column.value" >
mask="YYYY-MM-DD HH:mm:ss"
@input="hideRefPopProxyAction('qDateProxy')" />
mask="YYYY-MM-DD HH:mm:ss"
format24h with-seconds
@input="hideRefPopProxyAction('qTimeProxy')" />
v-model="formElement.column.value">
mask="YYYY-MM-DD"
@input="hideRefPopProxyAction('qDateProxy')" />
v-model="formElement.column.value" >
mask="HH:mm:ss"
format24h with-seconds
@input="hideRefPopProxyAction('qTimeProxy')" />
v-model="formElement.column.value" >
v-else-if="isNumberType(formElement.column.dataType)"
v-model="formElement.column.value"
:placeholder="formElement.column.description"
type="number">
v-model="formElement.column.value"
@input="(data)=>{
formElement.column.value = data.url;
}">
v-model="formElement.column.value"
:placeholder="formElement.column.description"
:type="formElement.isPwd ? 'password' : 'text'" >
:name="formElement.isPwd ? 'visibility_off' : 'visibility'"
class="cursor-pointer"
@click="formElement.isPwd = !formElement.isPwd"
/>
