Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev

This commit is contained in:
JiangQiming 2023-03-16 18:38:53 +08:00
commit f8fb98df44
19 changed files with 267 additions and 261 deletions

View File

@ -89,6 +89,10 @@ const props: JUploadProps = defineProps({
type: String, type: String,
default: '', default: '',
}, },
accept:{
type:Array,
default:()=>[],
}
}); });
const loading = ref<boolean>(false); const loading = ref<boolean>(false);

View File

@ -206,6 +206,17 @@ const findDetailRoutes = (routes: any[]): any[] => {
export const findCodeRoute = (asyncRouterMap: any[]) => { export const findCodeRoute = (asyncRouterMap: any[]) => {
const routeMeta = {} const routeMeta = {}
function getDetail( code: string, url: string) {
const detail = findDetailRouteItem(code, url)
if (!detail) return
routeMeta[(detail as MenuItem).code] = {
path: detail.url,
title: detail.name,
parentName: code,
buttons: detail.buttons?.map((b: any) => b.id) || []
}
}
function findChildren (data: any[], code: string = '') { function findChildren (data: any[], code: string = '') {
data.forEach(route => { data.forEach(route => {
routeMeta[route.code] = { routeMeta[route.code] = {
@ -214,29 +225,24 @@ export const findCodeRoute = (asyncRouterMap: any[]) => {
parentName: code, parentName: code,
buttons: route.buttons?.map((b: any) => b.id) || [] buttons: route.buttons?.map((b: any) => b.id) || []
} }
const detail = findDetailRouteItem(route.code, route.url)
if (detail) {
routeMeta[(detail as MenuItem).code] = {
path: detail.url,
title: detail.name,
parentName: route.code,
buttons: detail.buttons?.map((b: any) => b.id) || []
}
}
const otherRoutes = extraRouteObj[route.code] const otherRoutes = extraRouteObj[route.code]
if (otherRoutes) { if (otherRoutes) {
otherRoutes.children.map((item: any) => { otherRoutes.children.map((item: any) => {
const _code = `${route.code}/${item.code}` const _code = `${route.code}/${item.code}`
const url = `${route.url}/${item.code}`
routeMeta[_code] = { routeMeta[_code] = {
path: `${route.url}/${item.code}`, path: `${route.url}/${item.code}`,
title: item.name, title: item.name,
parentName: route.code, parentName: route.code,
buttons: item.buttons?.map((b: any) => b.id) || [] buttons: item.buttons?.map((b: any) => b.id) || []
} }
getDetail(_code, url)
}) })
} }
getDetail(route.code, route.url)
if (route.children) { if (route.children) {
findChildren(route.children, route.code) findChildren(route.children, route.code)
} }

View File

@ -1,10 +1,11 @@
<!-- 新增编辑弹窗 --> <!-- 新增编辑弹窗 -->
<template> <template>
<j-modal <j-modal
v-if="visible"
:title="props.title" :title="props.title"
:maskClosable="false" :maskClosable="false"
destroy-on-close destroy-on-close
v-model:visible="visible" visible
@ok="submitData" @ok="submitData"
@cancel="close" @cancel="close"
okText="确定" okText="确定"
@ -117,20 +118,20 @@ const submitData = async () => {
if (props.isChild === 1) { if (props.isChild === 1) {
addParams.value = { addParams.value = {
...formModel.value, ...formModel.value,
// sortIndex: sortIndex:
// childArr.value[childArr.value.length - 1].sortIndex + 1, childArr.value[childArr.value.length - 1].sortIndex + 1,
parentId: addObj.value.id, parentId: addObj.value.id,
}; };
} else if (props.isChild === 2) { } else if (props.isChild === 2) {
addParams.value = { addParams.value = {
parentId: addObj.value.id, parentId: addObj.value.id,
...formModel.value, ...formModel.value,
// sortIndex: 1, sortIndex: 1,
}; };
} else if (props.isChild === 3) { } else if (props.isChild === 3) {
addParams.value = { addParams.value = {
...formModel.value, ...formModel.value,
// sortIndex: arr.value[arr.value.length - 1].sortIndex + 1, sortIndex: arr.value[arr.value.length - 1].sortIndex + 1,
}; };
} }
const res = await saveTree(addParams.value); const res = await saveTree(addParams.value);
@ -163,7 +164,7 @@ const submitData = async () => {
/** /**
* 显示弹窗 * 显示弹窗
*/ */
const show = (row: any) => { const show = async (row: any) => {
// //
if (props.isAdd === 0) { if (props.isAdd === 0) {
if (props.isChild === 1) { if (props.isChild === 1) {
@ -179,6 +180,7 @@ const show = (row: any) => {
visible.value = true; visible.value = true;
} }
} else if (props.isChild === 3) { } else if (props.isChild === 3) {
const res = await getTableData();
arr.value = listData.value.sort(compare('sortIndex')); arr.value = listData.value.sort(compare('sortIndex'));
if (arr.value.length > 0) { if (arr.value.length > 0) {
formModel.value = { formModel.value = {
@ -250,7 +252,6 @@ const close = () => {
visible.value = false; visible.value = false;
resetFields(); resetFields();
}; };
getTableData();
//ID //ID
watch([() => props.isAdd], () => {}, { immediate: false, deep: true }); watch([() => props.isAdd], () => {}, { immediate: false, deep: true });
defineExpose({ defineExpose({

View File

@ -9,8 +9,10 @@
<JProTable <JProTable
ref="tableRef" ref="tableRef"
:columns="table.columns" :columns="table.columns"
:dataSource="dataSource" :request="queryTree"
model="TABLE" model="TABLE"
type="TREE"
:scroll="{ y: 550 }"
:defaultParams="{ :defaultParams="{
paging: false, paging: false,
sorts: [ sorts: [
@ -21,7 +23,7 @@
}, },
], ],
}" }"
:params="query.params" :params="params"
:loading="tableLoading" :loading="tableLoading"
> >
<template #headerTitle> <template #headerTitle>
@ -118,38 +120,13 @@ const query = reactive({
scopedSlots: true, scopedSlots: true,
}, },
], ],
params: {
paging: false,
sorts: [
{ name: 'sortIndex', order: 'asc' },
{
name: 'createTime',
order: 'desc',
},
],
},
}); });
/** let params = ref();
* 查询树形列表
*/
const getTableData = async () => {
tableLoading.value = true;
const res = await queryTree(query.params);
if (res.status === 200) {
dataSource.value = res.result;
}
tableLoading.value = false;
};
getTableData();
/** /**
* 搜索 * 搜索
*/ */
const handleSearch = (e: any) => { const handleSearch = (e: any) => {
query.params = { params.value = e
...query.params,
...e,
};
getTableData();
}; };
/** /**
* 操作栏按钮 * 操作栏按钮
@ -200,6 +177,9 @@ const getActions = (
{ {
key: 'delete', key: 'delete',
text: '删除', text: '删除',
tooltip: {
title: '删除',
},
popConfirm: { popConfirm: {
title: '确认删除?', title: '确认删除?',
okText: ' 确定', okText: ' 确定',
@ -208,7 +188,7 @@ const getActions = (
const resp = await deleteTree(data.id); const resp = await deleteTree(data.id);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
getTableData(); tableRef.value.reload();
} else { } else {
message.error('操作失败!'); message.error('操作失败!');
} }
@ -227,20 +207,20 @@ const table = reactive({
dataIndex: 'name', dataIndex: 'name',
key: 'name', key: 'name',
ellipsis: true, ellipsis: true,
width:600 width: 600,
}, },
{ {
title: '排序', title: '排序',
dataIndex: 'sortIndex', dataIndex: 'sortIndex',
key: 'sortIndex', key: 'sortIndex',
scopedSlots: true, scopedSlots: true,
width:200 width: 200,
}, },
{ {
title: '说明', title: '说明',
dataIndex: 'description', dataIndex: 'description',
key: 'description', key: 'description',
width:700 width: 700,
}, },
{ {
title: '操作', title: '操作',
@ -265,7 +245,7 @@ const table = reactive({
* 刷新表格数据 * 刷新表格数据
*/ */
refresh: () => { refresh: () => {
getTableData(); tableRef.value.reload();
}, },
}); });
const { add, columns, refresh } = toRefs(table); const { add, columns, refresh } = toRefs(table);

View File

@ -7,7 +7,7 @@
:pagination="false" :pagination="false"
> >
<template #bodyCell="{ column, text, record }"> <template #bodyCell="{ column, text, record }">
<div style="width: 280px"> <div>
<template v-if="['valueType', 'name'].includes(column.dataIndex)"> <template v-if="['valueType', 'name'].includes(column.dataIndex)">
<span>{{ text }}</span> <span>{{ text }}</span>
</template> </template>

View File

@ -214,7 +214,7 @@ defineExpose({ saveBtn });
<style lang="less" scoped> <style lang="less" scoped>
.function { .function {
padding: 15px; padding: 24px 15px 0 15px;
background-color: #e7eaec; background-color: #e7eaec;
} }
</style> </style>

View File

@ -30,7 +30,7 @@
<j-col :span="8"> <j-col :span="8">
<div class="right-log"> <div class="right-log">
<TitleComponent data="日志" /> <TitleComponent data="日志" />
<div :style="{ marginTop: '10px' }"> <div class="right-log-box">
<template v-if="logList.length"> <template v-if="logList.length">
<Log <Log
v-for="item in logList" v-for="item in logList"
@ -38,7 +38,9 @@
:key="item.key" :key="item.key"
/> />
</template> </template>
<j-empty v-else /> <div v-else class="right-log-box-empty">
<j-empty />
</div>
</div> </div>
</div> </div>
</j-col> </j-col>
@ -187,8 +189,21 @@ onUnmounted(() => {
padding-left: 20px; padding-left: 20px;
border-left: 1px solid rgba(0, 0, 0, 0.09); border-left: 1px solid rgba(0, 0, 0, 0.09);
overflow: hidden; overflow: hidden;
max-height: 600px; height: 100%;
overflow-y: auto; overflow-y: auto;
min-height: 400px; min-height: 400px;
.right-log-box {
padding-top: 10px;
height: calc(100% - 40px);
width: 100%;
.right-log-box-empty {
height: 100%;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
} }
</style> </style>

View File

@ -23,73 +23,15 @@
<j-row type="flex"> <j-row type="flex">
<j-col flex="180px"> <j-col flex="180px">
<j-form-item name="photoUrl"> <j-form-item name="photoUrl">
<Upload v-model="form.photoUrl" /> <j-pro-upload
v-model="form.photoUrl"
:accept="
imageTypes && imageTypes.length
? imageTypes.toString()
: ''
"
/>
</j-form-item> </j-form-item>
<!-- <j-form-item>
<div class="upload-image-warp-logo">
<div class="upload-image-border-logo">
<a-upload
name="file"
:action="FILE_UPLOAD"
:headers="headers"
:showUploadList="false"
:beforeUpload="beforeUpload"
@change="handleChange"
:accept="
imageTypes && imageTypes.length
? imageTypes.toString()
: ''
"
>
<div class="upload-image-content-logo">
<div
class="loading-logo"
v-if="logoLoading"
>
<LoadingOutlined
style="font-size: 28px"
/>
</div>
<div
class="upload-image"
v-if="photoValue"
:style="
photoValue
? `background-image: url(${photoValue});`
: ''
"
></div>
<div
v-if="photoValue"
class="upload-image-mask"
>
点击修改
</div>
<div v-else>
<div v-if="logoLoading">
<LoadingOutlined
style="font-size: 28px"
/>
</div>
<div v-else>
<PlusOutlined
style="font-size: 28px"
/>
</div>
</div>
</div>
</a-upload>
<div v-if="logoLoading">
<div class="upload-loading-mask">
<LoadingOutlined
v-if="logoLoading"
style="font-size: 28px"
/>
</div>
</div>
</div>
</div>
</j-form-item> -->
</j-col> </j-col>
<j-col flex="auto"> <j-col flex="auto">
<j-form-item name="id"> <j-form-item name="id">
@ -186,8 +128,11 @@
</j-row> </j-row>
</j-radio-group> </j-radio-group>
</j-form-item> </j-form-item>
<j-form-item label="说明" name="describe"> <j-form-item label="说明" name="description">
<j-textarea <j-textarea
:maxlength="200"
showCount
:auto-size="{ minRows: 4, maxRows: 5 }"
v-model:value="form.describe" v-model:value="form.describe"
placeholder="请输入说明" placeholder="请输入说明"
/> />
@ -319,6 +264,9 @@ const rules = reactive({
trigger: 'blur', trigger: 'blur',
}, },
], ],
description: [
{ max: 200, message: '最多可输入200位字符', trigger: 'blur' },
],
}); });
const valueChange = (value: string, label: string) => { const valueChange = (value: string, label: string) => {

View File

@ -123,9 +123,6 @@
:status="statusMap.get(slotProps.state)" :status="statusMap.get(slotProps.state)"
/> />
</template> </template>
<template #id="slotProps">
<a>{{ slotProps.id }}</a>
</template>
<template #action="slotProps"> <template #action="slotProps">
<j-space :size="16"> <j-space :size="16">
<template <template

View File

@ -36,10 +36,10 @@
placeholder="请选择" placeholder="请选择"
:options="handleOptions" :options="handleOptions"
:tabsOptions="tabOptions" :tabsOptions="tabOptions"
:metricOption="upperOptions" :metricOptions="upperOptions"
v-model:value="propertyModelRef.propertiesValue" v-model:value="propertyModelRef.propertiesValue"
v-model:source="propertyModelRef.source" v-model:source="propertyModelRef.source"
@change="onValueChange" @select="onValueChange"
> >
<template v-slot="{ label }"> <template v-slot="{ label }">
<j-input :value="label" /> <j-input :value="label" />

View File

@ -52,7 +52,7 @@
<j-select <j-select
showSearch showSearch
placeholder="请选择属性" placeholder="请选择属性"
v-model:value="modelRef.message.properties" v-model:value="modelRef.message.properties[0]"
> >
<j-select-option <j-select-option
v-for="item in metadata?.properties || []" v-for="item in metadata?.properties || []"
@ -80,9 +80,9 @@ import TopCard from '../device/TopCard.vue';
import { detail } from '@/api/device/instance'; import { detail } from '@/api/device/instance';
import EditTable from './EditTable.vue'; import EditTable from './EditTable.vue';
import WriteProperty from './WriteProperty.vue'; import WriteProperty from './WriteProperty.vue';
import { queryBuiltInParams } from '@/api/rule-engine/scene';
import { useSceneStore } from '@/store/scene'; import { useSceneStore } from '@/store/scene';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { getParams } from '../../../util'
const sceneStore = useSceneStore(); const sceneStore = useSceneStore();
const { data } = storeToRefs(sceneStore); const { data } = storeToRefs(sceneStore);
@ -121,7 +121,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
branchGroup: { branchesName: {
type: Number, type: Number,
default: 0, default: 0,
}, },
@ -131,7 +131,7 @@ const formRef = ref();
const modelRef = reactive({ const modelRef = reactive({
message: { message: {
messageType: undefined, messageType: 'INVOKE_FUNCTION',
functionId: undefined, functionId: undefined,
properties: undefined, properties: undefined,
inputs: [], inputs: [],
@ -166,7 +166,7 @@ const _property = computed(() => {
Object.keys(modelRef.message.properties || {})?.[0] === item.id Object.keys(modelRef.message.properties || {})?.[0] === item.id
); );
} }
return modelRef.message?.properties === item.id; return modelRef.message?.properties?.[0] === item.id;
}); });
return _item; return _item;
}); });
@ -178,18 +178,26 @@ const _function = computed(() => {
return _item; return _item;
}); });
const queryBuiltIn = async () => {
const _params = {
branch: props.thenName,
branchGroup: props.branchesName,
action: props.name - 1,
};
const _data = await getParams(_params, unref(data));
builtInList.value = _data
};
const onMessageTypeChange = (val: string) => { const onMessageTypeChange = (val: string) => {
if (['WRITE_PROPERTY', 'INVOKE_FUNCTION'].includes(val)) { const flag = ['WRITE_PROPERTY', 'INVOKE_FUNCTION'].includes(val)
const _params = { modelRef.message = {
branch: props.thenName, messageType: val,
branchGroup: props.branchGroup, functionId: undefined,
action: props.name - 1, properties:(flag ? undefined : []) as any,
}; inputs: [],
queryBuiltInParams(unref(data), _params).then((res: any) => { };
if (res.status === 200) { if (flag) {
builtInList.value = res.result; queryBuiltIn();
}
});
} }
}; };
@ -223,10 +231,9 @@ watch(
(newVal) => { (newVal) => {
if (newVal?.messageType) { if (newVal?.messageType) {
modelRef.message = newVal; modelRef.message = newVal;
if (newVal.messageType === 'READ_PROPERTY') { if (['WRITE_PROPERTY', 'INVOKE_FUNCTION'].includes(newVal.messageType)) {
modelRef.message.properties = newVal.properties?.[0]; queryBuiltIn();
} }
onMessageTypeChange(newVal.messageType);
} }
}, },
{ immediate: true }, { immediate: true },
@ -238,18 +245,16 @@ const onFormSave = () => {
.validate() .validate()
.then((_data: any) => { .then((_data: any) => {
// //
const _properties = _data.message.properties || modelRef.message.properties
const obj = { const obj = {
message: { message: {
...modelRef.message, ...modelRef.message,
..._data.message, ..._data.message,
properties: _data.message.messageType === 'READ_PROPERTY' ? [_properties] : _properties,
propertiesName: propertiesName:
deviceMessageType.value === 'INVOKE_FUNCTION' deviceMessageType.value === 'INVOKE_FUNCTION'
? _function.value?.name ? _function.value?.name
: _property.value?.name, : _property.value?.name,
}, },
} };
resolve(obj); resolve(obj);
}) })
.catch((err: any) => { .catch((err: any) => {

View File

@ -61,7 +61,7 @@
</j-button> </j-button>
<j-button <j-button
danger danger
v-if="tagData.length > 1" v-if="tagList.length > 1"
style="padding: 0 8px" style="padding: 0 8px"
@click="deleteItem(index)" @click="deleteItem(index)"
> >
@ -109,6 +109,7 @@ const addItem = () => {
const deleteItem = (_index: number) => { const deleteItem = (_index: number) => {
tagList.value.splice(_index, 1); tagList.value.splice(_index, 1);
onValueChange();
}; };
const onTypeSelect = (key: any, _index: number) => { const onTypeSelect = (key: any, _index: number) => {
@ -168,26 +169,23 @@ watch(
); );
const onValueChange = () => { const onValueChange = () => {
const newValue = tagList.value const _data = tagList.value.filter((item) => !!item.value);
.filter((item) => !!item.value) const newValue = _data.map((item: any) => {
.map((item: any) => { return {
return { column: item.id,
column: item.id, type: item.type,
type: item.type, value: item.value,
value: item.value, };
}; });
}); const arr = _data.map((item: any) => {
const arr = newValue return {
.filter((item) => !!item.value) column: item.name,
.map((item: any) => { type: item.type,
return { value: item.value,
column: item.name, };
type: item.type, });
value: item.value,
};
});
emits('update:value', [{ value: newValue, name: '标签' }]); emits('update:value', [{ value: newValue, name: '标签' }]);
emits('change', [{ value: newValue, name: '标签' }], undefined); emits('change', [{ value: newValue, name: '标签' }], arr);
}; };
</script> </script>

View File

@ -30,7 +30,10 @@
name="selectorValues" name="selectorValues"
:rules="[{ required: true, message: '请选择关系' }]" :rules="[{ required: true, message: '请选择关系' }]"
> >
<RelationSelect @change="onRelationChange" v-model:value="modelRef.selectorValues" /> <RelationSelect
@change="onRelationChange"
v-model:value="modelRef.selectorValues"
/>
</j-form-item> </j-form-item>
<j-form-item <j-form-item
v-else-if="modelRef.selector === 'tag'" v-else-if="modelRef.selector === 'tag'"
@ -75,12 +78,13 @@
import { useSceneStore } from '@/store/scene'; import { useSceneStore } from '@/store/scene';
import TopCard from './TopCard.vue'; import TopCard from './TopCard.vue';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { queryBuiltInParams } from '@/api/rule-engine/scene';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
import NoticeApi from '@/api/notice/config'; import NoticeApi from '@/api/notice/config';
import Device from './Device.vue'; import Device from './Device.vue';
import Tag from './Tag.vue'; import Tag from './Tag.vue';
import RelationSelect from './RelationSelect.vue' import RelationSelect from './RelationSelect.vue';
import { getParams } from '../../../util';
import { handleParamsData } from '../../../components/Terms/util';
const props = defineProps({ const props = defineProps({
values: { values: {
@ -95,7 +99,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
branchGroup: { branchesName: {
type: Number, type: Number,
default: 0, default: 0,
}, },
@ -185,15 +189,18 @@ const filterTree = (nodes: any[]) => {
const sourceChangeEvent = async () => { const sourceChangeEvent = async () => {
const _params = { const _params = {
branch: props.thenName, branch: props.thenName,
branchGroup: props.branchGroup, branchGroup: props.branchesName,
action: props.name - 1, action: props.name - 1,
}; };
const resp = await queryBuiltInParams(unref(data), _params); //
if (resp.status === 200) { const productId =
const array = filterTree(resp.result as any[]); data.value?.branches?.[props.branchesName].then?.[props.thenName]
// ?.actions?.[props.name > 0 ? props.name - 1 : 0]?.device?.productId;
// if (props.formProductId === DeviceModel.productId)// TODO if (productId === props.values?.productDetail?.id) {
builtInList.value = [] // array; const _data = await getParams(_params, unref(data));
builtInList.value = handleParamsData(filterTree(_data), 'id');
} else {
builtInList.value = [];
} }
}; };
@ -277,16 +284,13 @@ const onTagChange = (val: any[], arr: any[]) => {
modelRef.deviceId = 'deviceId'; modelRef.deviceId = 'deviceId';
modelRef.source = 'fixed'; modelRef.source = 'fixed';
} }
if (arr) { emits('save', unref(modelRef), {}, arr ? { tagList: arr } : {});
tagList.value = arr;
}
emits('save', unref(modelRef), {}, {tagList: tagList.value});
}; };
const onVariableChange = (val: any, node: any) => { const onVariableChange = (val: any, node: any) => {
modelRef.deviceId = val; modelRef.deviceId = val;
emits('save', unref(modelRef), node);
modelRef.selectorValues = [{ value: val, name: node.description }] as any; modelRef.selectorValues = [{ value: val, name: node.description }] as any;
emits('save', unref(modelRef), node);
}; };
watchEffect(() => { watchEffect(() => {

View File

@ -29,7 +29,7 @@
v-else-if="current === 1" v-else-if="current === 1"
:name="name" :name="name"
:parallel="parallel" :parallel="parallel"
:branchGroup="branchGroup" :branchesName="branchesName"
:thenName="thenName" :thenName="thenName"
:values="DeviceModel" :values="DeviceModel"
@save="onDeviceSave" @save="onDeviceSave"
@ -38,7 +38,7 @@
<Action <Action
v-else-if="current === 2" v-else-if="current === 2"
:name="name" :name="name"
:branchGroup="branchGroup" :branchesName="branchesName"
:thenName="thenName" :thenName="thenName"
:values="DeviceModel" :values="DeviceModel"
ref="actionRef" ref="actionRef"
@ -91,7 +91,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
branchGroup: { branchesName: {
type: Number, type: Number,
default: 0, default: 0,
}, },
@ -132,18 +132,18 @@ const onCancel = () => {
const onSave = (_data: any) => { const onSave = (_data: any) => {
const item: any = { const item: any = {
selector: DeviceModel.selector, selector: DeviceModel.selector,
source: DeviceModel.source, source: DeviceModel.source,
selectorValues: DeviceModel.selectorValues, selectorValues: DeviceModel.selectorValues,
productId: DeviceModel.productId, productId: DeviceModel.productId,
message: _data.message, message: _data.message,
}; };
// //
if (DeviceModel.selector === 'variable') { if (DeviceModel.selector === 'variable') {
item.selector = 'fixed'; item.selector = 'fixed';
} }
if (DeviceModel.selector === 'relation') { if (DeviceModel.selector === 'relation') {
item.upperKey = 'scene.deviceId'; item.upperKey = 'scene.deviceId';
} }
const _options: any = { const _options: any = {
name: '-', // name: '-', //
@ -158,7 +158,8 @@ const onSave = (_data: any) => {
columns: [], columns: [],
otherColumns: [], otherColumns: [],
}; };
_options.name = DeviceModel.deviceDetail?.name || DeviceModel.selectorValues?.[0]?.name; _options.name =
DeviceModel.deviceDetail?.name || DeviceModel.selectorValues?.[0]?.name;
const _type = _data.message.messageType; const _type = _data.message.messageType;
if (_type === 'INVOKE_FUNCTION') { if (_type === 'INVOKE_FUNCTION') {
_options.type = '执行'; _options.type = '执行';
@ -183,7 +184,14 @@ const onSave = (_data: any) => {
} }
} }
if (_options.selector === 'tag') { if (_options.selector === 'tag') {
_options.tagList = DeviceModel.tagList.map((it) => ({ // const arr = _data.map((item: any) => {
// return {
// column: item.name,
// type: item.type,
// value: item.value,
// };
// });
_options.taglist = DeviceModel.tagList.map((it) => ({
name: it.column || it.name, name: it.column || it.name,
type: it.type ? (it.type === 'and' ? '并且' : '或者') : '', type: it.type ? (it.type === 'and' ? '并且' : '或者') : '',
value: it.value, value: it.value,
@ -205,10 +213,8 @@ const save = async (step?: number) => {
if (deviceRef.value) { if (deviceRef.value) {
await deviceRef.value?.onFormSave(); await deviceRef.value?.onFormSave();
current.value = 2; current.value = 2;
} else { } else if (DeviceModel.selectorValues.length) {
if(DeviceModel.selector === 'fixed' && DeviceModel.selectorValues?.length){ current.value = 2;
current.value = 2;
}
} }
} else { } else {
if (actionRef.value) { if (actionRef.value) {
@ -233,7 +239,7 @@ const prev = () => {
const saveClick = () => save(); const saveClick = () => save();
const onDeviceSave = (_data: any, _detail: any, obj?: any) => { const onDeviceSave = (_data: any, _detail: any, obj?: any) => {
Object.assign(DeviceModel, {..._data, ...obj}); Object.assign(DeviceModel, { ..._data, ...obj });
DeviceModel.deviceDetail = _detail; DeviceModel.deviceDetail = _detail;
}; };
@ -245,6 +251,28 @@ watch(
detail(newValue.productId).then((resp) => { detail(newValue.productId).then((resp) => {
if (resp.status === 200) { if (resp.status === 200) {
DeviceModel.productDetail = resp.result; DeviceModel.productDetail = resp.result;
if (
DeviceModel.selector === 'tag' &&
DeviceModel.selectorValues[0]?.value
) {
const metadata = JSON.parse(
DeviceModel.productDetail?.metadata || '{}',
);
const tags = metadata.tags || [];
const arr = DeviceModel.selectorValues[0]?.value
.filter((item: any) => !!item.value)
.map((item: any) => {
return {
column:
tags.find(
(i: any) => i.id === item.column,
)?.name || item.column,
type: item.type,
value: item.value,
};
});
DeviceModel.tagList = arr;
}
} }
}); });
} }

View File

@ -26,6 +26,7 @@
</j-popconfirm> </j-popconfirm>
<j-form-item <j-form-item
v-for='(item, index) in termsOptions' v-for='(item, index) in termsOptions'
:key='item.key'
:name='["branches", branchName, "then", thenName, "actions", actionName, "terms", name, "terms", index]' :name='["branches", branchName, "then", thenName, "actions", actionName, "terms", name, "terms", index]'
:rules='rules' :rules='rules'
> >

View File

@ -19,14 +19,16 @@
v-if="data?.executor === 'alarm'" v-if="data?.executor === 'alarm'"
> >
<template v-if="data?.alarm?.mode === 'trigger'"> <template v-if="data?.alarm?.mode === 'trigger'">
满足条件后将触发<j-button style="padding: 0;" 满足条件后将触发<j-button
style="padding: 0"
type="link" type="link"
@click.stop="triggerVisible = true" @click.stop="triggerVisible = true"
>关联此场景的告警</j-button >关联此场景的告警</j-button
> >
</template> </template>
<template v-else> <template v-else>
满足条件后将解除<j-button style="padding: 0;" 满足条件后将解除<j-button
style="padding: 0"
type="link" type="link"
@click.stop="triggerVisible = true" @click.stop="triggerVisible = true"
>关联此场景的告警</j-button >关联此场景的告警</j-button
@ -278,10 +280,16 @@
/> />
{{ data?.options?.type }} {{ data?.options?.type }}
<span <span
v-for="i in data?.options?.taglist || []" v-for="(i, _index) in data?.options?.taglist ||
[]"
:key="i.value" :key="i.value"
> >
{{ i.type }} {{
_index !== 0 &&
_index !==
(data?.options?.taglist || []).length &&
i.type
}}
{{ i.name }}{{ i.value }} {{ i.name }}{{ i.value }}
</span> </span>
{{ data?.options?.productName }} {{ data?.options?.productName }}
@ -318,27 +326,33 @@
</j-popconfirm> </j-popconfirm>
</div> </div>
<template v-if="!isLast && type === 'serial'"> <template v-if="!isLast && type === 'serial'">
<div :class='["actions-item-filter-warp", termsOptions.length ? "filter-border" : ""]'> <div
<template v-if='termsOptions.length'> :class="[
<div class='actions-item-filter-warp-tip'> 'actions-item-filter-warp',
满足此条件后执行后续动作 termsOptions.length ? 'filter-border' : '',
]"
>
<template v-if="termsOptions.length">
<div class="actions-item-filter-warp-tip">
满足此条件后执行后续动作
</div>
<div class="actions-item-filter-overflow">
<FilterGroup
v-for="(item, index) in termsOptions"
:key="item.key"
:branchName="branchesName"
:thenName="thenName"
:actionName="name"
:name="index"
:isLast="index === termsOptions.length - 1"
:isFirst="index === 0"
/>
</div>
</template>
<div v-else class="filter-add-button">
<AIcon type="PlusOutlined" style="padding-right: 4px" />
<span>添加过滤条件</span>
</div> </div>
<div class='actions-item-filter-overflow'>
<FilterGroup
v-for='(item, index) in termsOptions'
:branchName='branchesName'
:thenName='thenName'
:actionName='name'
:name='index'
:isLast='index === termsOptions.length - 1'
:isFirst='index === 0'
/>
</div>
</template>
<div v-else class='filter-add-button'>
<AIcon type='PlusOutlined' style='padding-right: 4px;' />
<span>添加过滤条件</span>
</div>
</div> </div>
</template> </template>
<!-- 编辑 --> <!-- 编辑 -->
@ -378,8 +392,8 @@ import ActionTypeComponent from '../Modal/ActionTypeComponent.vue';
import TriggerAlarm from '../TriggerAlarm/index.vue'; import TriggerAlarm from '../TriggerAlarm/index.vue';
import { useSceneStore } from '@/store/scene'; import { useSceneStore } from '@/store/scene';
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia';
import { iconMap, itemNotifyIconMap, typeIconMap } from './util' import { iconMap, itemNotifyIconMap, typeIconMap } from './util';
import FilterGroup from './FilterGroup.vue' import FilterGroup from './FilterGroup.vue';
const sceneStore = useSceneStore(); const sceneStore = useSceneStore();
const { data: _data } = storeToRefs(sceneStore); const { data: _data } = storeToRefs(sceneStore);
@ -390,8 +404,8 @@ const props = defineProps({
default: 0, default: 0,
}, },
thenName: { thenName: {
type: Number, type: Number,
default: 0, default: 0,
}, },
name: { name: {
type: Number, type: Number,
@ -421,11 +435,15 @@ const triggerVisible = ref<boolean>(false);
const actionType = ref(''); const actionType = ref('');
const termsOptions = computed(() => { const termsOptions = computed(() => {
if (!props.parallel) { // if (!props.parallel) {
return _data.value.branches![props.branchesName].then?.[props.thenName].actions?.[props.name].terms || [] //
} return (
return [] _data.value.branches![props.branchesName].then?.[props.thenName]
}) .actions?.[props.name].terms || []
);
}
return [];
});
const onDelete = () => { const onDelete = () => {
emit('delete'); emit('delete');
@ -463,12 +481,14 @@ const onPropsCancel = () => {
actionType.value = ''; actionType.value = '';
}; };
watch(() => props.data, () => { watch(
if (props.data) { () => props.data,
() => {
} if (props.data) {
}, { immediate: true, deep: true}) }
},
{ immediate: true, deep: true },
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@ -589,16 +609,16 @@ watch(() => props.data, () => {
} }
.actions-item-filter-warp-tip { .actions-item-filter-warp-tip {
position: absolute; position: absolute;
top: 0; top: 0;
left: 16px; left: 16px;
z-index: 2; z-index: 2;
color: rgba(0, 0, 0, 0.55); color: rgba(0, 0, 0, 0.55);
font-weight: 800; font-weight: 800;
font-size: 14px; font-size: 14px;
line-height: 1; line-height: 1;
background-color: #fff; background-color: #fff;
transform: translateY(-50%); transform: translateY(-50%);
} }
.actions-item-filter-overflow { .actions-item-filter-overflow {
@ -609,11 +629,11 @@ watch(() => props.data, () => {
row-gap: 16px; row-gap: 16px;
} }
.filter-add-button{ .filter-add-button {
width: 100%; width: 100%;
color: rgba(0, 0, 0, 0.3); color: rgba(0, 0, 0, 0.3);
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
} }
.terms-params { .terms-params {

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<template v-if="actionType === 'device'"> <template v-if="actionType === 'device'">
<Device v-bind="props" :value="data?.device" @cancel="onCancel" @save="onPropsOk" :thenName="branchesName" /> <Device v-bind="props" :value="data?.device" @cancel="onCancel" @save="onPropsOk" />
</template> </template>
<template v-else-if="actionType === 'notify'"> <template v-else-if="actionType === 'notify'">
<Notify :options="data?.options" :value="data?.notify" @cancel="onCancel" @save="onPropsOk" /> <Notify :options="data?.options" :value="data?.notify" @cancel="onCancel" @save="onPropsOk" />
@ -24,7 +24,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
branchGroup: { thenName: {
type: Number, type: Number,
default: 0, default: 0,
}, },

View File

@ -47,7 +47,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
branchGroup: { thenName: {
type: Number, type: Number,
default: 0, default: 0,
}, },

View File

@ -279,7 +279,6 @@ const onChange = (
} else { } else {
_values = getObj(_source, _value, isRelation); _values = getObj(_source, _value, isRelation);
} }
console.log(_values, '_values')
emit('update:value', _values); emit('update:value', _values);
emit('change', { sendTo: _names.filter((item) => !!item).join(',') }); emit('change', { sendTo: _names.filter((item) => !!item).join(',') });
}; };