fix: 加fullpage

This commit is contained in:
100011797 2023-03-30 17:01:58 +08:00
parent 8239b2c308
commit c38923f468
22 changed files with 2263 additions and 2003 deletions

View File

@ -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);

View File

@ -1,8 +1,10 @@
<template> <template>
<page-container> <page-container>
<FullPage>
<j-card> <j-card>
<j-row :gutter="24"> <div class="box">
<j-col :span="16"> <div class="left">
<div class="left-content">
<TitleComponent data="基本信息" /> <TitleComponent data="基本信息" />
<j-form <j-form
:layout="'vertical'" :layout="'vertical'"
@ -49,7 +51,9 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
@ -57,7 +61,8 @@
<j-select <j-select
placeholder="请选择服务地址" placeholder="请选择服务地址"
v-model:value=" v-model:value="
modelRef.accessConfig.regionId modelRef.accessConfig
.regionId
" "
show-search show-search
@blur="productChange" @blur="productChange"
@ -67,14 +72,19 @@
:key="item.id" :key="item.id"
:value="item.id" :value="item.id"
:label="item.name" :label="item.name"
>{{ item.name }}</j-select-option >{{
item.name
}}</j-select-option
> >
</j-select> </j-select>
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col :span="24"> <j-col :span="24">
<j-form-item <j-form-item
:name="['accessConfig', 'instanceId']" :name="[
'accessConfig',
'instanceId',
]"
> >
<template #label> <template #label>
<span> <span>
@ -84,7 +94,9 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
@ -92,7 +104,8 @@
<j-input <j-input
placeholder="请输入实例ID" placeholder="请输入实例ID"
v-model:value=" v-model:value="
modelRef.accessConfig.instanceId modelRef.accessConfig
.instanceId
" "
@blur="productChange" @blur="productChange"
/> />
@ -100,7 +113,10 @@
</j-col> </j-col>
<j-col :span="24"> <j-col :span="24">
<j-form-item <j-form-item
:name="['accessConfig', 'accessKeyId']" :name="[
'accessConfig',
'accessKeyId',
]"
:rules="[ :rules="[
{ {
required: true, required: true,
@ -120,7 +136,9 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
@ -128,7 +146,8 @@
<j-input <j-input
placeholder="请输入accessKey" placeholder="请输入accessKey"
v-model:value=" v-model:value="
modelRef.accessConfig.accessKeyId modelRef.accessConfig
.accessKeyId
" "
@blur="productChange" @blur="productChange"
/> />
@ -136,11 +155,15 @@
</j-col> </j-col>
<j-col :span="24"> <j-col :span="24">
<j-form-item <j-form-item
:name="['accessConfig', 'accessSecret']" :name="[
'accessConfig',
'accessSecret',
]"
:rules="[ :rules="[
{ {
required: true, required: true,
message: '请输入accessSecret', message:
'请输入accessSecret',
}, },
{ {
max: 64, max: 64,
@ -156,7 +179,9 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
@ -164,7 +189,8 @@
<j-input <j-input
placeholder="请输入accessSecret" placeholder="请输入accessSecret"
v-model:value=" v-model:value="
modelRef.accessConfig.accessSecret modelRef.accessConfig
.accessSecret
" "
@blur="productChange" @blur="productChange"
/> />
@ -186,7 +212,9 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
@ -224,11 +252,12 @@
:key="index" :key="index"
:header=" :header="
item.productKey item.productKey
? (aliyunProductList.find( ? aliyunProductList.find(
(i) => (i) =>
i.productKey === i.productKey ===
item.productKey, item.productKey,
)?.productName || `产品映射${index + 1}`) )?.productName ||
`产品映射${index + 1}`
: `产品映射${index + 1}` : `产品映射${index + 1}`
" "
> >
@ -261,9 +290,12 @@
> >
<j-select-option <j-select-option
v-for="i in getAliyunProductList( v-for="i in getAliyunProductList(
item?.productKey || '' item?.productKey ||
'',
)" )"
:key="i.productKey" :key="
i.productKey
"
:value=" :value="
i.productKey i.productKey
" "
@ -300,11 +332,16 @@
> >
<j-select-option <j-select-option
v-for="i in getPlatProduct( v-for="i in getPlatProduct(
item.productId || '' item.productId ||
'',
)" )"
:key="i.id" :key="i.id"
:value="i?.id" :value="
:label="i.name" i?.id
"
:label="
i.name
"
>{{ >{{
i.name i.name
}}</j-select-option }}</j-select-option
@ -322,7 +359,10 @@
<j-col :span="24"> <j-col :span="24">
<j-button <j-button
type="dashed" type="dashed"
style="width: 100%; margin-top: 10px" style="
width: 100%;
margin-top: 10px;
"
@click="addItem" @click="addItem"
> >
<AIcon <AIcon
@ -341,7 +381,9 @@
}" }"
> >
<j-textarea <j-textarea
v-model:value="modelRef.description" v-model:value="
modelRef.description
"
placeholder="请输入说明" placeholder="请输入说明"
showCount showCount
:maxlength="200" :maxlength="200"
@ -355,17 +397,22 @@
type="primary" type="primary"
:loading="loading" :loading="loading"
@click="saveBtn" @click="saveBtn"
:hasPermission="['Northbound/AliCloud:add', 'Northbound/AliCloud:update']" :hasPermission="[
'Northbound/AliCloud:add',
'Northbound/AliCloud:update',
]"
> >
保存 保存
</PermissionButton> </PermissionButton>
</div> </div>
</j-col> </div>
<j-col :span="8"> </div>
<div class="right">
<Doc /> <Doc />
</j-col> </div>
</j-row> </div>
</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();
@ -540,3 +589,22 @@ 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>

View File

@ -5,11 +5,14 @@
target="northbound-aliyun" target="northbound-aliyun"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="instanceRef" ref="instanceRef"
:columns="columns" :columns="columns"
:request="query" :request="query"
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params" :params="params"
> >
<template #headerTitle> <template #headerTitle>
@ -19,7 +22,9 @@
@click="handleAdd" @click="handleAdd"
hasPermission="Northbound/AliCloud:add" hasPermission="Northbound/AliCloud:add"
> >
<template #icon><AIcon type="PlusOutlined" /></template> <template #icon
><AIcon type="PlusOutlined"
/></template>
新增 新增
</PermissionButton> </PermissionButton>
</j-space> </j-space>
@ -72,7 +77,9 @@
:popConfirm="item.popConfirm" :popConfirm="item.popConfirm"
:tooltip="item.tooltip" :tooltip="item.tooltip"
@click="item.onClick" @click="item.onClick"
:hasPermission="'Northbound/AliCloud:' + item.key" :hasPermission="
'Northbound/AliCloud:' + item.key
"
> >
<AIcon <AIcon
type="DeleteOutlined" type="DeleteOutlined"
@ -110,14 +117,21 @@
@click="i.onClick" @click="i.onClick"
type="link" type="link"
:danger="i.key === 'delete'" :danger="i.key === 'delete'"
:hasPermission="i.key === 'view' ? true : 'Northbound/AliCloud:' + i.key" :hasPermission="
i.key === 'view'
? true
: 'Northbound/AliCloud:' + i.key
"
> >
<template #icon><AIcon :type="i.icon" /></template> <template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
</template> </template>
</JProTable> </JProTable>
</FullPage>
</page-container> </page-container>
</template> </template>

View File

@ -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);

View File

@ -1,8 +1,10 @@
<template> <template>
<page-container> <page-container>
<FullPage>
<j-card> <j-card>
<j-row :gutter="24"> <div class="box">
<j-col :span="16"> <div class="left">
<div class="left-content">
<TitleComponent data="基本信息" /> <TitleComponent data="基本信息" />
<j-form <j-form
:layout="'vertical'" :layout="'vertical'"
@ -58,7 +60,9 @@
:key="item.id" :key="item.id"
:value="item.id" :value="item.id"
:label="item.name" :label="item.name"
>{{ item.name }}</j-select-option >{{
item.name
}}</j-select-option
> >
</j-select> </j-select>
</j-form-item> </j-form-item>
@ -79,14 +83,18 @@
> >
<AIcon <AIcon
type="QuestionCircleOutlined" type="QuestionCircleOutlined"
style="margin-left: 2px" style="
margin-left: 2px;
"
/> />
</j-tooltip> </j-tooltip>
</span> </span>
</template> </template>
<j-select <j-select
placeholder="请选择设备类型" placeholder="请选择设备类型"
v-model:value="modelRef.applianceType" v-model:value="
modelRef.applianceType
"
show-search show-search
@change="typeChange" @change="typeChange"
> >
@ -95,7 +103,9 @@
:key="item.id" :key="item.id"
:value="item.id" :value="item.id"
:label="item.name" :label="item.name"
>{{ item.name }}</j-select-option >{{
item.name
}}</j-select-option
> >
</j-select> </j-select>
</j-form-item> </j-form-item>
@ -105,14 +115,18 @@
label="产品名称" label="产品名称"
> >
<j-input <j-input
v-model:value="modelRef.productName" v-model:value="
modelRef.productName
"
/> />
</j-form-item> </j-form-item>
</j-col> </j-col>
<j-col :span="24"> <j-col :span="24">
<p>动作映射</p> <p>动作映射</p>
<j-collapse <j-collapse
v-if="modelRef.actionMappings.length" v-if="
modelRef.actionMappings.length
"
:activeKey="actionActiveKey" :activeKey="actionActiveKey"
@change="onActionCollChange" @change="onActionCollChange"
> >
@ -127,7 +141,8 @@
item.action, item.action,
).find( ).find(
(i) => (i) =>
i.id === item.action, i.id ===
item.action,
)?.name )?.name
: `动作映射${index + 1}` : `动作映射${index + 1}`
" "
@ -147,7 +162,8 @@
]" ]"
:rules="{ :rules="{
required: true, required: true,
message: '请选择动作', message:
'请选择动作',
}" }"
> >
<template #label> <template #label>
@ -175,8 +191,12 @@
'', '',
)" )"
:key="i.id" :key="i.id"
:value="i.id" :value="
:label="i.name" i.id
"
:label="
i.name
"
>{{ >{{
i.name i.name
}}</j-select-option }}</j-select-option
@ -193,7 +213,8 @@
]" ]"
:rules="{ :rules="{
required: true, required: true,
message: '请选择操作', message:
'请选择操作',
}" }"
> >
<template #label> <template #label>
@ -267,7 +288,10 @@
<j-col :span="24"> <j-col :span="24">
<j-button <j-button
type="dashed" type="dashed"
style="width: 100%; margin-top: 10px" style="
width: 100%;
margin-top: 10px;
"
@click="addItem" @click="addItem"
> >
<AIcon <AIcon
@ -279,7 +303,9 @@
<j-col :span="24"> <j-col :span="24">
<p style="margin-top: 20px">属性映射</p> <p style="margin-top: 20px">属性映射</p>
<j-collapse <j-collapse
v-if="modelRef.propertyMappings.length" v-if="
modelRef.propertyMappings.length
"
:activeKey="propertyActiveKey" :activeKey="propertyActiveKey"
@change="onPropertyCollChange" @change="onPropertyCollChange"
> >
@ -294,7 +320,8 @@
item.source, item.source,
).find( ).find(
(i) => (i) =>
i.id === item.source, i.id ===
item.source,
)?.name )?.name
: `属性映射${index + 1}` : `属性映射${index + 1}`
" "
@ -302,7 +329,11 @@
<template #extra <template #extra
><AIcon ><AIcon
type="DeleteOutlined" type="DeleteOutlined"
@click="delPropertyItem(index)" @click="
delPropertyItem(
index,
)
"
/></template> /></template>
<j-row :gutter="24"> <j-row :gutter="24">
<j-col :span="12"> <j-col :span="12">
@ -332,7 +363,9 @@
'', '',
)" )"
:key="i.id" :key="i.id"
:value="i.id" :value="
i.id
"
>{{ >{{
i.name i.name
}}</j-select-option }}</j-select-option
@ -367,7 +400,9 @@
item.target, item.target,
)" )"
:key="i.id" :key="i.id"
:value="i.id" :value="
i.id
"
>{{ >{{
i.name i.name
}}</j-select-option }}</j-select-option
@ -385,7 +420,10 @@
<j-col :span="24"> <j-col :span="24">
<j-button <j-button
type="dashed" type="dashed"
style="width: 100%; margin-top: 10px" style="
width: 100%;
margin-top: 10px;
"
@click="addPropertyItem" @click="addPropertyItem"
> >
<AIcon <AIcon
@ -404,7 +442,9 @@
}" }"
> >
<j-textarea <j-textarea
v-model:value="modelRef.description" v-model:value="
modelRef.description
"
placeholder="请输入说明" placeholder="请输入说明"
showCount showCount
:maxlength="200" :maxlength="200"
@ -426,12 +466,14 @@
保存 保存
</PermissionButton> </PermissionButton>
</div> </div>
</j-col> </div>
<j-col :span="8"> </div>
<div class="right">
<Doc /> <Doc />
</j-col> </div>
</j-row> </div>
</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,
}, },
}; };
}; };
@ -721,3 +763,22 @@ 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>

View File

@ -5,11 +5,14 @@
target="northbound-dueros" target="northbound-dueros"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="instanceRef" ref="instanceRef"
:columns="columns" :columns="columns"
:request="query" :request="query"
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:params="params" :params="params"
> >
<template #headerTitle> <template #headerTitle>
@ -19,7 +22,9 @@
@click="handleAdd" @click="handleAdd"
hasPermission="Northbound/DuerOS:add" hasPermission="Northbound/DuerOS:add"
> >
<template #icon><AIcon type="PlusOutlined" /></template> <template #icon
><AIcon type="PlusOutlined"
/></template>
新增 新增
</PermissionButton> </PermissionButton>
</j-space> </j-space>
@ -47,7 +52,9 @@
</Ellipsis> </Ellipsis>
<j-row style="margin-top: 15px"> <j-row style="margin-top: 15px">
<j-col :span="12"> <j-col :span="12">
<div class="card-item-content-text">产品</div> <div class="card-item-content-text">
产品
</div>
<Ellipsis> <Ellipsis>
<div>{{ slotProps?.productName }}</div> <div>{{ slotProps?.productName }}</div>
</Ellipsis> </Ellipsis>
@ -57,7 +64,9 @@
设备类型 设备类型
</div> </div>
<Ellipsis> <Ellipsis>
<div>{{ slotProps?.applianceType?.text }}</div> <div>
{{ slotProps?.applianceType?.text }}
</div>
</Ellipsis> </Ellipsis>
</j-col> </j-col>
</j-row> </j-row>
@ -113,14 +122,21 @@
@click="i.onClick" @click="i.onClick"
type="link" type="link"
:danger="i.key === 'delete'" :danger="i.key === 'delete'"
:hasPermission="i.key === 'view' ? true : 'Northbound/DuerOS:' + i.key" :hasPermission="
i.key === 'view'
? true
: 'Northbound/DuerOS:' + i.key
"
> >
<template #icon><AIcon :type="i.icon" /></template> <template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
</template> </template>
</JProTable> </JProTable>
</FullPage>
</page-container> </page-container>
</template> </template>

View File

@ -1,5 +1,4 @@
<template> <template>
<j-card>
<SaveChild <SaveChild
v-if="childVisible" v-if="childVisible"
@close-child-save="closeChildSave" @close-child-save="closeChildSave"
@ -10,12 +9,16 @@
:columns="columns" :columns="columns"
target="child-device" target="child-device"
@search="handleSearch" @search="handleSearch"
class="child-device-search" class="device-child-device-search"
/> />
<!-- <j-divider /> -->
<JProTable <JProTable
ref="childDeviceRef" ref="childDeviceRef"
:columns="columns" :columns="columns"
:request="query" :request="query"
:bodyStyle="{
padding: 0
}"
:defaultParams="{ :defaultParams="{
terms: [ terms: [
{ {
@ -33,13 +36,12 @@
:params="params" :params="params"
:model="'TABLE'" :model="'TABLE'"
> >
<template #headerTitle> <template #rightExtraRender>
<j-space> <j-space>
<PermissionButton <PermissionButton
type="primary" type="primary"
v-if=" v-if="
detail?.accessProvider === detail?.accessProvider === 'official-edge-gateway'
'official-edge-gateway'
" "
hasPermission="device/Instance:update" hasPermission="device/Instance:update"
@click=" @click="
@ -98,9 +100,7 @@
style="padding: 0px" style="padding: 0px"
:hasPermission="'device/Instance:' + i.key" :hasPermission="'device/Instance:' + i.key"
> >
<template #icon <template #icon><AIcon :type="i.icon" /></template>
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
@ -108,7 +108,6 @@
</JProTable> </JProTable>
<BindChildDevice v-if="visible" @change="closeBindDevice" /> <BindChildDevice v-if="visible" @change="closeBindDevice" />
</div> </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>

View File

@ -1,5 +1,4 @@
<template> <template>
<j-card>
<div class="diagnose"> <div class="diagnose">
<div <div
class="diagnose-header" class="diagnose-header"
@ -9,19 +8,11 @@
<div class="diagnose-img"> <div class="diagnose-img">
<div <div
v-if="topState === 'loading'" v-if="topState === 'loading'"
style=" style="width: 100%; height: 100%; position: relative"
width: 100%;
height: 100%;
position: relative;
"
> >
<img <img
:src="headerImgMap.get(topState)" :src="headerImgMap.get(topState)"
style=" style="height: 100%; position: absolute; z-index: 2"
height: 100%;
position: absolute;
z-index: 2;
"
/> />
<img <img
:src="getImage('/diagnose/loading-1.png')" :src="getImage('/diagnose/loading-1.png')"
@ -66,9 +57,7 @@
" "
v-for="item in tabList" v-for="item in tabList"
:key="item.key" :key="item.key"
:style=" :style="activeKey === item.key ? { ...activeStyle } : {}"
activeKey === item.key ? { ...activeStyle } : {}
"
@click="onTabChange(item.key)" @click="onTabChange(item.key)"
> >
{{ item.text }} {{ item.text }}
@ -90,7 +79,6 @@
</template> </template>
</div> </div>
</div> </div>
</j-card>
</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>

View File

@ -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>

View File

@ -1,5 +1,4 @@
<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"
@ -17,7 +16,6 @@
</j-tabs> </j-tabs>
<component :is="tabs[activeKey]" /> <component :is="tabs[activeKey]" />
</template> </template>
</j-card>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -1,5 +1,4 @@
<template> <template>
<j-card>
<j-descriptions bordered> <j-descriptions bordered>
<template #title> <template #title>
设备信息 设备信息
@ -84,7 +83,6 @@
@close="visible = false" @close="visible = false"
@save="saveBtn" @save="saveBtn"
/> />
</j-card>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>

View File

@ -1,11 +1,10 @@
<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="search" class="device-log-search"
/> />
<JProTable <JProTable
ref="instanceRefLog" ref="instanceRefLog"
@ -22,9 +21,7 @@
<template #timestamp="slotProps"> <template #timestamp="slotProps">
{{ {{
slotProps.timestamp slotProps.timestamp
? moment(slotProps.timestamp).format( ? moment(slotProps.timestamp).format('YYYY-MM-DD HH:mm:ss')
'YYYY-MM-DD HH:mm:ss',
)
: '' : ''
}} }}
</template> </template>
@ -45,7 +42,6 @@
</j-space> </j-space>
</template> </template>
</JProTable> </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>

View File

@ -1,6 +1,5 @@
<template> <template>
<j-card>
<div> <div>
<div class="top"> <div class="top">
<div class="top-left"> <div class="top-left">
@ -8,15 +7,23 @@
<AIcon type="ExclamationCircleOutlined" /> <AIcon type="ExclamationCircleOutlined" />
<template v-if="topTitle === 'rest'"> <template v-if="topTitle === 'rest'">
当前数据解析内容已脱离产品影响 当前数据解析内容已脱离产品影响
<PermissionButton type="link" hasPermission="device/Instance:update" @click="rest()"> <PermissionButton
type="link"
hasPermission="device/Instance:update"
@click="rest()"
>
重置 重置
</PermissionButton> </PermissionButton>
后将继承产品数据解析内容 后将继承产品数据解析内容
</template> </template>
<template v-else> <template v-else>
当前数据解析内容继承自产品, 当前数据解析内容继承自产品,
<PermissionButton type="link" hasPermission="device/Instance:update" @click="readOnly = false" <PermissionButton
:style="color"> type="link"
hasPermission="device/Instance:update"
@click="readOnly = false"
:style="color"
>
修改 修改
</PermissionButton> </PermissionButton>
后将脱离产品影响 后将脱离产品影响
@ -25,163 +32,231 @@
</div> </div>
<div> <div>
脚本语言: 脚本语言:
<j-select :defaultValue="'JavaScript'" style="width: 200px;margin-left: 5px;"> <j-select
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option> :defaultValue="'JavaScript'"
style="width: 200px; margin-left: 5px"
>
<j-select-option value="JavaScript"
>JavaScript(ECMAScript 5)</j-select-option
>
</j-select> </j-select>
<AIcon type="ExpandOutlined" style="margin-left: 20px;" @click="toggle" /> <AIcon
type="ExpandOutlined"
style="margin-left: 20px"
@click="toggle"
/>
</div> </div>
</div> </div>
<div class="edit" ref="el"> <div class="edit" ref="el">
<div v-show="readOnly" class="edit-only" @click="() => { <div
v-show="readOnly"
class="edit-only"
@click="
() => {
message.warning({ message.warning({
key: 1, key: 1,
content: () => '请点击上方修改字样,用以编辑脚本', content: () => '请点击上方修改字样,用以编辑脚本',
style: { style: {
marginTop: '260px' marginTop: '260px',
},
});
} }
"
}) ></div>
}"></div> <j-monaco-editor
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" /> language="javascript"
style="height: 100%"
theme="vs"
v-model:modelValue="editorValue"
/>
</div> </div>
<div class="bottom"> <div class="bottom">
<div style="width: 49.5%;"> <div style="width: 49.5%">
<div class="bottom-title"> <div class="bottom-title">
<div class="bottom-title-text">模拟输入</div> <div class="bottom-title-text">模拟输入</div>
<div class="bottom-title-topic"> <div class="bottom-title-topic">
<template v-if="instanceStore.current.transport === 'MQTT'"> <template
<div style="margin-right: 5px;">Topic:</div> v-if="instanceStore.current.transport === 'MQTT'"
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList" >
:allowClear="true" :filterOption="filterOption" v-model:value="topic" /> <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> <div style="margin-right: 5px">URL:</div>
<j-input placeholder="请输入URL" v-model:value="url" style="width: 300px"></j-input> <j-input
placeholder="请输入URL"
v-model:value="url"
style="width: 300px"
></j-input>
</template> </template>
</div> </div>
</div> </div>
<j-textarea :rows="5" placeholder="// 二进制数据以0x开头的十六进制输入字符串数据输入原始字符串" style="margin-top: 10px;" <j-textarea
v-model:value="simulation" /> :rows="5"
placeholder="// 二进制数据以0x开头的十六进制输入字符串数据输入原始字符串"
style="margin-top: 10px"
v-model:value="simulation"
/>
</div> </div>
<div style="width: 49.5%;"> <div style="width: 49.5%">
<div class="bottom-title"> <div class="bottom-title">
<div class="bottom-title-text">运行结果</div> <div class="bottom-title-text">运行结果</div>
</div> </div>
<j-textarea :autoSize="{ minRows: 5 }" :style="resStyle" v-model:value="result" /> <j-textarea
:autoSize="{ minRows: 5 }"
:style="resStyle"
v-model:value="result"
/>
</div> </div>
</div> </div>
</div> </div>
<div style="margin-top: 10px;margin-left: 10px;"> <div style="margin-top: 10px; margin-left: 10px">
<PermissionButton type="primary" hasPermission="device/Instance:update" :loading="loading" <PermissionButton
:disabled="isDisabled" @click="debug()" :tooltip="{ type="primary"
hasPermission="device/Instance:update"
:loading="loading"
:disabled="isDisabled"
@click="debug()"
:tooltip="{
title: '需输入脚本和模拟数据后再点击', title: '需输入脚本和模拟数据后再点击',
}"> }"
>
调试 调试
</PermissionButton> </PermissionButton>
<PermissionButton hasPermission="device/Instance:update" :loading="loading" :disabled="!isTest" @click="save()" <PermissionButton
:style="{ marginLeft: '10px' }" :tooltip="{ hasPermission="device/Instance:update"
:loading="loading"
:disabled="!isTest"
@click="save()"
:style="{ marginLeft: '10px' }"
:tooltip="{
title: isTest ? '' : '请先调试', title: isTest ? '' : '请先调试',
}"> }"
>
保存 保存
</PermissionButton> </PermissionButton>
</div> </div>
</j-card>
</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(() =>
isBoolean(resultValue.value.success)
? {
'margin-top': '10px', 'margin-top': '10px',
'border-color': resultValue.value.success ? 'green' : 'red' 'border-color': resultValue.value.success ? 'green' : 'red',
} : { }
: {
'margin-top': '10px', 'margin-top': '10px',
})) },
const filterOption = (inputValue: any, option: any) => option!.value.indexOf(inputValue) !== -1 );
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'>

View File

@ -1,5 +1,4 @@
<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
@ -17,11 +16,7 @@
:tabBarStyle="{ width: '200px' }" :tabBarStyle="{ width: '200px' }"
@change="tabChange" @change="tabChange"
> >
<j-tab-pane <j-tab-pane v-for="i in tabList" :key="i.key" :tab="i.tab" />
v-for="i in tabList"
:key="i.key"
:tab="i.tab"
/>
</j-tabs> </j-tabs>
<JEmpty v-else style="margin: 180px 0" /> <JEmpty v-else style="margin: 180px 0" />
</div> </div>
@ -31,7 +26,6 @@
<JEmpty v-else style="margin: 220px 0" /> <JEmpty v-else style="margin: 220px 0" />
</div> </div>
</div> </div>
</j-card>
</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) => {
if (events && newVal.length) {
newVal.map((item: any) => { newVal.map((item: any) => {
tabList.value.push({ tabList.value.push({
...item, ...item,
key: item.id, key: item.id,
tab: item.name, tab: item.name,
type: 'event', type: 'event',
}) });
}) });
} }
}, { },
{
deep: true, deep: true,
immediate: 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>

View File

@ -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>

View File

@ -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>
<FullPage>
<j-card :bordered="false">
<component <component
:is="tabs[instanceStore.tabActiveKey]" :is="tabs[instanceStore.tabActiveKey]"
v-bind="{ type: 'device' }" v-bind="{ type: 'device' }"
@onJump="onTabChange" @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,7 +272,7 @@ 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));
@ -274,10 +280,10 @@ const getDetailFn = async () => {
getDetail(); getDetail();
} }
instanceStore.tabActiveKey = routerParams.params.value.tab || 'Info'; instanceStore.tabActiveKey = routerParams.params.value.tab || 'Info';
} };
onMounted(() => { onMounted(() => {
getDetailFn() getDetailFn();
}); });
const onBack = () => { const onBack = () => {

View File

@ -5,11 +5,14 @@
target="device-instance" target="device-instance"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="instanceRef" ref="instanceRef"
:columns="columns" :columns="columns"
:request="query" :request="query"
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
:rowSelection=" :rowSelection="
isCheck isCheck
? { ? {
@ -27,7 +30,9 @@
@click="handleAdd" @click="handleAdd"
hasPermission="device/Instance:add" hasPermission="device/Instance:add"
> >
<template #icon><AIcon type="PlusOutlined" /></template> <template #icon
><AIcon type="PlusOutlined"
/></template>
新增 新增
</PermissionButton> </PermissionButton>
<BatchDropdown <BatchDropdown
@ -159,7 +164,9 @@
> >
<template #img> <template #img>
<img <img
:src="getImage('/device/instance/device-card.png')" :src="
getImage('/device/instance/device-card.png')
"
/> />
</template> </template>
<template #content> <template #content>
@ -220,7 +227,11 @@
</template> </template>
<template #createTime="slotProps"> <template #createTime="slotProps">
<span>{{ <span>{{
slotProps?.createTime ? dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') : '' slotProps?.createTime
? dayjs(slotProps.createTime).format(
'YYYY-MM-DD HH:mm:ss',
)
: ''
}}</span> }}</span>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
@ -245,12 +256,15 @@
: 'device/Instance:' + i.key : 'device/Instance:' + i.key
" "
> >
<template #icon><AIcon :type="i.icon" /></template> <template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
</template> </template>
</JProTable> </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;

View File

@ -5,6 +5,7 @@
target="edge-device" target="edge-device"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="edgeDeviceRef" ref="edgeDeviceRef"
:columns="columns" :columns="columns"
@ -20,7 +21,9 @@
@click="handleAdd" @click="handleAdd"
hasPermission="edge/Device:add" hasPermission="edge/Device:add"
> >
<template #icon><AIcon type="PlusOutlined" /></template> <template #icon
><AIcon type="PlusOutlined"
/></template>
新增 新增
</PermissionButton> </PermissionButton>
<PermissionButton <PermissionButton
@ -48,7 +51,9 @@
> >
<template #img> <template #img>
<img <img
:src="getImage('/device/instance/device-card.png')" :src="
getImage('/device/instance/device-card.png')
"
/> />
</template> </template>
<template #content> <template #content>
@ -112,7 +117,9 @@
</template> </template>
<template #registryTime="slotProps"> <template #registryTime="slotProps">
<span>{{ <span>{{
dayjs(slotProps.registryTime).format('YYYY-MM-DD HH:mm:ss') dayjs(slotProps.registryTime).format(
'YYYY-MM-DD HH:mm:ss',
)
}}</span> }}</span>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
@ -131,21 +138,33 @@
type="link" type="link"
style="padding: 0 5px" style="padding: 0 5px"
:danger="i.key === 'delete'" :danger="i.key === 'delete'"
:hasPermission="i.key === 'view' ? true : 'edge/Device:' + i.key" :hasPermission="
i.key === 'view'
? true
: 'edge/Device:' + i.key
"
> >
<template #icon><AIcon :type="i.icon" /></template> <template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
</template> </template>
</JProTable> </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>

View File

@ -5,6 +5,7 @@
target="edge-resource" target="edge-resource"
@search="handleSearch" @search="handleSearch"
/> />
<FullPage>
<JProTable <JProTable
ref="edgeResourceRef" ref="edgeResourceRef"
:columns="columns" :columns="columns"
@ -26,7 +27,9 @@
> >
<template #img> <template #img>
<img <img
:src="getImage('/device/instance/device-card.png')" :src="
getImage('/device/instance/device-card.png')
"
/> />
</template> </template>
<template #content> <template #content>
@ -42,7 +45,8 @@
</div> </div>
<Ellipsis>{{ <Ellipsis>{{
options.find( options.find(
(i) => i.value === slotProps.category, (i) =>
i.value === slotProps.category,
)?.label || slotProps.category )?.label || slotProps.category
}}</Ellipsis> }}</Ellipsis>
</j-col> </j-col>
@ -99,7 +103,9 @@
</template> </template>
<template #createTime="slotProps"> <template #createTime="slotProps">
<span>{{ <span>{{
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') dayjs(slotProps.createTime).format(
'YYYY-MM-DD HH:mm:ss',
)
}}</span> }}</span>
</template> </template>
<template #action="slotProps"> <template #action="slotProps">
@ -124,12 +130,16 @@
: 'edge/Resource:' + i.key : 'edge/Resource:' + i.key
" "
> >
<template #icon><AIcon :type="i.icon" /></template> <template #icon
><AIcon :type="i.icon"
/></template>
</PermissionButton> </PermissionButton>
</template> </template>
</j-space> </j-space>
</template> </template>
</JProTable> </JProTable>
</FullPage>
<Save <Save
v-if="visible" v-if="visible"
:data="current" :data="current"

View File

@ -278,7 +278,7 @@ watch(
} }
} }
}, },
{ immediate: true, deep: true }, { immediate: true },
); );
watch( watch(

View File

@ -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';
} }
} }
}, },

View File

@ -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',