281 lines
10 KiB
Vue
281 lines
10 KiB
Vue
<template>
|
|
<template v-if="isVisible('time', schema)">
|
|
<el-time-select v-model="model[schema.column]" start="00:00" step="00:15" end="23:59"
|
|
:disabled="isDisabled(schema)" :placeholder="getPlaceholder(schema)" format="HH:mm" />
|
|
</template>
|
|
<template v-else-if="isVisible('date', schema)">
|
|
<el-date-picker v-if="isRange(schema)" :disabled="isDisabled(schema)" type="daterange" :editable="false"
|
|
format="YYYY-MM-DD" value-format="YYYY-MM-DD" v-model="model[schema.column]"
|
|
:start-placeholder="getStartPlaceholder(schema)"
|
|
:end-placeholder="getEndPlaceholder(schema)"></el-date-picker>
|
|
<el-date-picker v-else :disabled="isDisabled(schema)" type="date" v-model="model[schema.column]"
|
|
:editable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
|
:placeholder="getPlaceholder(schema)"></el-date-picker>
|
|
</template>
|
|
<template v-else-if="isVisible('datetime', schema)">
|
|
<el-date-picker v-if="isRange(schema)" :disabled="isDisabled(schema)" :editable="false" format="YYYY-MM-DD"
|
|
value-format="YYYY-MM-DD HH:mm:ss" time-format="HH:mm:ss" type="datetimerange" :prefix-icon="Calendar"
|
|
v-model="model[schema.column]" :teleported="false" :start-placeholder="getStartPlaceholder(schema)"
|
|
:disabled-date="getIsDateDisable" :end-placeholder="getEndPlaceholder(schema)"></el-date-picker>
|
|
<el-date-picker v-else :disabled="isDisabled(schema)" type="datetime" :editable="false"
|
|
format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss" v-model="model[schema.column]"
|
|
:placeholder="getPlaceholder(schema)"></el-date-picker>
|
|
</template>
|
|
<template v-else-if="isVisible('dropdown', schema)">
|
|
<el-select clearable v-if="!isDropdownMulitLevel(schema)" v-model="model[schema.column]"
|
|
:multiple="schema.format === 'multiSelect'" :disabled="isDisabled(schema)"
|
|
:placeholder="getPlaceholder(schema)" :allow-create="isDropdownCreated(schema)"
|
|
:filterable="isDropdownFilterable(schema)" :default-first-option="isDropdownDefaultFirst(schema)">
|
|
<template v-for="(v, k) in schema.attribute.values" :key="k">
|
|
<el-option v-if="typeof v === 'object'" :label="v.label" :value="v.value"></el-option>
|
|
<el-option v-else :label="v" :value="k"></el-option>
|
|
</template>
|
|
</el-select>
|
|
<level-select v-model="model[schema.column]" :options="schema.attribute.values" clearable v-else></level-select>
|
|
</template>
|
|
<template v-else-if="isVisible('search_boolean', schema)">
|
|
<el-select clearable v-model="model[schema.column]">
|
|
<template v-for="(v, k) in booleanValues" :key="k">
|
|
<el-option :label="v" :value="k"></el-option>
|
|
</template>
|
|
</el-select>
|
|
</template>
|
|
<template v-else-if="isVisible('cascader', schema)">
|
|
<el-cascader :disabled="isDisabled(schema)" :options="schema.attribute.values" filterable clearable
|
|
:placeholder="getPlaceholder(schema)" v-model="model[schema.column]" :validate-event="false"></el-cascader>
|
|
</template>
|
|
<template v-else-if="isVisible('color', schema)">
|
|
<el-color-picker v-model="model[schema.column]" :disabled="isDisabled(schema)" />
|
|
</template>
|
|
<template v-else-if="isVisible('boolean', schema)">
|
|
<el-switch :disabled="isDisabled(schema)" :inactive-value="0" :active-value="1"
|
|
v-model="model[schema.column]"></el-switch>
|
|
</template>
|
|
<template v-else-if="isVisible('file', schema)">
|
|
<upload :action="schema.attribute.upload_url" v-model="model[schema.column]"></upload>
|
|
</template>
|
|
<template v-else-if="isVisible('password', schema)">
|
|
<el-input :disabled="isDisabled(schema)" show-password :placeholder="getPlaceholder(schema)"
|
|
v-model.trim="model[schema.column]"></el-input>
|
|
</template>
|
|
<template v-else-if="isVisible('multistr', schema)">
|
|
<el-input type="textarea" :disabled="isDisabled(schema)" :placeholder="getPlaceholder(schema)"
|
|
:show-word-limit="isShowWordLimit(schema)" :maxlength="schema.rule.max"
|
|
v-model="model[schema.column]"></el-input>
|
|
</template>
|
|
<template v-else-if="isVisible('number', schema)">
|
|
<el-input :disabled="isDisabled(schema)" :prefix-icon="schema.attribute.icon || ''"
|
|
:placeholder="getPlaceholder(schema)" v-model.number="model[schema.column]"
|
|
:clearable="isSearch ? true : false">
|
|
<template v-if="schema.attribute.suffix" #append>
|
|
{{ schema.attribute.suffix }}
|
|
</template>
|
|
</el-input>
|
|
</template>
|
|
<template v-else>
|
|
<el-input :disabled="isDisabled(schema)" :prefix-icon="schema.attribute.icon || ''"
|
|
:placeholder="getPlaceholder(schema)" v-model.trim="model[schema.column]"
|
|
:clearable="isSearch ? true : false">
|
|
<template v-if="schema.attribute.suffix" #append>
|
|
{{ schema.attribute.suffix }}
|
|
</template>
|
|
</el-input>
|
|
</template>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, computed } from 'vue';
|
|
import Upload from './Upload.vue';
|
|
import { Calendar } from '@element-plus/icons-vue'
|
|
import { generateSchemaDescription } from '../libs/form';
|
|
import LevelSelect from './LevelSelect.vue';
|
|
const props = defineProps({
|
|
model: {
|
|
type: Object,
|
|
},
|
|
schema: {
|
|
type: Object,
|
|
},
|
|
scenario: {
|
|
type: String,
|
|
},
|
|
})
|
|
|
|
const isDropdownCreated = (schema) => {
|
|
if (props.scenario === 'search') {
|
|
return false;
|
|
}
|
|
let ret = schema.attribute.dropdown && schema.attribute.dropdown.created || false;
|
|
return ret;
|
|
}
|
|
|
|
const isDropdownFilterable = (schema) => {
|
|
if (props.scenario === 'search') {
|
|
return false;
|
|
}
|
|
return schema.attribute.dropdown && schema.attribute.dropdown.filterable || false;
|
|
}
|
|
|
|
const isDropdownDefaultFirst = (schema) => {
|
|
return schema.attribute.dropdown && schema.attribute.dropdown.default_first || false;
|
|
}
|
|
|
|
const isDropdownMulitLevel = (schema) => {
|
|
let values = schema.attribute.values;
|
|
if (Array.isArray(values)) {
|
|
for (let i in values) {
|
|
let row = values[i];
|
|
if (row.children && Array.isArray(row.children)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const isShowWordLimit = (schema) => {
|
|
return false
|
|
}
|
|
|
|
const isDisabled = (schema) => {
|
|
return schema.attribute.disable.indexOf(props.scenario) > -1 || schema.attribute.readonly.indexOf(props.scenario) > -1
|
|
}
|
|
|
|
const booleanValues = computed(() => {
|
|
return {
|
|
1: '是',
|
|
0: '否'
|
|
}
|
|
})
|
|
|
|
const maxLength = (schema) => {
|
|
if (schema.type === 'string') {
|
|
return schema.rule.max || 100
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
const isSearch = computed(() => {
|
|
return props.scenario === 'search';
|
|
})
|
|
|
|
|
|
const getIsDateDisable = (date) => {
|
|
if (props.schema.attribute.end_of_now) {
|
|
return date.getTime() > (new Date()).getTime();
|
|
}
|
|
return false
|
|
}
|
|
|
|
const isVisible = (type, schema) => {
|
|
let visible = false
|
|
switch (type) {
|
|
case 'number':
|
|
visible = (['integer', 'decimal'].indexOf(schema.format) > -1 || ['integer', 'double'].indexOf(schema.type) > -1)
|
|
break
|
|
case 'password':
|
|
visible = ['password', 'pass'].indexOf(schema.format) > -1
|
|
break
|
|
case 'time':
|
|
visible = ['time'].indexOf(schema.format) > -1
|
|
break
|
|
case 'date':
|
|
visible = ['date'].indexOf(schema.format) > -1
|
|
break
|
|
case 'datetime':
|
|
visible = ['datetime', 'timestamp'].indexOf(schema.format) > -1
|
|
break
|
|
case 'dropdown':
|
|
visible = ['dropdown', 'multiSelect'].indexOf(schema.format) > -1
|
|
break
|
|
case 'cascader':
|
|
visible = ['cascader'].indexOf(schema.format) > -1
|
|
break
|
|
case 'multistr':
|
|
if (props.scenario !== 'search') {
|
|
visible = ['textarea'].indexOf(schema.format) > -1
|
|
}
|
|
break
|
|
case 'color':
|
|
visible = ['color'].indexOf(schema.format) > -1
|
|
break
|
|
case 'file':
|
|
if (props.scenario !== 'file') {
|
|
if (['file'].indexOf(schema.format) > -1) {
|
|
if (schema.attribute.upload_url) {
|
|
visible = true;
|
|
}
|
|
}
|
|
}
|
|
break
|
|
case 'boolean':
|
|
if (
|
|
props.scenario !== 'search' &&
|
|
['bool', 'boolean'].indexOf(schema.format) > -1
|
|
) {
|
|
visible = true
|
|
} else {
|
|
visible = false
|
|
}
|
|
break
|
|
case 'search_boolean':
|
|
if (
|
|
props.scenario === 'search' &&
|
|
['bool', 'boolean'].indexOf(schema.format) > -1
|
|
) {
|
|
visible = true
|
|
} else {
|
|
visible = false
|
|
}
|
|
break
|
|
case 'string':
|
|
visible = ['string', 'text'].indexOf(schema.format) > -1
|
|
break
|
|
}
|
|
return visible
|
|
}
|
|
|
|
const getPlaceholder = (schema) => {
|
|
let placeholder = '';
|
|
if (schema.attribute.tooltip) {
|
|
placeholder = schema.attribute.tooltip
|
|
} else {
|
|
if (['dropdown'].indexOf(schema.format) > -1) {
|
|
placeholder = '请选择' + schema.label
|
|
} else {
|
|
placeholder = '请输入' + schema.label
|
|
}
|
|
}
|
|
return placeholder
|
|
}
|
|
|
|
const getStartPlaceholder = (schema) => {
|
|
let placeholder = '';
|
|
if (schema.attribute.tooltip) {
|
|
placeholder = schema.attribute.tooltip
|
|
} else {
|
|
placeholder = '起始' + schema.label
|
|
}
|
|
return placeholder
|
|
}
|
|
|
|
const getEndPlaceholder = (schema) => {
|
|
let placeholder = '';
|
|
if (schema.attribute.tooltip) {
|
|
placeholder = schema.attribute.tooltip
|
|
} else {
|
|
placeholder = '结束' + schema.label
|
|
}
|
|
return placeholder
|
|
}
|
|
|
|
const isRange = (schema) => {
|
|
return props.scenario === 'search'
|
|
}
|
|
|
|
onMounted(() => {
|
|
props.schema.attribute.description = generateSchemaDescription(props.schema, props.scenario)
|
|
})
|
|
|
|
</script> |