fix: 加fullpage
This commit is contained in:
parent
8239b2c308
commit
c38923f468
|
@ -57,7 +57,7 @@ import { getImage } from '@/utils/comm';
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.doc {
|
.doc {
|
||||||
height: 1000px;
|
height: 100%;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: rgba(#000, 0.8);
|
color: rgba(#000, 0.8);
|
||||||
|
|
|
@ -1,371 +1,418 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<j-card>
|
<FullPage>
|
||||||
<j-row :gutter="24">
|
<j-card>
|
||||||
<j-col :span="16">
|
<div class="box">
|
||||||
<TitleComponent data="基本信息" />
|
<div class="left">
|
||||||
<j-form
|
<div class="left-content">
|
||||||
:layout="'vertical'"
|
<TitleComponent data="基本信息" />
|
||||||
ref="formRef"
|
<j-form
|
||||||
:model="modelRef"
|
:layout="'vertical'"
|
||||||
>
|
ref="formRef"
|
||||||
<j-row :gutter="24">
|
:model="modelRef"
|
||||||
<j-col :span="24">
|
>
|
||||||
<j-form-item
|
<j-row :gutter="24">
|
||||||
label="名称"
|
<j-col :span="24">
|
||||||
name="name"
|
<j-form-item
|
||||||
:rules="[
|
label="名称"
|
||||||
{
|
name="name"
|
||||||
required: true,
|
:rules="[
|
||||||
message: '请输入名称',
|
{
|
||||||
},
|
required: true,
|
||||||
{
|
message: '请输入名称',
|
||||||
max: 64,
|
},
|
||||||
message: '最多输入64个字符',
|
{
|
||||||
},
|
max: 64,
|
||||||
]"
|
message: '最多输入64个字符',
|
||||||
>
|
},
|
||||||
<j-input
|
]"
|
||||||
placeholder="请输入名称"
|
|
||||||
v-model:value="modelRef.name"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-form-item
|
|
||||||
:name="['accessConfig', 'regionId']"
|
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请选择服务地址',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
服务地址
|
|
||||||
<j-tooltip
|
|
||||||
title="阿里云内部给每台机器设置的唯一编号"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择服务地址"
|
|
||||||
v-model:value="
|
|
||||||
modelRef.accessConfig.regionId
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
@blur="productChange"
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="item in regionsList"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
>{{ item.name }}</j-select-option
|
|
||||||
>
|
>
|
||||||
</j-select>
|
<j-input
|
||||||
</j-form-item>
|
placeholder="请输入名称"
|
||||||
</j-col>
|
v-model:value="modelRef.name"
|
||||||
<j-col :span="24">
|
/>
|
||||||
<j-form-item
|
</j-form-item>
|
||||||
:name="['accessConfig', 'instanceId']"
|
</j-col>
|
||||||
>
|
<j-col :span="24">
|
||||||
<template #label>
|
<j-form-item
|
||||||
<span>
|
:name="['accessConfig', 'regionId']"
|
||||||
实例ID
|
:rules="[
|
||||||
<j-tooltip
|
{
|
||||||
title="阿里云物联网平台中的实例ID,没有则不填"
|
required: true,
|
||||||
>
|
message: '请选择服务地址',
|
||||||
<AIcon
|
},
|
||||||
type="QuestionCircleOutlined"
|
]"
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-input
|
|
||||||
placeholder="请输入实例ID"
|
|
||||||
v-model:value="
|
|
||||||
modelRef.accessConfig.instanceId
|
|
||||||
"
|
|
||||||
@blur="productChange"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-form-item
|
|
||||||
:name="['accessConfig', 'accessKeyId']"
|
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请输入accessKey',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
max: 64,
|
|
||||||
message: '最多输入64个字符',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
accessKey
|
|
||||||
<j-tooltip
|
|
||||||
title="用于程序通知方式调用云服务API的用户标识"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-input
|
|
||||||
placeholder="请输入accessKey"
|
|
||||||
v-model:value="
|
|
||||||
modelRef.accessConfig.accessKeyId
|
|
||||||
"
|
|
||||||
@blur="productChange"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-form-item
|
|
||||||
:name="['accessConfig', 'accessSecret']"
|
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请输入accessSecret',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
max: 64,
|
|
||||||
message: '最多输入64个字符',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
accessSecret
|
|
||||||
<j-tooltip
|
|
||||||
title="用于程序通知方式调用云服务费API的秘钥标识"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-input
|
|
||||||
placeholder="请输入accessSecret"
|
|
||||||
v-model:value="
|
|
||||||
modelRef.accessConfig.accessSecret
|
|
||||||
"
|
|
||||||
@blur="productChange"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-form-item
|
|
||||||
name="bridgeProductKey"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message: '请选择网桥产品',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
网桥产品
|
|
||||||
<j-tooltip
|
|
||||||
title="物联网平台对应的阿里云产品"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择网桥产品"
|
|
||||||
v-model:value="
|
|
||||||
modelRef.bridgeProductKey
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="item in aliyunProductList"
|
|
||||||
:key="item.productKey"
|
|
||||||
:value="item.productKey"
|
|
||||||
:label="item.productName"
|
|
||||||
>{{
|
|
||||||
item.productName
|
|
||||||
}}</j-select-option
|
|
||||||
>
|
>
|
||||||
</j-select>
|
<template #label>
|
||||||
</j-form-item>
|
<span>
|
||||||
</j-col>
|
服务地址
|
||||||
<j-col :span="24">
|
<j-tooltip
|
||||||
<p>产品映射</p>
|
title="阿里云内部给每台机器设置的唯一编号"
|
||||||
<j-collapse
|
|
||||||
v-if="modelRef.mappings.length"
|
|
||||||
:activeKey="activeKey"
|
|
||||||
@change="onCollChange"
|
|
||||||
>
|
|
||||||
<j-collapse-panel
|
|
||||||
v-for="(
|
|
||||||
item, index
|
|
||||||
) in modelRef.mappings"
|
|
||||||
:key="index"
|
|
||||||
:header="
|
|
||||||
item.productKey
|
|
||||||
? (aliyunProductList.find(
|
|
||||||
(i) =>
|
|
||||||
i.productKey ===
|
|
||||||
item.productKey,
|
|
||||||
)?.productName || `产品映射${index + 1}`)
|
|
||||||
: `产品映射${index + 1}`
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #extra
|
|
||||||
><AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
@click="delItem(index)"
|
|
||||||
/></template>
|
|
||||||
<j-row :gutter="24">
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
label="阿里云产品"
|
|
||||||
:name="[
|
|
||||||
'mappings',
|
|
||||||
index,
|
|
||||||
'productKey',
|
|
||||||
]"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message:
|
|
||||||
'请选择阿里云产品',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择阿里云产品"
|
|
||||||
v-model:value="
|
|
||||||
item.productKey
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
>
|
>
|
||||||
<j-select-option
|
<AIcon
|
||||||
v-for="i in getAliyunProductList(
|
type="QuestionCircleOutlined"
|
||||||
item?.productKey || ''
|
style="
|
||||||
)"
|
margin-left: 2px;
|
||||||
:key="i.productKey"
|
|
||||||
:value="
|
|
||||||
i.productKey
|
|
||||||
"
|
"
|
||||||
:label="
|
/>
|
||||||
i.productName
|
</j-tooltip>
|
||||||
"
|
</span>
|
||||||
>{{
|
</template>
|
||||||
i.productName
|
<j-select
|
||||||
}}</j-select-option
|
placeholder="请选择服务地址"
|
||||||
>
|
v-model:value="
|
||||||
</j-select>
|
modelRef.accessConfig
|
||||||
</j-form-item>
|
.regionId
|
||||||
</j-col>
|
"
|
||||||
<j-col :span="12">
|
show-search
|
||||||
<j-form-item
|
@blur="productChange"
|
||||||
label="平台产品"
|
>
|
||||||
:name="[
|
<j-select-option
|
||||||
'mappings',
|
v-for="item in regionsList"
|
||||||
index,
|
:key="item.id"
|
||||||
'productId',
|
:value="item.id"
|
||||||
]"
|
:label="item.name"
|
||||||
:rules="{
|
>{{
|
||||||
required: true,
|
item.name
|
||||||
message:
|
}}</j-select-option
|
||||||
'请选择平台产品',
|
|
||||||
}"
|
|
||||||
>
|
>
|
||||||
<j-select
|
</j-select>
|
||||||
placeholder="请选择平台产品"
|
</j-form-item>
|
||||||
v-model:value="
|
</j-col>
|
||||||
item.productId
|
<j-col :span="24">
|
||||||
"
|
<j-form-item
|
||||||
show-search
|
:name="[
|
||||||
|
'accessConfig',
|
||||||
|
'instanceId',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
实例ID
|
||||||
|
<j-tooltip
|
||||||
|
title="阿里云物联网平台中的实例ID,没有则不填"
|
||||||
>
|
>
|
||||||
<j-select-option
|
<AIcon
|
||||||
v-for="i in getPlatProduct(
|
type="QuestionCircleOutlined"
|
||||||
item.productId || ''
|
style="
|
||||||
)"
|
margin-left: 2px;
|
||||||
:key="i.id"
|
"
|
||||||
:value="i?.id"
|
/>
|
||||||
:label="i.name"
|
</j-tooltip>
|
||||||
>{{
|
</span>
|
||||||
i.name
|
</template>
|
||||||
}}</j-select-option
|
<j-input
|
||||||
|
placeholder="请输入实例ID"
|
||||||
|
v-model:value="
|
||||||
|
modelRef.accessConfig
|
||||||
|
.instanceId
|
||||||
|
"
|
||||||
|
@blur="productChange"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-form-item
|
||||||
|
:name="[
|
||||||
|
'accessConfig',
|
||||||
|
'accessKeyId',
|
||||||
|
]"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入accessKey',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多输入64个字符',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
accessKey
|
||||||
|
<j-tooltip
|
||||||
|
title="用于程序通知方式调用云服务API的用户标识"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
style="
|
||||||
|
margin-left: 2px;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-input
|
||||||
|
placeholder="请输入accessKey"
|
||||||
|
v-model:value="
|
||||||
|
modelRef.accessConfig
|
||||||
|
.accessKeyId
|
||||||
|
"
|
||||||
|
@blur="productChange"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-form-item
|
||||||
|
:name="[
|
||||||
|
'accessConfig',
|
||||||
|
'accessSecret',
|
||||||
|
]"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请输入accessSecret',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
max: 64,
|
||||||
|
message: '最多输入64个字符',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
accessSecret
|
||||||
|
<j-tooltip
|
||||||
|
title="用于程序通知方式调用云服务费API的秘钥标识"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
style="
|
||||||
|
margin-left: 2px;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-input
|
||||||
|
placeholder="请输入accessSecret"
|
||||||
|
v-model:value="
|
||||||
|
modelRef.accessConfig
|
||||||
|
.accessSecret
|
||||||
|
"
|
||||||
|
@blur="productChange"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-form-item
|
||||||
|
name="bridgeProductKey"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message: '请选择网桥产品',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
网桥产品
|
||||||
|
<j-tooltip
|
||||||
|
title="物联网平台对应的阿里云产品"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
style="
|
||||||
|
margin-left: 2px;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择网桥产品"
|
||||||
|
v-model:value="
|
||||||
|
modelRef.bridgeProductKey
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="item in aliyunProductList"
|
||||||
|
:key="item.productKey"
|
||||||
|
:value="item.productKey"
|
||||||
|
:label="item.productName"
|
||||||
|
>{{
|
||||||
|
item.productName
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<p>产品映射</p>
|
||||||
|
<j-collapse
|
||||||
|
v-if="modelRef.mappings.length"
|
||||||
|
:activeKey="activeKey"
|
||||||
|
@change="onCollChange"
|
||||||
|
>
|
||||||
|
<j-collapse-panel
|
||||||
|
v-for="(
|
||||||
|
item, index
|
||||||
|
) in modelRef.mappings"
|
||||||
|
:key="index"
|
||||||
|
:header="
|
||||||
|
item.productKey
|
||||||
|
? aliyunProductList.find(
|
||||||
|
(i) =>
|
||||||
|
i.productKey ===
|
||||||
|
item.productKey,
|
||||||
|
)?.productName ||
|
||||||
|
`产品映射${index + 1}`
|
||||||
|
: `产品映射${index + 1}`
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #extra
|
||||||
|
><AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
@click="delItem(index)"
|
||||||
|
/></template>
|
||||||
|
<j-row :gutter="24">
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="阿里云产品"
|
||||||
|
:name="[
|
||||||
|
'mappings',
|
||||||
|
index,
|
||||||
|
'productKey',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择阿里云产品',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
</j-select>
|
<j-select
|
||||||
</j-form-item>
|
placeholder="请选择阿里云产品"
|
||||||
</j-col>
|
v-model:value="
|
||||||
</j-row>
|
item.productKey
|
||||||
</j-collapse-panel>
|
"
|
||||||
</j-collapse>
|
show-search
|
||||||
<j-card v-else>
|
>
|
||||||
<j-empty />
|
<j-select-option
|
||||||
</j-card>
|
v-for="i in getAliyunProductList(
|
||||||
</j-col>
|
item?.productKey ||
|
||||||
<j-col :span="24">
|
'',
|
||||||
<j-button
|
)"
|
||||||
type="dashed"
|
:key="
|
||||||
style="width: 100%; margin-top: 10px"
|
i.productKey
|
||||||
@click="addItem"
|
"
|
||||||
|
:value="
|
||||||
|
i.productKey
|
||||||
|
"
|
||||||
|
:label="
|
||||||
|
i.productName
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
i.productName
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="平台产品"
|
||||||
|
:name="[
|
||||||
|
'mappings',
|
||||||
|
index,
|
||||||
|
'productId',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择平台产品',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择平台产品"
|
||||||
|
v-model:value="
|
||||||
|
item.productId
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="i in getPlatProduct(
|
||||||
|
item.productId ||
|
||||||
|
'',
|
||||||
|
)"
|
||||||
|
:key="i.id"
|
||||||
|
:value="
|
||||||
|
i?.id
|
||||||
|
"
|
||||||
|
:label="
|
||||||
|
i.name
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
i.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</j-collapse-panel>
|
||||||
|
</j-collapse>
|
||||||
|
<j-card v-else>
|
||||||
|
<j-empty />
|
||||||
|
</j-card>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-button
|
||||||
|
type="dashed"
|
||||||
|
style="
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
"
|
||||||
|
@click="addItem"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="PlusOutlined"
|
||||||
|
style="margin-left: 2px"
|
||||||
|
/>添加
|
||||||
|
</j-button>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24" style="margin-top: 20px">
|
||||||
|
<j-form-item
|
||||||
|
label="说明"
|
||||||
|
name="description"
|
||||||
|
:rules="{
|
||||||
|
max: 200,
|
||||||
|
message: '最多输入200个字符',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<j-textarea
|
||||||
|
v-model:value="
|
||||||
|
modelRef.description
|
||||||
|
"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
showCount
|
||||||
|
:maxlength="200"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</j-form>
|
||||||
|
<div v-if="type === 'edit'">
|
||||||
|
<PermissionButton
|
||||||
|
type="primary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="saveBtn"
|
||||||
|
:hasPermission="[
|
||||||
|
'Northbound/AliCloud:add',
|
||||||
|
'Northbound/AliCloud:update',
|
||||||
|
]"
|
||||||
>
|
>
|
||||||
<AIcon
|
保存
|
||||||
type="PlusOutlined"
|
</PermissionButton>
|
||||||
style="margin-left: 2px"
|
</div>
|
||||||
/>添加
|
</div>
|
||||||
</j-button>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24" style="margin-top: 20px">
|
|
||||||
<j-form-item
|
|
||||||
label="说明"
|
|
||||||
name="description"
|
|
||||||
:rules="{
|
|
||||||
max: 200,
|
|
||||||
message: '最多输入200个字符',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<j-textarea
|
|
||||||
v-model:value="modelRef.description"
|
|
||||||
placeholder="请输入说明"
|
|
||||||
showCount
|
|
||||||
:maxlength="200"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</j-form>
|
|
||||||
<div v-if="type === 'edit'">
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
:loading="loading"
|
|
||||||
@click="saveBtn"
|
|
||||||
:hasPermission="['Northbound/AliCloud:add', 'Northbound/AliCloud:update']"
|
|
||||||
>
|
|
||||||
保存
|
|
||||||
</PermissionButton>
|
|
||||||
</div>
|
</div>
|
||||||
</j-col>
|
<div class="right">
|
||||||
<j-col :span="8">
|
<Doc />
|
||||||
<Doc />
|
</div>
|
||||||
</j-col>
|
</div>
|
||||||
</j-row>
|
</j-card>
|
||||||
</j-card>
|
</FullPage>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -489,14 +536,16 @@ const saveBtn = () => {
|
||||||
.validate()
|
.validate()
|
||||||
.then(async (data: any) => {
|
.then(async (data: any) => {
|
||||||
const product = (aliyunProductList.value || []).find(
|
const product = (aliyunProductList.value || []).find(
|
||||||
(item: any) =>
|
(item: any) => item?.productKey === data?.bridgeProductKey,
|
||||||
item?.productKey === data?.bridgeProductKey,
|
|
||||||
);
|
);
|
||||||
data.bridgeProductName = product?.productName || '';
|
data.bridgeProductName = product?.productName || '';
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const resp = await savePatch({...toRaw(modelRef), ...data}).finally(() => {
|
const resp = await savePatch({
|
||||||
|
...toRaw(modelRef),
|
||||||
|
...data,
|
||||||
|
}).finally(() => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
})
|
});
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
message.success('操作成功!');
|
message.success('操作成功!');
|
||||||
formRef.value.resetFields();
|
formRef.value.resetFields();
|
||||||
|
@ -539,4 +588,23 @@ watch(
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
.left {
|
||||||
|
.left-content {
|
||||||
|
width: 66%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
width: 33%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,119 +5,133 @@
|
||||||
target="northbound-aliyun"
|
target="northbound-aliyun"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
/>
|
/>
|
||||||
<JProTable
|
<FullPage>
|
||||||
ref="instanceRef"
|
<JProTable
|
||||||
:columns="columns"
|
ref="instanceRef"
|
||||||
:request="query"
|
:columns="columns"
|
||||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
:request="query"
|
||||||
:params="params"
|
:defaultParams="{
|
||||||
>
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
<template #headerTitle>
|
}"
|
||||||
<j-space>
|
:params="params"
|
||||||
<PermissionButton
|
>
|
||||||
type="primary"
|
<template #headerTitle>
|
||||||
@click="handleAdd"
|
<j-space>
|
||||||
hasPermission="Northbound/AliCloud:add"
|
<PermissionButton
|
||||||
|
type="primary"
|
||||||
|
@click="handleAdd"
|
||||||
|
hasPermission="Northbound/AliCloud:add"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon type="PlusOutlined"
|
||||||
|
/></template>
|
||||||
|
新增
|
||||||
|
</PermissionButton>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
<template #card="slotProps">
|
||||||
|
<CardBox
|
||||||
|
:value="slotProps"
|
||||||
|
@click="handleView(slotProps.id)"
|
||||||
|
:actions="getActions(slotProps, 'card')"
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:statusText="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
enabled: 'processing',
|
||||||
|
disabled: 'error',
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
<template #img>
|
||||||
新增
|
<img :src="getImage('/northbound/aliyun.png')" />
|
||||||
</PermissionButton>
|
</template>
|
||||||
</j-space>
|
<template #content>
|
||||||
</template>
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
<template #card="slotProps">
|
<span style="font-size: 16px; font-weight: 600">
|
||||||
<CardBox
|
{{ slotProps.name }}
|
||||||
:value="slotProps"
|
</span>
|
||||||
@click="handleView(slotProps.id)"
|
</Ellipsis>
|
||||||
:actions="getActions(slotProps, 'card')"
|
<j-row style="margin-top: 15px">
|
||||||
:status="slotProps.state?.value"
|
<j-col :span="12">
|
||||||
:statusText="slotProps.state?.text"
|
<div class="card-item-content-text">
|
||||||
:statusNames="{
|
网桥产品
|
||||||
enabled: 'processing',
|
|
||||||
disabled: 'error',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #img>
|
|
||||||
<img :src="getImage('/northbound/aliyun.png')" />
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
|
||||||
<span style="font-size: 16px; font-weight: 600">
|
|
||||||
{{ slotProps.name }}
|
|
||||||
</span>
|
|
||||||
</Ellipsis>
|
|
||||||
<j-row style="margin-top: 15px">
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
网桥产品
|
|
||||||
</div>
|
|
||||||
<Ellipsis>
|
|
||||||
<div>
|
|
||||||
{{ slotProps?.bridgeProductName }}
|
|
||||||
</div>
|
</div>
|
||||||
</Ellipsis>
|
<Ellipsis>
|
||||||
</j-col>
|
<div>
|
||||||
<j-col :span="12">
|
{{ slotProps?.bridgeProductName }}
|
||||||
<div class="card-item-content-text">
|
</div>
|
||||||
<label>说明</label>
|
</Ellipsis>
|
||||||
</div>
|
</j-col>
|
||||||
<Ellipsis>
|
<j-col :span="12">
|
||||||
<div>{{ slotProps?.description }}</div>
|
<div class="card-item-content-text">
|
||||||
</Ellipsis>
|
<label>说明</label>
|
||||||
</j-col>
|
</div>
|
||||||
</j-row>
|
<Ellipsis>
|
||||||
</template>
|
<div>{{ slotProps?.description }}</div>
|
||||||
<template #actions="item">
|
</Ellipsis>
|
||||||
<PermissionButton
|
</j-col>
|
||||||
:disabled="item.disabled"
|
</j-row>
|
||||||
:popConfirm="item.popConfirm"
|
</template>
|
||||||
:tooltip="item.tooltip"
|
<template #actions="item">
|
||||||
@click="item.onClick"
|
<PermissionButton
|
||||||
:hasPermission="'Northbound/AliCloud:' + item.key"
|
:disabled="item.disabled"
|
||||||
|
:popConfirm="item.popConfirm"
|
||||||
|
:tooltip="item.tooltip"
|
||||||
|
@click="item.onClick"
|
||||||
|
:hasPermission="
|
||||||
|
'Northbound/AliCloud:' + item.key
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
v-if="item.key === 'delete'"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<BadgeStatus
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
enabled: 'processing',
|
||||||
|
disabled: 'error',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space>
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
>
|
>
|
||||||
<AIcon
|
<PermissionButton
|
||||||
type="DeleteOutlined"
|
:disabled="i.disabled"
|
||||||
v-if="item.key === 'delete'"
|
:popConfirm="i.popConfirm"
|
||||||
/>
|
:tooltip="i.tooltip"
|
||||||
<template v-else>
|
style="padding: 0 5px"
|
||||||
<AIcon :type="item.icon" />
|
@click="i.onClick"
|
||||||
<span>{{ item?.text }}</span>
|
type="link"
|
||||||
</template>
|
:danger="i.key === 'delete'"
|
||||||
</PermissionButton>
|
:hasPermission="
|
||||||
</template>
|
i.key === 'view'
|
||||||
</CardBox>
|
? true
|
||||||
</template>
|
: 'Northbound/AliCloud:' + i.key
|
||||||
<template #state="slotProps">
|
"
|
||||||
<BadgeStatus
|
>
|
||||||
:status="slotProps.state?.value"
|
<template #icon
|
||||||
:text="slotProps.state?.text"
|
><AIcon :type="i.icon"
|
||||||
:statusNames="{
|
/></template>
|
||||||
enabled: 'processing',
|
</PermissionButton>
|
||||||
disabled: 'error',
|
</template>
|
||||||
}"
|
</j-space>
|
||||||
/>
|
</template>
|
||||||
</template>
|
</JProTable>
|
||||||
<template #action="slotProps">
|
</FullPage>
|
||||||
<j-space>
|
|
||||||
<template
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
:disabled="i.disabled"
|
|
||||||
:popConfirm="i.popConfirm"
|
|
||||||
:tooltip="i.tooltip"
|
|
||||||
style="padding: 0 5px"
|
|
||||||
@click="i.onClick"
|
|
||||||
type="link"
|
|
||||||
:danger="i.key === 'delete'"
|
|
||||||
:hasPermission="i.key === 'view' ? true : 'Northbound/AliCloud:' + i.key"
|
|
||||||
>
|
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
</j-space>
|
|
||||||
</template>
|
|
||||||
</JProTable>
|
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ import { getImage } from '@/utils/comm';
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.doc {
|
.doc {
|
||||||
height: 1000px;
|
height: 100%;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
color: rgba(#000, 0.8);
|
color: rgba(#000, 0.8);
|
||||||
|
|
|
@ -1,437 +1,479 @@
|
||||||
<template>
|
<template>
|
||||||
<page-container>
|
<page-container>
|
||||||
<j-card>
|
<FullPage>
|
||||||
<j-row :gutter="24">
|
<j-card>
|
||||||
<j-col :span="16">
|
<div class="box">
|
||||||
<TitleComponent data="基本信息" />
|
<div class="left">
|
||||||
<j-form
|
<div class="left-content">
|
||||||
:layout="'vertical'"
|
<TitleComponent data="基本信息" />
|
||||||
ref="formRef"
|
<j-form
|
||||||
:model="modelRef"
|
:layout="'vertical'"
|
||||||
>
|
ref="formRef"
|
||||||
<j-row :gutter="24">
|
:model="modelRef"
|
||||||
<j-col :span="24">
|
>
|
||||||
<j-form-item
|
<j-row :gutter="24">
|
||||||
label="名称"
|
<j-col :span="24">
|
||||||
name="name"
|
<j-form-item
|
||||||
:rules="[
|
label="名称"
|
||||||
{
|
name="name"
|
||||||
required: true,
|
:rules="[
|
||||||
message: '请输入名称',
|
{
|
||||||
},
|
required: true,
|
||||||
{
|
message: '请输入名称',
|
||||||
max: 64,
|
},
|
||||||
message: '最多输入64个字符',
|
{
|
||||||
},
|
max: 64,
|
||||||
|
message: '最多输入64个字符',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
placeholder="请输入名称"
|
||||||
|
v-model:value="modelRef.name"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="产品"
|
||||||
|
name="id"
|
||||||
|
:rules="[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择产品',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
:disabled="
|
||||||
|
type !== 'edit' &&
|
||||||
|
modelRef.id &&
|
||||||
|
modelRef.id !== ':id'
|
||||||
|
"
|
||||||
|
placeholder="请选择产品"
|
||||||
|
v-model:value="modelRef.id"
|
||||||
|
show-search
|
||||||
|
@change="productChange"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="item in productList"
|
||||||
|
:key="item.id"
|
||||||
|
:value="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
>{{
|
||||||
|
item.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
name="applianceType"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message: '请选择设备类型',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
设备类型
|
||||||
|
<j-tooltip
|
||||||
|
title="DuerOS平台拟定的规范"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
style="
|
||||||
|
margin-left: 2px;
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择设备类型"
|
||||||
|
v-model:value="
|
||||||
|
modelRef.applianceType
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
@change="typeChange"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="item in typeList"
|
||||||
|
:key="item.id"
|
||||||
|
:value="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
>{{
|
||||||
|
item.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
<j-form-item
|
||||||
|
name="productName"
|
||||||
|
v-show="false"
|
||||||
|
label="产品名称"
|
||||||
|
>
|
||||||
|
<j-input
|
||||||
|
v-model:value="
|
||||||
|
modelRef.productName
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<p>动作映射</p>
|
||||||
|
<j-collapse
|
||||||
|
v-if="
|
||||||
|
modelRef.actionMappings.length
|
||||||
|
"
|
||||||
|
:activeKey="actionActiveKey"
|
||||||
|
@change="onActionCollChange"
|
||||||
|
>
|
||||||
|
<j-collapse-panel
|
||||||
|
v-for="(
|
||||||
|
item, index
|
||||||
|
) in modelRef.actionMappings"
|
||||||
|
:key="index"
|
||||||
|
:header="
|
||||||
|
item.action
|
||||||
|
? getTypesActions(
|
||||||
|
item.action,
|
||||||
|
).find(
|
||||||
|
(i) =>
|
||||||
|
i.id ===
|
||||||
|
item.action,
|
||||||
|
)?.name
|
||||||
|
: `动作映射${index + 1}`
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #extra
|
||||||
|
><AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
@click="delItem(index)"
|
||||||
|
/></template>
|
||||||
|
<j-row :gutter="24">
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
:name="[
|
||||||
|
'actionMappings',
|
||||||
|
index,
|
||||||
|
'action',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择动作',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
动作
|
||||||
|
<j-tooltip
|
||||||
|
title="DuerOS平台拟定的设备类型具有的相关动作"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择动作"
|
||||||
|
v-model:value="
|
||||||
|
item.action
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="i in getTypesActions(
|
||||||
|
item.action ||
|
||||||
|
'',
|
||||||
|
)"
|
||||||
|
:key="i.id"
|
||||||
|
:value="
|
||||||
|
i.id
|
||||||
|
"
|
||||||
|
:label="
|
||||||
|
i.name
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
i.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
:name="[
|
||||||
|
'actionMappings',
|
||||||
|
index,
|
||||||
|
'actionType',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择操作',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #label>
|
||||||
|
<span>
|
||||||
|
操作
|
||||||
|
<j-tooltip
|
||||||
|
title="映射物联网平台中所选产品具备的动作"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="QuestionCircleOutlined"
|
||||||
|
/>
|
||||||
|
</j-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择操作"
|
||||||
|
v-model:value="
|
||||||
|
item.actionType
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
@change="
|
||||||
|
() =>
|
||||||
|
onActionTypeChange(
|
||||||
|
index,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
value="command"
|
||||||
|
>下发指令</j-select-option
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
value="latestData"
|
||||||
|
>获取历史数据</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col
|
||||||
|
:span="24"
|
||||||
|
v-if="item.actionType"
|
||||||
|
>
|
||||||
|
<j-form-item
|
||||||
|
:name="[
|
||||||
|
'actionMappings',
|
||||||
|
index,
|
||||||
|
'command',
|
||||||
|
]"
|
||||||
|
>
|
||||||
|
<Command
|
||||||
|
ref="command"
|
||||||
|
:metadata="
|
||||||
|
findProductMetadata
|
||||||
|
"
|
||||||
|
v-model:modelValue="
|
||||||
|
item.command
|
||||||
|
"
|
||||||
|
:actionType="
|
||||||
|
item.actionType
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</j-collapse-panel>
|
||||||
|
</j-collapse>
|
||||||
|
<j-card v-else>
|
||||||
|
<j-empty />
|
||||||
|
</j-card>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-button
|
||||||
|
type="dashed"
|
||||||
|
style="
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
"
|
||||||
|
@click="addItem"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="PlusOutlined"
|
||||||
|
style="margin-left: 2px"
|
||||||
|
/>新增动作
|
||||||
|
</j-button>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<p style="margin-top: 20px">属性映射</p>
|
||||||
|
<j-collapse
|
||||||
|
v-if="
|
||||||
|
modelRef.propertyMappings.length
|
||||||
|
"
|
||||||
|
:activeKey="propertyActiveKey"
|
||||||
|
@change="onPropertyCollChange"
|
||||||
|
>
|
||||||
|
<j-collapse-panel
|
||||||
|
v-for="(
|
||||||
|
item, index
|
||||||
|
) in modelRef.propertyMappings"
|
||||||
|
:key="index"
|
||||||
|
:header="
|
||||||
|
item.source
|
||||||
|
? getDuerOSProperties(
|
||||||
|
item.source,
|
||||||
|
).find(
|
||||||
|
(i) =>
|
||||||
|
i.id ===
|
||||||
|
item.source,
|
||||||
|
)?.name
|
||||||
|
: `属性映射${index + 1}`
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #extra
|
||||||
|
><AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
@click="
|
||||||
|
delPropertyItem(
|
||||||
|
index,
|
||||||
|
)
|
||||||
|
"
|
||||||
|
/></template>
|
||||||
|
<j-row :gutter="24">
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="DuerOS属性"
|
||||||
|
:name="[
|
||||||
|
'propertyMappings',
|
||||||
|
index,
|
||||||
|
'source',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择DuerOS属性',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择DuerOS属性"
|
||||||
|
v-model:value="
|
||||||
|
item.source
|
||||||
|
"
|
||||||
|
show-search
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="i in getDuerOSProperties(
|
||||||
|
item.source ||
|
||||||
|
'',
|
||||||
|
)"
|
||||||
|
:key="i.id"
|
||||||
|
:value="
|
||||||
|
i.id
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
i.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<j-form-item
|
||||||
|
label="平台属性"
|
||||||
|
:name="[
|
||||||
|
'propertyMappings',
|
||||||
|
index,
|
||||||
|
'target',
|
||||||
|
]"
|
||||||
|
:rules="{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请选择平台属性',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<j-select
|
||||||
|
placeholder="请选择平台属性"
|
||||||
|
v-model:value="
|
||||||
|
item.target
|
||||||
|
"
|
||||||
|
mode="tags"
|
||||||
|
show-search
|
||||||
|
>
|
||||||
|
<j-select-option
|
||||||
|
v-for="i in getProductProperties(
|
||||||
|
item.target,
|
||||||
|
)"
|
||||||
|
:key="i.id"
|
||||||
|
:value="
|
||||||
|
i.id
|
||||||
|
"
|
||||||
|
>{{
|
||||||
|
i.name
|
||||||
|
}}</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</j-collapse-panel>
|
||||||
|
</j-collapse>
|
||||||
|
<j-card v-else>
|
||||||
|
<j-empty />
|
||||||
|
</j-card>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24">
|
||||||
|
<j-button
|
||||||
|
type="dashed"
|
||||||
|
style="
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
"
|
||||||
|
@click="addPropertyItem"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="PlusOutlined"
|
||||||
|
style="margin-left: 2px"
|
||||||
|
/>新增属性
|
||||||
|
</j-button>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="24" style="margin-top: 20px">
|
||||||
|
<j-form-item
|
||||||
|
label="说明"
|
||||||
|
name="description"
|
||||||
|
:rules="{
|
||||||
|
max: 200,
|
||||||
|
message: '最多输入200个字符',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<j-textarea
|
||||||
|
v-model:value="
|
||||||
|
modelRef.description
|
||||||
|
"
|
||||||
|
placeholder="请输入说明"
|
||||||
|
showCount
|
||||||
|
:maxlength="200"
|
||||||
|
/>
|
||||||
|
</j-form-item>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</j-form>
|
||||||
|
<div v-if="type === 'edit'">
|
||||||
|
<PermissionButton
|
||||||
|
type="primary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="saveBtn"
|
||||||
|
:hasPermission="[
|
||||||
|
'Northbound/DuerOS:add',
|
||||||
|
'Northbound/DuerOS:update',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<j-input
|
保存
|
||||||
placeholder="请输入名称"
|
</PermissionButton>
|
||||||
v-model:value="modelRef.name"
|
</div>
|
||||||
/>
|
</div>
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
label="产品"
|
|
||||||
name="id"
|
|
||||||
:rules="[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: '请选择产品',
|
|
||||||
},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<j-select
|
|
||||||
:disabled="
|
|
||||||
type !== 'edit' &&
|
|
||||||
modelRef.id &&
|
|
||||||
modelRef.id !== ':id'
|
|
||||||
"
|
|
||||||
placeholder="请选择产品"
|
|
||||||
v-model:value="modelRef.id"
|
|
||||||
show-search
|
|
||||||
@change="productChange"
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="item in productList"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
>{{ item.name }}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
name="applianceType"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message: '请选择设备类型',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
设备类型
|
|
||||||
<j-tooltip
|
|
||||||
title="DuerOS平台拟定的规范"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择设备类型"
|
|
||||||
v-model:value="modelRef.applianceType"
|
|
||||||
show-search
|
|
||||||
@change="typeChange"
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="item in typeList"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.id"
|
|
||||||
:label="item.name"
|
|
||||||
>{{ item.name }}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
<j-form-item
|
|
||||||
name="productName"
|
|
||||||
v-show="false"
|
|
||||||
label="产品名称"
|
|
||||||
>
|
|
||||||
<j-input
|
|
||||||
v-model:value="modelRef.productName"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<p>动作映射</p>
|
|
||||||
<j-collapse
|
|
||||||
v-if="modelRef.actionMappings.length"
|
|
||||||
:activeKey="actionActiveKey"
|
|
||||||
@change="onActionCollChange"
|
|
||||||
>
|
|
||||||
<j-collapse-panel
|
|
||||||
v-for="(
|
|
||||||
item, index
|
|
||||||
) in modelRef.actionMappings"
|
|
||||||
:key="index"
|
|
||||||
:header="
|
|
||||||
item.action
|
|
||||||
? getTypesActions(
|
|
||||||
item.action,
|
|
||||||
).find(
|
|
||||||
(i) =>
|
|
||||||
i.id === item.action,
|
|
||||||
)?.name
|
|
||||||
: `动作映射${index + 1}`
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #extra
|
|
||||||
><AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
@click="delItem(index)"
|
|
||||||
/></template>
|
|
||||||
<j-row :gutter="24">
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
:name="[
|
|
||||||
'actionMappings',
|
|
||||||
index,
|
|
||||||
'action',
|
|
||||||
]"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message: '请选择动作',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
动作
|
|
||||||
<j-tooltip
|
|
||||||
title="DuerOS平台拟定的设备类型具有的相关动作"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择动作"
|
|
||||||
v-model:value="
|
|
||||||
item.action
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="i in getTypesActions(
|
|
||||||
item.action ||
|
|
||||||
'',
|
|
||||||
)"
|
|
||||||
:key="i.id"
|
|
||||||
:value="i.id"
|
|
||||||
:label="i.name"
|
|
||||||
>{{
|
|
||||||
i.name
|
|
||||||
}}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
:name="[
|
|
||||||
'actionMappings',
|
|
||||||
index,
|
|
||||||
'actionType',
|
|
||||||
]"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message: '请选择操作',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #label>
|
|
||||||
<span>
|
|
||||||
操作
|
|
||||||
<j-tooltip
|
|
||||||
title="映射物联网平台中所选产品具备的动作"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="QuestionCircleOutlined"
|
|
||||||
/>
|
|
||||||
</j-tooltip>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择操作"
|
|
||||||
v-model:value="
|
|
||||||
item.actionType
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
@change="
|
|
||||||
() =>
|
|
||||||
onActionTypeChange(
|
|
||||||
index,
|
|
||||||
)
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
value="command"
|
|
||||||
>下发指令</j-select-option
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
value="latestData"
|
|
||||||
>获取历史数据</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col
|
|
||||||
:span="24"
|
|
||||||
v-if="item.actionType"
|
|
||||||
>
|
|
||||||
<j-form-item
|
|
||||||
:name="[
|
|
||||||
'actionMappings',
|
|
||||||
index,
|
|
||||||
'command',
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<Command
|
|
||||||
ref="command"
|
|
||||||
:metadata="
|
|
||||||
findProductMetadata
|
|
||||||
"
|
|
||||||
v-model:modelValue="
|
|
||||||
item.command
|
|
||||||
"
|
|
||||||
:actionType="
|
|
||||||
item.actionType
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</j-collapse-panel>
|
|
||||||
</j-collapse>
|
|
||||||
<j-card v-else>
|
|
||||||
<j-empty />
|
|
||||||
</j-card>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-button
|
|
||||||
type="dashed"
|
|
||||||
style="width: 100%; margin-top: 10px"
|
|
||||||
@click="addItem"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="PlusOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>新增动作
|
|
||||||
</j-button>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<p style="margin-top: 20px">属性映射</p>
|
|
||||||
<j-collapse
|
|
||||||
v-if="modelRef.propertyMappings.length"
|
|
||||||
:activeKey="propertyActiveKey"
|
|
||||||
@change="onPropertyCollChange"
|
|
||||||
>
|
|
||||||
<j-collapse-panel
|
|
||||||
v-for="(
|
|
||||||
item, index
|
|
||||||
) in modelRef.propertyMappings"
|
|
||||||
:key="index"
|
|
||||||
:header="
|
|
||||||
item.source
|
|
||||||
? getDuerOSProperties(
|
|
||||||
item.source,
|
|
||||||
).find(
|
|
||||||
(i) =>
|
|
||||||
i.id === item.source,
|
|
||||||
)?.name
|
|
||||||
: `属性映射${index + 1}`
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<template #extra
|
|
||||||
><AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
@click="delPropertyItem(index)"
|
|
||||||
/></template>
|
|
||||||
<j-row :gutter="24">
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
label="DuerOS属性"
|
|
||||||
:name="[
|
|
||||||
'propertyMappings',
|
|
||||||
index,
|
|
||||||
'source',
|
|
||||||
]"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message:
|
|
||||||
'请选择DuerOS属性',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择DuerOS属性"
|
|
||||||
v-model:value="
|
|
||||||
item.source
|
|
||||||
"
|
|
||||||
show-search
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="i in getDuerOSProperties(
|
|
||||||
item.source ||
|
|
||||||
'',
|
|
||||||
)"
|
|
||||||
:key="i.id"
|
|
||||||
:value="i.id"
|
|
||||||
>{{
|
|
||||||
i.name
|
|
||||||
}}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<j-form-item
|
|
||||||
label="平台属性"
|
|
||||||
:name="[
|
|
||||||
'propertyMappings',
|
|
||||||
index,
|
|
||||||
'target',
|
|
||||||
]"
|
|
||||||
:rules="{
|
|
||||||
required: true,
|
|
||||||
message:
|
|
||||||
'请选择平台属性',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<j-select
|
|
||||||
placeholder="请选择平台属性"
|
|
||||||
v-model:value="
|
|
||||||
item.target
|
|
||||||
"
|
|
||||||
mode="tags"
|
|
||||||
show-search
|
|
||||||
>
|
|
||||||
<j-select-option
|
|
||||||
v-for="i in getProductProperties(
|
|
||||||
item.target,
|
|
||||||
)"
|
|
||||||
:key="i.id"
|
|
||||||
:value="i.id"
|
|
||||||
>{{
|
|
||||||
i.name
|
|
||||||
}}</j-select-option
|
|
||||||
>
|
|
||||||
</j-select>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</j-collapse-panel>
|
|
||||||
</j-collapse>
|
|
||||||
<j-card v-else>
|
|
||||||
<j-empty />
|
|
||||||
</j-card>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24">
|
|
||||||
<j-button
|
|
||||||
type="dashed"
|
|
||||||
style="width: 100%; margin-top: 10px"
|
|
||||||
@click="addPropertyItem"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="PlusOutlined"
|
|
||||||
style="margin-left: 2px"
|
|
||||||
/>新增属性
|
|
||||||
</j-button>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="24" style="margin-top: 20px">
|
|
||||||
<j-form-item
|
|
||||||
label="说明"
|
|
||||||
name="description"
|
|
||||||
:rules="{
|
|
||||||
max: 200,
|
|
||||||
message: '最多输入200个字符',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<j-textarea
|
|
||||||
v-model:value="modelRef.description"
|
|
||||||
placeholder="请输入说明"
|
|
||||||
showCount
|
|
||||||
:maxlength="200"
|
|
||||||
/>
|
|
||||||
</j-form-item>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</j-form>
|
|
||||||
<div v-if="type === 'edit'">
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
:loading="loading"
|
|
||||||
@click="saveBtn"
|
|
||||||
:hasPermission="[
|
|
||||||
'Northbound/DuerOS:add',
|
|
||||||
'Northbound/DuerOS:update',
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
保存
|
|
||||||
</PermissionButton>
|
|
||||||
</div>
|
</div>
|
||||||
</j-col>
|
<div class="right">
|
||||||
<j-col :span="8">
|
<Doc />
|
||||||
<Doc />
|
</div>
|
||||||
</j-col>
|
</div>
|
||||||
</j-row>
|
</j-card>
|
||||||
</j-card>
|
</FullPage>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -504,7 +546,7 @@ const onActionTypeChange = (_index: number) => {
|
||||||
properties: undefined,
|
properties: undefined,
|
||||||
functionId: undefined,
|
functionId: undefined,
|
||||||
inputs: [],
|
inputs: [],
|
||||||
value: undefined
|
value: undefined,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -720,4 +762,23 @@ watch(
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true, deep: true },
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.box {
|
||||||
|
position: relative;
|
||||||
|
.left {
|
||||||
|
.left-content {
|
||||||
|
width: 66%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.right {
|
||||||
|
width: 33%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,122 +5,138 @@
|
||||||
target="northbound-dueros"
|
target="northbound-dueros"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
/>
|
/>
|
||||||
<JProTable
|
<FullPage>
|
||||||
ref="instanceRef"
|
<JProTable
|
||||||
:columns="columns"
|
ref="instanceRef"
|
||||||
:request="query"
|
:columns="columns"
|
||||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
:request="query"
|
||||||
:params="params"
|
:defaultParams="{
|
||||||
>
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
<template #headerTitle>
|
}"
|
||||||
<j-space>
|
:params="params"
|
||||||
<PermissionButton
|
>
|
||||||
type="primary"
|
<template #headerTitle>
|
||||||
@click="handleAdd"
|
<j-space>
|
||||||
hasPermission="Northbound/DuerOS:add"
|
|
||||||
>
|
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
|
||||||
新增
|
|
||||||
</PermissionButton>
|
|
||||||
</j-space>
|
|
||||||
</template>
|
|
||||||
<template #card="slotProps">
|
|
||||||
<CardBox
|
|
||||||
:value="slotProps"
|
|
||||||
@click="handleView(slotProps.id)"
|
|
||||||
:actions="getActions(slotProps, 'card')"
|
|
||||||
:status="slotProps.state?.value"
|
|
||||||
:statusText="slotProps.state?.text"
|
|
||||||
:statusNames="{
|
|
||||||
enabled: 'processing',
|
|
||||||
disabled: 'error',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #img>
|
|
||||||
<img :src="getImage('/cloud/dueros.png')" />
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
|
||||||
<span style="font-size: 16px; font-weight: 600">
|
|
||||||
{{ slotProps.name }}
|
|
||||||
</span>
|
|
||||||
</Ellipsis>
|
|
||||||
<j-row style="margin-top: 15px">
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">产品</div>
|
|
||||||
<Ellipsis>
|
|
||||||
<div>{{ slotProps?.productName }}</div>
|
|
||||||
</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
设备类型
|
|
||||||
</div>
|
|
||||||
<Ellipsis>
|
|
||||||
<div>{{ slotProps?.applianceType?.text }}</div>
|
|
||||||
</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</template>
|
|
||||||
<template #actions="item">
|
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:disabled="item.disabled"
|
type="primary"
|
||||||
:popConfirm="item.popConfirm"
|
@click="handleAdd"
|
||||||
:tooltip="{
|
hasPermission="Northbound/DuerOS:add"
|
||||||
...item.tooltip,
|
|
||||||
}"
|
|
||||||
@click="item.onClick"
|
|
||||||
:hasPermission="'Northbound/DuerOS:' + item.key"
|
|
||||||
>
|
>
|
||||||
<AIcon
|
<template #icon
|
||||||
type="DeleteOutlined"
|
><AIcon type="PlusOutlined"
|
||||||
v-if="item.key === 'delete'"
|
/></template>
|
||||||
/>
|
新增
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item?.text }}</span>
|
|
||||||
</template>
|
|
||||||
</PermissionButton>
|
</PermissionButton>
|
||||||
</template>
|
</j-space>
|
||||||
</CardBox>
|
</template>
|
||||||
</template>
|
<template #card="slotProps">
|
||||||
<template #state="slotProps">
|
<CardBox
|
||||||
<BadgeStatus
|
:value="slotProps"
|
||||||
:status="slotProps.state?.value"
|
@click="handleView(slotProps.id)"
|
||||||
:text="slotProps.state?.text"
|
:actions="getActions(slotProps, 'card')"
|
||||||
:statusNames="{
|
:status="slotProps.state?.value"
|
||||||
enabled: 'processing',
|
:statusText="slotProps.state?.text"
|
||||||
disabled: 'error',
|
:statusNames="{
|
||||||
}"
|
enabled: 'processing',
|
||||||
/>
|
disabled: 'error',
|
||||||
</template>
|
}"
|
||||||
<template #applianceType="slotProps">
|
|
||||||
{{ slotProps.applianceType.text }}
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<j-space>
|
|
||||||
<template
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
>
|
>
|
||||||
<PermissionButton
|
<template #img>
|
||||||
:disabled="i.disabled"
|
<img :src="getImage('/cloud/dueros.png')" />
|
||||||
:popConfirm="i.popConfirm"
|
</template>
|
||||||
:tooltip="{
|
<template #content>
|
||||||
...i.tooltip,
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
}"
|
<span style="font-size: 16px; font-weight: 600">
|
||||||
style="padding: 0 5px"
|
{{ slotProps.name }}
|
||||||
@click="i.onClick"
|
</span>
|
||||||
type="link"
|
</Ellipsis>
|
||||||
:danger="i.key === 'delete'"
|
<j-row style="margin-top: 15px">
|
||||||
:hasPermission="i.key === 'view' ? true : 'Northbound/DuerOS:' + i.key"
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
产品
|
||||||
|
</div>
|
||||||
|
<Ellipsis>
|
||||||
|
<div>{{ slotProps?.productName }}</div>
|
||||||
|
</Ellipsis>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
设备类型
|
||||||
|
</div>
|
||||||
|
<Ellipsis>
|
||||||
|
<div>
|
||||||
|
{{ slotProps?.applianceType?.text }}
|
||||||
|
</div>
|
||||||
|
</Ellipsis>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</template>
|
||||||
|
<template #actions="item">
|
||||||
|
<PermissionButton
|
||||||
|
:disabled="item.disabled"
|
||||||
|
:popConfirm="item.popConfirm"
|
||||||
|
:tooltip="{
|
||||||
|
...item.tooltip,
|
||||||
|
}"
|
||||||
|
@click="item.onClick"
|
||||||
|
:hasPermission="'Northbound/DuerOS:' + item.key"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
v-if="item.key === 'delete'"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<BadgeStatus
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
enabled: 'processing',
|
||||||
|
disabled: 'error',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #applianceType="slotProps">
|
||||||
|
{{ slotProps.applianceType.text }}
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space>
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
>
|
>
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
<PermissionButton
|
||||||
</PermissionButton>
|
:disabled="i.disabled"
|
||||||
</template>
|
:popConfirm="i.popConfirm"
|
||||||
</j-space>
|
:tooltip="{
|
||||||
</template>
|
...i.tooltip,
|
||||||
</JProTable>
|
}"
|
||||||
|
style="padding: 0 5px"
|
||||||
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
|
:hasPermission="
|
||||||
|
i.key === 'view'
|
||||||
|
? true
|
||||||
|
: 'Northbound/DuerOS:' + i.key
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
</JProTable>
|
||||||
|
</FullPage>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -1,114 +1,113 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<SaveChild
|
||||||
<SaveChild
|
v-if="childVisible"
|
||||||
v-if="childVisible"
|
@close-child-save="closeChildSave"
|
||||||
@close-child-save="closeChildSave"
|
:childData="_current"
|
||||||
:childData="_current"
|
/>
|
||||||
|
<div v-else>
|
||||||
|
<pro-search
|
||||||
|
:columns="columns"
|
||||||
|
target="child-device"
|
||||||
|
@search="handleSearch"
|
||||||
|
class="device-child-device-search"
|
||||||
/>
|
/>
|
||||||
<div v-else>
|
<!-- <j-divider /> -->
|
||||||
<pro-search
|
<JProTable
|
||||||
:columns="columns"
|
ref="childDeviceRef"
|
||||||
target="child-device"
|
:columns="columns"
|
||||||
@search="handleSearch"
|
:request="query"
|
||||||
class="child-device-search"
|
:bodyStyle="{
|
||||||
/>
|
padding: 0
|
||||||
<JProTable
|
}"
|
||||||
ref="childDeviceRef"
|
:defaultParams="{
|
||||||
:columns="columns"
|
terms: [
|
||||||
:request="query"
|
{
|
||||||
:defaultParams="{
|
column: 'parentId',
|
||||||
terms: [
|
value: detail?.id || '',
|
||||||
{
|
termType: 'eq',
|
||||||
column: 'parentId',
|
},
|
||||||
value: detail?.id || '',
|
],
|
||||||
termType: 'eq',
|
}"
|
||||||
},
|
:rowSelection="{
|
||||||
],
|
selectedRowKeys: _selectedRowKeys,
|
||||||
}"
|
onChange: onSelectChange,
|
||||||
:rowSelection="{
|
}"
|
||||||
selectedRowKeys: _selectedRowKeys,
|
@cancelSelect="cancelSelect"
|
||||||
onChange: onSelectChange,
|
:params="params"
|
||||||
}"
|
:model="'TABLE'"
|
||||||
@cancelSelect="cancelSelect"
|
>
|
||||||
:params="params"
|
<template #rightExtraRender>
|
||||||
:model="'TABLE'"
|
<j-space>
|
||||||
>
|
<PermissionButton
|
||||||
<template #headerTitle>
|
type="primary"
|
||||||
<j-space>
|
v-if="
|
||||||
|
detail?.accessProvider === 'official-edge-gateway'
|
||||||
|
"
|
||||||
|
hasPermission="device/Instance:update"
|
||||||
|
@click="
|
||||||
|
_current = {};
|
||||||
|
childVisible = true;
|
||||||
|
"
|
||||||
|
>新增并绑定</PermissionButton
|
||||||
|
>
|
||||||
|
<PermissionButton
|
||||||
|
type="primary"
|
||||||
|
@click="visible = true"
|
||||||
|
hasPermission="device/Instance:update"
|
||||||
|
>
|
||||||
|
绑定</PermissionButton
|
||||||
|
>
|
||||||
|
<PermissionButton
|
||||||
|
type="primary"
|
||||||
|
hasPermission="device/Instance:update"
|
||||||
|
:popConfirm="{
|
||||||
|
title: '确定解绑吗?',
|
||||||
|
onConfirm: handleUnBind,
|
||||||
|
}"
|
||||||
|
>批量解除</PermissionButton
|
||||||
|
>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
<template #registryTime="slotProps">
|
||||||
|
{{
|
||||||
|
slotProps.registryTime
|
||||||
|
? moment(slotProps.registryTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<j-badge
|
||||||
|
:text="slotProps.state.text"
|
||||||
|
:status="statusMap.get(slotProps.state.value)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space :size="16">
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
|
>
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
type="primary"
|
:disabled="i.disabled"
|
||||||
v-if="
|
:popConfirm="i.popConfirm"
|
||||||
detail?.accessProvider ===
|
:tooltip="{
|
||||||
'official-edge-gateway'
|
...i.tooltip,
|
||||||
"
|
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
@click="
|
|
||||||
_current = {};
|
|
||||||
childVisible = true;
|
|
||||||
"
|
|
||||||
>新增并绑定</PermissionButton
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
@click="visible = true"
|
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
>
|
|
||||||
绑定</PermissionButton
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
type="primary"
|
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
:popConfirm="{
|
|
||||||
title: '确定解绑吗?',
|
|
||||||
onConfirm: handleUnBind,
|
|
||||||
}"
|
}"
|
||||||
>批量解除</PermissionButton
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
style="padding: 0px"
|
||||||
|
:hasPermission="'device/Instance:' + i.key"
|
||||||
>
|
>
|
||||||
</j-space>
|
<template #icon><AIcon :type="i.icon" /></template>
|
||||||
</template>
|
</PermissionButton>
|
||||||
<template #registryTime="slotProps">
|
</template>
|
||||||
{{
|
</j-space>
|
||||||
slotProps.registryTime
|
</template>
|
||||||
? moment(slotProps.registryTime).format(
|
</JProTable>
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
<BindChildDevice v-if="visible" @change="closeBindDevice" />
|
||||||
)
|
</div>
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</template>
|
|
||||||
<template #state="slotProps">
|
|
||||||
<j-badge
|
|
||||||
:text="slotProps.state.text"
|
|
||||||
:status="statusMap.get(slotProps.state.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<j-space :size="16">
|
|
||||||
<template
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
>
|
|
||||||
<PermissionButton
|
|
||||||
:disabled="i.disabled"
|
|
||||||
:popConfirm="i.popConfirm"
|
|
||||||
:tooltip="{
|
|
||||||
...i.tooltip,
|
|
||||||
}"
|
|
||||||
@click="i.onClick"
|
|
||||||
type="link"
|
|
||||||
style="padding: 0px"
|
|
||||||
:hasPermission="'device/Instance:' + i.key"
|
|
||||||
>
|
|
||||||
<template #icon
|
|
||||||
><AIcon :type="i.icon"
|
|
||||||
/></template>
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
</j-space>
|
|
||||||
</template>
|
|
||||||
</JProTable>
|
|
||||||
<BindChildDevice v-if="visible" @change="closeBindDevice" />
|
|
||||||
</div>
|
|
||||||
</j-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -147,10 +146,10 @@ const columns = [
|
||||||
dataIndex: 'id',
|
dataIndex: 'id',
|
||||||
key: 'id',
|
key: 'id',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
search:{
|
search: {
|
||||||
type:'string',
|
type: 'string',
|
||||||
defaultTermType: 'eq'
|
defaultTermType: 'eq',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '设备名称',
|
title: '设备名称',
|
||||||
|
@ -303,12 +302,8 @@ const closeChildSave = () => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style lang="less">
|
||||||
.child-device-search {
|
.device-child-device-search {
|
||||||
border-bottom: 1px solid #f0f0f0;
|
padding: 0px;
|
||||||
}
|
|
||||||
|
|
||||||
:deep(._jtable-body_1eyxz_1 ._jtable-body-header_1eyxz_6) {
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,96 +1,84 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<div class="diagnose">
|
||||||
<div class="diagnose">
|
<div
|
||||||
<div
|
class="diagnose-header"
|
||||||
class="diagnose-header"
|
:style="{ background: headerColorMap.get(topState) }"
|
||||||
:style="{ background: headerColorMap.get(topState) }"
|
>
|
||||||
>
|
<div class="diagnose-top">
|
||||||
<div class="diagnose-top">
|
<div class="diagnose-img">
|
||||||
<div class="diagnose-img">
|
<div
|
||||||
<div
|
v-if="topState === 'loading'"
|
||||||
v-if="topState === 'loading'"
|
style="width: 100%; height: 100%; position: relative"
|
||||||
style="
|
>
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: relative;
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
:src="headerImgMap.get(topState)"
|
|
||||||
style="
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 2;
|
|
||||||
"
|
|
||||||
/>
|
|
||||||
<img
|
|
||||||
:src="getImage('/diagnose/loading-1.png')"
|
|
||||||
class="diagnose-loading"
|
|
||||||
style="height: 100%"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<img
|
<img
|
||||||
v-else
|
|
||||||
:src="headerImgMap.get(topState)"
|
:src="headerImgMap.get(topState)"
|
||||||
|
style="height: 100%; position: absolute; z-index: 2"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
:src="getImage('/diagnose/loading-1.png')"
|
||||||
|
class="diagnose-loading"
|
||||||
style="height: 100%"
|
style="height: 100%"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="diagnose-text">
|
<img
|
||||||
<div class="diagnose-title">
|
v-else
|
||||||
{{ headerTitleMap.get(topState) }}
|
:src="headerImgMap.get(topState)"
|
||||||
</div>
|
style="height: 100%"
|
||||||
<div class="diagnose-desc">
|
|
||||||
<template v-if="topState !== 'loading'">{{
|
|
||||||
headerDescMap.get(topState)
|
|
||||||
}}</template>
|
|
||||||
<template v-else>已诊断{{ count }}个</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="diagnose-progress">
|
|
||||||
<j-progress
|
|
||||||
:percent="percent"
|
|
||||||
:showInfo="false"
|
|
||||||
size="small"
|
|
||||||
:strokeColor="progressMap.get(topState)"
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="diagnose-radio">
|
<div class="diagnose-text">
|
||||||
<div
|
<div class="diagnose-title">
|
||||||
class="diagnose-radio-item"
|
{{ headerTitleMap.get(topState) }}
|
||||||
:class="
|
</div>
|
||||||
item.key === 'message' && topState !== 'success'
|
<div class="diagnose-desc">
|
||||||
? 'disabled'
|
<template v-if="topState !== 'loading'">{{
|
||||||
: ''
|
headerDescMap.get(topState)
|
||||||
"
|
}}</template>
|
||||||
v-for="item in tabList"
|
<template v-else>已诊断{{ count }}个</template>
|
||||||
:key="item.key"
|
|
||||||
:style="
|
|
||||||
activeKey === item.key ? { ...activeStyle } : {}
|
|
||||||
"
|
|
||||||
@click="onTabChange(item.key)"
|
|
||||||
>
|
|
||||||
{{ item.text }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="diagnose-progress">
|
||||||
<template v-if="!first">
|
<j-progress
|
||||||
<Message v-show="activeKey === 'message'" />
|
:percent="percent"
|
||||||
</template>
|
:showInfo="false"
|
||||||
<template v-if="flag">
|
size="small"
|
||||||
<Status
|
:strokeColor="progressMap.get(topState)"
|
||||||
v-show="activeKey !== 'message'"
|
style="width: 100%"
|
||||||
:providerType="providerType"
|
/>
|
||||||
@countChange="countChange"
|
</div>
|
||||||
@percentChange="percentChange"
|
<div class="diagnose-radio">
|
||||||
@stateChange="stateChange"
|
<div
|
||||||
/>
|
class="diagnose-radio-item"
|
||||||
</template>
|
:class="
|
||||||
|
item.key === 'message' && topState !== 'success'
|
||||||
|
? 'disabled'
|
||||||
|
: ''
|
||||||
|
"
|
||||||
|
v-for="item in tabList"
|
||||||
|
:key="item.key"
|
||||||
|
:style="activeKey === item.key ? { ...activeStyle } : {}"
|
||||||
|
@click="onTabChange(item.key)"
|
||||||
|
>
|
||||||
|
{{ item.text }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</j-card>
|
<div>
|
||||||
|
<template v-if="!first">
|
||||||
|
<Message v-show="activeKey === 'message'" />
|
||||||
|
</template>
|
||||||
|
<template v-if="flag">
|
||||||
|
<Status
|
||||||
|
v-show="activeKey !== 'message'"
|
||||||
|
:providerType="providerType"
|
||||||
|
@countChange="countChange"
|
||||||
|
@percentChange="percentChange"
|
||||||
|
@stateChange="stateChange"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -160,7 +148,7 @@ const countChange = (num: number) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = () => {
|
const init = () => {
|
||||||
flag.value = true
|
flag.value = true;
|
||||||
activeKey.value = 'status';
|
activeKey.value = 'status';
|
||||||
const provider = instanceStore.current?.accessProvider;
|
const provider = instanceStore.current?.accessProvider;
|
||||||
if (provider === 'fixed-media' || provider === 'gb28181-2016') {
|
if (provider === 'fixed-media' || provider === 'gb28181-2016') {
|
||||||
|
@ -175,16 +163,16 @@ const init = () => {
|
||||||
providerType.value = 'network';
|
providerType.value = 'network';
|
||||||
}
|
}
|
||||||
topState.value = 'loading';
|
topState.value = 'loading';
|
||||||
}
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
init()
|
init();
|
||||||
}, 500)
|
}, 500);
|
||||||
});
|
});
|
||||||
|
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
flag.value = false
|
flag.value = false;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
||||||
<j-card>
|
<j-card :bordered="false" style="padding: 0">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<j-space>
|
<j-space>
|
||||||
<j-button @click="visible = true">批量映射</j-button>
|
<j-button @click="visible = true">批量映射</j-button>
|
||||||
|
@ -188,7 +188,7 @@
|
||||||
:edgeId="instanceStore.current.parentId"
|
:edgeId="instanceStore.current.parentId"
|
||||||
/>
|
/>
|
||||||
</j-spin>
|
</j-spin>
|
||||||
<j-card v-else>
|
<j-card v-else :bordered="false" style="padding: 0">
|
||||||
<JEmpty description="暂无数据,请配置物模型" style="margin: 10% 0" />
|
<JEmpty description="暂无数据,请配置物模型" style="margin: 10% 0" />
|
||||||
</j-card>
|
</j-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,23 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<j-empty
|
||||||
<j-empty
|
v-if="!metadata || (metadata && !metadata.functions.length)"
|
||||||
v-if="!metadata || (metadata && !metadata.functions.length)"
|
style="margin-top: 50px"
|
||||||
style="margin-top: 50px"
|
>
|
||||||
>
|
<template #description>
|
||||||
<template #description>
|
请配置对应产品的
|
||||||
请配置对应产品的
|
<!-- <a @click="emits('onJump', 'Metadata')">物模型属性功能</a> -->
|
||||||
<!-- <a @click="emits('onJump', 'Metadata')">物模型属性功能</a> -->
|
<a @click="onJump">物模型属性功能</a>
|
||||||
<a @click="onJump">物模型属性功能</a>
|
|
||||||
</template>
|
|
||||||
</j-empty>
|
|
||||||
<template v-else>
|
|
||||||
<j-tabs v-model:activeKey="activeKey">
|
|
||||||
<j-tab-pane key="Simple" tab="精简模式" />
|
|
||||||
<j-tab-pane key="Advance" tab="高级模式" />
|
|
||||||
</j-tabs>
|
|
||||||
<component :is="tabs[activeKey]" />
|
|
||||||
</template>
|
</template>
|
||||||
</j-card>
|
</j-empty>
|
||||||
|
<template v-else>
|
||||||
|
<j-tabs v-model:activeKey="activeKey">
|
||||||
|
<j-tab-pane key="Simple" tab="精简模式" />
|
||||||
|
<j-tab-pane key="Advance" tab="高级模式" />
|
||||||
|
</j-tabs>
|
||||||
|
<component :is="tabs[activeKey]" />
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
|
@ -1,90 +1,88 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<j-descriptions bordered>
|
||||||
<j-descriptions bordered>
|
<template #title>
|
||||||
<template #title>
|
设备信息
|
||||||
设备信息
|
<PermissionButton
|
||||||
<PermissionButton
|
type="link"
|
||||||
type="link"
|
@click="visible = true"
|
||||||
@click="visible = true"
|
hasPermission="device/Instance:update"
|
||||||
hasPermission="device/Instance:update"
|
|
||||||
>
|
|
||||||
<template #icon><AIcon type="EditOutlined" /></template>
|
|
||||||
编辑
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
<j-descriptions-item label="设备ID">{{
|
|
||||||
instanceStore.current?.id
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="产品名称">{{
|
|
||||||
instanceStore.current?.productName
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="产品分类">{{
|
|
||||||
instanceStore.current?.classifiedName
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="设备类型">{{
|
|
||||||
instanceStore.current?.deviceType?.text
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="固件版本">{{
|
|
||||||
instanceStore.current?.firmwareInfo?.version
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="连接协议">{{
|
|
||||||
instanceStore.current?.transport
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="消息协议">{{
|
|
||||||
instanceStore.current?.protocolName
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="创建时间">{{
|
|
||||||
instanceStore.current?.createTime
|
|
||||||
? moment(instanceStore.current?.createTime).format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)
|
|
||||||
: ''
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="注册时间">{{
|
|
||||||
instanceStore.current?.registerTime
|
|
||||||
? moment(instanceStore.current?.registerTime).format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)
|
|
||||||
: ''
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item label="最后上线时间">{{
|
|
||||||
instanceStore.current?.onlineTime
|
|
||||||
? moment(instanceStore.current?.onlineTime).format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
|
||||||
)
|
|
||||||
: ''
|
|
||||||
}}</j-descriptions-item>
|
|
||||||
<j-descriptions-item
|
|
||||||
label="父设备"
|
|
||||||
v-if="
|
|
||||||
instanceStore.current?.deviceType?.value === 'childrenDevice'
|
|
||||||
"
|
|
||||||
>{{ instanceStore.current?.parentId }}</j-descriptions-item
|
|
||||||
>
|
>
|
||||||
<j-descriptions-item label="说明">{{
|
<template #icon><AIcon type="EditOutlined" /></template>
|
||||||
instanceStore.current?.description
|
编辑
|
||||||
}}</j-descriptions-item>
|
</PermissionButton>
|
||||||
</j-descriptions>
|
</template>
|
||||||
<Config />
|
<j-descriptions-item label="设备ID">{{
|
||||||
<Tags
|
instanceStore.current?.id
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="产品名称">{{
|
||||||
|
instanceStore.current?.productName
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="产品分类">{{
|
||||||
|
instanceStore.current?.classifiedName
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="设备类型">{{
|
||||||
|
instanceStore.current?.deviceType?.text
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="固件版本">{{
|
||||||
|
instanceStore.current?.firmwareInfo?.version
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="连接协议">{{
|
||||||
|
instanceStore.current?.transport
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="消息协议">{{
|
||||||
|
instanceStore.current?.protocolName
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="创建时间">{{
|
||||||
|
instanceStore.current?.createTime
|
||||||
|
? moment(instanceStore.current?.createTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="注册时间">{{
|
||||||
|
instanceStore.current?.registerTime
|
||||||
|
? moment(instanceStore.current?.registerTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item label="最后上线时间">{{
|
||||||
|
instanceStore.current?.onlineTime
|
||||||
|
? moment(instanceStore.current?.onlineTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}</j-descriptions-item>
|
||||||
|
<j-descriptions-item
|
||||||
|
label="父设备"
|
||||||
v-if="
|
v-if="
|
||||||
instanceStore.current?.tags &&
|
instanceStore.current?.deviceType?.value === 'childrenDevice'
|
||||||
instanceStore.current?.tags.length > 0
|
|
||||||
"
|
"
|
||||||
/>
|
>{{ instanceStore.current?.parentId }}</j-descriptions-item
|
||||||
<Relation
|
>
|
||||||
v-if="
|
<j-descriptions-item label="说明">{{
|
||||||
instanceStore.current?.relations &&
|
instanceStore.current?.description
|
||||||
instanceStore.current?.relations.length > 0
|
}}</j-descriptions-item>
|
||||||
"
|
</j-descriptions>
|
||||||
/>
|
<Config />
|
||||||
<Save
|
<Tags
|
||||||
v-if="visible"
|
v-if="
|
||||||
:data="instanceStore.current"
|
instanceStore.current?.tags &&
|
||||||
@close="visible = false"
|
instanceStore.current?.tags.length > 0
|
||||||
@save="saveBtn"
|
"
|
||||||
/>
|
/>
|
||||||
</j-card>
|
<Relation
|
||||||
|
v-if="
|
||||||
|
instanceStore.current?.relations &&
|
||||||
|
instanceStore.current?.relations.length > 0
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<Save
|
||||||
|
v-if="visible"
|
||||||
|
:data="instanceStore.current"
|
||||||
|
@close="visible = false"
|
||||||
|
@save="saveBtn"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
|
|
@ -1,51 +1,47 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<pro-search
|
||||||
<pro-search
|
:columns="columns"
|
||||||
:columns="columns"
|
target="device-instance-log"
|
||||||
target="device-instance-log"
|
@search="handleSearch"
|
||||||
@search="handleSearch"
|
type="simple"
|
||||||
type="simple"
|
class="device-log-search"
|
||||||
class="search"
|
/>
|
||||||
/>
|
<JProTable
|
||||||
<JProTable
|
ref="instanceRefLog"
|
||||||
ref="instanceRefLog"
|
:columns="columns"
|
||||||
:columns="columns"
|
:request="(e: Record<string, any>) => queryLog(instanceStore.current.id, e)"
|
||||||
:request="(e: Record<string, any>) => queryLog(instanceStore.current.id, e)"
|
model="TABLE"
|
||||||
model="TABLE"
|
:defaultParams="{ sorts: [{ name: 'timestamp', order: 'desc' }] }"
|
||||||
:defaultParams="{ sorts: [{ name: 'timestamp', order: 'desc' }] }"
|
:params="params"
|
||||||
:params="params"
|
:bodyStyle="{ padding: 0 }"
|
||||||
:bodyStyle="{ padding: 0 }"
|
>
|
||||||
>
|
<template #type="slotProps">
|
||||||
<template #type="slotProps">
|
{{ slotProps?.type?.text }}
|
||||||
{{ slotProps?.type?.text }}
|
</template>
|
||||||
</template>
|
<template #timestamp="slotProps">
|
||||||
<template #timestamp="slotProps">
|
{{
|
||||||
{{
|
slotProps.timestamp
|
||||||
slotProps.timestamp
|
? moment(slotProps.timestamp).format('YYYY-MM-DD HH:mm:ss')
|
||||||
? moment(slotProps.timestamp).format(
|
: ''
|
||||||
'YYYY-MM-DD HH:mm:ss',
|
}}
|
||||||
)
|
</template>
|
||||||
: ''
|
<template #action="slotProps">
|
||||||
}}
|
<j-space>
|
||||||
</template>
|
<template
|
||||||
<template #action="slotProps">
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
<j-space>
|
:key="i.key"
|
||||||
<template
|
>
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
<j-button
|
||||||
:key="i.key"
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
style="padding: 0px"
|
||||||
>
|
>
|
||||||
<j-button
|
<template #icon><AIcon :type="i.icon" /></template>
|
||||||
@click="i.onClick"
|
</j-button>
|
||||||
type="link"
|
</template>
|
||||||
style="padding: 0px"
|
</j-space>
|
||||||
>
|
</template>
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
</JProTable>
|
||||||
</j-button>
|
|
||||||
</template>
|
|
||||||
</j-space>
|
|
||||||
</template>
|
|
||||||
</JProTable>
|
|
||||||
</j-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -125,11 +121,7 @@ const getActions = (
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
let content = '';
|
let content = '';
|
||||||
try {
|
try {
|
||||||
content = JSON.stringify(
|
content = JSON.stringify(JSON.parse(data.content), null, 2);
|
||||||
JSON.parse(data.content),
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
content = data.content;
|
content = data.content;
|
||||||
}
|
}
|
||||||
|
@ -139,7 +131,7 @@ const getActions = (
|
||||||
content: h(Textarea, {
|
content: h(Textarea, {
|
||||||
bordered: false,
|
bordered: false,
|
||||||
rows: 15,
|
rows: 15,
|
||||||
value: content
|
value: content,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -152,8 +144,8 @@ const handleSearch = (_params: any) => {
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less">
|
||||||
.search {
|
.device-log-search {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
|
@ -1,187 +1,262 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<div>
|
||||||
<div>
|
<div class="top">
|
||||||
<div class="top">
|
<div class="top-left">
|
||||||
<div class="top-left">
|
<div>
|
||||||
<div>
|
<AIcon type="ExclamationCircleOutlined" />
|
||||||
<AIcon type="ExclamationCircleOutlined" />
|
<template v-if="topTitle === 'rest'">
|
||||||
<template v-if="topTitle === 'rest'">
|
当前数据解析内容已脱离产品影响,
|
||||||
当前数据解析内容已脱离产品影响,
|
<PermissionButton
|
||||||
<PermissionButton type="link" hasPermission="device/Instance:update" @click="rest()">
|
type="link"
|
||||||
重置
|
hasPermission="device/Instance:update"
|
||||||
</PermissionButton>
|
@click="rest()"
|
||||||
后将继承产品数据解析内容
|
>
|
||||||
|
重置
|
||||||
|
</PermissionButton>
|
||||||
|
后将继承产品数据解析内容
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
当前数据解析内容继承自产品,
|
||||||
|
<PermissionButton
|
||||||
|
type="link"
|
||||||
|
hasPermission="device/Instance:update"
|
||||||
|
@click="readOnly = false"
|
||||||
|
:style="color"
|
||||||
|
>
|
||||||
|
修改
|
||||||
|
</PermissionButton>
|
||||||
|
后将脱离产品影响。
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
脚本语言:
|
||||||
|
<j-select
|
||||||
|
:defaultValue="'JavaScript'"
|
||||||
|
style="width: 200px; margin-left: 5px"
|
||||||
|
>
|
||||||
|
<j-select-option value="JavaScript"
|
||||||
|
>JavaScript(ECMAScript 5)</j-select-option
|
||||||
|
>
|
||||||
|
</j-select>
|
||||||
|
<AIcon
|
||||||
|
type="ExpandOutlined"
|
||||||
|
style="margin-left: 20px"
|
||||||
|
@click="toggle"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="edit" ref="el">
|
||||||
|
<div
|
||||||
|
v-show="readOnly"
|
||||||
|
class="edit-only"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
message.warning({
|
||||||
|
key: 1,
|
||||||
|
content: () => '请点击上方修改字样,用以编辑脚本',
|
||||||
|
style: {
|
||||||
|
marginTop: '260px',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
></div>
|
||||||
|
<j-monaco-editor
|
||||||
|
language="javascript"
|
||||||
|
style="height: 100%"
|
||||||
|
theme="vs"
|
||||||
|
v-model:modelValue="editorValue"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="bottom">
|
||||||
|
<div style="width: 49.5%">
|
||||||
|
<div class="bottom-title">
|
||||||
|
<div class="bottom-title-text">模拟输入</div>
|
||||||
|
<div class="bottom-title-topic">
|
||||||
|
<template
|
||||||
|
v-if="instanceStore.current.transport === 'MQTT'"
|
||||||
|
>
|
||||||
|
<div style="margin-right: 5px">Topic:</div>
|
||||||
|
<j-auto-complete
|
||||||
|
placeholder="请输入Topic"
|
||||||
|
style="width: 300px"
|
||||||
|
:options="topicList"
|
||||||
|
:allowClear="true"
|
||||||
|
:filterOption="filterOption"
|
||||||
|
v-model:value="topic"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
当前数据解析内容继承自产品,
|
<div style="margin-right: 5px">URL:</div>
|
||||||
<PermissionButton type="link" hasPermission="device/Instance:update" @click="readOnly = false"
|
<j-input
|
||||||
:style="color">
|
placeholder="请输入URL"
|
||||||
修改
|
v-model:value="url"
|
||||||
</PermissionButton>
|
style="width: 300px"
|
||||||
后将脱离产品影响。
|
></j-input>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<j-textarea
|
||||||
脚本语言:
|
:rows="5"
|
||||||
<j-select :defaultValue="'JavaScript'" style="width: 200px;margin-left: 5px;">
|
placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串"
|
||||||
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option>
|
style="margin-top: 10px"
|
||||||
</j-select>
|
v-model:value="simulation"
|
||||||
<AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" />
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="edit" ref="el">
|
<div style="width: 49.5%">
|
||||||
<div v-show="readOnly" class="edit-only" @click="() => {
|
<div class="bottom-title">
|
||||||
message.warning({
|
<div class="bottom-title-text">运行结果</div>
|
||||||
key: 1,
|
|
||||||
content: () => '请点击上方修改字样,用以编辑脚本',
|
|
||||||
style: {
|
|
||||||
marginTop: '260px'
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}"></div>
|
|
||||||
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
|
||||||
</div>
|
|
||||||
<div class="bottom">
|
|
||||||
<div style="width: 49.5%;">
|
|
||||||
<div class="bottom-title">
|
|
||||||
<div class="bottom-title-text">模拟输入</div>
|
|
||||||
<div class="bottom-title-topic">
|
|
||||||
<template v-if="instanceStore.current.transport === 'MQTT'">
|
|
||||||
<div style="margin-right: 5px;">Topic:</div>
|
|
||||||
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
|
||||||
:allowClear="true" :filterOption="filterOption" v-model:value="topic" />
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<div style="margin-right: 5px;">URL:</div>
|
|
||||||
<j-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></j-input>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<j-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串" style="margin-top: 10px;"
|
|
||||||
v-model:value="simulation" />
|
|
||||||
</div>
|
|
||||||
<div style="width: 49.5%;">
|
|
||||||
<div class="bottom-title">
|
|
||||||
<div class="bottom-title-text">运行结果</div>
|
|
||||||
</div>
|
|
||||||
<j-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<j-textarea
|
||||||
|
:autoSize="{ minRows: 5 }"
|
||||||
|
:style="resStyle"
|
||||||
|
v-model:value="result"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 10px;margin-left: 10px;">
|
</div>
|
||||||
<PermissionButton type="primary" hasPermission="device/Instance:update" :loading="loading"
|
<div style="margin-top: 10px; margin-left: 10px">
|
||||||
:disabled="isDisabled" @click="debug()" :tooltip="{
|
<PermissionButton
|
||||||
title: '需输入脚本和模拟数据后再点击',
|
type="primary"
|
||||||
}">
|
hasPermission="device/Instance:update"
|
||||||
调试
|
:loading="loading"
|
||||||
</PermissionButton>
|
:disabled="isDisabled"
|
||||||
<PermissionButton hasPermission="device/Instance:update" :loading="loading" :disabled="!isTest" @click="save()"
|
@click="debug()"
|
||||||
:style="{ marginLeft: '10px' }" :tooltip="{
|
:tooltip="{
|
||||||
title: isTest ? '' : '请先调试',
|
title: '需输入脚本和模拟数据后再点击',
|
||||||
}">
|
}"
|
||||||
保存
|
>
|
||||||
</PermissionButton>
|
调试
|
||||||
</div>
|
</PermissionButton>
|
||||||
</j-card>
|
<PermissionButton
|
||||||
|
hasPermission="device/Instance:update"
|
||||||
|
:loading="loading"
|
||||||
|
:disabled="!isTest"
|
||||||
|
@click="save()"
|
||||||
|
:style="{ marginLeft: '10px' }"
|
||||||
|
:tooltip="{
|
||||||
|
title: isTest ? '' : '请先调试',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
保存
|
||||||
|
</PermissionButton>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang='ts' name="Parsing">
|
<script setup lang='ts' name="Parsing">
|
||||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||||
// import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
// import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||||
import { useFullscreen } from '@vueuse/core'
|
import { useFullscreen } from '@vueuse/core';
|
||||||
import { useInstanceStore } from '@/store/instance';
|
import { useInstanceStore } from '@/store/instance';
|
||||||
import {
|
import {
|
||||||
deviceCode,
|
deviceCode,
|
||||||
getProtocal,
|
getProtocal,
|
||||||
testCode,
|
testCode,
|
||||||
saveDeviceCode,
|
saveDeviceCode,
|
||||||
delDeviceCode
|
delDeviceCode,
|
||||||
} from '@/api/device/instance'
|
} from '@/api/device/instance';
|
||||||
import { message } from 'jetlinks-ui-components';
|
import { message } from 'jetlinks-ui-components';
|
||||||
import { isBoolean } from 'lodash';
|
import { isBoolean } from 'lodash';
|
||||||
|
|
||||||
const defaultValue =
|
const defaultValue =
|
||||||
'//解码函数\r\nfunction decode(context) {\r\n //原始报文\r\n var buffer = context.payload();\r\n // 转为json\r\n // var json = context.json();\r\n //mqtt 时通过此方法获取topic\r\n // var topic = context.topic();\r\n\r\n // 提取变量\r\n // var topicVars = context.pathVars("/{deviceId}/**",topic)\r\n //温度属性\r\n var temperature = buffer.getShort(3) * 10;\r\n //湿度属性\r\n var humidity = buffer.getShort(6) * 10;\r\n return {\r\n "temperature": temperature,\r\n "humidity": humidity\r\n };\r\n}\r\n';
|
'//解码函数\r\nfunction decode(context) {\r\n //原始报文\r\n var buffer = context.payload();\r\n // 转为json\r\n // var json = context.json();\r\n //mqtt 时通过此方法获取topic\r\n // var topic = context.topic();\r\n\r\n // 提取变量\r\n // var topicVars = context.pathVars("/{deviceId}/**",topic)\r\n //温度属性\r\n var temperature = buffer.getShort(3) * 10;\r\n //湿度属性\r\n var humidity = buffer.getShort(6) * 10;\r\n return {\r\n "temperature": temperature,\r\n "humidity": humidity\r\n };\r\n}\r\n';
|
||||||
|
|
||||||
const el = ref<HTMLElement | null>(null)
|
const el = ref<HTMLElement | null>(null);
|
||||||
const { toggle } = useFullscreen(el)
|
const { toggle } = useFullscreen(el);
|
||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
|
|
||||||
|
const topTitle = ref<string>('');
|
||||||
const topTitle = ref<string>('')
|
const readOnly = ref<boolean>(true);
|
||||||
const readOnly = ref<boolean>(true)
|
const url = ref<string>('');
|
||||||
const url = ref<string>('')
|
const topic = ref<string>('');
|
||||||
const topic = ref<string>('')
|
const topicList = ref([]);
|
||||||
const topicList = ref([])
|
const simulation = ref<string>('');
|
||||||
const simulation = ref<string>('')
|
const resultValue = ref<any>({});
|
||||||
const resultValue = ref<any>({})
|
const loading = ref<boolean>(false);
|
||||||
const loading = ref<boolean>(false)
|
const isTest = ref<boolean>(false);
|
||||||
const isTest = ref<boolean>(false)
|
const editorValue = ref<string>('');
|
||||||
const editorValue = ref<string>('')
|
|
||||||
|
|
||||||
const color = computed(() => ({
|
const color = computed(() => ({
|
||||||
color: readOnly.value ? '#415ed1' : '#a6a6a6'
|
color: readOnly.value ? '#415ed1' : '#a6a6a6',
|
||||||
}))
|
}));
|
||||||
const resStyle = computed(() => (isBoolean(resultValue.value.success) ? {
|
const resStyle = computed(() =>
|
||||||
'margin-top': '10px',
|
isBoolean(resultValue.value.success)
|
||||||
'border-color': resultValue.value.success ? 'green' : 'red'
|
? {
|
||||||
} : {
|
'margin-top': '10px',
|
||||||
'margin-top': '10px',
|
'border-color': resultValue.value.success ? 'green' : 'red',
|
||||||
}))
|
}
|
||||||
const filterOption = (inputValue: any, option: any) => option!.value.indexOf(inputValue) !== -1
|
: {
|
||||||
|
'margin-top': '10px',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const filterOption = (inputValue: any, option: any) =>
|
||||||
|
option!.value.indexOf(inputValue) !== -1;
|
||||||
|
|
||||||
const isDisabled = computed(() => simulation.value === '')
|
const isDisabled = computed(() => simulation.value === '');
|
||||||
|
|
||||||
const result = computed(() => resultValue.value.success ? JSON.stringify(resultValue.value.outputs?.[0]) : resultValue.value.reason)
|
const result = computed(() =>
|
||||||
|
resultValue.value.success
|
||||||
|
? JSON.stringify(resultValue.value.outputs?.[0])
|
||||||
|
: resultValue.value.reason,
|
||||||
|
);
|
||||||
|
|
||||||
//重置
|
//重置
|
||||||
const rest = async () => {
|
const rest = async () => {
|
||||||
const res = await delDeviceCode(instanceStore.current.productId, instanceStore.current.id)
|
const res = await delDeviceCode(
|
||||||
|
instanceStore.current.productId,
|
||||||
|
instanceStore.current.id,
|
||||||
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
getDeviceCode();
|
getDeviceCode();
|
||||||
message.success('操作成功')
|
message.success('操作成功');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//获取topic
|
//获取topic
|
||||||
const getTopic = async () => {
|
const getTopic = async () => {
|
||||||
const res: any = await getProtocal(instanceStore.current.protocol, instanceStore.current.transport)
|
const res: any = await getProtocal(
|
||||||
|
instanceStore.current.protocol,
|
||||||
|
instanceStore.current.transport,
|
||||||
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const item = res.result.routes?.map((items: any) => ({
|
const item = res.result.routes?.map((items: any) => ({
|
||||||
value: items.topic,
|
value: items.topic,
|
||||||
}));
|
}));
|
||||||
// setTopicList(item);
|
// setTopicList(item);
|
||||||
topicList.value = item
|
topicList.value = item;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
//获取设备解析规则
|
//获取设备解析规则
|
||||||
const getDeviceCode = async () => {
|
const getDeviceCode = async () => {
|
||||||
const res: any = await deviceCode(instanceStore.current.productId, instanceStore.current.id)
|
const res: any = await deviceCode(
|
||||||
|
instanceStore.current.productId,
|
||||||
|
instanceStore.current.id,
|
||||||
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const item = res.result?.configuration?.script ? res.result?.configuration?.script : defaultValue
|
const item = res.result?.configuration?.script
|
||||||
|
? res.result?.configuration?.script
|
||||||
|
: defaultValue;
|
||||||
if (res.result?.deviceId) {
|
if (res.result?.deviceId) {
|
||||||
readOnly.value = false
|
readOnly.value = false;
|
||||||
topTitle.value = 'rest'
|
topTitle.value = 'rest';
|
||||||
editorValue.value = item
|
editorValue.value = item;
|
||||||
} else {
|
} else {
|
||||||
readOnly.value = true
|
readOnly.value = true;
|
||||||
topTitle.value = 'edit'
|
topTitle.value = 'edit';
|
||||||
editorValue.value = item
|
editorValue.value = item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
//调试
|
//调试
|
||||||
const test = async (dataTest: any) => {
|
const test = async (dataTest: any) => {
|
||||||
loading.value = true
|
loading.value = true;
|
||||||
const res = await testCode(dataTest)
|
const res = await testCode(dataTest);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
loading.value = false
|
loading.value = false;
|
||||||
resultValue.value = res?.result
|
resultValue.value = res?.result;
|
||||||
} else {
|
} else {
|
||||||
loading.value = false
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -193,15 +268,18 @@ const save = async () => {
|
||||||
script: editorValue.value,
|
script: editorValue.value,
|
||||||
lang: 'javascript',
|
lang: 'javascript',
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
const res = await saveDeviceCode(instanceStore.current.productId, instanceStore.current.id, item)
|
const res = await saveDeviceCode(
|
||||||
|
instanceStore.current.productId,
|
||||||
|
instanceStore.current.id,
|
||||||
|
item,
|
||||||
|
);
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
message.success('保存成功');
|
message.success('保存成功');
|
||||||
getDeviceCode();
|
getDeviceCode();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const debug = () => {
|
const debug = () => {
|
||||||
if (instanceStore.current.transport === 'MQTT') {
|
if (instanceStore.current.transport === 'MQTT') {
|
||||||
if (topic.value !== '') {
|
if (topic.value !== '') {
|
||||||
|
@ -215,8 +293,8 @@ const debug = () => {
|
||||||
},
|
},
|
||||||
provider: 'jsr223',
|
provider: 'jsr223',
|
||||||
payload: simulation.value,
|
payload: simulation.value,
|
||||||
})
|
});
|
||||||
isTest.value = true
|
isTest.value = true;
|
||||||
} else {
|
} else {
|
||||||
message.error('请输入topic');
|
message.error('请输入topic');
|
||||||
}
|
}
|
||||||
|
@ -233,19 +311,17 @@ const debug = () => {
|
||||||
},
|
},
|
||||||
payload: simulation.value,
|
payload: simulation.value,
|
||||||
});
|
});
|
||||||
isTest.value = true
|
isTest.value = true;
|
||||||
} else {
|
} else {
|
||||||
message.error('请输入url');
|
message.error('请输入url');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDeviceCode()
|
getDeviceCode();
|
||||||
getTopic()
|
getTopic();
|
||||||
})
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang='less'>
|
<style scoped lang='less'>
|
||||||
|
|
|
@ -1,37 +1,31 @@
|
||||||
<template>
|
<template>
|
||||||
<j-card>
|
<div class="property-box">
|
||||||
<div class="property-box">
|
<div class="property-box-left">
|
||||||
<div class="property-box-left">
|
<j-input-search
|
||||||
<j-input-search
|
v-model:value="value"
|
||||||
v-model:value="value"
|
placeholder="请输入事件名称"
|
||||||
placeholder="请输入事件名称"
|
style="width: 200px; margin-bottom: 10px"
|
||||||
style="width: 200px; margin-bottom: 10px"
|
@search="onSearch"
|
||||||
@search="onSearch"
|
:allowClear="true"
|
||||||
:allowClear="true"
|
/>
|
||||||
/>
|
<j-tabs
|
||||||
<j-tabs
|
tab-position="left"
|
||||||
tab-position="left"
|
style="height: 600px"
|
||||||
style="height: 600px"
|
v-if="tabList.length"
|
||||||
v-if="tabList.length"
|
v-model:activeKey="activeKey"
|
||||||
v-model:activeKey="activeKey"
|
:tabBarStyle="{ width: '200px' }"
|
||||||
:tabBarStyle="{ width: '200px' }"
|
@change="tabChange"
|
||||||
@change="tabChange"
|
>
|
||||||
>
|
<j-tab-pane v-for="i in tabList" :key="i.key" :tab="i.tab" />
|
||||||
<j-tab-pane
|
</j-tabs>
|
||||||
v-for="i in tabList"
|
<JEmpty v-else style="margin: 180px 0" />
|
||||||
:key="i.key"
|
|
||||||
:tab="i.tab"
|
|
||||||
/>
|
|
||||||
</j-tabs>
|
|
||||||
<JEmpty v-else style="margin: 180px 0" />
|
|
||||||
</div>
|
|
||||||
<div class="property-box-right">
|
|
||||||
<Event v-if="type === 'event'" :data="data" />
|
|
||||||
<Property v-else-if="type === 'property'" :data="properties" />
|
|
||||||
<JEmpty v-else style="margin: 220px 0" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</j-card>
|
<div class="property-box-right">
|
||||||
|
<Event v-if="type === 'event'" :data="data" />
|
||||||
|
<Property v-else-if="type === 'property'" :data="properties" />
|
||||||
|
<JEmpty v-else style="margin: 220px 0" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
@ -51,28 +45,32 @@ const tabList = ref<{ key: string; tab: string; type: 'property' | 'event' }[]>(
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
const type = ref<string>('property');
|
const type = ref<string>('property');
|
||||||
const data = ref<Record<string, any>>({})
|
const data = ref<Record<string, any>>({});
|
||||||
const value = ref<string>('');
|
const value = ref<string>('');
|
||||||
const instanceStore = useInstanceStore()
|
const instanceStore = useInstanceStore();
|
||||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}')
|
const metadata = JSON.parse(instanceStore.current?.metadata || '{}');
|
||||||
const properties = metadata.properties
|
const properties = metadata.properties;
|
||||||
const events = metadata.events
|
const events = metadata.events;
|
||||||
|
|
||||||
watch(() => events, (newVal) => {
|
watch(
|
||||||
if(events && newVal.length){
|
() => events,
|
||||||
newVal.map((item: any) => {
|
(newVal) => {
|
||||||
tabList.value.push({
|
if (events && newVal.length) {
|
||||||
...item,
|
newVal.map((item: any) => {
|
||||||
key: item.id,
|
tabList.value.push({
|
||||||
tab: item.name,
|
...item,
|
||||||
type: 'event',
|
key: item.id,
|
||||||
})
|
tab: item.name,
|
||||||
})
|
type: 'event',
|
||||||
}
|
});
|
||||||
}, {
|
});
|
||||||
deep: true,
|
}
|
||||||
immediate: true
|
},
|
||||||
})
|
{
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
const onSearch = () => {
|
const onSearch = () => {
|
||||||
const arr = [
|
const arr = [
|
||||||
|
@ -87,33 +85,32 @@ const onSearch = () => {
|
||||||
key: item.id,
|
key: item.id,
|
||||||
tab: item.name,
|
tab: item.name,
|
||||||
type: 'event',
|
type: 'event',
|
||||||
}
|
};
|
||||||
})
|
}),
|
||||||
]
|
];
|
||||||
if(value.value){
|
if (value.value) {
|
||||||
const li = arr.filter((i: any) => {
|
const li = arr.filter((i: any) => {
|
||||||
return i?.tab.indexOf(value.value) !== -1;
|
return i?.tab.indexOf(value.value) !== -1;
|
||||||
})
|
});
|
||||||
tabList.value = _.cloneDeep(li)
|
tabList.value = _.cloneDeep(li);
|
||||||
} else {
|
} else {
|
||||||
tabList.value = _.cloneDeep(arr)
|
tabList.value = _.cloneDeep(arr);
|
||||||
}
|
}
|
||||||
const dt = tabList.value?.[0]
|
const dt = tabList.value?.[0];
|
||||||
if (dt) {
|
if (dt) {
|
||||||
data.value = dt
|
data.value = dt;
|
||||||
type.value = dt.type;
|
type.value = dt.type;
|
||||||
} else {
|
} else {
|
||||||
type.value = ''
|
type.value = '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const tabChange = (key: string) => {
|
const tabChange = (key: string) => {
|
||||||
const dt = tabList.value.find((i) => i.key === key);
|
const dt = tabList.value.find((i) => i.key === key);
|
||||||
if (dt) {
|
if (dt) {
|
||||||
data.value = dt
|
data.value = dt;
|
||||||
type.value = dt.type;
|
type.value = dt.type;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
||||||
<j-card>
|
<j-card :bordered="false" borderStyle="padding: 0">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<j-space>
|
<j-space>
|
||||||
<j-button @click="visible = true">批量映射</j-button>
|
<j-button @click="visible = true">批量映射</j-button>
|
||||||
|
@ -107,7 +107,7 @@
|
||||||
:metaData="modelRef.dataSource"
|
:metaData="modelRef.dataSource"
|
||||||
/>
|
/>
|
||||||
</j-spin>
|
</j-spin>
|
||||||
<j-card v-else>
|
<j-card v-else :bordered="false" borderStyle="padding: 0">
|
||||||
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
||||||
</j-card>
|
</j-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
<template #title>
|
<template #title>
|
||||||
<div style="display: flex; align-items: center">
|
<div style="display: flex; align-items: center">
|
||||||
<j-tooltip :title="instanceStore.current?.name">
|
<j-tooltip :title="instanceStore.current?.name">
|
||||||
<div class="deviceDetailHead">{{ instanceStore.current?.name }}</div>
|
<div class="deviceDetailHead">
|
||||||
|
{{ instanceStore.current?.name }}
|
||||||
|
</div>
|
||||||
</j-tooltip>
|
</j-tooltip>
|
||||||
<j-divider type="vertical" />
|
<j-divider type="vertical" />
|
||||||
<j-space>
|
<j-space>
|
||||||
|
@ -95,11 +97,15 @@
|
||||||
style="margin-right: 20px; cursor: pointer"
|
style="margin-right: 20px; cursor: pointer"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<component
|
<FullPage>
|
||||||
:is="tabs[instanceStore.tabActiveKey]"
|
<j-card :bordered="false">
|
||||||
v-bind="{ type: 'device' }"
|
<component
|
||||||
@onJump="onTabChange"
|
:is="tabs[instanceStore.tabActiveKey]"
|
||||||
/>
|
v-bind="{ type: 'device' }"
|
||||||
|
@onJump="onTabChange"
|
||||||
|
/>
|
||||||
|
</j-card>
|
||||||
|
</FullPage>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -121,12 +127,12 @@ import { message } from 'jetlinks-ui-components';
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import { getWebSocket } from '@/utils/websocket';
|
import { getWebSocket } from '@/utils/websocket';
|
||||||
import { useMenuStore } from '@/store/menu';
|
import { useMenuStore } from '@/store/menu';
|
||||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||||
|
|
||||||
const menuStory = useMenuStore();
|
const menuStory = useMenuStore();
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const routerParams = useRouterParams()
|
const routerParams = useRouterParams();
|
||||||
const instanceStore = useInstanceStore();
|
const instanceStore = useInstanceStore();
|
||||||
|
|
||||||
const statusMap = new Map();
|
const statusMap = new Map();
|
||||||
|
@ -266,18 +272,18 @@ const getDetail = () => {
|
||||||
// );
|
// );
|
||||||
|
|
||||||
const getDetailFn = async () => {
|
const getDetailFn = async () => {
|
||||||
const _id = route.params?.id
|
const _id = route.params?.id;
|
||||||
if (_id) {
|
if (_id) {
|
||||||
await instanceStore.refresh(String(_id));
|
await instanceStore.refresh(String(_id));
|
||||||
getStatus(String(_id));
|
getStatus(String(_id));
|
||||||
list.value = [...initList];
|
list.value = [...initList];
|
||||||
getDetail();
|
getDetail();
|
||||||
}
|
}
|
||||||
instanceStore.tabActiveKey = routerParams.params.value.tab || 'Info';
|
instanceStore.tabActiveKey = routerParams.params.value.tab || 'Info';
|
||||||
}
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getDetailFn()
|
getDetailFn();
|
||||||
});
|
});
|
||||||
|
|
||||||
const onBack = () => {
|
const onBack = () => {
|
||||||
|
|
|
@ -5,37 +5,42 @@
|
||||||
target="device-instance"
|
target="device-instance"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
/>
|
/>
|
||||||
<JProTable
|
<FullPage>
|
||||||
ref="instanceRef"
|
<JProTable
|
||||||
:columns="columns"
|
ref="instanceRef"
|
||||||
:request="query"
|
:columns="columns"
|
||||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
:request="query"
|
||||||
:rowSelection="
|
:defaultParams="{
|
||||||
isCheck
|
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||||
? {
|
}"
|
||||||
selectedRowKeys: _selectedRowKeys,
|
:rowSelection="
|
||||||
onChange: onSelectChange,
|
isCheck
|
||||||
}
|
? {
|
||||||
: false
|
selectedRowKeys: _selectedRowKeys,
|
||||||
"
|
onChange: onSelectChange,
|
||||||
:params="params"
|
}
|
||||||
>
|
: false
|
||||||
<template #headerTitle>
|
"
|
||||||
<j-space>
|
:params="params"
|
||||||
<PermissionButton
|
>
|
||||||
type="primary"
|
<template #headerTitle>
|
||||||
@click="handleAdd"
|
<j-space>
|
||||||
hasPermission="device/Instance:add"
|
<PermissionButton
|
||||||
>
|
type="primary"
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
@click="handleAdd"
|
||||||
新增
|
hasPermission="device/Instance:add"
|
||||||
</PermissionButton>
|
>
|
||||||
<BatchDropdown
|
<template #icon
|
||||||
v-model:isCheck="isCheck"
|
><AIcon type="PlusOutlined"
|
||||||
:actions="batchActions"
|
/></template>
|
||||||
@change="onCheckChange"
|
新增
|
||||||
/>
|
</PermissionButton>
|
||||||
<!-- <j-dropdown>
|
<BatchDropdown
|
||||||
|
v-model:isCheck="isCheck"
|
||||||
|
:actions="batchActions"
|
||||||
|
@change="onCheckChange"
|
||||||
|
/>
|
||||||
|
<!-- <j-dropdown>
|
||||||
<j-button
|
<j-button
|
||||||
>批量操作 <AIcon type="DownOutlined"
|
>批量操作 <AIcon type="DownOutlined"
|
||||||
/></j-button>
|
/></j-button>
|
||||||
|
@ -141,116 +146,125 @@
|
||||||
</j-menu>
|
</j-menu>
|
||||||
</template>
|
</template>
|
||||||
</j-dropdown> -->
|
</j-dropdown> -->
|
||||||
</j-space>
|
</j-space>
|
||||||
</template>
|
</template>
|
||||||
<template #card="slotProps">
|
<template #card="slotProps">
|
||||||
<CardBox
|
<CardBox
|
||||||
:value="slotProps"
|
:value="slotProps"
|
||||||
@click="handleClick"
|
@click="handleClick"
|
||||||
:actions="getActions(slotProps, 'card')"
|
:actions="getActions(slotProps, 'card')"
|
||||||
:active="_selectedRowKeys.includes(slotProps.id)"
|
:active="_selectedRowKeys.includes(slotProps.id)"
|
||||||
:status="slotProps.state?.value"
|
:status="slotProps.state?.value"
|
||||||
:statusText="slotProps.state?.text"
|
:statusText="slotProps.state?.text"
|
||||||
:statusNames="{
|
:statusNames="{
|
||||||
online: 'processing',
|
online: 'processing',
|
||||||
offline: 'error',
|
offline: 'error',
|
||||||
notActive: 'warning',
|
notActive: 'warning',
|
||||||
}"
|
}"
|
||||||
>
|
|
||||||
<template #img>
|
|
||||||
<img
|
|
||||||
:src="getImage('/device/instance/device-card.png')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
|
||||||
<span style="font-size: 16px; font-weight: 600">
|
|
||||||
{{ slotProps.name }}
|
|
||||||
</span>
|
|
||||||
</Ellipsis>
|
|
||||||
<j-row style="margin-top: 20px">
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
设备类型
|
|
||||||
</div>
|
|
||||||
<div>{{ slotProps.deviceType?.text }}</div>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
产品名称
|
|
||||||
</div>
|
|
||||||
<Ellipsis style="width: 100%">
|
|
||||||
{{ slotProps.productName }}
|
|
||||||
</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</template>
|
|
||||||
<template #actions="item">
|
|
||||||
<PermissionButton
|
|
||||||
:disabled="item.disabled"
|
|
||||||
:popConfirm="item.popConfirm"
|
|
||||||
:tooltip="{
|
|
||||||
...item.tooltip,
|
|
||||||
}"
|
|
||||||
@click="item.onClick"
|
|
||||||
:hasPermission="'device/Instance:' + item.key"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
v-if="item.key === 'delete'"
|
|
||||||
/>
|
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item?.text }}</span>
|
|
||||||
</template>
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
</CardBox>
|
|
||||||
</template>
|
|
||||||
<template #state="slotProps">
|
|
||||||
<BadgeStatus
|
|
||||||
:status="slotProps.state?.value"
|
|
||||||
:text="slotProps.state?.text"
|
|
||||||
:statusNames="{
|
|
||||||
online: 'processing',
|
|
||||||
offline: 'error',
|
|
||||||
notActive: 'warning',
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #createTime="slotProps">
|
|
||||||
<span>{{
|
|
||||||
slotProps?.createTime ? dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') : ''
|
|
||||||
}}</span>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<j-space>
|
|
||||||
<template
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
>
|
>
|
||||||
<PermissionButton
|
<template #img>
|
||||||
:disabled="i.disabled"
|
<img
|
||||||
:popConfirm="i.popConfirm"
|
:src="
|
||||||
:tooltip="{
|
getImage('/device/instance/device-card.png')
|
||||||
...i.tooltip,
|
"
|
||||||
}"
|
/>
|
||||||
@click="i.onClick"
|
</template>
|
||||||
type="link"
|
<template #content>
|
||||||
style="padding: 0 5px"
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
:danger="i.key === 'delete'"
|
<span style="font-size: 16px; font-weight: 600">
|
||||||
:hasPermission="
|
{{ slotProps.name }}
|
||||||
i.key === 'view'
|
</span>
|
||||||
? true
|
</Ellipsis>
|
||||||
: 'device/Instance:' + i.key
|
<j-row style="margin-top: 20px">
|
||||||
"
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
设备类型
|
||||||
|
</div>
|
||||||
|
<div>{{ slotProps.deviceType?.text }}</div>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
产品名称
|
||||||
|
</div>
|
||||||
|
<Ellipsis style="width: 100%">
|
||||||
|
{{ slotProps.productName }}
|
||||||
|
</Ellipsis>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</template>
|
||||||
|
<template #actions="item">
|
||||||
|
<PermissionButton
|
||||||
|
:disabled="item.disabled"
|
||||||
|
:popConfirm="item.popConfirm"
|
||||||
|
:tooltip="{
|
||||||
|
...item.tooltip,
|
||||||
|
}"
|
||||||
|
@click="item.onClick"
|
||||||
|
:hasPermission="'device/Instance:' + item.key"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
v-if="item.key === 'delete'"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<BadgeStatus
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
online: 'processing',
|
||||||
|
offline: 'error',
|
||||||
|
notActive: 'warning',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #createTime="slotProps">
|
||||||
|
<span>{{
|
||||||
|
slotProps?.createTime
|
||||||
|
? dayjs(slotProps.createTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
: ''
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space>
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
>
|
>
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
<PermissionButton
|
||||||
</PermissionButton>
|
:disabled="i.disabled"
|
||||||
</template>
|
:popConfirm="i.popConfirm"
|
||||||
</j-space>
|
:tooltip="{
|
||||||
</template>
|
...i.tooltip,
|
||||||
</JProTable>
|
}"
|
||||||
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
style="padding: 0 5px"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
|
:hasPermission="
|
||||||
|
i.key === 'view'
|
||||||
|
? true
|
||||||
|
: 'device/Instance:' + i.key
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
</JProTable>
|
||||||
|
</FullPage>
|
||||||
</page-container>
|
</page-container>
|
||||||
<Import
|
<Import
|
||||||
v-if="importVisible"
|
v-if="importVisible"
|
||||||
|
@ -867,7 +881,7 @@ const handleSearch = (_params: any) => {
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
...item2,
|
...item2,
|
||||||
column: 'productId$product-info'
|
column: 'productId$product-info',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return item2;
|
return item2;
|
||||||
|
|
|
@ -5,147 +5,166 @@
|
||||||
target="edge-device"
|
target="edge-device"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
/>
|
/>
|
||||||
<JProTable
|
<FullPage>
|
||||||
ref="edgeDeviceRef"
|
<JProTable
|
||||||
:columns="columns"
|
ref="edgeDeviceRef"
|
||||||
:request="query"
|
:columns="columns"
|
||||||
:defaultParams="defaultParams"
|
:request="query"
|
||||||
:params="params"
|
:defaultParams="defaultParams"
|
||||||
:gridColumn="3"
|
:params="params"
|
||||||
>
|
:gridColumn="3"
|
||||||
<template #headerTitle>
|
>
|
||||||
<j-space>
|
<template #headerTitle>
|
||||||
<PermissionButton
|
<j-space>
|
||||||
type="primary"
|
|
||||||
@click="handleAdd"
|
|
||||||
hasPermission="edge/Device:add"
|
|
||||||
>
|
|
||||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
|
||||||
新增
|
|
||||||
</PermissionButton>
|
|
||||||
<PermissionButton
|
|
||||||
@click="importVisible = true"
|
|
||||||
hasPermission="edge/Device:import"
|
|
||||||
>
|
|
||||||
<template #icon
|
|
||||||
><AIcon type="ImportOutlined"
|
|
||||||
/></template>
|
|
||||||
导入
|
|
||||||
</PermissionButton>
|
|
||||||
</j-space>
|
|
||||||
</template>
|
|
||||||
<template #card="slotProps">
|
|
||||||
<CardBox
|
|
||||||
:value="slotProps"
|
|
||||||
:actions="getActions(slotProps, 'card')"
|
|
||||||
:status="slotProps.state?.value"
|
|
||||||
:statusText="slotProps.state?.text"
|
|
||||||
:statusNames="{
|
|
||||||
online: 'processing',
|
|
||||||
offline: 'error',
|
|
||||||
notActive: 'warning',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<template #img>
|
|
||||||
<img
|
|
||||||
:src="getImage('/device/instance/device-card.png')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
|
||||||
<span
|
|
||||||
style="font-size: 16px; font-weight: 600"
|
|
||||||
@click.stop="handleView(slotProps.id)"
|
|
||||||
>
|
|
||||||
{{ slotProps.name }}
|
|
||||||
</span>
|
|
||||||
</Ellipsis>
|
|
||||||
<j-row style="margin-top: 20px">
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
设备类型
|
|
||||||
</div>
|
|
||||||
<div>{{ slotProps.deviceType?.text }}</div>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
产品名称
|
|
||||||
</div>
|
|
||||||
<Ellipsis style="width: 100%">
|
|
||||||
{{ slotProps.productName }}
|
|
||||||
</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</template>
|
|
||||||
<template #actions="item">
|
|
||||||
<PermissionButton
|
<PermissionButton
|
||||||
:disabled="item.disabled"
|
type="primary"
|
||||||
:popConfirm="item.popConfirm"
|
@click="handleAdd"
|
||||||
:tooltip="{
|
hasPermission="edge/Device:add"
|
||||||
...item.tooltip,
|
|
||||||
}"
|
|
||||||
@click="item.onClick"
|
|
||||||
:hasPermission="'edge/Device:' + item.key"
|
|
||||||
>
|
>
|
||||||
<AIcon
|
<template #icon
|
||||||
type="DeleteOutlined"
|
><AIcon type="PlusOutlined"
|
||||||
v-if="item.key === 'delete'"
|
/></template>
|
||||||
|
新增
|
||||||
|
</PermissionButton>
|
||||||
|
<PermissionButton
|
||||||
|
@click="importVisible = true"
|
||||||
|
hasPermission="edge/Device:import"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon type="ImportOutlined"
|
||||||
|
/></template>
|
||||||
|
导入
|
||||||
|
</PermissionButton>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
<template #card="slotProps">
|
||||||
|
<CardBox
|
||||||
|
:value="slotProps"
|
||||||
|
:actions="getActions(slotProps, 'card')"
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:statusText="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
online: 'processing',
|
||||||
|
offline: 'error',
|
||||||
|
notActive: 'warning',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #img>
|
||||||
|
<img
|
||||||
|
:src="
|
||||||
|
getImage('/device/instance/device-card.png')
|
||||||
|
"
|
||||||
/>
|
/>
|
||||||
<template v-else>
|
</template>
|
||||||
<AIcon :type="item.icon" />
|
<template #content>
|
||||||
<span>{{ item?.text }}</span>
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
</template>
|
<span
|
||||||
</PermissionButton>
|
style="font-size: 16px; font-weight: 600"
|
||||||
</template>
|
@click.stop="handleView(slotProps.id)"
|
||||||
</CardBox>
|
>
|
||||||
</template>
|
{{ slotProps.name }}
|
||||||
<template #state="slotProps">
|
</span>
|
||||||
<BadgeStatus
|
</Ellipsis>
|
||||||
:status="slotProps.state?.value"
|
<j-row style="margin-top: 20px">
|
||||||
:text="slotProps.state?.text"
|
<j-col :span="12">
|
||||||
:statusNames="{
|
<div class="card-item-content-text">
|
||||||
online: 'processing',
|
设备类型
|
||||||
offline: 'error',
|
</div>
|
||||||
notActive: 'warning',
|
<div>{{ slotProps.deviceType?.text }}</div>
|
||||||
}"
|
</j-col>
|
||||||
/>
|
<j-col :span="12">
|
||||||
</template>
|
<div class="card-item-content-text">
|
||||||
<template #registryTime="slotProps">
|
产品名称
|
||||||
<span>{{
|
</div>
|
||||||
dayjs(slotProps.registryTime).format('YYYY-MM-DD HH:mm:ss')
|
<Ellipsis style="width: 100%">
|
||||||
}}</span>
|
{{ slotProps.productName }}
|
||||||
</template>
|
</Ellipsis>
|
||||||
<template #action="slotProps">
|
</j-col>
|
||||||
<j-space>
|
</j-row>
|
||||||
<template
|
</template>
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
<template #actions="item">
|
||||||
:key="i.key"
|
<PermissionButton
|
||||||
>
|
:disabled="item.disabled"
|
||||||
<PermissionButton
|
:popConfirm="item.popConfirm"
|
||||||
:disabled="i.disabled"
|
:tooltip="{
|
||||||
:popConfirm="i.popConfirm"
|
...item.tooltip,
|
||||||
:tooltip="{
|
}"
|
||||||
...i.tooltip,
|
@click="item.onClick"
|
||||||
}"
|
:hasPermission="'edge/Device:' + item.key"
|
||||||
@click="i.onClick"
|
>
|
||||||
type="link"
|
<AIcon
|
||||||
style="padding: 0 5px"
|
type="DeleteOutlined"
|
||||||
:danger="i.key === 'delete'"
|
v-if="item.key === 'delete'"
|
||||||
:hasPermission="i.key === 'view' ? true : 'edge/Device:' + i.key"
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<BadgeStatus
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
online: 'processing',
|
||||||
|
offline: 'error',
|
||||||
|
notActive: 'warning',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #registryTime="slotProps">
|
||||||
|
<span>{{
|
||||||
|
dayjs(slotProps.registryTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space>
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
>
|
>
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
<PermissionButton
|
||||||
</PermissionButton>
|
:disabled="i.disabled"
|
||||||
</template>
|
:popConfirm="i.popConfirm"
|
||||||
</j-space>
|
:tooltip="{
|
||||||
</template>
|
...i.tooltip,
|
||||||
</JProTable>
|
}"
|
||||||
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
style="padding: 0 5px"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
|
:hasPermission="
|
||||||
|
i.key === 'view'
|
||||||
|
? true
|
||||||
|
: 'edge/Device:' + i.key
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
</JProTable>
|
||||||
|
</FullPage>
|
||||||
<Save
|
<Save
|
||||||
v-if="visible"
|
v-if="visible"
|
||||||
:data="current"
|
:data="current"
|
||||||
@close="visible = false"
|
@close="visible = false"
|
||||||
@save="saveBtn"
|
@save="saveBtn"
|
||||||
/>
|
/>
|
||||||
<Import @save="onRefresh" @close="importVisible = false" v-if="importVisible" type="official-edge-gateway" />
|
<Import
|
||||||
|
@save="onRefresh"
|
||||||
|
@close="importVisible = false"
|
||||||
|
v-if="importVisible"
|
||||||
|
type="official-edge-gateway"
|
||||||
|
/>
|
||||||
</page-container>
|
</page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -192,18 +211,18 @@ const visible = ref<boolean>(false);
|
||||||
const current = ref<Record<string, any>>({});
|
const current = ref<Record<string, any>>({});
|
||||||
|
|
||||||
const transformData = (arr: any[]): any[] => {
|
const transformData = (arr: any[]): any[] => {
|
||||||
if(Array.isArray(arr) && arr.length){
|
if (Array.isArray(arr) && arr.length) {
|
||||||
return (arr || []).map((item: any) => {
|
return (arr || []).map((item: any) => {
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
id: `classifiedId is ${item.id}`,
|
id: `classifiedId is ${item.id}`,
|
||||||
children: transformData(item.children)
|
children: transformData(item.children),
|
||||||
}
|
};
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
@ -471,9 +490,9 @@ const saveBtn = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRefresh = () => {
|
const onRefresh = () => {
|
||||||
importVisible.value = false
|
importVisible.value = false;
|
||||||
edgeDeviceRef.value?.reload();
|
edgeDeviceRef.value?.reload();
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -5,131 +5,141 @@
|
||||||
target="edge-resource"
|
target="edge-resource"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
/>
|
/>
|
||||||
<JProTable
|
<FullPage>
|
||||||
ref="edgeResourceRef"
|
<JProTable
|
||||||
:columns="columns"
|
ref="edgeResourceRef"
|
||||||
:request="query"
|
:columns="columns"
|
||||||
:defaultParams="defaultParams"
|
:request="query"
|
||||||
:params="params"
|
:defaultParams="defaultParams"
|
||||||
>
|
:params="params"
|
||||||
<template #card="slotProps">
|
>
|
||||||
<CardBox
|
<template #card="slotProps">
|
||||||
:value="slotProps"
|
<CardBox
|
||||||
@click="handleView(slotProps)"
|
:value="slotProps"
|
||||||
:actions="getActions(slotProps, 'card')"
|
@click="handleView(slotProps)"
|
||||||
:status="slotProps.state?.value"
|
:actions="getActions(slotProps, 'card')"
|
||||||
:statusText="slotProps.state?.text"
|
:status="slotProps.state?.value"
|
||||||
:statusNames="{
|
:statusText="slotProps.state?.text"
|
||||||
enabled: 'processing',
|
:statusNames="{
|
||||||
disabled: 'error',
|
enabled: 'processing',
|
||||||
}"
|
disabled: 'error',
|
||||||
>
|
}"
|
||||||
<template #img>
|
|
||||||
<img
|
|
||||||
:src="getImage('/device/instance/device-card.png')"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<Ellipsis style="width: calc(100% - 100px)">
|
|
||||||
<span style="font-size: 16px; font-weight: 600">
|
|
||||||
{{ slotProps.name }}
|
|
||||||
</span>
|
|
||||||
</Ellipsis>
|
|
||||||
<j-row style="margin-top: 20px">
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
通讯协议
|
|
||||||
</div>
|
|
||||||
<Ellipsis>{{
|
|
||||||
options.find(
|
|
||||||
(i) => i.value === slotProps.category,
|
|
||||||
)?.label || slotProps.category
|
|
||||||
}}</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
<j-col :span="12">
|
|
||||||
<div class="card-item-content-text">
|
|
||||||
所属边缘网关
|
|
||||||
</div>
|
|
||||||
<Ellipsis style="width: 100%">
|
|
||||||
{{ slotProps.sourceName }}
|
|
||||||
</Ellipsis>
|
|
||||||
</j-col>
|
|
||||||
</j-row>
|
|
||||||
</template>
|
|
||||||
<template #actions="item">
|
|
||||||
<PermissionButton
|
|
||||||
:disabled="item.disabled"
|
|
||||||
:popConfirm="item.popConfirm"
|
|
||||||
:tooltip="{
|
|
||||||
...item.tooltip,
|
|
||||||
}"
|
|
||||||
@click="item.onClick"
|
|
||||||
:hasPermission="'edge/Resource:' + item.key"
|
|
||||||
>
|
|
||||||
<AIcon
|
|
||||||
type="DeleteOutlined"
|
|
||||||
v-if="item.key === 'delete'"
|
|
||||||
/>
|
|
||||||
<template v-else>
|
|
||||||
<AIcon :type="item.icon" />
|
|
||||||
<span>{{ item?.text }}</span>
|
|
||||||
</template>
|
|
||||||
</PermissionButton>
|
|
||||||
</template>
|
|
||||||
</CardBox>
|
|
||||||
</template>
|
|
||||||
<template #state="slotProps">
|
|
||||||
<BadgeStatus
|
|
||||||
:status="slotProps.state?.value"
|
|
||||||
:text="slotProps.state?.text"
|
|
||||||
:statusNames="{
|
|
||||||
enabled: 'processing',
|
|
||||||
disabled: 'error',
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #sourceId="slotProps">
|
|
||||||
{{ slotProps.sourceName }}
|
|
||||||
</template>
|
|
||||||
<template #category="slotProps">
|
|
||||||
{{
|
|
||||||
options.find((i) => i.value === slotProps.category)
|
|
||||||
?.label || slotProps.category
|
|
||||||
}}
|
|
||||||
</template>
|
|
||||||
<template #createTime="slotProps">
|
|
||||||
<span>{{
|
|
||||||
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
}}</span>
|
|
||||||
</template>
|
|
||||||
<template #action="slotProps">
|
|
||||||
<j-space>
|
|
||||||
<template
|
|
||||||
v-for="i in getActions(slotProps, 'table')"
|
|
||||||
:key="i.key"
|
|
||||||
>
|
>
|
||||||
<PermissionButton
|
<template #img>
|
||||||
:disabled="i.disabled"
|
<img
|
||||||
:popConfirm="i.popConfirm"
|
:src="
|
||||||
:tooltip="{
|
getImage('/device/instance/device-card.png')
|
||||||
...i.tooltip,
|
"
|
||||||
}"
|
/>
|
||||||
@click="i.onClick"
|
</template>
|
||||||
type="link"
|
<template #content>
|
||||||
style="padding: 0 5px"
|
<Ellipsis style="width: calc(100% - 100px)">
|
||||||
:danger="i.key === 'delete'"
|
<span style="font-size: 16px; font-weight: 600">
|
||||||
:hasPermission="
|
{{ slotProps.name }}
|
||||||
i.key === 'view'
|
</span>
|
||||||
? true
|
</Ellipsis>
|
||||||
: 'edge/Resource:' + i.key
|
<j-row style="margin-top: 20px">
|
||||||
"
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
通讯协议
|
||||||
|
</div>
|
||||||
|
<Ellipsis>{{
|
||||||
|
options.find(
|
||||||
|
(i) =>
|
||||||
|
i.value === slotProps.category,
|
||||||
|
)?.label || slotProps.category
|
||||||
|
}}</Ellipsis>
|
||||||
|
</j-col>
|
||||||
|
<j-col :span="12">
|
||||||
|
<div class="card-item-content-text">
|
||||||
|
所属边缘网关
|
||||||
|
</div>
|
||||||
|
<Ellipsis style="width: 100%">
|
||||||
|
{{ slotProps.sourceName }}
|
||||||
|
</Ellipsis>
|
||||||
|
</j-col>
|
||||||
|
</j-row>
|
||||||
|
</template>
|
||||||
|
<template #actions="item">
|
||||||
|
<PermissionButton
|
||||||
|
:disabled="item.disabled"
|
||||||
|
:popConfirm="item.popConfirm"
|
||||||
|
:tooltip="{
|
||||||
|
...item.tooltip,
|
||||||
|
}"
|
||||||
|
@click="item.onClick"
|
||||||
|
:hasPermission="'edge/Resource:' + item.key"
|
||||||
|
>
|
||||||
|
<AIcon
|
||||||
|
type="DeleteOutlined"
|
||||||
|
v-if="item.key === 'delete'"
|
||||||
|
/>
|
||||||
|
<template v-else>
|
||||||
|
<AIcon :type="item.icon" />
|
||||||
|
<span>{{ item?.text }}</span>
|
||||||
|
</template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</CardBox>
|
||||||
|
</template>
|
||||||
|
<template #state="slotProps">
|
||||||
|
<BadgeStatus
|
||||||
|
:status="slotProps.state?.value"
|
||||||
|
:text="slotProps.state?.text"
|
||||||
|
:statusNames="{
|
||||||
|
enabled: 'processing',
|
||||||
|
disabled: 'error',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #sourceId="slotProps">
|
||||||
|
{{ slotProps.sourceName }}
|
||||||
|
</template>
|
||||||
|
<template #category="slotProps">
|
||||||
|
{{
|
||||||
|
options.find((i) => i.value === slotProps.category)
|
||||||
|
?.label || slotProps.category
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
|
<template #createTime="slotProps">
|
||||||
|
<span>{{
|
||||||
|
dayjs(slotProps.createTime).format(
|
||||||
|
'YYYY-MM-DD HH:mm:ss',
|
||||||
|
)
|
||||||
|
}}</span>
|
||||||
|
</template>
|
||||||
|
<template #action="slotProps">
|
||||||
|
<j-space>
|
||||||
|
<template
|
||||||
|
v-for="i in getActions(slotProps, 'table')"
|
||||||
|
:key="i.key"
|
||||||
>
|
>
|
||||||
<template #icon><AIcon :type="i.icon" /></template>
|
<PermissionButton
|
||||||
</PermissionButton>
|
:disabled="i.disabled"
|
||||||
</template>
|
:popConfirm="i.popConfirm"
|
||||||
</j-space>
|
:tooltip="{
|
||||||
</template>
|
...i.tooltip,
|
||||||
</JProTable>
|
}"
|
||||||
|
@click="i.onClick"
|
||||||
|
type="link"
|
||||||
|
style="padding: 0 5px"
|
||||||
|
:danger="i.key === 'delete'"
|
||||||
|
:hasPermission="
|
||||||
|
i.key === 'view'
|
||||||
|
? true
|
||||||
|
: 'edge/Resource:' + i.key
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<template #icon
|
||||||
|
><AIcon :type="i.icon"
|
||||||
|
/></template>
|
||||||
|
</PermissionButton>
|
||||||
|
</template>
|
||||||
|
</j-space>
|
||||||
|
</template>
|
||||||
|
</JProTable>
|
||||||
|
</FullPage>
|
||||||
|
|
||||||
<Save
|
<Save
|
||||||
v-if="visible"
|
v-if="visible"
|
||||||
:data="current"
|
:data="current"
|
||||||
|
|
|
@ -278,7 +278,7 @@ watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true, deep: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|
|
@ -154,7 +154,7 @@ const TypeList = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '按变量',
|
label: '按变量',
|
||||||
value: 'variable',
|
value: 'context',
|
||||||
image: getImage('/scene/device-variable.png'),
|
image: getImage('/scene/device-variable.png'),
|
||||||
tip: '选择设备ID为上游变量值的设备',
|
tip: '选择设备ID为上游变量值的设备',
|
||||||
},
|
},
|
||||||
|
@ -236,7 +236,7 @@ const filterType = async (newVal: any) => {
|
||||||
!props.parallel &&
|
!props.parallel &&
|
||||||
props.name !== 0
|
props.name !== 0
|
||||||
) {
|
) {
|
||||||
const array = TypeList.filter((item) => item.value === 'variable');
|
const array = TypeList.filter((item) => item.value === 'context');
|
||||||
_list.push(...array);
|
_list.push(...array);
|
||||||
}
|
}
|
||||||
list.value = _list;
|
list.value = _list;
|
||||||
|
@ -246,7 +246,7 @@ const filterType = async (newVal: any) => {
|
||||||
!props.parallel &&
|
!props.parallel &&
|
||||||
props.name !== 0
|
props.name !== 0
|
||||||
) {
|
) {
|
||||||
const array = TypeList.filter((item) => item.value === 'variable');
|
const array = TypeList.filter((item) => item.value === 'context');
|
||||||
_list.push(...array);
|
_list.push(...array);
|
||||||
}
|
}
|
||||||
list.value = _list;
|
list.value = _list;
|
||||||
|
@ -287,7 +287,12 @@ const onTagChange = (val: any[], arr: any[]) => {
|
||||||
modelRef.source = 'fixed';
|
modelRef.source = 'fixed';
|
||||||
}
|
}
|
||||||
const tagName = arr.map((i, _index) => {
|
const tagName = arr.map((i, _index) => {
|
||||||
const _type = (_index !== 0 && _index !== (arr || []).length && i.type) ? (i.type === 'and' ? '并且' : '或者') : '';
|
const _type =
|
||||||
|
_index !== 0 && _index !== (arr || []).length && i.type
|
||||||
|
? i.type === 'and'
|
||||||
|
? '并且'
|
||||||
|
: '或者'
|
||||||
|
: '';
|
||||||
return `${_type}${i.name}为${i.value}`;
|
return `${_type}${i.name}为${i.value}`;
|
||||||
});
|
});
|
||||||
emits('save', unref(modelRef), { tagName: tagName.join('') });
|
emits('save', unref(modelRef), { tagName: tagName.join('') });
|
||||||
|
@ -295,6 +300,8 @@ const onTagChange = (val: any[], arr: any[]) => {
|
||||||
|
|
||||||
const onVariableChange = (val: any, node: any) => {
|
const onVariableChange = (val: any, node: any) => {
|
||||||
modelRef.deviceId = val;
|
modelRef.deviceId = val;
|
||||||
|
modelRef.source = 'upper';
|
||||||
|
modelRef.upperKey = val;
|
||||||
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
||||||
emits('save', unref(modelRef), { name: node.description });
|
emits('save', unref(modelRef), { name: node.description });
|
||||||
};
|
};
|
||||||
|
@ -333,7 +340,7 @@ watch(
|
||||||
return item.children.find((i: any) => i.id === param);
|
return item.children.find((i: any) => i.id === param);
|
||||||
});
|
});
|
||||||
if (isVariable) {
|
if (isVariable) {
|
||||||
modelRef.selector = 'variable';
|
modelRef.selector = 'context';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -181,6 +181,7 @@ const onProductChange = (_val: any, bol: boolean) => {
|
||||||
JSON.parse(_val.metadata || '{}'),
|
JSON.parse(_val.metadata || '{}'),
|
||||||
DeviceModel?.message,
|
DeviceModel?.message,
|
||||||
);
|
);
|
||||||
|
console.log(flag)
|
||||||
if (!flag) {
|
if (!flag) {
|
||||||
DeviceModel.message = {
|
DeviceModel.message = {
|
||||||
messageType: 'INVOKE_FUNCTION',
|
messageType: 'INVOKE_FUNCTION',
|
||||||
|
|
Loading…
Reference in New Issue