公共查询栏组件
该组件在表单组件基础上进行封装,封装为具有某些特定样式及功能的公共查询组件,可结合表格或其他列表类组件进行数据查询
案例背景
项目中表格类页面非常多,需要封装一个样式统一的查询栏组件结合表格组件进行使用。如下:
组件功能分析
该组件需具备能力如下:
- 1、分栏展示表单组件,并支持响应式控制分栏数量
- 2、查询区域可进行折叠展开
- 3、支持查询,重置
- 4、对外暴露的配置项如下:
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
defaultValues | 默认值, 设置公共查询区域表单项的默认数据 | Record<string, any> | {} |
searchColumns | 查询字段 | ColumnItem[] | [] |
search | 查询动作 | string | - |
reset | 重置动作 | string | - |
size | 组件尺寸 | large/medium/small/mini | medium |
labelWidth | 标签宽度, 配置表单项标签宽度 | large/medium/small/mini | medium |
Type
ColumnItem
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
title | 标题 | string | - |
name | 字段名 | string | - |
type | 表单类型 | input/date/select/inputNumber | - |
placeholder | 占位提示 | string | - |
required | 是否必填 | boolean | false |
requiredMsg | 必填错误提示 | string | - |
options | 选项值 | Array | [] |
组件属性
在根组件的属性配置处编辑组件对外暴露的属性值配置 详细配置介绍
组件的配置项如下:
属性配置json数据如下:
json
[
{
"label": "属性",
"type": "tab",
"coms": [
{
"col": "status",
"default": "default",
"bindParam": true,
"label": "默认状态",
"type": "radio",
"props": {
"options": [
{
"value": "默认",
"key": "default"
},
{
"value": "隐藏",
"key": "hidden"
},
{
"value": "销毁",
"key": "destroy"
}
]
}
},
{
"col": "defaultValues",
"default": {},
"bindParam": true,
"label": "默认值",
"type": "code",
"props": {}
},
{
"col": "searchColumns",
"label": "查询字段配置",
"type": "table",
"props": {
"columns": [
{
"col": "title",
"label": "标题",
"type": "input",
"props": {}
},
{
"col": "name",
"label": "数据字段",
"type": "input",
"props": {}
},
{
"col": "placeholder",
"label": "占位提示",
"type": "input",
"props": {}
},
{
"col": "type",
"default": "input",
"label": "类型",
"type": "select",
"props": {
"options": [
{
"value": "输入框",
"key": "input"
},
{
"value": "数字输入框",
"key": "inputNumber"
},
{
"value": "下拉选择",
"key": "select"
},
{
"value": "日期选择",
"key": "date"
}
]
}
},
{
"col": "options",
"showCondition": {
"val": "select",
"col": "type"
},
"bindParam": true,
"label": "选项值",
"type": "code",
"props": {}
},
{
"col": "required",
"label": "是否必填",
"type": "switch",
"props": {}
},
{
"col": "requiredMsg",
"showCondition": {
"val": true,
"col": "required"
},
"label": "必填提示信息",
"type": "input",
"props": {}
}
]
}
},
{
"col": "search",
"label": "查询",
"type": "function"
},
{
"col": "reset",
"label": "重置",
"type": "function"
}
]
},
{
"label": "样式",
"type": "tab",
"coms": [
{
"col": "baseStyle",
"label": "自定义样式",
"type": "style"
},
{
"col": "size",
"default": "medium",
"label": "尺寸",
"type": "radio",
"props": {
"options": [
{
"value": "大",
"key": "large"
},
{
"value": "中",
"key": "medium"
},
{
"value": "小",
"key": "small"
},
{
"value": "迷你",
"key": "mini"
}
]
}
},
{
"col": "labelWidth",
"default": "100",
"label": "标签宽度",
"type": "input",
"props": {
"addonAfter": "px"
}
}
]
},
{
"label": "高级",
"type": "tab",
"coms": [
{
"col": "uniqueKey",
"label": "唯一标识",
"type": "uniqueId"
}
]
}
]
视图实现
该自定义组件中所需基础组件为:表单容器,布局容器,按钮,其他表单项组件
步骤一:响应式布局配置
1、使用布局容器实现响应式布局,布局容器下存在两列,第一列放置表单项组件表单项,第二列放置查询,重置等按钮组件,本例中我们假设支持的表单类型为输入框,数字输入框,下拉选择,日期四种类型,则在第一列中拖入该四种类型的基础组件
2、接下来配置列的响应式布局,选中第一列配置响应式相关属性。
3、选中第二列,设置栅格占位格数为auto,这样该列会自动填满剩余空间,并在样式中通过flex布局设置按钮位置居右
步骤二:表单项循环渲染配置
1、表单项为动态数组数据,数量不固定,需要根据配置进行循环渲染表单项组件,选中布局容器的第一列在高级配置中配置循环数据的绑定变量
2、对列组件绑定循环变量后,接下来对表单组件绑定表单配置项中的属性值,以其下的输入框的默认状态为例,其余类似标题,占位提示等对外配置的属性亦是同理
步骤三:实现展开,收起功能
1、定义两个变量
- expand 控制当前状态是展开还是收起
- statusMap 控制表单项所在列组件的显隐
2、定义公共处理函数calculateCol处理展开收起时显示哪些列,隐藏哪些列
处理函数具体如下:javascript
function fn(ctx) {
if (ctx.state.expand) {
ctx.setState({
statusMap: ctx.customProps.searchColumns.reduce((obj, item) => {
obj[item.name] = "default";
return obj;
}, {})
})
return;
}
const width = window.innerWidth;
// 判断当前窗口在那个尺寸下
const isxs = width < 576;
const issm = width >= 576 && width < 768;
const ismd = width >= 768 && width < 992;
const islg = width >= 992 && width < 1200;
const isxl = width >= 1200 && width < 1600;
const isxxl = width >= 1600;
let showColCount = ctx.customProps.searchColumns?.length;
// 根据不同的屏幕尺寸 定义收起是展示几列表单项数据
if (isxs) {
showColCount = 1
} else if(issm) {
showColCount = 1
} else if(ismd) {
showColCount = 2
} else if(islg) {
showColCount = 2
} else if(isxl) {
showColCount = 3
} else if(isxxl) {
showColCount = 3
}
// 根据展示的列数处理每一列的显隐状态
ctx.setState({
statusMap: ctx.customProps.searchColumns.reduce((obj, item, index) => {
obj[item.name] = index < showColCount ? "default" : "hidden";
return obj;
}, {})
})
}
2、展开收起按钮点击时,组件onMounted时,window.onresize事件中调用calculateCol处理函数处理列显隐状态数据
3、将状态绑定到列的状态变量上,用来在展开收起时控制列的显隐
组件完整json配置
json
{
"pages": [
{
"key": 0,
"type": "component",
"name": "低代码业务组件",
"code": "",
"display": "",
"props": {
"advancedMode": true,
"baseStyle": ":rootNode {\n background-color: #fff;\n}",
"hideCopy": false,
"config": [
{
"label": "属性",
"type": "tab",
"coms": [
{
"col": "status",
"default": "default",
"bindParam": true,
"label": "默认状态",
"type": "radio",
"props": {
"options": [
{
"value": "默认",
"key": "default"
},
{
"value": "隐藏",
"key": "hidden"
},
{
"value": "销毁",
"key": "destroy"
}
]
}
},
{
"col": "defaultValues",
"default": {},
"bindParam": true,
"label": "默认值",
"type": "code",
"props": {}
},
{
"col": "searchColumns",
"label": "查询字段配置",
"type": "table",
"props": {
"columns": [
{
"col": "title",
"label": "标题",
"type": "input",
"props": {}
},
{
"col": "name",
"label": "数据字段",
"type": "input",
"props": {}
},
{
"col": "placeholder",
"label": "占位提示",
"type": "input",
"props": {}
},
{
"col": "type",
"default": "input",
"label": "类型",
"type": "select",
"props": {
"options": [
{
"value": "输入框",
"key": "input"
},
{
"value": "数字输入框",
"key": "inputNumber"
},
{
"value": "下拉选择",
"key": "select"
},
{
"value": "日期选择",
"key": "date"
}
]
}
},
{
"col": "options",
"showCondition": {
"val": "select",
"col": "type"
},
"bindParam": true,
"label": "选项值",
"type": "code",
"props": {}
},
{
"col": "required",
"label": "是否必填",
"type": "switch",
"props": {}
},
{
"col": "requiredMsg",
"showCondition": {
"val": true,
"col": "required"
},
"label": "必填提示信息",
"type": "input",
"props": {}
}
]
}
},
{
"col": "search",
"label": "查询",
"type": "function"
},
{
"col": "reset",
"label": "重置",
"type": "function"
}
]
},
{
"label": "样式",
"type": "tab",
"coms": [
{
"col": "baseStyle",
"label": "自定义样式",
"type": "style"
},
{
"col": "size",
"default": "medium",
"label": "尺寸",
"type": "radio",
"props": {
"options": [
{
"value": "大",
"key": "large"
},
{
"value": "中",
"key": "medium"
},
{
"value": "小",
"key": "small"
},
{
"value": "迷你",
"key": "mini"
}
]
}
},
{
"col": "labelWidth",
"default": "100",
"label": "标签宽度",
"type": "input",
"props": {
"addonAfter": "px"
}
}
]
},
{
"label": "高级",
"type": "tab",
"coms": [
{
"col": "uniqueKey",
"label": "唯一标识",
"type": "uniqueId"
}
]
}
],
"events": {
"onMounted": [
{
"method": "onMounted",
"name": "intl_design.events.onMounted",
"id": 1713321997651,
"type": "js",
"value": "/**\n * 挂载完成后执行\n * \n */\nfunction action(ctx, params) {\n ctx.func.calculateCol(ctx)\n window.onresize = () => {\n ctx.func.calculateCol(ctx)\n }\n ctx.setValue(1713236295574, ctx.customProps.defaultValues)\n}\n"
}
]
}
},
"bindProps": {},
"coms": [
{
"key": 1713236295574,
"type": "node",
"name": {
"default": "表单容器",
"intlKey": "intl_design.hiformcontainer"
},
"code": "HiFormContainer",
"display": "",
"props": {
"layout": "horizontal",
"boxShadow": {},
"backgroundColor": "transparent",
"size": "medium",
"borderRadius": {},
"labelAlign": "right",
"loop": {
"data": []
},
"display": {},
"labelWidth": "100",
"status": "default"
},
"bindProps": {
"boxShadow": {},
"size": "props.size",
"loop": {},
"labelWidth": "props.labelWidth"
},
"coms": [
{
"key": 1713235241085,
"type": "node",
"name": {
"default": "布局容器",
"intlKey": "intl_design.hicontainer"
},
"code": "HiContainer",
"display": "flex",
"props": {
"boxShadow": {},
"baseStyle": ":rootNode {\n .arco-form-item-label-col {\n\n }\n}",
"grid": "8:8:8",
"background": {},
"loop": {
"data": []
},
"status": "default",
"font": {
"mode": "custom",
"textAlign": "left",
"fontWeight": "normal"
}
},
"bindProps": {
"boxShadow": {},
"background": {},
"loop": {}
},
"coms": [
{
"key": 1713235241380,
"type": "node",
"name": "列",
"code": "HiContainerCol",
"display": "",
"props": {
"col": "8",
"boxShadow": {},
"display": {},
"index": 0,
"xxl": 6,
"empty": {
"enable": false,
"icon": "null-list",
"text": "暂无数据"
},
"xl": 6,
"background": {},
"loop": {
"bind": true,
"data": [],
"bound": true
},
"responsive": true,
"md": 8,
"sm": 12,
"xs": 24,
"lg": 8,
"events": {},
"status": "default",
"font": {
"mode": "custom",
"textAlign": "left",
"fontWeight": "normal"
}
},
"bindProps": {
"boxShadow": {},
"background": {},
"loop": {
"data": "props.searchColumns"
},
"status": "state.statusMap[item.name]"
},
"coms": [
{
"key": 1713235278755,
"type": "node",
"name": {
"default": "数字输入框",
"intlKey": "intl_design.hiinputnumber"
},
"code": "HiInputNumber",
"display": "flex",
"props": {
"formItem": true,
"minWidth": 200,
"title": "数字输入框",
"showLabel": true,
"mode": "embed",
"boxStyle": {
"padding": [
"0",
"8",
"0",
"8"
]
},
"baseStyle": ":rootNode {\n}",
"loop": {
"data": []
},
"valueType": "custom",
"width": "100%",
"name": "INPUTNUMBER_8Y43FXVJ",
"append": {},
"events": {},
"validate": {
"required": false
},
"status": "default"
},
"bindProps": {
"loop": {},
"name": "item.name",
"placeholder": "item.placeholder",
"title": "item.title",
"append": {},
"status": "item.type === \"inputNumber\" ? \"default\" : \"hide\"",
"validate": {
"requiredMsg": "item.requiredMsg",
"required": "item.required"
}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235282538,
"type": "node",
"name": {
"default": "日期",
"intlKey": "intl_design.hidatepicker"
},
"code": "HiDatePicker",
"display": "flex",
"props": {
"formItem": true,
"format": "YYYY-MM-DD",
"minWidth": 200,
"title": "日期",
"type": "date",
"showLabel": true,
"boxStyle": {
"padding": [
"0",
"8",
"0",
"8"
]
},
"loop": {
"data": []
},
"valueType": "custom",
"width": "100%",
"name": "DATE_QP5QSPK0",
"append": {},
"events": {},
"validate": {
"required": false
},
"status": "default"
},
"bindProps": {
"loop": {},
"name": "item.name",
"placeholder": "item.placeholder",
"title": "item.title",
"status": "item.type === \"date\" ? \"default\" : \"hide\"",
"validate": {
"requiredMsg": "item.requiredMsg",
"required": "item.required"
}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235270587,
"type": "node",
"name": {
"default": "下拉单选",
"intlKey": "intl_design.hiselect"
},
"code": "HiSelect",
"display": "flex",
"props": {
"formItem": true,
"boxStyle": {
"padding": [
"0",
"8",
"0",
"8"
]
},
"loop": {
"data": []
},
"fieldNames": {
"title": "value",
"key": "key"
},
"width": "100%",
"name": "SELECT_FSIHFTE2",
"minWidth": 200,
"title": "下拉单选",
"showLabel": true,
"events": {},
"validate": {
"func": "function validate(value, callback) {\n if (!value) return callback('必填');\n callback(); // 通过校验\n}"
},
"status": "default"
},
"bindProps": {
"loop": {},
"name": "item.name",
"options": "item.options",
"placeholder": "item.placeholder",
"title": "item.title",
"status": "item.type === \"select\" ? \"default\" : \"hide\"",
"validate": {
"requiredMsg": "item.requiredMsg",
"required": "item.required"
}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235267260,
"type": "node",
"name": {
"default": "输入框",
"intlKey": "intl_design.hiinput"
},
"code": "HiInput",
"display": "flex",
"props": {
"formItem": true,
"minWidth": 200,
"title": "输入框",
"showLabel": true,
"boxStyle": {
"padding": [
"0",
"8",
"0",
"8"
]
},
"loop": {
"data": []
},
"valueType": "custom",
"width": "100%",
"name": "INPUT_4A65THAW",
"append": {},
"events": {},
"validate": {},
"status": "default"
},
"bindProps": {
"loop": {},
"name": "item.name",
"placeholder": "item.placeholder",
"title": "item.title",
"append": {},
"status": "item.type === \"input\" ? \"default\" : \"hide\"",
"validate": {
"requiredMsg": "item.requiredMsg",
"required": "item.required"
}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235241381,
"type": "node",
"name": "列",
"code": "HiContainerCol",
"display": "",
"props": {
"col": "auto",
"boxShadow": {},
"baseStyle": ":rootNode {\n display: flex;\n justify-content: flex-end;\n}",
"background": {},
"loop": {
"data": []
},
"display": {},
"index": 1,
"events": {},
"status": "default",
"font": {
"mode": "custom",
"textAlign": "left",
"fontWeight": "normal"
},
"empty": {
"enable": false,
"icon": "null-list",
"text": "暂无数据"
}
},
"bindProps": {
"boxShadow": {},
"background": {},
"loop": {}
},
"coms": [
{
"key": 1713235261287,
"type": "node",
"name": {
"default": "按钮",
"intlKey": "intl_design.hibutton"
},
"code": "HiButton",
"display": "inline-block",
"props": {
"authControl": false,
"baseStyle": ":rootNode {\n \n}",
"shape": "square",
"size": "medium",
"btnStatus": "normal",
"loop": {
"data": []
},
"title": "查询",
"type": "primary",
"events": {
"onClick": [
{
"method": "onClick",
"name": "intl_design.events.onClickButton",
"id": 1713316259445,
"type": "js",
"value": "/**\n * 点击按钮\n * \n */\nfunction action(ctx, params) {\n ctx.validate('1713236295574', function(res, data) {\n if (res) {\n ctx.customProps.search(data)\n }\n })\n}\n"
}
]
},
"status": "default"
},
"bindProps": {
"size": "props.size",
"loop": {}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235254344,
"type": "node",
"name": {
"default": "按钮",
"intlKey": "intl_design.hibutton"
},
"code": "HiButton",
"display": "inline-block",
"props": {
"authControl": false,
"baseStyle": ":rootNode {\n margin: 0 8px;\n}",
"shape": "square",
"size": "medium",
"btnStatus": "normal",
"loop": {
"data": []
},
"title": "重置",
"type": "secondary",
"events": {
"onClick": [
{
"method": "onClick",
"name": "intl_design.events.onClickButton",
"id": 1713320637994,
"type": "js",
"value": "/**\n * 点击按钮\n * \n */\nfunction action(ctx, params) {\n ctx.customProps.reset()\n}\n"
}
]
},
"status": "default"
},
"bindProps": {
"size": "props.size",
"loop": {}
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
},
{
"key": 1713235257215,
"type": "node",
"name": {
"default": "按钮",
"intlKey": "intl_design.hibutton"
},
"code": "HiButton",
"display": "inline-block",
"props": {
"authControl": false,
"shape": "square",
"size": "medium",
"btnStatus": "normal",
"loop": {
"data": []
},
"icon": "icon-double-down",
"title": "展开/收起",
"type": "secondary",
"events": {
"onClick": [
{
"method": "onClick",
"name": "intl_design.events.onClickButton",
"id": 1713248739207,
"type": "js",
"value": "/**\n * 点击按钮\n * \n */\nfunction action(ctx, params) {\n ctx.setState({\n expand:!ctx.state.expand\n })\n ctx.func.calculateCol(ctx)\n}\n"
}
]
},
"status": "default"
},
"bindProps": {
"size": "props.size",
"loop": {},
"icon": "state.expand ? \"icon-double-up\" : \"icon-double-down\"",
"title": "state.expand ? \"收起\" : \"展开\""
},
"coms": [],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"mode": "",
"hideRemove": false,
"hideCopy": false
}
],
"params": [
{
"id": 2,
"name": "expand",
"desc": "展开/收起",
"default": false,
"loop": false
},
{
"id": 3,
"name": "statusMap",
"desc": "控制组件展开收起时的状态",
"default": {},
"loop": false
}
],
"apis": [],
"funcs": [
{
"id": 0,
"name": "calculateCol",
"desc": "",
"func": "function fn(ctx) {\n if (ctx.state.expand) {\n ctx.setState({\n statusMap: ctx.customProps.searchColumns.reduce((obj, item) => {\n obj[item.name] = \"default\";\n return obj;\n }, {})\n })\n return;\n }\n const width = window.innerWidth;\n const isxs = width < 576;\n const issm = width >= 576 && width < 768;\n const ismd = width >= 768 && width < 992;\n const islg = width >= 992 && width < 1200;\n const isxl = width >= 1200 && width < 1600;\n const isxxl = width >= 1600;\n let showColCount = ctx.customProps.searchColumns?.length;\n if (isxs) {\n showColCount = 1\n } else if(issm) {\n showColCount = 1\n } else if(ismd) {\n showColCount = 2\n } else if(islg) {\n showColCount = 2\n } else if(isxl) {\n showColCount = 3\n } else if(isxxl) {\n showColCount = 3\n }\n ctx.setState({\n statusMap: ctx.customProps.searchColumns.reduce((obj, item, index) => {\n obj[item.name] = index < showColCount ? \"default\" : \"hidden\";\n return obj;\n }, {})\n })\n}"
}
]
}