页面树结构

版本比较

标识

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

  1. 已经使用了vue的数据绑定能力将整体宽度、整体高度和标签内容设置为args.height,heightType,width,widthType以及args.label五个参数。
  2. 其中<span v-show="t_edit" ref="edit">标签的内容仍然保持为空,因此如果此时调试控件是不会有和上述5个参数对应的属性编辑框出现的。

下面看如何得到属性编辑框。

2.2

...

给控件增加选项配置面板

为了给控件增加属性编辑功能,DWF提供了一个称之为EditBox的标签和配套的函数,只要控件的代码中包含args属性是DWF建模工具可以自动识别的,表单建模工具会自动为其在属性编辑区建立对应的输入控件。增加EditBox需要执行下面的步骤:为了给控件增加选项编辑功能,DWF提供了一个称之为EditBox的组件和配套的函数,只要控件的代码中包含args属性是DWF建模工具可以自动识别的,表单建模工具会自动为其在属性编辑区建立对应的输入控件。增加EditBox需要执行下面的步骤:

  1. 在控件vue文件中的<template>内增加<EditBox>标签并配置参数。
  2. 在脚本部分通过import引入_EditBox.vue文件和EditBox的component组件。
  3. 引入DWF表单引擎传入的prop参数,以便EditBox作为标签参数绑定。

...

首先,引入EditBox标签的方法很简单,如下代码所示:

代码块
languagexml
   		<span v-show="t_edit" ref="edit">
			<!--
			属性编辑框区域
			需要该插件获取attributes, router, route, root, query_oprs, itemValue的prop
			对于不需要设置目标属性的插件,可以将attributes去掉
			对于不需要设置事件的插件,可以将router, route, root, query_oprs去掉
			-->
			<EditBox
				v-model="args"
				:router="router"
				:route="route"
				:root="root"
				:itemValue="itemValue"
				:query_oprs="query_oprs"
				:targetclass="itemValue.data.targetClass"
			>
				<div slot="attribute">
					<!--           <EditBox
                v-if="actEdit"
                :addinName="name"
                :widgetAnnotation="widgetAnnotation"
                :editExtendInfo="editExtendInfo"
                属性选项放置区域ref="editbox"
                v-model="args"
       一般一个控件的prop都属于属性选项
					-->
				</div>
				<div slot="layout">
					<!--         :attributes="filter_attributes"
                :router="router"
        样式选项放置区域        :route="route"
				:store="store"
               仅有涉及到高度,宽度,对齐等样式的选项放在这里
					-->
				</div>
				<div slot="operation">
					<!-- :root="root"
                :itemValue="itemValue"
                :query_oprs="query_oprs"
        事件选项放置区域
					--        :dataTypes="dataTypes"
                :targetclass="itemValue.data.targetClass"
            >
				<<div slot="attribute"></div>
			</EditBox>
			<div slot="layout"></div>
				<div slot="operation"></div>
			</EditBox>
		</span>
  1. 在EditBox里增加了一系列prop变量绑定,例如:attributes, router, route, root, query_oprs, itemValue。
  2. 在标签里如果出现需要自定义的部分可以分别在<div slot>标签里添加,这里先不考虑添加自定义属性。
    <div slot="attribute">表示选项面板的基础选项。
    <div slot="layout">表示涉及到布局和样式的面板。
    <div slot="operation">表示事件的列表可以绑定操作。

引入EditBox脚本

接下来,直接引入EditBox标签对应的脚本实现,具体代码片段如下所示:

代码块
languagejs
<script>
// 引入控件自身的属性编辑框,DWF给出的标准实现
import EditBox from "@/ext_components/form/_EditBox.vue";
export default {
	// 引入控件的设置框对应的组件,对应在标签内可以引用
	components: {
		EditBox,
	},
	// 引入DWF的控件编辑辅助属性
	props: [
		"widgetAnnotation",
		"itemValue",
		"attributes",
		"route",
		"router",
		"root",
	<script>
// 引入控件自身的属性编辑框,DWF给出的标准实现
import EditBox from "@/ext_components/form/_EditBox.vue";
export default {
	// 引入控件的设置框对应的组件,对应在标签内可以引用
	components: {
		EditBox,
	},
	// 引入DWF的控件编辑辅助属性
	props: [
        'addin',
        'basicArgs',
        'argsProps',
        'activeUUID',
        'store',
        'itemValue',
        'attributes',
        'relation',
        'editExtendInfo',
        'widgetAnnotation',
        'checkResult',
        'query_oprs',
        'route',
        'router',
        'root',
        'Message',
        'echarts',
    ],
...
</script>

上述代码中import和component部分是标准操作直接引入即可

props是vue的对象传递机制,DWF在控件初始化的时候会将一些全局js变量传入,可以传入的对象并且被EditBox识别的有:上述代码中import和component部分是标准操作直接引入即可,props是vue的对象传递机制,DWF在控件初始化的时候会将一些全局js变量传入,可以传入的对象并且被EditBox识别的有:

  1. widgetAnnotation="widgetAnnotation":控件标注所用参数,DWF会通过props直接传递一个缺省值进来
  2. router="router":当前路由对象,DWF会通过props直接传递一个缺省值进来
  3. route="route":当前路由信息,DWF会通过props直接传递一个缺省值进来
  4. root="root":根组件对象,DWF会通过props直接传递一个缺省值进来
  5. itemValue="itemValue":表单对应JSON实例化以后的对象,DWF会通过props直接传递一个缺省值进来:表单对应JSON实例化以后的对象,DWF会通过props直接传递一个缺省值进来。
  6. dataTypes="dataTypes":目标属性类型:目标属性类型,需要返回一个数组表明可以接受的DWF数据类型。
  7. attributes="filter_attributes":过滤之后的目标属性:过滤之后的目标属性,需要控件里提供一个空的实现
  8. targetclass="itemValue.data.targetClass":表单类:表单目标类

增加args属性

引入了EditBox以后,还需要在vue文件脚本部分的data()函数中返回args对象,用于保存和初始化需要展示的控件属性。

...

  • 通知表单建模工具需要保留在数据库中的参数。
  • 还原表单上次保存的样子,此时控件的setArgs和getArgs会被建模工具调用。
  • 在应用端表单展现的时候,展示真实的表单,同样的,控件的setArgs和getArgs会被建模工具调用。
  • EditBox会自动扫描args的内容并自动识别可以产生属性配置的界面,这些属性在编辑以后,DWF会自动将其保存在表单对应JSON文件中,详细的自动识别清单可以参阅: DWF可自动识别的args参数

对于本章提到的args参数,height,heightType,width,widthType,label代码如下所示:

...

每一个控件需要一个title在args里面用于在建模阶段显示控件的名称,除此之外,对于本章例子里用到的args参数是:height,heightType,width,widthType,代码如下所示。


代码块
	// Vue数据绑定的时候要求返回的结果
	data() {
		return {
			//插件的名字
			name: name,
			// Vue数据绑定的时候要求返回的结果
	data() {
		return {表示是否已经进入画布区
			t_preview: true,
			//是否需要编辑属性
			t_edit: false,
			//插件的名字 属性配置项,按需设置
			nameaddIcon: "blankControl"true,
			//表示是否已经进入画布区 用于控制画布区的复制,删除和角标
			actEdit: false,
			actIndex: -1,
			t_previewsetModal: false,
			//是否需要编辑属性 支持的数据类型
			t_editdataTypes: false[],
			args: {
				// 属性配置项,按需设置用于提示用户名称
				argstitle: {"进阶控件",
				height: 300,
				heightType: "px",
				width: 100,
				widthType: "%": "%",
				label: "Empty!",
				// 给出控件可以支持的事件类型
				eventRange: ["单击", "双击"],
				labelevents: "Empty!"[],
			},
		};
	},

2.3 为控件增加事件

除了配置项以外,控件内的事件也可以添加到里面来,如果需要添加控件自身的事件响应,具体操作是:

...

综上所述,如果希望为进阶的控件添加单击和双击事件,那么可以在args添加如下的代码:

代码块
languagejs
languagejs
	// Vue数据绑定的时候要求返回的结果
	data() {
		return {
			//插件的名字
			name: name,
			//表示是否已经进入画布区
			t_preview: true,
			// Vue数据绑定的时候要求返回的结果
	data() {
		return {是否需要编辑属性
			t_edit: false,
			// 属性配置项,按需设置
			addIcon: true,
			//插件的名字 用于控制画布区的复制,删除和角标
			nameactEdit: "blankControl"false,
			//表示是否已经进入画布区actIndex: -1,
			t_previewsetModal: false,
			//是否需要编辑属性// 支持的数据类型
			dataTypes: [],
			t_editargs: false,{
				// 属性配置项,按需设置用于提示用户名称
			args	title: {"进阶控件",
				height: 300,
				heightType: "px",
				width: 100,
				widthType: "%",
				label: "Empty!",
				// 给出控件可以支持的事件类型
				eventRange: ["单击", "双击"],
				events: [],
			},
		};
	},

...

了解如何绑定原始事件并且触发操作以后,剩余的部分就非常简单了,在标签部分将标签的原始事件与函数对应起来,然后调用前面描述的triggerEvent方法触发事件配置对应的参数,先看如何绑定标签上的事件,以本章的进阶控件为例,原本设计了两个事件:单击和双击,运用vue规定的语法在template部分的标签中增加@click和@dbclick分别绑定到onClick() 和 onDoubleClick()方法上,代码如下:


<template>
代码块
languagexml
languagexml
<template>
	<!--
      建模时的预览前端,即插件的实际显示样式
      :addinName="name"和ref="main"一般情况不可去除
	-->
	<section :style="{
				width: args.width + args.widthType,
				}" :addinName="name" ref="main">
		<!-- 在画布区的显示内容 -->
		<span
			:style="{
				height: args.height+ args.heightType,
				width: args.width + args.widthType,
				}"
			style="
				font-size: 50px;
				display: flex;
				justify-content: center;
				align-items: center;"
			<!-- 绑定标签上的时间调用函数 -->
			@click="onClick"
			@dblclick="onDoubleClick"
		>{{args.label}}</span>
	</section>
</template>

...

代码块
languagexml
collapsetrue
<template>
	<!--
      建模时的预览前端,即插件的实际显示样式
      :addinName="name"和ref="main"一般情况不可去除
	-->
	<section
		v-if="t_preview"
		:addinName="name"
		ref="main"
		:style="{	
				width: args.width + args.widthType,
				}"
	>
		<!-- 在画布区的显示内容 -->
		<span
			:style="{
				height: args.height + args.heightType,	
				width: 100
				}"		<span
			:style="{
				font-sizeheight: 50px;
				display: flex;args.height + args.heightType,
				justify-contentwidth: center;100,
				align-items: center;"
		>{{ args.label }}</span>
		<span v-show="t_edit" ref="edit">}"
			style="
			<!--
	font-size: 50px;
				属性编辑框区域display: flex;
			需要该插件获取attributes, router, route, root, query_oprs, itemValue的prop	justify-content: center;
				align-items: center;
			对于不需要设置目标属性的插件,可以将attributes去掉"
			对于不需要设置事件的插件,可以将router, route, root, query_oprs去掉>{{ args.label }}</span
		>
	--	<span v-show="t_edit" ref="edit">
			<EditBox
				v-modelif="argsactEdit"
				:routeraddinName="routername"
				:routewidgetAnnotation="routewidgetAnnotation"
				:rooteditExtendInfo="rooteditExtendInfo"
				:itemValueref="itemValueeditbox"
				:query_oprsv-model="query_oprsargs"
				:targetclassattributes="itemValue.data.targetClassfilter_attributes"
				>:router="router"
				<div slot:route="attributeroute">
					<!--
                        属性选项放置区域
                        一般一个控件的prop都属于属性选项
					-->
				<:root="root"
				:itemValue="itemValue"
				:query_oprs="query_oprs"
				:dataTypes="dataTypes"
				:targetclass="itemValue.data.targetClass"
			>
				<div slot="attribute"></div>
				<div slot="layout"></div>
				<div slot="layoutoperation">></div>
			</EditBox>
		<!--
                        样式选项放置区域
                        仅有涉及到高度,宽度,对齐等样式的选项放在这里
					-->
	/span>
	</section>
	<section v-else :addinName="name">
		<span style="text-align: center">
			<div class="form-addin-icon">
				<!-- 控件拖放区图标的样式 -->
				<i class="iconfont"></i>
			</div>
			<!-- 在控件拖放区图标的名字 -->
			<div slotclass="operation">form-addin-name">进阶控件</div>
		</span>
			<!--
</section>
</template>


<script>
import EditBox from "@/ext_components/form/_EditBox.vue";

const name = "BlankControl";

export default {
	name: name,

    事件选项放置区域
					-->	props: [
		"addin",
		</div>"basicArgs",
			</EditBox>"argsProps",
		</span>"activeUUID",
	</section>
	<section v-else :addinName="name">"store",
		<span style="text-align: center;">"itemValue",
			<div class="form-addin-icon">"attributes",
		"relation",
		<!-- 控件拖放区图标的样式 -->
				<i class="iconfont"></i>
			</div>
			<!-- 在控件拖放区图标的名字 -->
			<div class="form-addin-name">进阶控件</div>
		</span>
	</section>
</template>

<script>
// 引入控件自身的属性编辑框,DWF给出的标准实现
import EditBox from "@/ext_components/form/_EditBox.vue";
export default {
	// 引入控件的设置框对应的组件,对应在标签内可以引用"editExtendInfo",
		"widgetAnnotation",
		"checkResult",
		"query_oprs",
		"route",
		"router",
		"root",
		"Message",
		"echarts",
	],

	components: {
		EditBox,
	},
	//
引入DWF的控件编辑辅助属性
	props: [data() {
		"widgetAnnotation",return {
		"itemValue",
		"attributes"	//插件的名字
			name: name,
		"route",	//表示是否已经进入画布区
		"router"	t_preview: true,
		"root",	//是否需要编辑属性
		"query_oprs"	t_edit: false,
	],
		// Vue数据绑定的时候要求返回的结果
	data() {属性配置项,按需设置
		return {	addIcon: true,
			//插件的名字 用于控制画布区的复制,删除和角标
			nameactEdit: "blankControl"false,
			//表示是否已经进入画布区actIndex: -1,
			t_previewsetModal: false,
			//是否需要编辑属性 支持的数据类型
			t_editdataTypes: false,
[],
			args: {
				// 属性配置项,按需设置用于提示用户名称
				argstitle: {"进阶控件",
				height: 300,
				heightType: "px",
				width: 100,
				widthType: "%",
				label: "Empty!",
				// 给出控件可以支持的事件类型
				eventRange: ["单击", "双击"],
				events: [],
			},
		};
	},
	methods:created() {},
		//* 		在建模的时候传入,提示控件是在画布区还是在控件列表中生命周期函数,在dom元素生成之后调用
		0:表示在画布区,已经被拖入
		1:表示在控件区,准备被拖入
		2: 表示在拖动中,还未放下mounted() {},
	computed: {
		*// 需要用到实体类属性列表时使用
		setDisplayTypefilter_attributes(type) {
			if (type == 0) this.t_preview = truereturn [];
			return this;},
		},
	methods: {
		// 默认不用变化,返回编辑框供建模工具绘制,当控件拖入画布区以后被点击的时候触发
		getEditBox() {
			this.t_edit = true;
			return this.$refs.edit;
		},
		// 当插件无法直接通过style设置高度时,使用setHeight方法设置高度
		setHeight() {
			if (!this.$refs.main) return;
		},
		// 现有表单加载在画布区加载控件的时候,会将之前的配置传入
		setArgs(args) {
			for (var i in args) {
				this.args[i] = args[i];
			}
			return this;
		},
		// 表单保存的时候将控件的设置合并到表单自身的JSON中
		getArgs() {
			return this.args;
		},
		// 是否允许其他子控件拖入,如果不允许则返回null返回控件绑定的目标属性,如果没有绑定返回undefined或者null
		getAllowgetFormName() {
			return nullthis.name;
		},
		// 返回控件绑定的目标属性,如果没有绑定返回undefined或者null
		getFormName(getDataType(args) {
			return nullthis.dataTypes;
		},
	},
};
</script>

<style>
</style>

...

代码块
collapsetrue
<template>
	<!--
      建模时的预览前端,即插件的实际显示样式
      :addinName="name"和ref="main"一般情况不可去除
	-->
	<section :style="{
				width: args.width + args.widthType,
				}" :addinName="name" ref="main">
		<!-- 在画布区的显示内容 -->
		<span
			:style="{
				height: args.height+ args.heightType,
				width: args.width + args.widthType,
				}"
			style="
				font-size: 50px;
				display: flex;
				justify-content: center;
				align-items: center;"
			@click="onClick"
			@dblclick="onDoubleClick"
		>{{args.label}}</span>
	</section>
</template>

<script>
export default {
	props: ["itemValue", "store"],
	// Vue数据绑定的时候要求返回的结果
	data() {
		return {
			//插件的名字
			name: "blankControlBlankControl",
			// 属性配置项,按需设置
			args: {
				// 用于提示用户名称
				title: "进阶控件",
				height: 300,
				heightType: "px",
				width: 100,
				widthType: "%",
				label: "Empty!"!",
				// 给出控件可以支持的事件类型
				eventRange: ["单击", "双击"],
				events: [],
			},
		};
	},
	methods: {
		/*
        type取值范围为 create, visit, edit
        需要根据三个状态修改具体前端和逻辑
        一般情况下:
            create创建态: 无数据,可编辑
            visit浏览态: 有数据,不可编辑
            edit编辑态: 有数据,可编辑
       */
		setDisplayType(type) {
			return this;
		},
		// 设置异常状态显示
		setError(error) {
			return this;
		},
		// 设置校验逻辑,返回true/false
		validate() {
			return true;
		},
		// 返回对应的目标属性名称,引擎在渲染的时候将根据其返回值提取属性的取值调用setValue()
		getFormName() {
			return nullthis.name;
		},
		// 获取插件对应的值,一般为this.value,特殊情况下需要进行格式转化,如日期字符串
		getValue() {
			return null;
		},
		/*
          设置插件对应的值, 如果目标属性为空,则传入的items为空,主要是针对多对象加载控件时使用
          items目前为对应值,items将为目标对象列表
          特殊情况下需要进行格式转化再赋值
        */
		setValue(items) {
			return this;
		},
		// 现有表单加载在画布区加载控件的时候,会将之前的配置传入
		setArgs(args) {
			for (var i in args) {
				this.args[i] = args[i];
			}
			return this;
		},
		// 表单保存的时候将控件的设置合并到表单自身的JSON中
		getArgs() {
			return this.args;
		},
		// 区域被单击以后的响应
		onClick() {
			this.triggerEvent("单击");
		},
		// 区域被双击以后的响应
		onDoubleClick() {
			this.triggerEvent("双击");
		},
		// 根据名字触发表单事件上配置的操作
		triggerEvent(eventName) {
			let eventConfig = null;
			// 提取事件对应的操作参数
			if (this.args.events && this.args.events.length > 0) {
				eventConfig = this.args.events.find((val) => {
					return val.name === eventName;
				});
			}
			// 触发实际操作
			if (eventConfig) {
				this.invokeOperation(
					eventConfig.opr_type,
					eventConfig.opr_path,
					this.itemValue,
					this.store
				);
			}
		},
	},
};
</script>

<style>
</style>

...

本章在最后还介绍了控件应用端的一些额外函数,当控件需要和DWF数据绑定并进行交互的时候这些函数就会被调用,接下来在表单建模进阶里将会介绍控件如何与后台数据交互。

4 附件

建模端进阶控件:

View file
nameassemble-to.yaml
height250
View file
nameblankControl.vue
height250

应用端进阶控件:

View file
nameassemble-to.yaml
height250
View filenameblankControl.vueheight250