iot-ui-vue/src/components/Metadata/Table/components/Array/index.vue

217 lines
5.5 KiB
Vue

<template>
<PopoverModal
v-model:visible="visible"
:placement="placement"
@ok="onOk"
@cancel="onCancel"
>
<template #content>
<div style="width: 450px">
<a-form ref="formRef" layout="vertical" :model="formData">
<a-form-item label="元素类型" required name="type" :rules="rules" :validate-first="true">
<TypeSelect v-model:value="formData.type"/>
</a-form-item>
<ScaleItem v-if="showDouble" v-model:value="formData.scale" />
<StringItem v-else-if="showString" v-model:value="formData.expands.maxLength" />
<BooleanItem v-else-if="showBoolean" v-model:value="formData.boolean" name="boolean"/>
<DateItem v-else-if="showDate" v-model:value="formData.format"/>
<EnumItem ref="enumTableRef" v-else-if="showEnum" v-model:value="formData.enum.elements"/>
<a-form-item v-else-if="showArray" label="子元素类型" required :name="['elementType','type']" :rules="[{ required: true, message: '请选择子元素类型'}]">
<TypeSelect v-model:value="formData.elementType.type" :filter="['array', 'object']" />
</a-form-item>
</a-form>
</div>
</template>
<slot>
<a-button type="link" :disabled="disabled" style="padding: 0">
<template #icon>
<AIcon type="EditOutlined" :class="{'table-form-required-aicon': !value.type}"/>
</template>
</a-button>
</slot>
</PopoverModal>
</template>
<script setup name="MetadataArray">
import { PopoverModal, TypeSelect } from '../index'
import ScaleItem from '../Double/ScaleItem.vue'
import StringItem from '../String/Item.vue'
import BooleanItem from '../Boolean/Item.vue'
import DateItem from '../Date/Item.vue'
import EnumItem from '../Enum/Item.vue'
import {cloneDeep, pick} from 'lodash-es'
import {Form} from "ant-design-vue";
const emit = defineEmits(['update:value', 'cancel', 'confirm']);
const props = defineProps({
value: {
type: Object,
default: () => ({}),
},
unitOptions: {
type: [Array, Function],
default: () => []
},
placement: {
type: String,
default: 'top',
},
disabled: {
type: Boolean,
default:false
}
});
const formItemContext = Form.useInjectFormItemContext();
const formRef = ref()
const enumTableRef = ref()
const visible = ref(false)
const formData = reactive({
type: props.value?.type,
scale: props.value?.scale,
expands: {
maxLength: props.value?.maxLength || props.value?.expands?.maxLength,
},
boolean: {
trueText: props.value?.trueText || '是',
trueValue: props.value?.trueValue || 'true',
falseText: props.value?.falseText || '否',
falseValue: props.value?.falseValue || 'false',
},
format: props.value?.format,
enum: {
multiple: props.value?.multiple,
elements: cloneDeep(props.value?.elements) || [],
},
elementType: props.value?.type === 'array' ? props.value.elementType : {
type: undefined
}
});
const showDouble = computed(() => {
return ['float', 'double'].includes(formData.type)
})
const showString = computed(() => {
return ['string', 'password'].includes(formData.type)
})
const showBoolean = computed(() => {
return formData.type === 'boolean'
})
const showDate = computed(() => {
return formData.type === 'date'
})
const showEnum = computed(() => {
return formData.type === 'enum'
})
const showArray = computed(() => {
return formData.type === 'array'
})
const rules = [
{
validator(_, value) {
if (!value) {
return Promise.reject('请选择元素类型');
}
return Promise.resolve();
},
trigger: 'change',
},
];
const typeChange = (e) => {
if (['float', 'double'].includes(e)) {
formData.scale = 2;
}
};
const initValue = () => {
formData.type = props.value?.type;
formData.scale = props.value?.scale;
formData.expands.maxLength = props.value?.maxLength || props.value?.expands?.maxLength;
formData.boolean = {
trueText: props.value?.trueText || '是',
trueValue: props.value?.trueValue || 'true',
falseText: props.value?.falseText || '否',
falseValue: props.value?.falseValue || 'false',
};
formData.format = props.value?.format;
formData.enum = {
multiple: props.value?.multiple,
elements: cloneDeep(props.value?.elements || []),
};
formData.elementType = props.value?.type === 'array' ? props.value.elementType : {
type: undefined
}
};
const handleValue = (type, data) => {
let newObject = {};
switch (type) {
case 'float':
case 'double':
newObject = pick(data, 'scale');
break;
case 'boolean':
newObject = { ...data.boolean };
break;
case 'enum':
newObject.elements = data.enum.elements;
break;
case 'string':
case 'password':
newObject = pick(data, 'expands');
break;
case 'date':
newObject = pick(data, 'format');
break;
case 'array':
newObject = pick(data, 'elementType')
}
return {
type: type,
...newObject,
};
};
const onOk = async () => {
const data = await formRef.value.validate()
let enumTable = true
if (enumTableRef.value) {
enumTable = !!(await enumTableRef.value.validate())
}
if (data && enumTable) {
visible.value = false
const _value = handleValue(formData.type, formData)
emit('update:value', _value);
emit('confirm', _value);
formItemContext.onFieldChange()
}
}
const onCancel = () => {
formRef.value?.resetFields();
initValue();
emit('cancel');
}
watch(() => JSON.stringify(props.value), () => {
initValue()
})
</script>
<style scoped>
</style>