iot-ui-vue/src/views/rule-engine/Scene/Save/components/Terms/ParamsItem.vue

387 lines
12 KiB
Vue

<template>
<div class='terms-params-item'>
<div v-if='!isFirst' class='term-type-warp'>
<DropdownButton
:options='[
{ label: "并且", value: "and" },
{ label: "或者", value: "or" },
]'
type='type'
v-model:value='paramsValue.type'
@select='typeSelect'
/>
</div>
<div
class='params-item_button'
@mouseover='mouseover'
@mouseout='mouseout'
>
<DropdownButton
:options='columnOptions'
icon='icon-zhihangdongzuoxie-1'
type='column'
value-name='column'
label-name='fullName'
placeholder='请选择参数'
v-model:value='paramsValue.column'
component='treeSelect'
@select='columnSelect'
/>
<DropdownButton
:options='termTypeOptions'
type="termType"
value-name='id'
label-name='name'
placeholder="操作符"
v-model:value='paramsValue.termType'
@select='termsTypeSelect'
/>
<DoubleParamsDropdown
v-if='showDouble'
icon='icon-canshu'
placeholder='参数值'
:options='valueOptions'
:metricOptions='metricOption'
:tabsOptions='tabsOptions'
v-model:value='paramsValue.value.value'
v-model:source='paramsValue.value.source'
@select='valueSelect'
/>
<ParamsDropdown
v-else
icon='icon-canshu'
placeholder='参数值'
:options='valueOptions'
:metricOptions='metricOption'
:tabsOptions='tabsOptions'
:metric='paramsValue.value?.metric'
v-model:value='paramsValue.value.value'
v-model:source='paramsValue.value.source'
@select='valueSelect'
/>
<j-popconfirm title='确认删除?' @confirm='onDelete' :overlayStyle='{minWidth: "180px"}'>
<div v-show='showDelete' class='button-delete'> <AIcon type='CloseOutlined' /></div>
</j-popconfirm>
</div>
<div class='term-add' @click.stop='termAdd' v-if='isLast'>
<div class='terms-content'>
<AIcon type='PlusOutlined' style='font-size: 12px' />
</div>
</div>
</div>
</template>
<script setup lang='ts' name='ParamsItem'>
import type { PropType } from 'vue'
import type { TermsType } from '@/views/rule-engine/Scene/typings'
import DropdownButton from '../DropdownButton'
import { getOption } from '../DropdownButton/util'
import ParamsDropdown, { DoubleParamsDropdown } from '../ParamsDropdown'
import {inject, watch} from 'vue'
import { ContextKey, arrayParamsKey, timeTypeKeys } from './util'
import { useSceneStore } from 'store/scene'
import { storeToRefs } from 'pinia';
import { Form } from 'jetlinks-ui-components'
import {indexOf, isArray, isObject, isString, pick , cloneDeep } from 'lodash-es'
const sceneStore = useSceneStore()
const { data: formModel } = storeToRefs(sceneStore)
const formItemContext = Form.useInjectFormItemContext();
type Emit = {
(e: 'update:value', data: TermsType): void
}
type TabsOption = {
label: string;
key: string;
component: string
}
const props = defineProps({
isFirst: {
type: Boolean,
default: true
},
isLast: {
type: Boolean,
default: true
},
showDeleteBtn: {
type: Boolean,
default: true
},
name: {
type: Number,
default: 0
},
termsName: {
type: Number,
default: 0
},
branchName: {
type: Number,
default: 0
},
whenName: {
type: Number,
default: 0
},
value: {
type: Object as PropType<TermsType>,
default: () => ({
column: '',
type: '',
termType: 'eq',
value: {
source: 'manual',
value: undefined
}
})
}
})
const emit = defineEmits<Emit>()
const paramsValue = reactive<TermsType>({
column: props.value?.column,
type: props.value?.type,
termType: props.value?.termType,
value: props.value?.value,
metric: undefined
})
const showDelete = ref(false)
const columnOptions: any = inject(ContextKey) //
const columnType = ref<string>()
const termTypeOptions = ref<Array<{ id: string, name: string}>>([]) // 条件值
const valueOptions = ref<any[]>([]) // 默认手动输入下拉
const metricOption = ref<any[]>([]) // 根据termType获取对应指标值
const isMetric = ref<boolean>(false) // 是否为指标值
const tabsOptions = ref<Array<TabsOption>>([{ label: '手动输入', key: 'manual', component: 'string' }])
const metricsCacheOption = ref<any[]>([]) // 缓存指标值
const handOptionByColumn = (option: any) => {
if (option) {
termTypeOptions.value = option.termTypes || []
metricsCacheOption.value = option.metrics?.map((item: any) => ({...item, label: item.name})) || []
tabsOptions.value.length = 1
tabsOptions.value[0].component = option.dataType
columnType.value = option.dataType
if (option.metrics && option.metrics.length) {
tabsOptions.value.push(
{ label: '指标值', key: 'metric', component: 'select' }
)
isMetric.value = true
} else {
isMetric.value = false
}
if (option.dataType === 'boolean') {
// 处理_options为Object时
const _options = option.options || option.others
if (isObject(_options)) {
const bool = (_options as any)?.bool
valueOptions.value = [
{ label: bool.falseText, value: String(bool.falseValue)},
{ label: bool.trueText, value: String(bool.trueValue)},
]
} else {
valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || [
{ label: '是', value: 'true' },
{ label: '否', value: 'false' },
]
}
} else if(option.dataType === 'enum') {
valueOptions.value = option.options?.map((item: any) => ({ ...item, label: item.name, value: item.id})) || []
} else{
valueOptions.value = (option.options || []).map((item: any) => ({ ...item, label: item.name, value: item.id}))
}
} else {
termTypeOptions.value = []
metricsCacheOption.value = []
valueOptions.value = []
}
}
watch(() => JSON.stringify(columnOptions.value), () => {
if (paramsValue.column) {
const option = getOption(columnOptions.value, paramsValue.column, 'column')
const copyValue = props.value
if (option && Object.keys(option).length) {
handOptionByColumn(option)
if (copyValue.error) {
copyValue.error = false
emit('update:value', copyValue)
formItemContext.onFieldChange()
}
} else {
copyValue.error = true
emit('update:value', copyValue)
formItemContext.onFieldChange()
}
}
}, { immediate: true })
const showDouble = computed(() => {
const isRange = paramsValue.termType ? arrayParamsKey.includes(paramsValue.termType) : false
const isSourceMetric = paramsValue.value?.source === 'metric'
if (metricsCacheOption.value.length) {
metricOption.value = metricsCacheOption.value.filter(item => isRange ? item.range : !item.range)
} else {
metricOption.value = []
}
if (isRange) {
if (isMetric.value) {
return !isSourceMetric
}
return true
}
return false
})
const mouseover = () => {
if (props.showDeleteBtn){
showDelete.value = true
}
}
const mouseout = () => {
if (props.showDeleteBtn){
showDelete.value = false
}
}
const columnSelect = (option: any) => {
const dataType = option.dataType
const hasTypeChange = dataType !== tabsOptions.value[0].component
let termTypeChange = false
// 如果参数类型未发生变化,则不修改操作符以及值
const termTypes = option.termTypes
if (!termTypes.some((item: {id: string}) => paramsValue.termType === item.id)) { // 修改操作符
termTypeChange = true
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
}
console.log('hasTypeChange', paramsValue.value.source, tabsOptions.value)
if (hasTypeChange || !tabsOptions.value.every(a => a.key === paramsValue.value.source )) { // 类型发生变化
paramsValue.termType = termTypes?.length ? termTypes[0].id : 'eq'
paramsValue.value = {
source: tabsOptions.value[0].key,
value: undefined
}
} else if (termTypeChange) {
const oldValue = isArray(paramsValue.value!.value) ? paramsValue.value!.value[0] : paramsValue.value!.value
const value = arrayParamsKey.includes(paramsValue.termType as string) ? [ oldValue, undefined ] : oldValue
const _source = paramsValue.value?.source || tabsOptions.value[0].key
const newValue: any = {
source: _source,
value: value
}
if (_source === 'metric') {
newValue.metric = paramsValue.value?.metric
}
paramsValue.value = newValue
}
console.log(paramsValue, hasTypeChange)
handOptionByColumn(option)
emit('update:value', { ...paramsValue })
nextTick(() => {
formItemContext.onFieldChange()
})
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][0] = option.name
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][1] = paramsValue.termType
}
const termsTypeSelect = (e: { key: string, name: string }) => {
const oldValue = isArray(paramsValue.value!.value) ? paramsValue.value!.value[0] : paramsValue.value!.value
let value = arrayParamsKey.includes(e.key) ? [ oldValue, undefined ] : oldValue
// 如果上次的值 在 timeTypeKeys中 则不变
if (columnType.value === 'date') {
if (timeTypeKeys.includes(e.key)) {
if (tabsOptions.value[0].component !== 'int') {
value = undefined
}
tabsOptions.value[0].component = 'int'
} else if (!timeTypeKeys.includes(e.key) && tabsOptions.value[0].component == 'int') {
value = undefined
tabsOptions.value[0].component = 'date'
}
}
const _source = paramsValue.value?.source || tabsOptions.value[0].key
const newValue: any = {
source: _source,
value: value
}
if (_source === 'metric') {
newValue.metric = paramsValue.value?.metric
const isArray = isString(paramsValue.value!.value) ? paramsValue.value!.value?.includes?.(',') : false
if (arrayParamsKey.includes(e.key) !== isArray) { // 有变化
newValue.value = undefined
}
}
paramsValue.value = newValue
emit('update:value', { ...paramsValue })
formItemContext.onFieldChange()
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][1] = e.name
}
const valueSelect = (v: any, label: string, labelObj: Record<number, any>, option: any) => {
if (paramsValue.value?.source === 'metric') {
paramsValue.value.metric = option?.id
}
const newValues = { ...paramsValue }
if (paramsValue.value?.source !== 'metric') {
delete newValues.value.metric
}
emit('update:value', { ...newValues })
formItemContext.onFieldChange()
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][2] = labelObj
}
const typeSelect = (e: any) => {
emit('update:value', { ...paramsValue })
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName][3] = e.label
}
const termAdd = () => {
const terms = {
column: undefined,
value: {
source: 'manual',
value: undefined
},
termType: undefined,
type: 'and',
key: `params_${new Date().getTime()}`
}
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.push(terms)
formModel.value.options!.when[props.branchName].terms[props.whenName].terms[props.termsName].push(['', '', '', '并且'])
}
const onDelete = () => {
formModel.value.branches?.[props.branchName]?.when?.[props.whenName]?.terms?.splice(props.termsName, 1)
formModel.value.options!.when[props.branchName].terms[props.whenName].terms.splice(props.termsName, 1)
}
nextTick(() => {
Object.assign(paramsValue, pick(props.value, ['column', 'options', 'termType', 'terms', 'type', 'value', 'metric', 'key']))
})
</script>
<style scoped>
</style>