<template>
|
<div class="comm-input">
|
<div v-if="Array.isArray(info.children)" class="range-input">
|
<CommInput
|
v-for="(subItem, subIndex) in info.children"
|
:info="{attrs: info.attrs || [], rules: info.rules || [], type: info.type, ...subItem}"
|
@updateValue="updateValue"
|
:parentName="info.name"
|
:key="subIndex"
|
:inputWidth="`${parseInt(inputWidth)/info.children.length - 6}px`"
|
></CommInput>
|
</div>
|
|
<p v-else-if="info.type === 'text'">{{info.value}}</p>
|
<component
|
v-else-if="info.type === 'select'"
|
@input="updateValue($event, info, parentName)"
|
:name="info.name"
|
:value="info.value"
|
v-bind="attrInfo"
|
v-bind:is="componentNames[info.type]"
|
>
|
<el-option
|
v-for="(optionsItem, optionsIndex) in info.options"
|
:key="optionsIndex"
|
:label="optionsItem.label"
|
:value="optionsItem.value"
|
></el-option>
|
</component>
|
|
<component
|
v-else
|
@input="updateValue($event, info, parentName)"
|
:name="info.name"
|
:value="info.value"
|
v-bind="attrInfo"
|
v-bind:is="componentNames[info.type]"
|
></component>
|
</div>
|
</template>
|
<script>
|
// type input textarea inputs select
|
export default {
|
name: 'CommInput',
|
props: {
|
/**
|
* info 单条配置信息 @example
|
* {type: 'input', label: '报单人:', value: '',name: 'formbllevel',attrs: [],rules:[]}
|
* */
|
info: {
|
type: Object,
|
required: true
|
},
|
|
// 自身递归时用到,外部不用传入
|
parentName: {
|
type: String,
|
default: ''
|
},
|
|
// 不同类型默认配置配置
|
typeInfo: {
|
type: Object,
|
default: () => {}
|
},
|
|
// 输入框或select的宽度
|
inputWidth: {
|
type: String,
|
default: '220px'
|
}
|
},
|
|
data() {
|
return {
|
defaultTypeInfo: {
|
input: {
|
placeholder: '请输入',
|
maxLength: 300
|
},
|
textarea: {
|
placeholder: '请输入',
|
maxLength: 3000
|
},
|
select: {
|
placeholder: '请选择'
|
},
|
time: {
|
placeholder: '请选择'
|
},
|
date: {
|
placeholder: '请选择'
|
},
|
dateRange: {
|
placeholder: '请选择'
|
}
|
},
|
componentNames: {
|
input: 'el-input',
|
textarea: 'el-input',
|
select: 'el-select',
|
time: 'el-time-select',
|
timePicker: 'el-time-picker',
|
date: 'el-date-picker',
|
dateRange: 'el-date-picker',
|
datetimerange: 'el-date-picker'
|
}
|
}
|
},
|
|
methods: {
|
// 更新值
|
updateValue(val, item, parentName) {
|
this.$emit('updateValue', val, item, parentName)
|
}
|
},
|
computed: {
|
// 导出属性信息
|
attrInfo() {
|
let { info, mixTypeInfo } = this
|
const { attrs, rules, type } = info
|
let result = mixTypeInfo[type] ? { ...mixTypeInfo[type] } : {}
|
|
// rules中如果设置了maxLength,则转移到属性中
|
if (Array.isArray(rules) && rules.length > 0) {
|
const maxItem = rules.find(item =>
|
Object.keys(item).includes('maxLength')
|
)
|
if (maxItem) {
|
result.maxLength = maxItem['maxLength']
|
}
|
}
|
if (type === 'textarea') {
|
result.type = 'textarea'
|
}
|
if (type === 'dateRange') {
|
result = {
|
...result,
|
'type': 'daterange',
|
'format': 'yyyy/MM/dd',
|
'unlink-panels': true,
|
'start-placeholder': "开始时间",
|
'end-placeholder': "结束时间"
|
}
|
}
|
|
if (type === 'datetimerange') {
|
result = {
|
...result,
|
'format': 'yyyy/MM/dd hh:mm:ss',
|
'type': 'datetimerange',
|
'start-placeholder': "开始时间",
|
'end-placeholder': "结束时间"
|
}
|
}
|
|
|
if (Array.isArray(attrs) && attrs.length > 0) {
|
result = attrs.reduce(
|
(pre, curr) => {
|
if (typeof curr === 'string') {
|
curr = { [curr]: true }
|
}
|
if (typeof curr === 'object') {
|
pre = { ...pre, ...curr }
|
// 只读或disabled元素不需要默认placeholder
|
if (curr.disabled || curr.readonly) {
|
pre.placeholder = ''
|
}
|
}
|
return { ...pre }
|
},
|
{ ...result }
|
)
|
}
|
return result
|
},
|
|
// 合并配置项
|
mixTypeInfo() {
|
const { typeInfo, defaultTypeInfo } = this
|
return { ...defaultTypeInfo, ...typeInfo }
|
}
|
}
|
}
|
</script>
|
<style lang="postcss" scoped>
|
.comm-input {
|
& .range-input {
|
padding: 0;
|
line-height: 32px;
|
height: 32px;
|
& .comm-input {
|
line-height: 24px;
|
}
|
& >>> input {
|
line-height: 24px;
|
height: 24px;
|
border: none;
|
}
|
}
|
& .form-text {
|
margin: 0;
|
line-height: 16px;
|
}
|
& >>> input[readonly] {
|
color: #888888;
|
}
|
}
|
.range-split {
|
position: relative;
|
&::before {
|
content: '-';
|
position: absolute;
|
z-index: 1;
|
line-height: 24px;
|
left: -4px;
|
top: 0;
|
}
|
}
|
</style>
|