<template>
|
<div v-for="(expression, index) in expressions" class="expression-item">
|
<div>
|
<template v-if="isStructure">
|
<el-input-number
|
:min="expressionProps.MinValue.min"
|
:max="expressionProps.MinValue.max"
|
placeholder="上限"
|
style="width: 140px"
|
v-model="(expression as StructureExpression).MinValue"
|
/>
|
<el-input-number
|
:min="expressionProps.MaxValue.min"
|
:max="expressionProps.MaxValue.max"
|
placeholder="下限"
|
style="width: 140px; margin: 0 10px"
|
v-model="(expression as StructureExpression).MaxValue"
|
/>
|
<el-input
|
v-if="expressionProps.Expression.required"
|
placeholder="扣分表达式"
|
style="width: 140px"
|
v-model="(expression as StructureExpression).Expression"
|
/>
|
</template>
|
|
<template v-else>
|
<el-input placeholder="表达式" style="width: 420px" v-model="(expressions[index] as string)" />
|
</template>
|
<el-button
|
v-if="type !== 'single'"
|
icon="ele-Minus"
|
style="margin-left: 10px"
|
@click="removeExpressionClick(index)"
|
type="danger"
|
circle
|
/>
|
</div>
|
|
<el-button v-if="index === 0 && type !== 'single'" icon="ele-Plus" @click="addExpressionClick" type="primary" circle />
|
</div>
|
</template>
|
<script setup lang="ts">
|
import { PropType, computed, toRefs } from 'vue';
|
import { ExpressionErrorEnum, ExpressionInput, StructureExpression } from '/@/components/form/expressionItem/types';
|
import Deepmerge from 'deepmerge';
|
|
export interface ExpressionProps {
|
MinValue?: {
|
max?: number;
|
min?: number;
|
};
|
MaxValue?: {
|
max?: number;
|
min?: number;
|
};
|
Expression?: {
|
required: Boolean;
|
};
|
}
|
const props = defineProps({
|
modelValue: Object as PropType<ExpressionInput[]>,
|
/** 是否是 {MinValue:null,MaxValue:null,Expression} 这类结构的表达式 */
|
isStructure: {
|
type: Boolean,
|
default: () => true,
|
},
|
defaultProps: {
|
type: Object as PropType<ExpressionProps>,
|
default: () => ({
|
MinValue: {
|
max: Infinity,
|
min: -Infinity,
|
},
|
MaxValue: {
|
max: Infinity,
|
min: -Infinity,
|
},
|
Expression: {
|
required: true,
|
},
|
}),
|
},
|
type: {
|
type: String as PropType<'single' | 'multiple' | 'tree'>,
|
default: 'multiple',
|
},
|
});
|
|
const { modelValue, defaultProps } = toRefs(props);
|
|
const expressionProps = computed(() => {
|
return Deepmerge(
|
{
|
MinValue: {
|
max: Infinity,
|
min: -Infinity,
|
},
|
MaxValue: {
|
max: Infinity,
|
min: -Infinity,
|
},
|
Expression: {
|
required: true,
|
},
|
},
|
defaultProps.value
|
) as ExpressionProps;
|
});
|
|
const emits = defineEmits<{
|
(event: 'update:modelValue', value: ExpressionInput[]): void;
|
}>();
|
|
const { isStructure } = toRefs(props);
|
|
const getDefaultValue = () => {
|
if (isStructure.value) {
|
const structureExpression = { MinValue: null, MaxValue: null };
|
if (expressionProps.value.Expression.required) {
|
return {
|
...structureExpression,
|
Expression: '',
|
};
|
} else {
|
return structureExpression;
|
}
|
}
|
};
|
const expressions = computed({
|
get() {
|
return modelValue.value;
|
},
|
set(value) {
|
emits('update:modelValue', value);
|
},
|
});
|
const removeExpressionClick = (index) => {
|
if (expressions.value.length !== 1) {
|
expressions.value.splice(index, 1);
|
} else {
|
expressions.value = [getDefaultValue()];
|
}
|
};
|
|
const addExpressionClick = () => {
|
expressions.value.push(getDefaultValue());
|
};
|
const checkExpression = () => {
|
if (isStructure.value) {
|
const currentExpression = expressions.value as StructureExpression[];
|
for (let i = 0; i < currentExpression.length; i++) {
|
const item = currentExpression[i];
|
if (!item.Expression && expressionProps.value.Expression.required) {
|
return ExpressionErrorEnum.ExpressionNull;
|
} else if (!item.MinValue && !item.MaxValue) {
|
return ExpressionErrorEnum.RangeNull;
|
} else if ((item.MinValue ?? -Infinity) > (item.MaxValue ?? Infinity)) {
|
return ExpressionErrorEnum.MinGTMax;
|
}
|
for (let j = i + 1; j < currentExpression.length; j++) {
|
if (!currentExpression[j].Expression && expressionProps.value.Expression.required) {
|
return ExpressionErrorEnum.ExpressionNull;
|
} else if (!currentExpression[j].MinValue && !currentExpression[j].MaxValue) {
|
return ExpressionErrorEnum.RangeNull;
|
} else if ((currentExpression[j].MinValue ?? -Infinity) > (currentExpression[j].MaxValue ?? Infinity)) {
|
return ExpressionErrorEnum.MinGTMax;
|
}
|
const minValue1 = item.MinValue ?? -Infinity;
|
const maxValue1 = item.MaxValue ?? Infinity;
|
|
const minValue2 = currentExpression[j].MinValue ?? -Infinity;
|
const maxValue2 = currentExpression[j].MaxValue ?? Infinity;
|
if (Math.max(minValue1, minValue2) < Math.min(maxValue1, maxValue2)) {
|
return ExpressionErrorEnum.Overlap;
|
}
|
}
|
}
|
} else {
|
if (expressionProps.value.Expression.required) {
|
for (let item of expressions.value as string[]) {
|
if (!item) {
|
return ExpressionErrorEnum.ExpressionNull;
|
}
|
}
|
}
|
}
|
};
|
|
defineExpose({
|
checkExpression,
|
});
|
</script>
|
<style scoped lang="scss">
|
.expression-item {
|
margin-top: 12px;
|
width: 100%;
|
display: flex;
|
justify-content: space-between;
|
&:first-child {
|
margin-top: 0;
|
}
|
}
|
</style>
|