组件目录
form.vue
<template>
<el-form
@submit.native.prevent
class="dynamic-form"
:ref="formConfig.ref"
:inline="formConfig.inline"
:model="value"
:label-position="formConfig.labelPosition"
:label-width="formConfig.labelWidth"
:size="formConfig.size"
:status-icon="formConfig.statusIcon"
>
<div
class="formWrap"
v-for="parentItem in formConfig.tabs"
:key="parentItem.name"
:label="parentItem.label"
:name="parentItem.name"
v-show="showOne==parentItem.name"
>
<dynamic-form-item
v-for="item in parentItem.formItemList"
:key="item.key"
:item="item"
:value="value[item.key]"
v-if="value[item.key]!==undefined&&item.show!=false"
@input="handleInput($event, item.key)"
:style="{'min-width':columnMinWidth}"
></dynamic-form-item>
</div>
<slot/>
</el-form>
</template>
<script>
export default {
data() {
// 密码验证
return {
activeName: "1"
};
},
props: {
formConfig: {
type: Object,
required: true
},
value: {
type: Object,
required: true
},
showOne: {
type: String
},
columnMinWidth: {
type: String
}
},
created() {},
mounted() {
// this.setDefaultValue();
},
methods: {
handleInput(val, key) {
// 这里element-ui没有上报event,直接就是value了
if(typeof(val) == 'string'){
val = val.replace(/\s+/g, "");//去除空格
}
this.$emit("input", { ...this.value, [key]: val });
},
setDefaultValue() {
const formData = { ...this.value };
var that = this;
// 设置默认值
that.formConfig.tabs.forEach(item => {
let formItemList = item.formItemList;
formItemList.forEach(item1 => {
const { key, value } = item1;
if (formData[key] === undefined || formData[key] === null) {
formData[key] = value;
}
});
});
that.$emit("input", { ...formData });
}
}
};
</script>
<style lang="scss">
.formWrap {
overflow: hidden;
}
</style>
item.vue
<style>
.block {
display: block !important;
display: flex !important;
}
.inputo,
.selecto {
width: 200px!important;
}
.form-itemo {
width: 48%;
float: left;
}
</style>
<template>
<el-form-item
class="form-itemo"
:rules="Rules"
:label="item.label"
:prop="item.key"
v-if="!item.isHide"
:class="{'block':item.block}"
>
<el-input
v-if="item.type==='input'"
v-bind="$attrs"
v-on="$listeners"
:type="item.subtype"
:min="item.min"
:max="item.max"
:minlength="item.minlength"
:maxlength="item.maxlength"
autocomplete="off"
:placeholder="item.placeholder"
:disabled="item.disabled"
:readonly="item.readonly"
:autosize="item.autosize"
:clearable="item.clearable"
class="inputo"
>
<template v-if="item.append" slot="append">{{item.append}}</template>
</el-input>
<el-select
v-else-if="item.type==='select'"
v-bind="$attrs"
v-on="$listeners"
:multiple="item.multiple"
:collapse-tags="item.collapseTags"
:disabled="item.disabled"
:props="item.props"
:clearable="item.clearable"
:multiple-limit="item.multipleLimit"
class="selecto"
>
<el-option
v-for="o in item.options||ajaxOptions"
:key="o[item.props.value]"
:label="o[item.props.label]"
:value="o[item.props.value]"
:disabled="o.disabled"
></el-option>
</el-select>
<el-cascader
v-else-if="item.type==='cascader'"
v-bind="$attrs"
v-on="$listeners"
:options="item.options||ajaxOptions"
:filterable="item.filterable"
:change-on-select="item.changeOnSelect"
:props="item.props"
:placeholder="item.placeholder"
:disabled="item.disabled"
:clearable="true"
class="selecto"
></el-cascader>
<el-checkbox
v-else-if="item.type==='switch' && item.appearance==='checkbox'"
v-bind="$attrs"
v-on="$listeners"
:disabled="item.disabled"
></el-checkbox>
<el-switch
v-else-if="item.type==='switch'"
v-bind="$attrs"
v-on="$listeners"
:disabled="item.disabled"
></el-switch>
<el-rate
v-else-if="item.type==='rate'"
v-bind="$attrs"
v-on="$listeners"
:colors="['#99A9BF', '#F7BA2A', '#FF9900']"
text-color="#ff9900"
></el-rate>
<el-color-picker
v-else-if="item.type==='color'"
v-bind="$attrs"
v-on="$listeners"
:show-alpha="item.showAlpha"
:color-format="item.format"
></el-color-picker>
<el-slider
v-else-if="item.type==='slider'"
v-bind="$attrs"
v-on="$listeners"
:range="item.isRange"
:show-stops="item.showStops"
:step="item.step"
:min="item.min"
:max="item.max"
></el-slider>
<el-radio-group v-else-if="item.type==='radio'" :disabled="item.disabled" v-bind="$attrs" v-on="$listeners">
<component
:is="item.button?'el-radio-button':'el-radio'"
v-for="o in item.options||ajaxOptions"
:key="o.code"
:label="o.code"
:disabled="o.disabled"
:border="item.border"
>{{o.name}}</component>
</el-radio-group>
<el-checkbox-group
v-else-if="item.type==='checkbox'"
:min="item.min"
:max="item.max"
v-bind="$attrs"
v-on="$listeners"
:props="item.props"
>
<component
:is="item.button?'el-checkbox-button':'el-checkbox'"
v-for="o in item.options||ajaxOptions"
:key="o.value"
:disabled="o.disabled"
:label="o.code"
:border="item.border"
>{{o.name}}</component>
</el-checkbox-group>
<el-time-picker
v-else-if="item.type==='time'"
:is-range="item.isRange"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间"
:value-format="item.valueFormat"
:format="item.valueFormat"
default-time="12:00:00"
:placeholder="item.placeholder"
:picker-options="item.pickerOptions"
v-bind="$attrs"
v-on="$listeners"
></el-time-picker>
<el-date-picker
v-else-if="item.type==='date'"
:type="item.subtype"
range-separator="-"
start-placeholder="开始时间"
end-placeholder="结束时间"
:value-format="item.valueFormat"
:format="item.format"
:placeholder="item.placeholder"
:picker-options="item.pickerOptions"
v-bind="$attrs"
v-on="$listeners"
:disabled="item.disabled"
></el-date-picker>
<span v-else-if="item.type==='txt'">{{item.txt}}</span>
<!-- <richtext v-else-if="item.type==='richtext'" v-bind="$attrs" v-on="$listeners"></richtext> -->
<span v-else>未知控件类型</span>
</el-form-item>
</template>
<script>
// import Richtext from "@/components/tinymce";
export default {
components: {
// Richtext
},
props: {
item: {
type: Object,
required: true
}
},
data() {
return {
ajaxOptions: [],
provinceData: [],
city: [],
area: []
};
},
methods: {},
computed: {
Rules() {
var that = this;
const rules = that.item.rules;
if (rules === undefined) return undefined;
const R = [];
rules.forEach(rule => {
// 请求验证
if (rule.sql) {
/* 请求验证 */
const validator = (rule2, value, callback) => {
that.$http
.post(rule.sql, {
// key: rule2.field,
value
// sql: rule.sql.replace(/{key}/gi, rule2.field)
})
.then(res => {
// eslint-disable-next-line
callback(!res.data.returnMsg || undefined);
})
.catch(err => {
console.log(err);
that.$message.error(err.message);
// eslint-disable-next-line
callback(false);
});
};
R.push({
validator,
message: rule.message,
trigger: "blur"
});
// 正则验证
} else if (rule.pattern) {
var reg = rule.pattern;
const validator = (rule2, value, callback) => {
if (value === "") {
callback(new Error("必填哦"));
} else if (!reg.test(value)) {
callback(new Error(rule.message));
} else {
callback();
}
};
R.push({
validator,
message: rule.message,
trigger: "blur"
});
} else {
R.push(rule);
}
});
return R;
}
},
created() {
const { optionsUrl, optionsParam, key, type } = this.item;
if (optionsUrl) {
var that = this;
that.$http
.post(optionsUrl, optionsParam)
.then(res => {
// console.log(res);
// console.log(that.item);
if (res.data.succeed == YESTAE_OMS.SUCCESS) {
that.item.options = res.data.datas;
if(res.data.datas.rows){
that.item.options = res.data.datas.rows
}
}
// that.$set(this.item, 'options', res)
// that.ajaxOptions = res.data.datas;
// console.log(that.item)
})
.catch(err => {
that.$message.error(err.message);
});
}
}
};
</script>
index.js输出一下
import Vue from 'vue'
import Form from './form'
import Item from './item'
Vue.component('dynamic-form', Form)
Vue.component('dynamic-form-item', Item)
最终使用
main.js中引入一下
import "@/components/dynamicForm";//添加编辑
list.vue
<template>
<div class="order-list">
<dynamic-search-form
ref="dynamicForm"
:formConfig="formConfig"
v-model="formInfo"
></dynamic-search-form>
</div>
</template>
<script>
export default {
name: "order-list",
data() {
return {
formInfo: {
platOrderNo: "",
orderType: "",
wareId: "",
area: [],
receiverAddress: "",
receiverPhone: "",
customRemark: "",
actualPaymax: "",
actualPaymin: "",
goodsSkuRangeType: "2",
goodsSkuRangeNum: "",
tradeTime: [],
nick: "",
shopId: "",
goodsSku: ""
},
// 注册表单项们
formConfig: {
ref: "formInfo",
inline: true, // 是否使用inline排版
labelPosition: "right", // 标签对齐方式
labelWidth: "100px", // 标签宽度
size: "small", // 尺寸
statusIcon: true, // 显示验证图标
formItemList: [
{
label: "原始订单号",
prop: "platOrderNo",
type: "input",
value: "",
key: "platOrderNo",
clearable: true,
placeholder: "请输入"
},
{
type: "select",
label: "订单类型",
key: "orderType",
prop: "orderType",
value: "",
placeholder: "全部",
clearable: true,
isHide: true,
props: {
value: "code",
label: "name"
},
optionsUrl: "PO0132",
optionsParam: { pcode: "orderType" },
options: []
},
{
type: "select",
label: "店铺名称",
key: "shopId",
prop: "shopId",
value: "",
clearable: true,
props: {
value: "id",
label: "shopName"
},
optionsUrl: "PO1005",
options: []
},
{
type: "select",
label: "仓库名称",
key: "wareId",
prop: "wareId",
placeholder: "全部",
value: "",
clearable: true,
props: {
value: "id",
label: "wareName"
},
optionsUrl: "PO0705",
options: []
},
{
label: "用户昵称",
prop: "nick",
type: "input",
value: "",
key: "nick",
clearable: true,
placeholder: "请输入"
},
{
label: "商品SKU",
prop: "goodsSku",
type: "input",
value: "",
key: "goodsSku",
clearable: true,
placeholder: "请输入"
},
{
label: "实付金额",
key: "actualPaymin",
prop: "actualPaymin",
type: "input",
isHide: false,
subtype: "number",
value: "",
min: 0,
clearable: true,
placeholder: "",
formItemStyle: {
width: "205px!important"
},
style: {
width: "80px!important"
}
},
{
label: "~",
key: "actualPaymax",
prop: "actualPaymax",
type: "input",
isHide: false,
subtype: "number",
value: "",
clearable: true,
min: 0,
placeholder: "",
labelWidth: "20px",
formItemStyle: {
width: "120px!important"
},
style: {
width: "80px!important"
}
},
{
label: "交易时间",
prop: "tradeTime",
type: "date",
subtype: "datetimerange",
valueFormat: "yyyy-MM-dd HH:mm:ss",
value: "",
key: "tradeTime",
clearable: true,
style: { width: "340px" },
placeholder: "请选择"
},
{
type: "select",
label: "SKU数量",
key: "goodsSkuRangeType",
prop: "goodsSkuRangeType",
value: "",
isHide: false,
clearable: true,
props: {
value: "code",
label: "name"
},
optionsUrl: "PO0132",
optionsParam: { pcode: "mathNum" },
options: [],
formItemStyle: {
width: "200px!important"
},
style: {
width: "80px!important"
}
},
{
label: "",
key: "goodsSkuRangeNum",
prop: "goodsSkuRangeNum",
type: "input",
subtype: "number",
value: "",
isHide: false,
clearable: true,
min: 1,
placeholder: "SKU数量",
formItemStyle: {
width: "100px!important"
},
style: {
width: "105px!important"
}
},
{
label: "客服备注",
key: "customRemark",
prop: "customRemark",
type: "input",
maxlength: 50,
value: "",
clearable: true,
placeholder: "请输入"
},
{
type: "area",
label: "省市区",
key: "area",
prop: "area",
value: "",
clearable: true,
changeOnSelect: true,
props: {
value: "cityCodeId",
label: "name",
children: "children"
},
options: [],
style: {
width: "202px!important"
}
},
{
label: "收货地址",
key: "receiverAddress",
prop: "receiverAddress",
type: "input",
maxlength: 30,
value: "",
clearable: true,
placeholder: "请输入"
},
{
label: "收件人电话",
key: "receiverPhone",
prop: "receiverPhone",
type: "input",
maxlength: 30,
isHide: false,
value: "",
clearable: true,
placeholder: "请输入"
}
]
},
};
},
computed: {
},
watch: {
},
methods: {
}
};
</script>
<style lang="scss">
</style>