fix: 修复设备接入更换接入方式,参数名称未发生变化问题
This commit is contained in:
parent
285d108bbc
commit
73e527f12c
|
@ -25,7 +25,7 @@
|
||||||
"event-source-polyfill": "^1.0.31",
|
"event-source-polyfill": "^1.0.31",
|
||||||
"global": "^4.4.0",
|
"global": "^4.4.0",
|
||||||
"jetlinks-store": "^0.0.3",
|
"jetlinks-store": "^0.0.3",
|
||||||
"jetlinks-ui-components": "^1.0.13",
|
"jetlinks-ui-components": "^1.0.16",
|
||||||
"js-cookie": "^3.0.1",
|
"js-cookie": "^3.0.1",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"less-loader": "^11.1.0",
|
"less-loader": "^11.1.0",
|
||||||
|
|
Binary file not shown.
|
@ -2,6 +2,15 @@
|
||||||
|
|
||||||
@DarkMenuItemColor: #808491 !important;
|
@DarkMenuItemColor: #808491 !important;
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: AliRegular;
|
||||||
|
src: url("/fonts/AlibabaPuHuiTi-2-55-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'AliRegular' !important;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-form-item-required:before {
|
.ant-form-item-required:before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -12px;
|
right: -12px;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@import "ant-design-vue/es/style/themes/index.less";
|
||||||
@import 'jetlinks-ui-components/es/style/variable.less';
|
@import 'jetlinks-ui-components/es/style/variable.less';
|
||||||
|
|
||||||
.ellipsisFn(@num: 1, @width: 100%) {
|
.ellipsisFn(@num: 1, @width: 100%) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<pro-search
|
<pro-search
|
||||||
class="device-search"
|
class="device-running-search"
|
||||||
type="simple"
|
type="simple"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
target="device-instance-running-events"
|
target="device-instance-running-events"
|
||||||
|
@ -45,23 +45,25 @@ const events = defineProps({
|
||||||
});
|
});
|
||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
|
|
||||||
const columns = ref<Record<string, any>>([
|
const defaultColumns = [
|
||||||
{
|
{
|
||||||
title: '时间',
|
title: '时间',
|
||||||
dataIndex: 'timestamp',
|
dataIndex: 'timestamp',
|
||||||
key: 'timestamp',
|
key: 'timestamp',
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'date',
|
type: 'date',
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
title: '操作',
|
{
|
||||||
dataIndex: 'action',
|
title: '操作',
|
||||||
key: 'action',
|
dataIndex: 'action',
|
||||||
scopedSlots: true,
|
key: 'action',
|
||||||
},
|
scopedSlots: true,
|
||||||
]);
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const columns = ref<Array<Record<string, any>>>([...defaultColumns]);
|
||||||
const params = ref<Record<string, any>>({});
|
const params = ref<Record<string, any>>({});
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const info = ref<Record<string, any>>({});
|
const info = ref<Record<string, any>>({});
|
||||||
|
@ -70,6 +72,7 @@ const _getEventList = (_params: any) =>
|
||||||
getEventList(instanceStore.current.id || '', events.data.id || '', _params);
|
getEventList(instanceStore.current.id || '', events.data.id || '', _params);
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
|
columns.value = [...defaultColumns]
|
||||||
if (events.data?.valueType?.type === 'object') {
|
if (events.data?.valueType?.type === 'object') {
|
||||||
(events.data.valueType?.properties || []).reverse().map((i: any) => {
|
(events.data.valueType?.properties || []).reverse().map((i: any) => {
|
||||||
columns.value.splice(0, 0, {
|
columns.value.splice(0, 0, {
|
||||||
|
@ -109,8 +112,10 @@ const detail = (_info: any) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
.device-search {
|
.device-running-search {
|
||||||
margin: 0 0 24px 0;
|
margin: 0 0 24px 0;
|
||||||
|
padding-top: 0 !important;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.device-running-event-modal {
|
.device-running-event-modal {
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
<div class="card-item-content-text">
|
<div class="card-item-content-text">
|
||||||
设备类型
|
设备类型
|
||||||
</div>
|
</div>
|
||||||
<div>直连设备</div>
|
<div>{{ slotProps?.deviceType?.text }}</div>
|
||||||
</j-col>
|
</j-col>
|
||||||
</j-row>
|
</j-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -257,12 +257,15 @@ const findProvidersByProvider = (provider: string) => {
|
||||||
*/
|
*/
|
||||||
const submitData = async () => {
|
const submitData = async () => {
|
||||||
if (selectedRowKeys.value.length) {
|
if (selectedRowKeys.value.length) {
|
||||||
|
|
||||||
if (checkData.value.channel === 'plugin') {
|
if (checkData.value.channel === 'plugin') {
|
||||||
const resp = await getProductByPluginId(checkData.value.channelId).catch(() => ({ success: false, result: []}))
|
const resp = await getProductByPluginId(checkData.value.channelId).catch(() => ({ success: false, result: []}))
|
||||||
|
const metadataResp = await getAccessConfig(props.productId!, checkData.value.id).catch(() => ({ success: false, result: {}}))
|
||||||
|
|
||||||
emit('submit', {
|
emit('submit', {
|
||||||
access: {...checkData.value},
|
access: {...checkData.value},
|
||||||
productTypes: resp.result
|
productTypes: resp.result,
|
||||||
|
metadata: metadataResp.result
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loading.value= true
|
loading.value= true
|
||||||
|
|
|
@ -615,11 +615,13 @@ const checkAccess = async (data: any) => {
|
||||||
productTypes.value = []
|
productTypes.value = []
|
||||||
productData.id = undefined
|
productData.id = undefined
|
||||||
productData.metadata = {}
|
productData.metadata = {}
|
||||||
|
metadata.value = data.metadata?.[0] || {
|
||||||
|
properties: []
|
||||||
|
}
|
||||||
if (data.access.channel === 'plugin') { // 插件设备
|
if (data.access.channel === 'plugin') { // 插件设备
|
||||||
markdownToHtml.value = ''
|
markdownToHtml.value = ''
|
||||||
productTypes.value = data.productTypes.map(item => ({ ...item, label: item.name, value: item.id}))
|
productTypes.value = data.productTypes.map(item => ({ ...item, label: item.name, value: item.id}))
|
||||||
} else {
|
} else {
|
||||||
metadata.value = data.metadata[0]
|
|
||||||
handleColumns()
|
handleColumns()
|
||||||
markdownToHtml.value = config.value?.document ? marked(config.value.document) : '';
|
markdownToHtml.value = config.value?.document ? marked(config.value.document) : '';
|
||||||
getGuide(!!data.metadata.length); //
|
getGuide(!!data.metadata.length); //
|
||||||
|
|
|
@ -20,12 +20,17 @@
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, text, record, index }">
|
<template #bodyCell="{ column, text, record, index }">
|
||||||
<template v-if='column.dataIndex === "name"'>
|
<template v-if='column.dataIndex === "name"'>
|
||||||
<span class='metadata-title'>{{ text }} ({{ record.id }})</span>
|
<span class='metadata-title'>
|
||||||
|
<j-ellipsis>
|
||||||
|
{{ text }} ({{ record.id }})
|
||||||
|
</j-ellipsis>
|
||||||
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-if='column.dataIndex === "plugin"'>
|
<template v-if='column.dataIndex === "plugin"'>
|
||||||
<j-select
|
<j-select
|
||||||
v-model:value='record.plugin'
|
v-model:value='record.plugin'
|
||||||
style='width: 100%'
|
style='width: 100%'
|
||||||
|
allowClear
|
||||||
@change='(id) => pluginChange(record, id)'
|
@change='(id) => pluginChange(record, id)'
|
||||||
>
|
>
|
||||||
<j-select-option
|
<j-select-option
|
||||||
|
@ -40,26 +45,28 @@
|
||||||
</j-table>
|
</j-table>
|
||||||
</div>
|
</div>
|
||||||
<div class='right'>
|
<div class='right'>
|
||||||
<div class='title'>
|
<j-scrollbar>
|
||||||
功能说明
|
<div class='title'>
|
||||||
</div>
|
功能说明
|
||||||
<p>
|
</div>
|
||||||
该功能用于将插件中的
|
<p>
|
||||||
<b>物模型属性标识</b>与
|
该功能用于将插件中的
|
||||||
<b>平台物模型属性标识</b>进行映射,当两方属性标识不一致时,可在当前页面直接修改映射管理,系统将以映射后的物模型属性进行数据处理。
|
<b>物模型属性标识</b>与
|
||||||
</p>
|
<b>平台物模型属性标识</b>进行映射,当两方属性标识不一致时,可在当前页面直接修改映射管理,系统将以映射后的物模型属性进行数据处理。
|
||||||
<p>
|
</p>
|
||||||
未完成映射的属性标识“目标属性”列数据为空,代表该属性值来源以在平台配置的来源为准。
|
<p>
|
||||||
</p>
|
未完成映射的属性标识“目标属性”列数据为空,代表该属性值来源以在平台配置的来源为准。
|
||||||
<p>
|
</p>
|
||||||
数据条背景亮起代表<b>标识一致</b>或<b>已完成映射</b>的属性。
|
<p>
|
||||||
</p>
|
数据条背景亮起代表<b>标识一致</b>或<b>已完成映射</b>的属性。
|
||||||
<div class='title'>
|
</p>
|
||||||
功能图示
|
<div class='title'>
|
||||||
</div>
|
功能图示
|
||||||
<div>
|
</div>
|
||||||
<img :src='getImage("/device/matadataMap.png")' />
|
<div>
|
||||||
</div>
|
<img :src='getImage("/device/matadataMap.png")' />
|
||||||
|
</div>
|
||||||
|
</j-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -87,7 +94,7 @@ const columns = [
|
||||||
{
|
{
|
||||||
title: '序号',
|
title: '序号',
|
||||||
dataIndex: 'index',
|
dataIndex: 'index',
|
||||||
width: 120
|
width: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '平台属性',
|
title: '平台属性',
|
||||||
|
@ -96,6 +103,7 @@ const columns = [
|
||||||
{
|
{
|
||||||
title: '目标属性',
|
title: '目标属性',
|
||||||
dataIndex: 'plugin',
|
dataIndex: 'plugin',
|
||||||
|
width: 250,
|
||||||
sorter: tableFilter
|
sorter: tableFilter
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -470,8 +470,8 @@ const query = reactive({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '接入方式',
|
title: '接入方式',
|
||||||
key: 'accessName',
|
key: 'accessId',
|
||||||
dataIndex: 'accessName',
|
dataIndex: 'accessId',
|
||||||
search: {
|
search: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
options: async () => {
|
options: async () => {
|
||||||
|
@ -482,7 +482,7 @@ const query = reactive({
|
||||||
typeList.value = [];
|
typeList.value = [];
|
||||||
typeList.value = resp.result.map((item: any) => ({
|
typeList.value = resp.result.map((item: any) => ({
|
||||||
label: item.name,
|
label: item.name,
|
||||||
value: item.name,
|
value: item.id,
|
||||||
}));
|
}));
|
||||||
res(typeList.value);
|
res(typeList.value);
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,8 @@ watch(
|
||||||
deviceId.value = newId as string;
|
deviceId.value = newId as string;
|
||||||
_control(newId).then((resp: any) => {
|
_control(newId).then((resp: any) => {
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
const item = `http://${resp.result?.url}/#/login?token=${resp.result.token}`;
|
const protocol = location.protocol
|
||||||
|
const item = `${protocol}//${resp.result?.url}/#/login?token=${resp.result.token}`;
|
||||||
url.value = item;
|
url.value = item;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,11 +16,13 @@
|
||||||
<template v-if="showType === 'network'">
|
<template v-if="showType === 'network'">
|
||||||
<Network
|
<Network
|
||||||
v-if="provider.id !== 'plugin_gateway'"
|
v-if="provider.id !== 'plugin_gateway'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Plugin
|
<Plugin
|
||||||
v-else
|
v-else
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
|
@ -28,21 +30,25 @@
|
||||||
|
|
||||||
<Media
|
<Media
|
||||||
v-if="showType === 'media'"
|
v-if="showType === 'media'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Channel
|
<Channel
|
||||||
v-if="showType === 'channel'"
|
v-if="showType === 'channel'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Edge
|
<Edge
|
||||||
v-if="showType === 'edge'"
|
v-if="showType === 'edge'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
<Cloud
|
<Cloud
|
||||||
v-if="showType === 'cloud'"
|
v-if="showType === 'cloud'"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:provider="provider"
|
:provider="provider"
|
||||||
:data="data"
|
:data="data"
|
||||||
/>
|
/>
|
||||||
|
@ -63,6 +69,7 @@ import Cloud from '../components/Cloud/index.vue';
|
||||||
import Plugin from '../components/Plugin/index.vue'
|
import Plugin from '../components/Plugin/index.vue'
|
||||||
import { getProviders, detail } from '@/api/link/accessConfig';
|
import { getProviders, detail } from '@/api/link/accessConfig';
|
||||||
import { accessConfigTypeFilter } from '@/utils/setting';
|
import { accessConfigTypeFilter } from '@/utils/setting';
|
||||||
|
import { queryProductList } from '@/api/device/product';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const id = route.params.id as string;
|
const id = route.params.id as string;
|
||||||
|
@ -73,6 +80,7 @@ const loading = ref(true);
|
||||||
const provider = ref({});
|
const provider = ref({});
|
||||||
const data = ref({});
|
const data = ref({});
|
||||||
const showType: any = ref('');
|
const showType: any = ref('');
|
||||||
|
const bindProduct = ref(false)
|
||||||
|
|
||||||
const goProviders = (param: any) => {
|
const goProviders = (param: any) => {
|
||||||
showType.value = param.type;
|
showType.value = param.type;
|
||||||
|
@ -188,8 +196,27 @@ const queryProviders = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否被产品使用
|
||||||
|
*/
|
||||||
|
const checkBindProduct = async (_id: string) => {
|
||||||
|
const resp = await queryProductList({
|
||||||
|
paging: false,
|
||||||
|
terms: [{
|
||||||
|
column: 'accessId',
|
||||||
|
termType: 'eq',
|
||||||
|
value: _id
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
console.log(resp.success && resp.result?.total)
|
||||||
|
if (resp.success && resp.result?.total) {
|
||||||
|
bindProduct.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getProvidersData = async () => {
|
const getProvidersData = async () => {
|
||||||
if (id !== ':id') {
|
if (id !== ':id') {
|
||||||
|
checkBindProduct(id)
|
||||||
getProviders().then((response: any) => {
|
getProviders().then((response: any) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
const _data = response.result || [];
|
const _data = response.result || [];
|
||||||
|
|
|
@ -22,13 +22,12 @@
|
||||||
}}</j-tooltip>
|
}}</j-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<div class="checked-icon">
|
<div class="checked-icon">
|
||||||
<div><CheckOutlined /></div>
|
<div><a-icon type='CheckOutlined' /></div>
|
||||||
</div>
|
</div>
|
||||||
</j-card>
|
</j-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="AccessCard">
|
<script lang="ts" setup name="AccessCard">
|
||||||
import { CheckOutlined } from '@ant-design/icons-vue';
|
|
||||||
|
|
||||||
const emit = defineEmits(['checkedChange']);
|
const emit = defineEmits(['checkedChange']);
|
||||||
|
|
||||||
|
@ -48,7 +47,9 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkedChange = (id: string) => {
|
const checkedChange = (id: string) => {
|
||||||
|
if (!props.disabled) {
|
||||||
emit('checkedChange', id);
|
emit('checkedChange', id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@
|
||||||
@search="procotolSearch"
|
@search="procotolSearch"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
v-if='showAddBtn'
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="addProcotol"
|
@click="addProcotol"
|
||||||
hasPermission="link/Protocol:add"
|
hasPermission="link/Protocol:add"
|
||||||
|
@ -199,6 +200,7 @@
|
||||||
<AccessCard
|
<AccessCard
|
||||||
@checkedChange="procotolChange"
|
@checkedChange="procotolChange"
|
||||||
:checked="procotolCurrent"
|
:checked="procotolCurrent"
|
||||||
|
:disabled='!showAddBtn'
|
||||||
:data="{ ...item, type: 'protocol' }"
|
:data="{ ...item, type: 'protocol' }"
|
||||||
>
|
>
|
||||||
</AccessCard>
|
</AccessCard>
|
||||||
|
@ -352,6 +354,10 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
bindProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const formRef1 = ref<FormInstance>();
|
const formRef1 = ref<FormInstance>();
|
||||||
|
@ -368,6 +374,10 @@ const formData = ref<Form>({
|
||||||
description: '',
|
description: '',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const showAddBtn = computed(() => {
|
||||||
|
return route.query.view === 'false' && !props.bindProduct
|
||||||
|
})
|
||||||
|
|
||||||
const current = ref(0);
|
const current = ref(0);
|
||||||
const stepCurrent = ref(0);
|
const stepCurrent = ref(0);
|
||||||
const steps = ref(['接入配置', '消息协议', '完成']);
|
const steps = ref(['接入配置', '消息协议', '完成']);
|
||||||
|
|
|
@ -260,6 +260,7 @@
|
||||||
@search="procotolSearch"
|
@search="procotolSearch"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
v-if='showAddBtn'
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="addProcotol"
|
@click="addProcotol"
|
||||||
hasPermission="link/Protocol:add"
|
hasPermission="link/Protocol:add"
|
||||||
|
@ -282,6 +283,7 @@
|
||||||
<AccessCard
|
<AccessCard
|
||||||
@checkedChange="procotolChange"
|
@checkedChange="procotolChange"
|
||||||
:checked="procotolCurrent"
|
:checked="procotolCurrent"
|
||||||
|
:disabled='!showAddBtn'
|
||||||
:data="{ ...item, type: 'protocol' }"
|
:data="{ ...item, type: 'protocol' }"
|
||||||
>
|
>
|
||||||
</AccessCard>
|
</AccessCard>
|
||||||
|
@ -434,6 +436,10 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
bindProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -462,6 +468,10 @@ const procotolList: any = ref([]);
|
||||||
const allProcotolList = ref([]);
|
const allProcotolList = ref([]);
|
||||||
const procotolCurrent: any = ref('');
|
const procotolCurrent: any = ref('');
|
||||||
|
|
||||||
|
const showAddBtn = computed(() => {
|
||||||
|
return route.query.view === 'false' && !props.bindProduct
|
||||||
|
})
|
||||||
|
|
||||||
const procotolChange = (id: string) => {
|
const procotolChange = (id: string) => {
|
||||||
procotolCurrent.value = id;
|
procotolCurrent.value = id;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
<Ctwing
|
<Ctwing
|
||||||
v-if="channel === 'Ctwing'"
|
v-if="channel === 'Ctwing'"
|
||||||
:provider="props.provider"
|
:provider="props.provider"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:data="props.data"
|
:data="props.data"
|
||||||
/>
|
/>
|
||||||
<OneNet
|
<OneNet
|
||||||
v-if="channel === 'OneNet'"
|
v-if="channel === 'OneNet'"
|
||||||
:provider="props.provider"
|
:provider="props.provider"
|
||||||
|
:bindProduct='bindProduct'
|
||||||
:data="props.data"
|
:data="props.data"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,6 +28,10 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
bindProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const channel = props.provider.channel;
|
const channel = props.provider.channel;
|
||||||
|
|
|
@ -530,7 +530,7 @@ const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
@search="networkSearch"
|
@search="networkSearch"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="addNetwork"
|
@click="addNetwork"
|
||||||
hasPermission="link/Type:add"
|
hasPermission="link/Type:add"
|
||||||
|
@ -112,6 +113,7 @@
|
||||||
@search="procotolSearch"
|
@search="procotolSearch"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
v-if='showAddBtn'
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="addProcotol"
|
@click="addProcotol"
|
||||||
hasPermission="link/Protocol:add"
|
hasPermission="link/Protocol:add"
|
||||||
|
@ -134,7 +136,7 @@
|
||||||
<AccessCard
|
<AccessCard
|
||||||
@checkedChange="procotolChange"
|
@checkedChange="procotolChange"
|
||||||
:checked="procotolCurrent"
|
:checked="procotolCurrent"
|
||||||
:disabled='id !== ":id"'
|
:disabled='!showAddBtn'
|
||||||
:data="{ ...item, type: 'protocol' }"
|
:data="{ ...item, type: 'protocol' }"
|
||||||
>
|
>
|
||||||
</AccessCard>
|
</AccessCard>
|
||||||
|
@ -352,6 +354,10 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
bindProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const clientHeight = document.body.clientHeight;
|
const clientHeight = document.body.clientHeight;
|
||||||
|
@ -396,6 +402,10 @@ const { resetFields, validate, validateInfos } = useForm(
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const showAddBtn = computed(() => {
|
||||||
|
return route.query.view === 'false' && !props.bindProduct
|
||||||
|
})
|
||||||
|
|
||||||
const queryNetworkList = async (id: string, include: string, data = {}) => {
|
const queryNetworkList = async (id: string, include: string, data = {}) => {
|
||||||
const resp = await getNetworkList(
|
const resp = await getNetworkList(
|
||||||
NetworkTypeMapping.get(id),
|
NetworkTypeMapping.get(id),
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
@search="pluginSearch"
|
@search="pluginSearch"
|
||||||
/>
|
/>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
|
v-if='showAddBtn'
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="addPlugin"
|
@click="addPlugin"
|
||||||
hasPermission="link/plugin:add"
|
hasPermission="link/plugin:add"
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
<AccessCard
|
<AccessCard
|
||||||
@checkedChange="AccessChange"
|
@checkedChange="AccessChange"
|
||||||
:checked="AccessCurrent"
|
:checked="AccessCurrent"
|
||||||
:disabled='paramsId !== ":id"'
|
:disabled='!showAddBtn'
|
||||||
:data="{ ...item, type: 'plugin' }"
|
:data="{ ...item, type: 'plugin' }"
|
||||||
>
|
>
|
||||||
<template #other>
|
<template #other>
|
||||||
|
@ -185,6 +186,10 @@ const props = defineProps({
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => {},
|
||||||
},
|
},
|
||||||
|
bindProduct: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -220,6 +225,10 @@ const queryPlugin = (params = {}) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showAddBtn = computed(() => {
|
||||||
|
return route.query.view === 'false' && !props.bindProduct
|
||||||
|
})
|
||||||
|
|
||||||
const getRules = (item: any) => {
|
const getRules = (item: any) => {
|
||||||
let typeName = '输入'
|
let typeName = '输入'
|
||||||
let rules: any[] = []
|
let rules: any[] = []
|
||||||
|
|
|
@ -157,7 +157,15 @@ watch(
|
||||||
.dash-board-item {
|
.dash-board-item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
//margin: 24px 12px;
|
//margin: 24px 12px;
|
||||||
min-width: 250px;
|
min-width: calc(25% - 24px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1400px) {
|
||||||
|
.dash-board {
|
||||||
|
.dash-board-item {
|
||||||
|
min-width: calc(50% - 24px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -43,19 +43,27 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
options: {},
|
options: {},
|
||||||
|
myChart: undefined
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
window.removeEventListener('resize', this.resize)
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
createChart(val) {
|
createChart(val) {
|
||||||
const chart = this.$refs.chartRef;
|
const chart = this.$refs.chartRef;
|
||||||
if (chart && Object.keys(val).length > 0) {
|
if (chart && Object.keys(val).length > 0 && !this.myChart) {
|
||||||
const myChart = echarts.init(chart);
|
console.log('createChart')
|
||||||
myChart.setOption(val);
|
this.myChart = echarts.init(chart);
|
||||||
window.addEventListener('resize', function () {
|
this.myChart.setOption(val);
|
||||||
myChart.resize();
|
window.addEventListener('resize', this.resize);
|
||||||
});
|
} else if (this.myChart) {
|
||||||
|
this.myChart.setOption(val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resize() {
|
||||||
|
this.myChart?.resize();
|
||||||
|
},
|
||||||
getOptions(max, formatter, val) {
|
getOptions(max, formatter, val) {
|
||||||
let formatterCount = 0;
|
let formatterCount = 0;
|
||||||
this.options = {
|
this.options = {
|
||||||
|
|
|
@ -110,17 +110,20 @@ export const Validator = {
|
||||||
),
|
),
|
||||||
regIPv6: new RegExp(/^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/),
|
regIPv6: new RegExp(/^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/),
|
||||||
regDomain: new RegExp(
|
regDomain: new RegExp(
|
||||||
/^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i,
|
// /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9_-](\?)?)*)*$/i,
|
||||||
|
/^[a-zA-Z0-9]+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,}$/
|
||||||
),
|
),
|
||||||
regOnlyNumber: new RegExp(/^\d+$/),
|
regOnlyNumber: new RegExp(/^\d+$/),
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateAddress = (_rule: any, value: string): Promise<any> => {
|
const validateAddress = (_rule: any, value: string): Promise<any> => {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const _domainStr = value
|
||||||
|
const _domain = _domainStr.replace(/^(https?|ftp):\/\/(www\.)?/i, '')
|
||||||
if (
|
if (
|
||||||
Validator.regIpv4.test(value) ||
|
Validator.regIpv4.test(value) ||
|
||||||
Validator.regIPv6.test(value) ||
|
Validator.regIPv6.test(value) ||
|
||||||
Validator.regDomain.test(value)
|
Validator.regDomain.test(_domain)
|
||||||
) {
|
) {
|
||||||
return resolve('');
|
return resolve('');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<j-upload
|
<j-upload
|
||||||
name="file"
|
name="file"
|
||||||
accept=".jar"
|
accept=".jar,.zip"
|
||||||
:action="uploadFile"
|
:action="uploadFile"
|
||||||
:headers="{
|
:headers="{
|
||||||
[TOKEN_KEY]: LocalStore.get(TOKEN_KEY),
|
[TOKEN_KEY]: LocalStore.get(TOKEN_KEY),
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<j-button>上传文件</j-button>
|
<j-button>上传文件</j-button>
|
||||||
<span class='upload-tip'>格式要求:{文件名}.jar/{文件名}.zip</span>
|
<span class='upload-tip'>格式要求:.jar .zip</span>
|
||||||
</div>
|
</div>
|
||||||
</j-upload>
|
</j-upload>
|
||||||
|
|
||||||
|
|
|
@ -207,9 +207,11 @@ watch(
|
||||||
* 部门点击
|
* 部门点击
|
||||||
*/
|
*/
|
||||||
const onTreeSelect = (keys: any) => {
|
const onTreeSelect = (keys: any) => {
|
||||||
|
if (keys.length) {
|
||||||
deptId.value = keys[0];
|
deptId.value = keys[0];
|
||||||
pageSize.value = 10;
|
pageSize.value = 10;
|
||||||
current.value = 1;
|
current.value = 1;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 右侧表格
|
// 右侧表格
|
||||||
|
|
|
@ -271,11 +271,11 @@ const columns = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '关联场景联动',
|
title: '关联场景联动',
|
||||||
dataIndex: 'sceneId',
|
dataIndex: 'scene',
|
||||||
wdith: 250,
|
|
||||||
scopedSlots: true,
|
scopedSlots: true,
|
||||||
search: {
|
search: {
|
||||||
type: 'select',
|
type: 'select',
|
||||||
|
// defaultTermType: 'rule-bind-alarm',
|
||||||
options: async () => {
|
options: async () => {
|
||||||
const res = await getScene(
|
const res = await getScene(
|
||||||
encodeQuery({
|
encodeQuery({
|
||||||
|
@ -338,7 +338,23 @@ const map = {
|
||||||
other: '其他',
|
other: '其他',
|
||||||
};
|
};
|
||||||
const handleSearch = (e: any) => {
|
const handleSearch = (e: any) => {
|
||||||
params.value = e;
|
const _terms = (e?.terms || []).map((item: any) => {
|
||||||
|
item.terms = item.terms.map((i: any) => {
|
||||||
|
if(i.column === 'scene'){
|
||||||
|
return {
|
||||||
|
...i,
|
||||||
|
termType: 'rule-bind-alarm',
|
||||||
|
column: 'id'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
params.value = {
|
||||||
|
...e,
|
||||||
|
terms: _terms
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const queryDefaultLevel = () => {
|
const queryDefaultLevel = () => {
|
||||||
queryLevel().then((res) => {
|
queryLevel().then((res) => {
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
<template>
|
||||||
|
<slot></slot>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang='ts' name='CheckItem'>
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { useSceneStore } from '@/store/scene'
|
||||||
|
import { Form } from 'jetlinks-ui-components'
|
||||||
|
import { queryProductList } from '@/api/device/product'
|
||||||
|
import { query as deviceQuery } from '@/api/device/instance'
|
||||||
|
import { getTreeData_api } from '@/api/system/department'
|
||||||
|
|
||||||
|
const sceneStore = useSceneStore()
|
||||||
|
const { data } = storeToRefs(sceneStore)
|
||||||
|
const formItemContext = Form.useInjectFormItemContext()
|
||||||
|
|
||||||
|
const formTouchOff = () => {
|
||||||
|
formItemContext.onFieldChange()
|
||||||
|
}
|
||||||
|
|
||||||
|
const check = async (): Promise<boolean> => {
|
||||||
|
const deviceTrigger = data.value.trigger!.device!
|
||||||
|
const productId = deviceTrigger.productId
|
||||||
|
|
||||||
|
// 判断产品是否删除
|
||||||
|
const proResp = await queryProductList({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: productId }]}]})
|
||||||
|
if (proResp.success && (proResp.result as any)?.total === 0) {
|
||||||
|
data.value.trigger!.device!.productId = ''
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const productDetail = proResp?.result?.data?.[0]
|
||||||
|
const selectorValues = deviceTrigger.selectorValues?.map(item => item.value)
|
||||||
|
let metadata = JSON.parse(productDetail?.metadata || '{}') // 获取当前产品物模型
|
||||||
|
|
||||||
|
// 判断设备是否删除
|
||||||
|
if (deviceTrigger.selector === 'fixed') { // 设备
|
||||||
|
const deviceResp = await deviceQuery({ terms: [{ column: 'id', termType: 'in', value: selectorValues?.toString() }]})
|
||||||
|
if (deviceResp.success && (deviceResp.result as any)?.total !== (selectorValues!.length)) {
|
||||||
|
data.value.trigger!.device!.selectorValues = undefined
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectorValues!.length === 1) {
|
||||||
|
const deviceDetail = deviceResp?.result?.data?.[0]
|
||||||
|
metadata = JSON.parse(deviceDetail?.metadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||||
|
}
|
||||||
|
} else if (deviceTrigger.selector === 'org') { // 组织
|
||||||
|
const orgResp = await getTreeData_api({
|
||||||
|
paging: false,
|
||||||
|
terms: [{ column: 'id', termType: 'eq', value: selectorValues![0] }]
|
||||||
|
})
|
||||||
|
|
||||||
|
if (orgResp.success && (orgResp.result as any[]).length !== selectorValues!.length) {
|
||||||
|
data.value.trigger!.device!.selectorValues = undefined
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断物模型
|
||||||
|
if (['readProperty', 'writeProperty'].includes(deviceTrigger.operation?.operator!)) {
|
||||||
|
let hasProperties = false
|
||||||
|
if (metadata.properties.length) {
|
||||||
|
if (deviceTrigger.operation?.readProperties && deviceTrigger.operation?.readProperties.length) {
|
||||||
|
hasProperties = metadata.properties.every((item: any) => deviceTrigger.operation!.readProperties!.includes(item.id))
|
||||||
|
} else if (deviceTrigger.operation?.writeProperties && Object.keys(deviceTrigger.operation?.writeProperties).length) {
|
||||||
|
const key = Object.keys(deviceTrigger.operation?.writeProperties)[0]
|
||||||
|
hasProperties = metadata.properties.some((item: any) => key ===item.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasProperties) {
|
||||||
|
if (deviceTrigger.operation?.operator === 'readProperty') {
|
||||||
|
deviceTrigger.operation!.readProperties = []
|
||||||
|
} else {
|
||||||
|
deviceTrigger.operation!.writeProperties = {}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceTrigger.operation?.operator === 'invokeFunction') {
|
||||||
|
let hasProperties = false
|
||||||
|
if (metadata.functions.length) {
|
||||||
|
const functionId = deviceTrigger.operation?.functionId
|
||||||
|
hasProperties = metadata.functions.some((item: any) => functionId ===item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasProperties) {
|
||||||
|
deviceTrigger.operation.functionId = undefined
|
||||||
|
deviceTrigger.operation.functionParameters = []
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceTrigger.operation?.operator === 'reportEvent') {
|
||||||
|
let hasProperties = false
|
||||||
|
if (metadata.events.length) {
|
||||||
|
const eventId = deviceTrigger.operation.eventId
|
||||||
|
hasProperties = metadata.events.some((item: any) => eventId ===item.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasProperties) {
|
||||||
|
deviceTrigger.operation.eventId = undefined
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkInit = async () => {
|
||||||
|
if (data.value.trigger?.device) {
|
||||||
|
const checkStatus = await check()
|
||||||
|
if (!checkStatus) {
|
||||||
|
formTouchOff()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkInit()
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -7,13 +7,15 @@
|
||||||
<template #label>
|
<template #label>
|
||||||
<TitleComponent data='触发规则' style='font-size: 14px;' />
|
<TitleComponent data='触发规则' style='font-size: 14px;' />
|
||||||
</template>
|
</template>
|
||||||
<AddButton
|
|
||||||
style='width: 100%'
|
<AddButton
|
||||||
@click='visible = true'
|
style='width: 100%'
|
||||||
>
|
@click='visible = true'
|
||||||
<Title :options='data.options.trigger' />
|
>
|
||||||
</AddButton>
|
<Title :options='data.options.trigger' />
|
||||||
<AddModel v-if='visible' @cancel='visible = false' @save='save' :value='data.trigger.device' :options='data.options.trigger' />
|
</AddButton>
|
||||||
|
<AddModel v-if='visible' @cancel='visible = false' @save='save' :value='data.trigger.device' :options='data.options.trigger' />
|
||||||
|
<CheckItem />
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<Terms />
|
<Terms />
|
||||||
</div>
|
</div>
|
||||||
|
@ -28,6 +30,7 @@ import Title from '../components/Title.vue'
|
||||||
import Terms from '../components/Terms'
|
import Terms from '../components/Terms'
|
||||||
import type { TriggerDevice } from '@/views/rule-engine/Scene/typings'
|
import type { TriggerDevice } from '@/views/rule-engine/Scene/typings'
|
||||||
import { EventEmitter, DeviceEmitterKey } from '@/views/rule-engine/Scene/Save/util'
|
import { EventEmitter, DeviceEmitterKey } from '@/views/rule-engine/Scene/Save/util'
|
||||||
|
import CheckItem from './CheckItem.vue'
|
||||||
|
|
||||||
const sceneStore = useSceneStore()
|
const sceneStore = useSceneStore()
|
||||||
const { data } = storeToRefs(sceneStore)
|
const { data } = storeToRefs(sceneStore)
|
||||||
|
@ -38,6 +41,21 @@ const rules = [{
|
||||||
validator(_: any, v: any) {
|
validator(_: any, v: any) {
|
||||||
if (!v) {
|
if (!v) {
|
||||||
return Promise.reject(new Error('请配置设备触发规则'));
|
return Promise.reject(new Error('请配置设备触发规则'));
|
||||||
|
} else {
|
||||||
|
console.log('device-validator', v)
|
||||||
|
if (
|
||||||
|
!v.productId ||
|
||||||
|
(['fixed', 'org'].includes(v.selector) && !v.selectorValues) ||
|
||||||
|
(v.operation?.operator === 'readProperty' && !v.operation!.readProperties.length) ||
|
||||||
|
(v.operation?.operator === 'writeProperty' && !Object.keys(v.operation!.writeProperties).length) ||
|
||||||
|
(v.operation?.operator === 'invokeFunction' && !v.operation.functionId) ||
|
||||||
|
(v.operation?.operator === 'reportEvent' && !v.operation.eventId)
|
||||||
|
) {
|
||||||
|
return Promise.reject(new Error('该数据已发生变更,请重新配置'));
|
||||||
|
}
|
||||||
|
// 判断产品
|
||||||
|
// 判断设备或者组织
|
||||||
|
// 判断属性、事件、功能
|
||||||
}
|
}
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts' name='ActionCheckItem'>
|
<script setup lang='ts' name='ActionCheckItem'>
|
||||||
import { ActionsType } from '@/views/rule-engine/Scene/typings'
|
import { ActionsType, FormModelType, PlatformRelation } from '@/views/rule-engine/Scene/typings'
|
||||||
import { useSceneStore } from '@/store/scene';
|
import { useSceneStore } from '@/store/scene';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { queryProductList } from '@/api/device/product'
|
import { queryProductList } from '@/api/device/product'
|
||||||
|
@ -11,7 +11,11 @@ import { query as deviceQuery } from '@/api/device/instance'
|
||||||
import noticeConfig from '@/api/notice/config'
|
import noticeConfig from '@/api/notice/config'
|
||||||
import noticeTemplate from '@/api/notice/template'
|
import noticeTemplate from '@/api/notice/template'
|
||||||
import { Form } from 'jetlinks-ui-components'
|
import { Form } from 'jetlinks-ui-components'
|
||||||
import { EventEmitter, EventSubscribeKeys } from '@/views/rule-engine/Scene/Save/util'
|
import { EventEmitter, EventSubscribeKeys, getParams } from '@/views/rule-engine/Scene/Save/util'
|
||||||
|
import { getOption } from '@/views/rule-engine/Scene/Save/components/DropdownButton/util'
|
||||||
|
import { getBuildInData, getNotifyVariablesUser } from './util'
|
||||||
|
import { defineExpose } from 'vue'
|
||||||
|
|
||||||
const sceneStore = useSceneStore();
|
const sceneStore = useSceneStore();
|
||||||
const { data: _data } = storeToRefs(sceneStore);
|
const { data: _data } = storeToRefs(sceneStore);
|
||||||
|
|
||||||
|
@ -34,21 +38,6 @@ const props = defineProps({
|
||||||
|
|
||||||
const sub = ref()
|
const sub = ref()
|
||||||
|
|
||||||
const rules = [{
|
|
||||||
validator(_: any, v?: ActionsType) {
|
|
||||||
if (v?.executor === 'device') {
|
|
||||||
if(
|
|
||||||
!v.device?.productId || // 产品已删除
|
|
||||||
!v.device?.selectorValues || // 设备已删除
|
|
||||||
(v.device.source === 'upper' && !v.device?.upperKey)
|
|
||||||
) {
|
|
||||||
return Promise.reject(new Error('该数据已发生变更,请重新配置'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
const formTouchOff = () => {
|
const formTouchOff = () => {
|
||||||
formItemContext.onFieldChange()
|
formItemContext.onFieldChange()
|
||||||
}
|
}
|
||||||
|
@ -64,17 +53,29 @@ const checkDeviceDelete = async () => {
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const productDetail = proResp?.result?.data?.[0]
|
||||||
|
let metadata = JSON.parse(productDetail?.metadata || '{}')
|
||||||
if (item?.selector === 'fixed') {
|
if (item?.selector === 'fixed') {
|
||||||
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
let hasDevice = false
|
||||||
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
|
if (item!.selectorValues) {
|
||||||
if (deviceResp.success && (deviceResp.result as any)?.total < (item!.selectorValues?.length || 0)) { // 某一个设备被删除
|
const deviceList = item!.selectorValues?.map(item => item.value) || []
|
||||||
|
const deviceResp = await deviceQuery({ terms: [{ terms: [{ column: 'id', termType: 'in', value: deviceList.toString() }]}]})
|
||||||
|
hasDevice = deviceResp.success && (deviceResp.result as any)?.total === (item!.selectorValues?.length || 0)
|
||||||
|
|
||||||
|
if (item!.selectorValues!.length === 1 && hasDevice) {
|
||||||
|
const deviceDetail = deviceResp?.result?.data?.[0]
|
||||||
|
metadata = JSON.parse(deviceDetail?.metadata || '{}') // 只选中一个设备,以设备物模型为准
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasDevice) { // 某一个设备被删除
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
|
||||||
console.log(item!.source, props.name)
|
} else if (item!.selector === 'context') { // 如果是按变量,校验上一个设备输出的产品id
|
||||||
if (item!.source === 'upper') { // 如果是按变量,校验上一个设备输出的产品id
|
|
||||||
if (props.name === 0) {
|
if (props.name === 0) {
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.upperKey = undefined
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.upperKey = undefined
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
|
@ -83,10 +84,99 @@ const checkDeviceDelete = async () => {
|
||||||
const prevItem = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name - 1].device
|
const prevItem = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name - 1].device
|
||||||
if (prevItem?.productId !== item?.productId) {
|
if (prevItem?.productId !== item?.productId) {
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.upperKey = undefined
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.upperKey = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
const _upperKey = item!.upperKey
|
||||||
|
const _params = {
|
||||||
|
branch: props.thenName,
|
||||||
|
branchGroup: props.branchesName,
|
||||||
|
action: props.name - 1,
|
||||||
|
};
|
||||||
|
const upperData = await getParams(_params, unref(_data.value));
|
||||||
|
const option = getOption(upperData, _upperKey, 'id')
|
||||||
|
if (!option) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.upperKey = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (item!.selector === 'relation') {
|
||||||
|
const _relationValue = (item!.selectorValues?.[0]?.value as any)?.relation
|
||||||
|
const relationData = await noticeConfig.getRelationUsers({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
|
terms: [
|
||||||
|
{ termType: 'eq', column: 'objectTypeName', value: '设备' },
|
||||||
|
{ termType: 'eq', column: 'relation', value: _relationValue }
|
||||||
|
],
|
||||||
|
}).catch(() => ({ success: false, result: []}))
|
||||||
|
if (!relationData.result?.length ) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if (item!.selector === 'tag') {
|
||||||
|
let hasAllTags = false
|
||||||
|
if (item!.selectorValues && metadata?.tags?.length) {
|
||||||
|
const values = (item!.selectorValues?.[0]?.value as any).map((item: any) => item.column)
|
||||||
|
const tagKeys = new Set(values)
|
||||||
|
hasAllTags = metadata?.tags?.every((item: any) => tagKeys.has(item.id))
|
||||||
|
}
|
||||||
|
if (!hasAllTags) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.selectorValues = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item!.message!.messageType === 'READ_PROPERTY') {
|
||||||
|
let hasProperties = false
|
||||||
|
if (item!.message!.properties && metadata.properties.length) {
|
||||||
|
const propertiesKey = item!.message!.properties?.[0]
|
||||||
|
hasProperties = metadata.properties?.some((item: any) => item.id === propertiesKey)
|
||||||
|
}
|
||||||
|
if (!hasProperties) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.message!.properties = []
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item!.message!.messageType === 'WRITE_PROPERTY') {
|
||||||
|
let hasProperties = false
|
||||||
|
if (item!.message!.properties && metadata.properties.length) {
|
||||||
|
const propertiesKey = Object.keys(item!.message!.properties!)?.[0]
|
||||||
|
hasProperties = metadata.properties?.some((item: any) => item.id === propertiesKey)
|
||||||
|
}
|
||||||
|
if (!hasProperties) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.message!.properties = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item!.message!.messageType === 'INVOKE_FUNCTION') {
|
||||||
|
const functionId = item!.message!.functionId
|
||||||
|
let hasFunctions = false
|
||||||
|
if (functionId && metadata.functions.length) {
|
||||||
|
hasFunctions = metadata.functions?.some((item: any) => item.id === functionId)
|
||||||
|
}
|
||||||
|
if (!hasFunctions) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.message!.functionId = undefined
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].device!.changeData = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,18 +185,114 @@ const checkDeviceDelete = async () => {
|
||||||
*/
|
*/
|
||||||
const checkNoticeDelete = async () => {
|
const checkNoticeDelete = async () => {
|
||||||
const item = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify
|
const item = _data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify
|
||||||
|
const _triggerType = _data.value.triggerType
|
||||||
const configResp = await noticeConfig.list({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.notifierId }]}]})
|
const configResp = await noticeConfig.list({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.notifierId }]}]})
|
||||||
if (configResp.success && (configResp.result as any)?.total === 0) {
|
if (configResp.success && (configResp.result as any)?.total === 0) { // 通知配置
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify!.notifierId = ''
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify!.notifierId = ''
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const templateResp = await noticeTemplate.list({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.templateId }]}]})
|
const templateResp = await noticeTemplate.list({ terms: [{ terms: [{ column: 'id', termType: 'eq', value: item!.templateId }]}]})
|
||||||
if (templateResp.success && (templateResp.result as any)?.total === 0) {
|
if (templateResp.success && (templateResp.result as any)?.total === 0) { // 通知模板
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify!.templateId = ''
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify!.templateId = ''
|
||||||
formTouchOff()
|
formTouchOff()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const templateDetailResp = await noticeTemplate.getTemplateDetail(item!.templateId)
|
||||||
|
if (templateDetailResp.success) {
|
||||||
|
const variableDefinitionsMap = new Map()
|
||||||
|
const itemVariableKeys = Object.keys(item!.variables)
|
||||||
|
const notifyType = item!.notifyType
|
||||||
|
templateDetailResp.result.variableDefinitions.map((dItem: any) => {
|
||||||
|
variableDefinitionsMap.set(dItem.id, dItem.expands?.businessType)
|
||||||
|
})
|
||||||
|
// 判断参数是否发生变化
|
||||||
|
let BuildInData: any = null
|
||||||
|
const hasAll = itemVariableKeys.every(async (variableKey: any) => {
|
||||||
|
if (variableDefinitionsMap.has(variableKey)) {
|
||||||
|
const itemData = item!.variables[variableKey]
|
||||||
|
if (itemData.source === 'upper') {
|
||||||
|
if (!BuildInData) {
|
||||||
|
const _params = {
|
||||||
|
branch: props.thenName,
|
||||||
|
branchGroup: props.branchesName,
|
||||||
|
action: props.name - 1,
|
||||||
|
};
|
||||||
|
BuildInData = await getBuildInData(_params, _data.value)
|
||||||
|
}
|
||||||
|
const option = BuildInData?.(itemData.upperKey!, 'id')
|
||||||
|
return !!option
|
||||||
|
} else if (itemData.source === 'fixed') {
|
||||||
|
const itemType = variableDefinitionsMap.get(variableKey)
|
||||||
|
let hasUser = false
|
||||||
|
|
||||||
|
if (itemType === 'user') { // 微信用户,钉钉用户
|
||||||
|
let resp = undefined;
|
||||||
|
if (notifyType === 'dingTalk') {
|
||||||
|
resp = await noticeConfig.queryDingTalkUsers(item!.notifierId);
|
||||||
|
} else {
|
||||||
|
resp = await noticeConfig.queryWechatUsers(item!.notifierId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp && resp.success) {
|
||||||
|
hasUser = resp.result.some((uItem: any) => uItem.id === itemData.value)
|
||||||
|
}
|
||||||
|
return hasUser
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType === 'tag') { // 标签
|
||||||
|
const resp = await noticeTemplate.getTags(item!.notifierId)
|
||||||
|
if (resp && resp.success) {
|
||||||
|
hasUser = resp.result.some((tag: any) => tag.id === itemData.value)
|
||||||
|
}
|
||||||
|
return hasUser
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemType === 'org') { // 组织
|
||||||
|
let resp = undefined;
|
||||||
|
if (notifyType === 'dingTalk') {
|
||||||
|
resp = await noticeConfig.dingTalkDept(item!.notifierId)
|
||||||
|
} else {
|
||||||
|
resp = await noticeConfig.weChatDept(item!.notifierId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp && resp.success) {
|
||||||
|
hasUser = resp.result.some((org: any) => org.id === itemData.value)
|
||||||
|
}
|
||||||
|
return hasUser
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (itemData.source == 'relation') {
|
||||||
|
// 获取平台用户
|
||||||
|
const userData = await getNotifyVariablesUser(_triggerType === 'device')
|
||||||
|
let hasUser = false
|
||||||
|
if (!hasUser && userData.platform.length) { // 平台用户
|
||||||
|
hasUser = userData.platform.some(uItem => {
|
||||||
|
return uItem.id === (itemData.relation as PlatformRelation)?.objectId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (!hasUser && userData.relation.length) { // 关系用户
|
||||||
|
hasUser = userData.relation.some(uItem => {
|
||||||
|
return uItem.id === (itemData.relation as PlatformRelation)?.objectId
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return hasUser
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
BuildInData = null
|
||||||
|
|
||||||
|
if (!hasAll) {
|
||||||
|
_data.value.branches![props.branchesName].then[props.thenName].actions[props.name].notify!.changeData! = true
|
||||||
|
formTouchOff()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const check = () => {
|
const check = () => {
|
||||||
|
@ -133,6 +319,10 @@ subscribe()
|
||||||
|
|
||||||
check()
|
check()
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
formTouchOff
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
:rules='rules'
|
:rules='rules'
|
||||||
>
|
>
|
||||||
<div class="actions-item">
|
<div class="actions-item">
|
||||||
<CheckItem v-bind='props'>
|
<CheckItem v-bind='props' ref='checkItemRef'>
|
||||||
<div class="item-options-warp">
|
<div class="item-options-warp">
|
||||||
<div class="item-options-type" @click="onAdd">
|
<div class="item-options-type" @click="onAdd">
|
||||||
<img
|
<img
|
||||||
|
@ -330,7 +330,7 @@
|
||||||
</j-popconfirm>
|
</j-popconfirm>
|
||||||
</CheckItem>
|
</CheckItem>
|
||||||
</div>
|
</div>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<template v-if="!isLast && type === 'serial'">
|
<template v-if="!isLast && type === 'serial'">
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
|
@ -361,7 +361,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- 编辑 -->
|
|
||||||
<template v-if="visible">
|
<template v-if="visible">
|
||||||
<Modal
|
<Modal
|
||||||
:name="name"
|
:name="name"
|
||||||
|
@ -373,6 +373,7 @@
|
||||||
@save="onSave"
|
@save="onSave"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- 编辑 -->
|
||||||
<template>
|
<template>
|
||||||
<ActionTypeComponent
|
<ActionTypeComponent
|
||||||
v-bind="props"
|
v-bind="props"
|
||||||
|
@ -405,7 +406,6 @@ import FilterGroup from './FilterGroup.vue';
|
||||||
import { randomString } from '@/utils/utils'
|
import { randomString } from '@/utils/utils'
|
||||||
import { EventEmitter, EventEmitterKeys } from '@/views/rule-engine/Scene/Save/util'
|
import { EventEmitter, EventEmitterKeys } from '@/views/rule-engine/Scene/Save/util'
|
||||||
import CheckItem from './CheckItem.vue'
|
import CheckItem from './CheckItem.vue'
|
||||||
import { Form } from 'jetlinks-ui-components'
|
|
||||||
|
|
||||||
const sceneStore = useSceneStore();
|
const sceneStore = useSceneStore();
|
||||||
const { data: _data } = storeToRefs(sceneStore);
|
const { data: _data } = storeToRefs(sceneStore);
|
||||||
|
@ -441,7 +441,7 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['delete', 'update']);
|
const emit = defineEmits(['delete', 'update']);
|
||||||
|
const checkItemRef = ref()
|
||||||
const visible = ref<boolean>(false);
|
const visible = ref<boolean>(false);
|
||||||
const triggerVisible = ref<boolean>(false);
|
const triggerVisible = ref<boolean>(false);
|
||||||
const actionType = ref('');
|
const actionType = ref('');
|
||||||
|
@ -450,7 +450,6 @@ const eventEmitterKey = ref(EventEmitterKeys({
|
||||||
branchGroup: props.thenName,
|
branchGroup: props.thenName,
|
||||||
action: props.name
|
action: props.name
|
||||||
}))
|
}))
|
||||||
const formItemContext = Form.useInjectFormItemContext()
|
|
||||||
const termsOptions = computed(() => {
|
const termsOptions = computed(() => {
|
||||||
if (!props.parallel) {
|
if (!props.parallel) {
|
||||||
// 串行
|
// 串行
|
||||||
|
@ -535,9 +534,8 @@ const onSave = (data: ActionsType, options: any) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
_data.value.branches![props.branchesName].then[props.thenName].actions.splice(props.name, 1, actionItem)
|
_data.value.branches![props.branchesName].then[props.thenName].actions.splice(props.name, 1, actionItem)
|
||||||
|
checkItemRef.value?.formTouchOff?.()
|
||||||
visible.value = false;
|
visible.value = false;
|
||||||
|
|
||||||
EventEmitter.emit(eventEmitterKey.value, data) // 发布消息
|
EventEmitter.emit(eventEmitterKey.value, data) // 发布消息
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -559,7 +557,22 @@ const rules = [{
|
||||||
validator(_: any, v?: ActionsType) {
|
validator(_: any, v?: ActionsType) {
|
||||||
console.log('validator-action-item',v)
|
console.log('validator-action-item',v)
|
||||||
if (v?.executor === 'device') {
|
if (v?.executor === 'device') {
|
||||||
if(v?.device?.source === 'fixed' && (!v.device?.productId || !v.device?.selectorValues)) {
|
const _device = v.device!
|
||||||
|
if (
|
||||||
|
(_device?.selector === 'fixed' && (!_device?.productId || !_device?.selectorValues?.length )) ||
|
||||||
|
(_device?.selector === 'context' && !_device?.upperKey) ||
|
||||||
|
(_device?.selector === 'relation' && !_device?.selectorValues?.length) ||
|
||||||
|
_device?.changeData === true
|
||||||
|
) {
|
||||||
|
return Promise.reject(new Error('该数据已发生变更,请重新配置'))
|
||||||
|
}
|
||||||
|
} else if (v?.executor === 'notify') {
|
||||||
|
const _notify = v.notify
|
||||||
|
if (
|
||||||
|
!_notify?.notifierId ||
|
||||||
|
!_notify?.templateId ||
|
||||||
|
_notify?.changeData === true
|
||||||
|
) {
|
||||||
return Promise.reject(new Error('该数据已发生变更,请重新配置'))
|
return Promise.reject(new Error('该数据已发生变更,请重新配置'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import { getImage } from '@/utils/comm'
|
import { getImage } from '@/utils/comm'
|
||||||
|
import NoticeApi from '@/api/notice/config'
|
||||||
|
import { getParams } from '@/views/rule-engine/Scene/Save/util'
|
||||||
|
import { getOption } from '@/views/rule-engine/Scene/Save/components/DropdownButton/util'
|
||||||
|
|
||||||
export const iconMap = new Map();
|
export const iconMap = new Map();
|
||||||
iconMap.set('trigger', getImage('/scene/action-bind-icon.png'));
|
iconMap.set('trigger', getImage('/scene/action-bind-icon.png'));
|
||||||
|
@ -25,4 +28,33 @@ export const typeIconMap = {
|
||||||
READ_PROPERTY: 'icon-zhihangdongzuodu',
|
READ_PROPERTY: 'icon-zhihangdongzuodu',
|
||||||
INVOKE_FUNCTION: 'icon-zhihangdongzuoxie-1',
|
INVOKE_FUNCTION: 'icon-zhihangdongzuoxie-1',
|
||||||
WRITE_PROPERTY: 'icon-zhihangdongzuoxie',
|
WRITE_PROPERTY: 'icon-zhihangdongzuoxie',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBuildInData = async (params: any, data: any) => {
|
||||||
|
const buildInData = await getParams(params, unref(data));
|
||||||
|
|
||||||
|
return function(upperKey: string, key: string ) {
|
||||||
|
return getOption(buildInData, upperKey, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getNotifyVariablesUser = (isRelationUser: boolean = false): Promise<{ platform: any[], relation: any[] }> => {
|
||||||
|
return new Promise(async (resolve) => {
|
||||||
|
let relationResp = undefined;
|
||||||
|
const platformResp = await NoticeApi.getPlatformUsers({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'name', order: 'asc' }],
|
||||||
|
});
|
||||||
|
if (isRelationUser) {
|
||||||
|
relationResp = await NoticeApi.getRelationUsers({
|
||||||
|
paging: false,
|
||||||
|
sorts: [{ name: 'name', order: 'asc' }],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
platform: platformResp.result || [],
|
||||||
|
relation: relationResp?.result || []
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
</j-modal>
|
</j-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup name='UpdateActionItemModal'>
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import Delay from '../Delay/index.vue';
|
import Delay from '../Delay/index.vue';
|
||||||
import Notify from '../Notify/index.vue';
|
import Notify from '../Notify/index.vue';
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
<j-date-picker
|
<j-date-picker
|
||||||
:value="value.value"
|
:value="value.value"
|
||||||
allowClear
|
allowClear
|
||||||
|
valueFormat='YYYY-MM-DD HH:mm:ss'
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
format="YYYY-MM-DD HH:mm:ss"
|
||||||
style="width: calc(100% - 120px)"
|
style="width: calc(100% - 120px)"
|
||||||
v-if="item.type === 'date'"
|
v-if="item.type === 'date'"
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
v-if="['email'].includes(notifyType)"
|
v-if="['email'].includes(notifyType)"
|
||||||
style="width: calc(100% - 120px)"
|
style="width: calc(100% - 120px)"
|
||||||
placeholder="请选择收信人"
|
placeholder="请选择收信人"
|
||||||
@change="(key, label) => onChange(source, key, false, label)"
|
@change="(key, label) => onChange(source, key, label)"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
@ -66,7 +66,7 @@
|
||||||
style="width: calc(100% - 120px)"
|
style="width: calc(100% - 120px)"
|
||||||
placeholder="请选择收信人"
|
placeholder="请选择收信人"
|
||||||
@change="
|
@change="
|
||||||
(key, label) => onChange(source, key, undefined, label)
|
(key, label) => onChange(source, key, label)
|
||||||
"
|
"
|
||||||
:tree-data="treeData"
|
:tree-data="treeData"
|
||||||
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
||||||
|
@ -102,7 +102,6 @@
|
||||||
onChange(
|
onChange(
|
||||||
source,
|
source,
|
||||||
val,
|
val,
|
||||||
false,
|
|
||||||
option?.label || option?.name,
|
option?.label || option?.name,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -120,7 +119,6 @@
|
||||||
onChange(
|
onChange(
|
||||||
source,
|
source,
|
||||||
val,
|
val,
|
||||||
false,
|
|
||||||
Array.isArray(val) ? val.join(',') : val,
|
Array.isArray(val) ? val.join(',') : val,
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
|
@ -132,7 +130,7 @@
|
||||||
:value="value?.value"
|
:value="value?.value"
|
||||||
@change="
|
@change="
|
||||||
(e) =>
|
(e) =>
|
||||||
onChange(source, e.target.value, false, e.target.value)
|
onChange(source, e.target.value, e.target.value)
|
||||||
"
|
"
|
||||||
></j-input>
|
></j-input>
|
||||||
</template>
|
</template>
|
||||||
|
@ -183,7 +181,13 @@ const triggerType = computed(() => {
|
||||||
|
|
||||||
const relationData = computed(() => {
|
const relationData = computed(() => {
|
||||||
const item = props.value;
|
const item = props.value;
|
||||||
if (item?.source === 'relation') {
|
if(notifyType.value === 'email'){
|
||||||
|
if(item && Array.isArray(item) && item.length){
|
||||||
|
if(item[0].source === 'relation'){
|
||||||
|
return item.map(i => i?.relation?.objectId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (item?.source === 'relation') {
|
||||||
const relation = item?.relation;
|
const relation = item?.relation;
|
||||||
if (relation) {
|
if (relation) {
|
||||||
if (relation.objectId) {
|
if (relation.objectId) {
|
||||||
|
@ -268,14 +272,15 @@ const getUser = async (_source: string, _triggerType: string) => {
|
||||||
key: 'p2',
|
key: 'p2',
|
||||||
selectable: false,
|
selectable: false,
|
||||||
children: relationResp.result.map((item: any) => {
|
children: relationResp.result.map((item: any) => {
|
||||||
treeDataMap.set(item.id, item)
|
const obj = {
|
||||||
return {
|
|
||||||
...item,
|
...item,
|
||||||
value: item.id,
|
value: item.id,
|
||||||
key: item.id,
|
key: item.id,
|
||||||
title: item.name,
|
title: item.name,
|
||||||
isRelation: true,
|
isRelation: true,
|
||||||
};
|
}
|
||||||
|
treeDataMap.set(item.id, obj)
|
||||||
|
return obj
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -302,7 +307,7 @@ const getObj = (
|
||||||
objectType: 'device',
|
objectType: 'device',
|
||||||
objectSource: {
|
objectSource: {
|
||||||
source: 'upper',
|
source: 'upper',
|
||||||
upperKey: 'deviceId',
|
upperKey: 'scene.deviceId',
|
||||||
},
|
},
|
||||||
related: {
|
related: {
|
||||||
objectType: 'user',
|
objectType: 'user',
|
||||||
|
@ -324,7 +329,7 @@ const getObj = (
|
||||||
const onChange = (
|
const onChange = (
|
||||||
_source: string = 'fixed',
|
_source: string = 'fixed',
|
||||||
_value?: string | string[],
|
_value?: string | string[],
|
||||||
isRelation?: boolean,
|
// isRelation?: boolean,
|
||||||
_name?: string,
|
_name?: string,
|
||||||
) => {
|
) => {
|
||||||
let _values: any = undefined;
|
let _values: any = undefined;
|
||||||
|
@ -332,16 +337,15 @@ const onChange = (
|
||||||
const _names: string[] = Array.isArray(_name) ? _name : [_name || ''];
|
const _names: string[] = Array.isArray(_name) ? _name : [_name || ''];
|
||||||
if (Array.isArray(_value)) {
|
if (Array.isArray(_value)) {
|
||||||
if (props?.notify?.notifyType === 'email') {
|
if (props?.notify?.notifyType === 'email') {
|
||||||
if (isRelation) {
|
_values = _value.map((item) => {
|
||||||
const arr = _value.map((item) => {
|
return {
|
||||||
const _item = labelMap.get(item);
|
source: "relation",
|
||||||
_names.push(_item?.name || '');
|
relation:{
|
||||||
return getObj('relation', item, _item?.relation);
|
objectType: "user",
|
||||||
});
|
objectId: item
|
||||||
_values = arr;
|
}
|
||||||
} else {
|
}
|
||||||
_values = getObj(_source, _value, false);
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const item = treeDataMap.get(_value)
|
const item = treeDataMap.get(_value)
|
||||||
|
|
|
@ -20,7 +20,7 @@ export const getParams = (params: Params, sceneModel: FormModelType): Promise<an
|
||||||
if (resp.success) {
|
if (resp.success) {
|
||||||
res(resp.result as any[])
|
res(resp.result as any[])
|
||||||
}
|
}
|
||||||
})
|
}).catch(() => res([]))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ export enum ActionDeviceSelector {
|
||||||
'fixed' = 'fixed',
|
'fixed' = 'fixed',
|
||||||
'tag' = 'tag',
|
'tag' = 'tag',
|
||||||
'relation' = 'relation',
|
'relation' = 'relation',
|
||||||
|
'context' = 'context',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ActionDeviceSource {
|
export enum ActionDeviceSource {
|
||||||
|
@ -236,6 +237,7 @@ export interface NotifyProps {
|
||||||
templateId: string;
|
templateId: string;
|
||||||
variables: Record<string, NotifyVariablesType>;
|
variables: Record<string, NotifyVariablesType>;
|
||||||
options?: Record<string, any>;
|
options?: Record<string, any>;
|
||||||
|
changeData?: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SelectorValuesType =
|
export type SelectorValuesType =
|
||||||
|
@ -264,6 +266,7 @@ export interface ActionsDeviceProps {
|
||||||
upperKey?: string;
|
upperKey?: string;
|
||||||
/** 来源为relation时不能为空 */
|
/** 来源为relation时不能为空 */
|
||||||
relation?: any;
|
relation?: any;
|
||||||
|
changeData?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BranchesThen {
|
export interface BranchesThen {
|
||||||
|
@ -321,6 +324,7 @@ export interface FormModelType {
|
||||||
* 拓展信息,用于前端存储一些渲染数据
|
* 拓展信息,用于前端存储一些渲染数据
|
||||||
*/
|
*/
|
||||||
options?: Record<string, any>;
|
options?: Record<string, any>;
|
||||||
|
triggerType?: 'device' | 'manual' | 'timer'
|
||||||
description?: string;
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1913,6 +1913,7 @@ function changeBackUpload(info: UploadChangeParam<UploadFile<any>>) {
|
||||||
message.error('logo上传失败,请稍后再试');
|
message.error('logo上传失败,请稍后再试');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearNullProp(obj: object) {
|
function clearNullProp(obj: object) {
|
||||||
if (typeof obj !== 'object') return;
|
if (typeof obj !== 'object') return;
|
||||||
for (const prop in obj) {
|
for (const prop in obj) {
|
||||||
|
@ -1930,15 +1931,19 @@ function clearNullProp(obj: object) {
|
||||||
* @param value
|
* @param value
|
||||||
*/
|
*/
|
||||||
const validateIP = (_rule: Rule, value: string) => {
|
const validateIP = (_rule: Rule, value: string) => {
|
||||||
const ipList = value?.split(/[\n,]/g).filter((i: string) => i && i.trim());
|
if (value) {
|
||||||
const errorIPList = ipList.filter(
|
const ipList = value?.split(/[\n,]/g).filter((i: string) => i && i.trim());
|
||||||
(f: string) => !testIP(f.replace(/\s*/g, '')),
|
const errorIPList = ipList?.filter(
|
||||||
);
|
(f: string) => !testIP(f.replace(/\s*/g, '')),
|
||||||
return new Promise((resolve, reject) => {
|
);
|
||||||
!errorIPList.length
|
return new Promise((resolve, reject) => {
|
||||||
? resolve('')
|
!errorIPList?.length
|
||||||
: reject(`[${errorIPList}]不是正确的IP地址`);
|
? resolve('')
|
||||||
});
|
: reject(`[${errorIPList}]不是正确的IP地址`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,18 @@
|
||||||
<j-form-item name="base-path">
|
<j-form-item name="base-path">
|
||||||
<template #label>
|
<template #label>
|
||||||
<span>base-path</span>
|
<span>base-path</span>
|
||||||
<j-tooltip title="系统后台访问的url">
|
<j-tooltip >
|
||||||
|
<template #title>
|
||||||
|
<div style='word-break: break-all;'>
|
||||||
|
<div>
|
||||||
|
系统后台访问的url。
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
格式:{http/https}: //{前端所在服务器IP地址}:{前端暴露的服务端口}/api
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<img
|
<img
|
||||||
class="img-style"
|
class="img-style"
|
||||||
:src="
|
:src="
|
||||||
|
@ -59,7 +70,7 @@
|
||||||
</template>
|
</template>
|
||||||
<j-input
|
<j-input
|
||||||
v-model:value="formValue['base-path']"
|
v-model:value="formValue['base-path']"
|
||||||
placeholder="输入base-path"
|
placeholder="{http/https}: //{前端所在服务器IP地址}:{前端暴露的服务端口}/api"
|
||||||
/>
|
/>
|
||||||
</j-form-item>
|
</j-form-item>
|
||||||
<j-row :gutter="24" :span="24">
|
<j-row :gutter="24" :span="24">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="product-container">
|
<div class="product-container">
|
||||||
<pro-search
|
<pro-search
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
target="category"
|
target="category-device"
|
||||||
@search="(params:any)=>queryParams = {...params}"
|
@search="(params:any)=>queryParams = {...params}"
|
||||||
style='margin-bottom: 0;'
|
style='margin-bottom: 0;'
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="product-container">
|
<div class="product-container">
|
||||||
<pro-search
|
<pro-search
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
target="category"
|
target="category-product"
|
||||||
@search="(params:any)=>queryParams = {...params}"
|
@search="(params:any)=>queryParams = {...params}"
|
||||||
style='margin-bottom: 0;'
|
style='margin-bottom: 0;'
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<pro-search
|
<pro-search
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
target="category"
|
target="category-user"
|
||||||
@search="handleParams"
|
@search="handleParams"
|
||||||
style='margin-bottom: 0;'
|
style='margin-bottom: 0;'
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
:model="form.data"
|
:model="form.data"
|
||||||
class="basic-form permiss-form"
|
class="basic-form permiss-form"
|
||||||
>
|
>
|
||||||
<j-form-item name="accessSupport" required>
|
<j-form-item name="accessSupport" required v-if="isNoCommunity">
|
||||||
<template #label>
|
<template #label>
|
||||||
<span style="margin-right: 3px">数据权限控制</span>
|
<span style="margin-right: 3px">数据权限控制</span>
|
||||||
<j-tooltip title="此菜单页面数据所对应的资产类型">
|
<j-tooltip title="此菜单页面数据所对应的资产类型">
|
||||||
|
@ -263,7 +263,6 @@ import { FormInstance } from 'ant-design-vue';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import ChooseIconDialog from '../components/ChooseIconDialog.vue';
|
import ChooseIconDialog from '../components/ChooseIconDialog.vue';
|
||||||
import PermissChoose from '../components/PermissChoose.vue';
|
import PermissChoose from '../components/PermissChoose.vue';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getMenuTree_api,
|
getMenuTree_api,
|
||||||
getAssetsType_api,
|
getAssetsType_api,
|
||||||
|
@ -273,6 +272,7 @@ import {
|
||||||
validCode_api,
|
validCode_api,
|
||||||
} from '@/api/system/menu';
|
} from '@/api/system/menu';
|
||||||
import { Rule } from 'ant-design-vue/lib/form';
|
import { Rule } from 'ant-design-vue/lib/form';
|
||||||
|
import { isNoCommunity } from '@/utils/utils';
|
||||||
|
|
||||||
const permission = 'system/Menu';
|
const permission = 'system/Menu';
|
||||||
// 路由
|
// 路由
|
||||||
|
|
|
@ -38,6 +38,7 @@ import {
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import { modeType } from '../typing';
|
import { modeType } from '../typing';
|
||||||
import { useDepartmentStore } from '@/store/department';
|
import { useDepartmentStore } from '@/store/department';
|
||||||
|
import { onlyMessage } from '@/utils/comm';
|
||||||
|
|
||||||
const department = useDepartmentStore();
|
const department = useDepartmentStore();
|
||||||
const emits = defineEmits([
|
const emits = defineEmits([
|
||||||
|
@ -136,11 +137,16 @@ const save = async () => {
|
||||||
// emits('refresh');
|
// emits('refresh');
|
||||||
// });
|
// });
|
||||||
// fix: bug#10829
|
// fix: bug#10829
|
||||||
removeKeys.length && (await delOperations_api(removeKeys));
|
if(addKeys.length || removeKeys.length) {
|
||||||
const res = await addOperations_api(addKeys);
|
removeKeys.length && (await delOperations_api(removeKeys));
|
||||||
if (res.success) {
|
const res = await addOperations_api(addKeys);
|
||||||
message.success('操作成功');
|
if (res.success) {
|
||||||
emits('refresh');
|
message.success('操作成功');
|
||||||
|
emits('refresh');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onlyMessage('请选择API接口','error')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else if (props.mode === 'appManger') {
|
} else if (props.mode === 'appManger') {
|
||||||
const removeItems = removeKeys.map((key) => ({
|
const removeItems = removeKeys.map((key) => ({
|
||||||
|
|
|
@ -109,6 +109,7 @@ import {
|
||||||
USER_CENTER_MENU_CODE,
|
USER_CENTER_MENU_CODE,
|
||||||
MESSAGE_SUBSCRIBE_MENU_CODE
|
MESSAGE_SUBSCRIBE_MENU_CODE
|
||||||
} from '@/utils/consts'
|
} from '@/utils/consts'
|
||||||
|
import { isNoCommunity } from '@/utils/utils'
|
||||||
|
|
||||||
const emits = defineEmits(['update:selectItems']);
|
const emits = defineEmits(['update:selectItems']);
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
@ -117,6 +118,7 @@ const props = defineProps({
|
||||||
});
|
});
|
||||||
const treeRef = ref();
|
const treeRef = ref();
|
||||||
let { ctx: that, proxy } = getCurrentInstance();
|
let { ctx: that, proxy } = getCurrentInstance();
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '菜单权限',
|
title: '菜单权限',
|
||||||
|
@ -130,13 +132,16 @@ const columns = [
|
||||||
key: 'action',
|
key: 'action',
|
||||||
width: '260px',
|
width: '260px',
|
||||||
},
|
},
|
||||||
{
|
];
|
||||||
|
|
||||||
|
if(isNoCommunity){
|
||||||
|
columns.push({
|
||||||
title: '数据权限',
|
title: '数据权限',
|
||||||
dataIndex: 'data',
|
dataIndex: 'data',
|
||||||
key: 'data',
|
key: 'data',
|
||||||
width: '50%',
|
width: '50%',
|
||||||
},
|
})
|
||||||
];
|
}
|
||||||
const tableData = ref<tableItemType[]>([]);
|
const tableData = ref<tableItemType[]>([]);
|
||||||
|
|
||||||
// 表头-全选
|
// 表头-全选
|
||||||
|
|
|
@ -270,6 +270,7 @@ type modalType = '' | 'add' | 'edit' | 'reset';
|
||||||
|
|
||||||
const handleParams = (params: any) => {
|
const handleParams = (params: any) => {
|
||||||
const newParams = (params?.terms as any[])?.map((item1) => {
|
const newParams = (params?.terms as any[])?.map((item1) => {
|
||||||
|
let arr: any[] = []
|
||||||
item1.terms = item1.terms.map((item2: any) => {
|
item1.terms = item1.terms.map((item2: any) => {
|
||||||
if (['telephone', 'email'].includes(item2.column)) {
|
if (['telephone', 'email'].includes(item2.column)) {
|
||||||
return {
|
return {
|
||||||
|
@ -277,8 +278,27 @@ const handleParams = (params: any) => {
|
||||||
value: [item2],
|
value: [item2],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (['type'].includes(item2.column) && item2.value === 'other') {
|
||||||
|
arr = [
|
||||||
|
{
|
||||||
|
...item2,
|
||||||
|
type: 'or',
|
||||||
|
termType: 'isnull',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...item2,
|
||||||
|
type: 'or',
|
||||||
|
termType: 'empty',
|
||||||
|
value: 1,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
return item2;
|
return item2;
|
||||||
});
|
});
|
||||||
|
if(arr.length){
|
||||||
|
item1.terms = [...item1.terms, ...arr]
|
||||||
|
}
|
||||||
return item1;
|
return item1;
|
||||||
});
|
});
|
||||||
queryParams.value = { terms: newParams || [] };
|
queryParams.value = { terms: newParams || [] };
|
||||||
|
|
|
@ -3823,10 +3823,10 @@ jetlinks-store@^0.0.3:
|
||||||
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
resolved "https://registry.npmjs.org/jetlinks-store/-/jetlinks-store-0.0.3.tgz"
|
||||||
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
integrity sha512-AZf/soh1hmmwjBZ00fr1emuMEydeReaI6IBTGByQYhTmK1Zd5pQAxC7WLek2snRAn/HHDgJfVz2hjditKThl6Q==
|
||||||
|
|
||||||
jetlinks-ui-components@^1.0.13:
|
jetlinks-ui-components@^1.0.16:
|
||||||
version "1.0.13"
|
version "1.0.16"
|
||||||
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.13.tgz#9f33fe41d9c453b4db01a3d5e0a86412c13cf652"
|
resolved "https://registry.jetlinks.cn/jetlinks-ui-components/-/jetlinks-ui-components-1.0.16.tgz#bdb65385a30a121065322e5156c13080c8328080"
|
||||||
integrity sha512-50QFseYmoN1OnvwbMI735q3MlUWW8tASGScfxUKDCD4c7EBr/tgU9exdW8i++ggbjvTfa8d3Lhg+L2gggLtnUQ==
|
integrity sha512-R3oE8tpXW4oaNSCeGXRK++paNJiHYDO89Id3YqzIVX6/bWMItOWrEU6JT4iPA9uYkPTfsYHxnG5qZRloLnpiZw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@vueuse/core" "^9.12.0"
|
"@vueuse/core" "^9.12.0"
|
||||||
"@vueuse/router" "^9.13.0"
|
"@vueuse/router" "^9.13.0"
|
||||||
|
|
Loading…
Reference in New Issue