moto/web/src/components/fragment/parts/FormItem.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>