355 lines
10 KiB
Vue
355 lines
10 KiB
Vue
<template>
|
|
<div>
|
|
<j-form :layout="'vertical'" ref="formRef" :model="modelRef">
|
|
<j-form-item
|
|
name="selector"
|
|
label="选择方式"
|
|
v-show="!(list.length === 1)"
|
|
:rules="[{ required: true, message: '请选择方式' }]"
|
|
>
|
|
<TopCard
|
|
:typeList="list"
|
|
v-model:value="modelRef.selector"
|
|
@change="onSelectorChange"
|
|
/>
|
|
</j-form-item>
|
|
<j-form-item
|
|
v-if="modelRef.selector === 'fixed'"
|
|
name="selectorValues"
|
|
:rules="[{ required: true, message: '请选择设备' }]"
|
|
>
|
|
<Device
|
|
:productId="values.productDetail.id"
|
|
v-model:value="modelRef.selectorValues"
|
|
@change="onDeviceChange"
|
|
/>
|
|
</j-form-item>
|
|
<j-form-item
|
|
v-else-if="modelRef.selector === 'relation'"
|
|
label="关系"
|
|
name="selectorValues"
|
|
:rules="[{ required: true, message: '请选择关系' }]"
|
|
>
|
|
<j-select
|
|
placeholder="请选择关系"
|
|
v-model:value="modelRef.selectorValues"
|
|
:options="relationList"
|
|
show-search
|
|
@change="onRelationChange"
|
|
/>
|
|
</j-form-item>
|
|
<j-form-item
|
|
v-else-if="modelRef.selector === 'tag'"
|
|
name="selectorValues"
|
|
:rules="[{ required: true, message: '请选择标签' }]"
|
|
>
|
|
<Tag
|
|
v-model:value="modelRef.selectorValues"
|
|
:tagData="tagList"
|
|
@change="onTagChange"
|
|
/>
|
|
</j-form-item>
|
|
<j-form-item
|
|
v-else
|
|
name="selectorValues"
|
|
label="变量"
|
|
:rules="[{ required: true, message: '请选择' }]"
|
|
>
|
|
<j-tree-select
|
|
style="width: 100%; height: 100%"
|
|
:tree-data="builtInList"
|
|
v-model:value="modelRef.selectorValues"
|
|
placeholder="请选择参数"
|
|
@select="onVariableChange"
|
|
:fieldNames="{ label: 'name', value: 'id' }"
|
|
>
|
|
<template #title="{ name, description }">
|
|
<j-space>
|
|
{{ name }}
|
|
<span style="color: grey; margin-left: 5px">{{
|
|
description
|
|
}}</span>
|
|
</j-space>
|
|
</template>
|
|
</j-tree-select>
|
|
</j-form-item>
|
|
</j-form>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang='ts' name="Device">
|
|
import { useSceneStore } from '@/store/scene';
|
|
import TopCard from './TopCard.vue';
|
|
import { storeToRefs } from 'pinia';
|
|
import { queryBuiltInParams } from '@/api/rule-engine/scene';
|
|
import { getImage } from '@/utils/comm';
|
|
import NoticeApi from '@/api/notice/config';
|
|
import Device from './Device.vue';
|
|
import Tag from './Tag.vue';
|
|
|
|
const props = defineProps({
|
|
values: {
|
|
type: Object,
|
|
default: () => {},
|
|
},
|
|
name: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
thenName: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
branchGroup: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
parallel: {
|
|
type: Boolean,
|
|
},
|
|
});
|
|
|
|
// save保存deviceDetail
|
|
const emits = defineEmits(['save', 'cancel']);
|
|
|
|
const sceneStore = useSceneStore();
|
|
const { data } = storeToRefs(sceneStore);
|
|
|
|
const formRef = ref();
|
|
|
|
const modelRef = reactive({
|
|
selector: 'fixed',
|
|
selectorValues: undefined,
|
|
deviceId: '',
|
|
source: '',
|
|
relationName: '',
|
|
upperKey: '',
|
|
message: undefined,
|
|
});
|
|
|
|
const list = ref<any[]>([]);
|
|
const builtInList = ref<any[]>([]);
|
|
const tagList = ref<any[]>([]);
|
|
const relationList = ref<any[]>([]);
|
|
|
|
const TypeList = [
|
|
{
|
|
label: '自定义',
|
|
value: 'fixed',
|
|
image: getImage('/scene/device-custom.png'),
|
|
tip: '自定义选择当前产品下的任意设备',
|
|
},
|
|
{
|
|
label: '按关系',
|
|
value: 'relation',
|
|
image: getImage('/scene/device-relation.png'),
|
|
tip: '选择与触发设备具有相同关系的设备',
|
|
},
|
|
{
|
|
label: '按标签',
|
|
value: 'tag',
|
|
image: getImage('/scene/device-tag.png'),
|
|
tip: '按标签选择产品下具有特定标签的设备',
|
|
},
|
|
{
|
|
label: '按变量',
|
|
value: 'variable',
|
|
image: getImage('/scene/device-variable.png'),
|
|
tip: '选择设备ID为上游变量值的设备',
|
|
},
|
|
];
|
|
|
|
const filterTree = (nodes: any[]) => {
|
|
if (!nodes?.length) {
|
|
return nodes;
|
|
}
|
|
const arr = nodes.filter((it) => {
|
|
if (
|
|
it.children.find(
|
|
(item: any) =>
|
|
item.id.indexOf('deviceId' || 'device_id' || 'device_Id') >
|
|
-1,
|
|
) &&
|
|
!it.children.find((item: any) => item.id.indexOf('boolean') > -1)
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
return arr.map((item) => {
|
|
if (item.children) {
|
|
}
|
|
return {
|
|
...item,
|
|
title: item.name,
|
|
value: item.id,
|
|
disabled: !!item.children,
|
|
};
|
|
});
|
|
};
|
|
|
|
const sourceChangeEvent = async () => {
|
|
const _params = {
|
|
branch: props.thenName,
|
|
branchGroup: props.branchGroup,
|
|
action: props.name - 1,
|
|
};
|
|
const resp = await queryBuiltInParams(unref(data), _params);
|
|
if (resp.status === 200) {
|
|
const array = filterTree(resp.result as any[]);
|
|
//判断相同产品才有按变量
|
|
// if (props.formProductId === DeviceModel.productId)// TODO
|
|
builtInList.value = array;
|
|
}
|
|
};
|
|
|
|
const queryRelationList = () => {
|
|
NoticeApi.getRelationUsers({
|
|
paging: false,
|
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
|
terms: [{ termType: 'eq', column: 'objectTypeName', value: '设备' }],
|
|
}).then((resp) => {
|
|
if (resp.status === 200) {
|
|
relationList.value = (resp.result as any[]).map((item) => {
|
|
return {
|
|
label: item.name,
|
|
value: item.relation,
|
|
};
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
const filterType = async () => {
|
|
const _list = TypeList.filter((item) => item.value === 'fixed');
|
|
if (unref(data)?.trigger?.type === 'device') {
|
|
//关系
|
|
const res = await NoticeApi.getRelationUsers({
|
|
paging: false,
|
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
|
terms: [
|
|
{ termType: 'eq', column: 'objectTypeName', value: '设备' },
|
|
],
|
|
});
|
|
if (res.status === 200 && res.result.length !== 0) {
|
|
const array = TypeList.filter((item) => item.value === 'relation');
|
|
_list.push(...array);
|
|
}
|
|
//标签
|
|
const tag = JSON.parse(
|
|
props.values.productDetail?.metadata || '{}',
|
|
)?.tags;
|
|
if (tag && tag.length !== 0) {
|
|
const array = TypeList.filter((item) => item.value === 'tag');
|
|
_list.push(...array);
|
|
}
|
|
//变量
|
|
if (
|
|
builtInList.value.length !== 0 &&
|
|
!props.parallel &&
|
|
props.name !== 0
|
|
) {
|
|
const array = TypeList.filter((item) => item.value === 'variable');
|
|
_list.push(...array);
|
|
}
|
|
list.value = _list;
|
|
} else {
|
|
if (
|
|
builtInList.value.length !== 0 &&
|
|
!props.parallel &&
|
|
props.name !== 0
|
|
) {
|
|
const array = TypeList.filter((item) => item.value === 'variable');
|
|
_list.push(...array);
|
|
}
|
|
list.value = _list;
|
|
}
|
|
};
|
|
|
|
const onSelectorChange = (val: string) => {
|
|
modelRef.selectorValues = undefined;
|
|
if (val === 'relation') {
|
|
queryRelationList();
|
|
}
|
|
};
|
|
|
|
const onDeviceChange = (_detail: any) => {
|
|
if (_detail) {
|
|
if (_detail.id) {
|
|
modelRef.deviceId = _detail.id;
|
|
modelRef.selectorValues = [
|
|
{ value: _detail.id, name: _detail.name },
|
|
] as any;
|
|
modelRef.message = {} as any;
|
|
} else {
|
|
modelRef.deviceId = '';
|
|
modelRef.selectorValues = [] as any;
|
|
}
|
|
emits('save', unref(modelRef), _detail);
|
|
}
|
|
};
|
|
|
|
const onRelationChange = (val: any, options: any) => {
|
|
modelRef.deviceId = 'deviceId';
|
|
modelRef.source = 'upper';
|
|
modelRef.selectorValues = val;
|
|
modelRef.upperKey = 'scene.deviceId';
|
|
modelRef.relationName = options.label;
|
|
emits('save', unref(modelRef), {});
|
|
};
|
|
|
|
const onTagChange = (val: any[], arr: any[]) => {
|
|
if (val) {
|
|
modelRef.deviceId = 'deviceId';
|
|
modelRef.source = 'fixed';
|
|
}
|
|
if (arr) {
|
|
tagList.value = arr;
|
|
}
|
|
emits('save', unref(modelRef), {});
|
|
};
|
|
|
|
const onVariableChange = (val: any, node: any) => {
|
|
modelRef.deviceId = val;
|
|
emits('save', unref(modelRef), node);
|
|
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
|
};
|
|
|
|
watchEffect(() => {
|
|
Object.assign(modelRef, props.values);
|
|
});
|
|
|
|
watch(
|
|
() => props.values.productDetail,
|
|
async (newVal) => {
|
|
await sourceChangeEvent();
|
|
if (newVal) {
|
|
const metadata = JSON.parse(newVal?.metadata || '{}');
|
|
tagList.value = metadata?.tags || [];
|
|
filterType();
|
|
}
|
|
},
|
|
{
|
|
immediate: true,
|
|
deep: true,
|
|
},
|
|
);
|
|
|
|
const onFormSave = () => {
|
|
return new Promise((resolve, reject) => {
|
|
formRef.value
|
|
.validate()
|
|
.then(async (_data: any) => {
|
|
resolve(_data);
|
|
})
|
|
.catch((err: any) => {
|
|
reject(err);
|
|
});
|
|
});
|
|
};
|
|
|
|
defineExpose({ onFormSave });
|
|
</script>
|
|
|
|
<style scoped lang='less'>
|
|
</style> |