Merge branch 'dev' of github.com:jetlinks/jetlinks-ui-vue into dev
This commit is contained in:
commit
f878cffe82
|
@ -5,6 +5,7 @@ type DepartmentStateType = {
|
|||
productId: string;
|
||||
optType: string | undefined;
|
||||
crossPageKeys: string[];
|
||||
changedApis: any;
|
||||
}
|
||||
|
||||
export const useDepartmentStore = defineStore({
|
||||
|
@ -16,6 +17,7 @@ export const useDepartmentStore = defineStore({
|
|||
// 2. optType === ': 产品资产分配后, 自动弹出设备资产分配
|
||||
optType: '',
|
||||
crossPageKeys: [], // 表格跨页多选的keys
|
||||
changedApis: {},
|
||||
}),
|
||||
actions: {
|
||||
setProductId(value: string) {
|
||||
|
@ -27,6 +29,9 @@ export const useDepartmentStore = defineStore({
|
|||
setSelectedKeys(value: string[], type?: string) {
|
||||
// 分页保留选中项
|
||||
this.crossPageKeys = type === 'concat' ? [...new Set([...this.crossPageKeys, ...value])] : value;
|
||||
},
|
||||
setChangedApis(value: any) {
|
||||
this.changedApis = { ...this.changedApis, ...value };
|
||||
}
|
||||
}
|
||||
})
|
|
@ -57,7 +57,7 @@ import { getImage } from '@/utils/comm';
|
|||
|
||||
<style lang="less" scoped>
|
||||
.doc {
|
||||
height: 1000px;
|
||||
height: 100%;
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
color: rgba(#000, 0.8);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="16">
|
||||
<div class="box">
|
||||
<div class="left">
|
||||
<div class="left-content">
|
||||
<TitleComponent data="基本信息" />
|
||||
<j-form
|
||||
:layout="'vertical'"
|
||||
|
@ -49,7 +51,9 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
|
@ -57,7 +61,8 @@
|
|||
<j-select
|
||||
placeholder="请选择服务地址"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.regionId
|
||||
modelRef.accessConfig
|
||||
.regionId
|
||||
"
|
||||
show-search
|
||||
@blur="productChange"
|
||||
|
@ -67,14 +72,19 @@
|
|||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>{{ item.name }}</j-select-option
|
||||
>{{
|
||||
item.name
|
||||
}}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'instanceId']"
|
||||
:name="[
|
||||
'accessConfig',
|
||||
'instanceId',
|
||||
]"
|
||||
>
|
||||
<template #label>
|
||||
<span>
|
||||
|
@ -84,7 +94,9 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
|
@ -92,7 +104,8 @@
|
|||
<j-input
|
||||
placeholder="请输入实例ID"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.instanceId
|
||||
modelRef.accessConfig
|
||||
.instanceId
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
|
@ -100,7 +113,10 @@
|
|||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'accessKeyId']"
|
||||
:name="[
|
||||
'accessConfig',
|
||||
'accessKeyId',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
|
@ -120,7 +136,9 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
|
@ -128,7 +146,8 @@
|
|||
<j-input
|
||||
placeholder="请输入accessKey"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.accessKeyId
|
||||
modelRef.accessConfig
|
||||
.accessKeyId
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
|
@ -136,11 +155,15 @@
|
|||
</j-col>
|
||||
<j-col :span="24">
|
||||
<j-form-item
|
||||
:name="['accessConfig', 'accessSecret']"
|
||||
:name="[
|
||||
'accessConfig',
|
||||
'accessSecret',
|
||||
]"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入accessSecret',
|
||||
message:
|
||||
'请输入accessSecret',
|
||||
},
|
||||
{
|
||||
max: 64,
|
||||
|
@ -156,7 +179,9 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
|
@ -164,7 +189,8 @@
|
|||
<j-input
|
||||
placeholder="请输入accessSecret"
|
||||
v-model:value="
|
||||
modelRef.accessConfig.accessSecret
|
||||
modelRef.accessConfig
|
||||
.accessSecret
|
||||
"
|
||||
@blur="productChange"
|
||||
/>
|
||||
|
@ -186,7 +212,9 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
|
@ -224,11 +252,12 @@
|
|||
:key="index"
|
||||
:header="
|
||||
item.productKey
|
||||
? (aliyunProductList.find(
|
||||
? aliyunProductList.find(
|
||||
(i) =>
|
||||
i.productKey ===
|
||||
item.productKey,
|
||||
)?.productName || `产品映射${index + 1}`)
|
||||
)?.productName ||
|
||||
`产品映射${index + 1}`
|
||||
: `产品映射${index + 1}`
|
||||
"
|
||||
>
|
||||
|
@ -261,9 +290,12 @@
|
|||
>
|
||||
<j-select-option
|
||||
v-for="i in getAliyunProductList(
|
||||
item?.productKey || ''
|
||||
item?.productKey ||
|
||||
'',
|
||||
)"
|
||||
:key="i.productKey"
|
||||
:key="
|
||||
i.productKey
|
||||
"
|
||||
:value="
|
||||
i.productKey
|
||||
"
|
||||
|
@ -300,11 +332,16 @@
|
|||
>
|
||||
<j-select-option
|
||||
v-for="i in getPlatProduct(
|
||||
item.productId || ''
|
||||
item.productId ||
|
||||
'',
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i?.id"
|
||||
:label="i.name"
|
||||
:value="
|
||||
i?.id
|
||||
"
|
||||
:label="
|
||||
i.name
|
||||
"
|
||||
>{{
|
||||
i.name
|
||||
}}</j-select-option
|
||||
|
@ -322,7 +359,10 @@
|
|||
<j-col :span="24">
|
||||
<j-button
|
||||
type="dashed"
|
||||
style="width: 100%; margin-top: 10px"
|
||||
style="
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
"
|
||||
@click="addItem"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -341,7 +381,9 @@
|
|||
}"
|
||||
>
|
||||
<j-textarea
|
||||
v-model:value="modelRef.description"
|
||||
v-model:value="
|
||||
modelRef.description
|
||||
"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:maxlength="200"
|
||||
|
@ -355,17 +397,22 @@
|
|||
type="primary"
|
||||
:loading="loading"
|
||||
@click="saveBtn"
|
||||
:hasPermission="['Northbound/AliCloud:add', 'Northbound/AliCloud:update']"
|
||||
:hasPermission="[
|
||||
'Northbound/AliCloud:add',
|
||||
'Northbound/AliCloud:update',
|
||||
]"
|
||||
>
|
||||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<Doc />
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -489,14 +536,16 @@ const saveBtn = () => {
|
|||
.validate()
|
||||
.then(async (data: any) => {
|
||||
const product = (aliyunProductList.value || []).find(
|
||||
(item: any) =>
|
||||
item?.productKey === data?.bridgeProductKey,
|
||||
(item: any) => item?.productKey === data?.bridgeProductKey,
|
||||
);
|
||||
data.bridgeProductName = product?.productName || '';
|
||||
loading.value = true;
|
||||
const resp = await savePatch({...toRaw(modelRef), ...data}).finally(() => {
|
||||
const resp = await savePatch({
|
||||
...toRaw(modelRef),
|
||||
...data,
|
||||
}).finally(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
formRef.value.resetFields();
|
||||
|
@ -540,3 +589,22 @@ watch(
|
|||
{ immediate: true, deep: true },
|
||||
);
|
||||
</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,11 +5,14 @@
|
|||
target="northbound-aliyun"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="instanceRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
|
@ -19,7 +22,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="Northbound/AliCloud:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined"
|
||||
/></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</j-space>
|
||||
|
@ -72,7 +77,9 @@
|
|||
:popConfirm="item.popConfirm"
|
||||
:tooltip="item.tooltip"
|
||||
@click="item.onClick"
|
||||
:hasPermission="'Northbound/AliCloud:' + item.key"
|
||||
:hasPermission="
|
||||
'Northbound/AliCloud:' + item.key
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
|
@ -110,14 +117,21 @@
|
|||
@click="i.onClick"
|
||||
type="link"
|
||||
: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>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ import { getImage } from '@/utils/comm';
|
|||
|
||||
<style lang="less" scoped>
|
||||
.doc {
|
||||
height: 1000px;
|
||||
height: 100%;
|
||||
padding: 24px;
|
||||
overflow-y: auto;
|
||||
color: rgba(#000, 0.8);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<j-card>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="16">
|
||||
<div class="box">
|
||||
<div class="left">
|
||||
<div class="left-content">
|
||||
<TitleComponent data="基本信息" />
|
||||
<j-form
|
||||
:layout="'vertical'"
|
||||
|
@ -58,7 +60,9 @@
|
|||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>{{ item.name }}</j-select-option
|
||||
>{{
|
||||
item.name
|
||||
}}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
@ -79,14 +83,18 @@
|
|||
>
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
style="
|
||||
margin-left: 2px;
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
<j-select
|
||||
placeholder="请选择设备类型"
|
||||
v-model:value="modelRef.applianceType"
|
||||
v-model:value="
|
||||
modelRef.applianceType
|
||||
"
|
||||
show-search
|
||||
@change="typeChange"
|
||||
>
|
||||
|
@ -95,7 +103,9 @@
|
|||
:key="item.id"
|
||||
:value="item.id"
|
||||
:label="item.name"
|
||||
>{{ item.name }}</j-select-option
|
||||
>{{
|
||||
item.name
|
||||
}}</j-select-option
|
||||
>
|
||||
</j-select>
|
||||
</j-form-item>
|
||||
|
@ -105,14 +115,18 @@
|
|||
label="产品名称"
|
||||
>
|
||||
<j-input
|
||||
v-model:value="modelRef.productName"
|
||||
v-model:value="
|
||||
modelRef.productName
|
||||
"
|
||||
/>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
<j-col :span="24">
|
||||
<p>动作映射</p>
|
||||
<j-collapse
|
||||
v-if="modelRef.actionMappings.length"
|
||||
v-if="
|
||||
modelRef.actionMappings.length
|
||||
"
|
||||
:activeKey="actionActiveKey"
|
||||
@change="onActionCollChange"
|
||||
>
|
||||
|
@ -127,7 +141,8 @@
|
|||
item.action,
|
||||
).find(
|
||||
(i) =>
|
||||
i.id === item.action,
|
||||
i.id ===
|
||||
item.action,
|
||||
)?.name
|
||||
: `动作映射${index + 1}`
|
||||
"
|
||||
|
@ -147,7 +162,8 @@
|
|||
]"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '请选择动作',
|
||||
message:
|
||||
'请选择动作',
|
||||
}"
|
||||
>
|
||||
<template #label>
|
||||
|
@ -175,8 +191,12 @@
|
|||
'',
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i.id"
|
||||
:label="i.name"
|
||||
:value="
|
||||
i.id
|
||||
"
|
||||
:label="
|
||||
i.name
|
||||
"
|
||||
>{{
|
||||
i.name
|
||||
}}</j-select-option
|
||||
|
@ -193,7 +213,8 @@
|
|||
]"
|
||||
:rules="{
|
||||
required: true,
|
||||
message: '请选择操作',
|
||||
message:
|
||||
'请选择操作',
|
||||
}"
|
||||
>
|
||||
<template #label>
|
||||
|
@ -267,7 +288,10 @@
|
|||
<j-col :span="24">
|
||||
<j-button
|
||||
type="dashed"
|
||||
style="width: 100%; margin-top: 10px"
|
||||
style="
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
"
|
||||
@click="addItem"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -279,7 +303,9 @@
|
|||
<j-col :span="24">
|
||||
<p style="margin-top: 20px">属性映射</p>
|
||||
<j-collapse
|
||||
v-if="modelRef.propertyMappings.length"
|
||||
v-if="
|
||||
modelRef.propertyMappings.length
|
||||
"
|
||||
:activeKey="propertyActiveKey"
|
||||
@change="onPropertyCollChange"
|
||||
>
|
||||
|
@ -294,7 +320,8 @@
|
|||
item.source,
|
||||
).find(
|
||||
(i) =>
|
||||
i.id === item.source,
|
||||
i.id ===
|
||||
item.source,
|
||||
)?.name
|
||||
: `属性映射${index + 1}`
|
||||
"
|
||||
|
@ -302,7 +329,11 @@
|
|||
<template #extra
|
||||
><AIcon
|
||||
type="DeleteOutlined"
|
||||
@click="delPropertyItem(index)"
|
||||
@click="
|
||||
delPropertyItem(
|
||||
index,
|
||||
)
|
||||
"
|
||||
/></template>
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="12">
|
||||
|
@ -332,7 +363,9 @@
|
|||
'',
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i.id"
|
||||
:value="
|
||||
i.id
|
||||
"
|
||||
>{{
|
||||
i.name
|
||||
}}</j-select-option
|
||||
|
@ -367,7 +400,9 @@
|
|||
item.target,
|
||||
)"
|
||||
:key="i.id"
|
||||
:value="i.id"
|
||||
:value="
|
||||
i.id
|
||||
"
|
||||
>{{
|
||||
i.name
|
||||
}}</j-select-option
|
||||
|
@ -385,7 +420,10 @@
|
|||
<j-col :span="24">
|
||||
<j-button
|
||||
type="dashed"
|
||||
style="width: 100%; margin-top: 10px"
|
||||
style="
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
"
|
||||
@click="addPropertyItem"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -404,7 +442,9 @@
|
|||
}"
|
||||
>
|
||||
<j-textarea
|
||||
v-model:value="modelRef.description"
|
||||
v-model:value="
|
||||
modelRef.description
|
||||
"
|
||||
placeholder="请输入说明"
|
||||
showCount
|
||||
:maxlength="200"
|
||||
|
@ -426,12 +466,14 @@
|
|||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</j-col>
|
||||
<j-col :span="8">
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<Doc />
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -504,7 +546,7 @@ const onActionTypeChange = (_index: number) => {
|
|||
properties: undefined,
|
||||
functionId: undefined,
|
||||
inputs: [],
|
||||
value: undefined
|
||||
value: undefined,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -721,3 +763,22 @@ watch(
|
|||
{ immediate: true, deep: true },
|
||||
);
|
||||
</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,11 +5,14 @@
|
|||
target="northbound-dueros"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="instanceRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
|
@ -19,7 +22,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="Northbound/DuerOS:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined"
|
||||
/></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
</j-space>
|
||||
|
@ -47,7 +52,9 @@
|
|||
</Ellipsis>
|
||||
<j-row style="margin-top: 15px">
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">产品</div>
|
||||
<div class="card-item-content-text">
|
||||
产品
|
||||
</div>
|
||||
<Ellipsis>
|
||||
<div>{{ slotProps?.productName }}</div>
|
||||
</Ellipsis>
|
||||
|
@ -57,7 +64,9 @@
|
|||
设备类型
|
||||
</div>
|
||||
<Ellipsis>
|
||||
<div>{{ slotProps?.applianceType?.text }}</div>
|
||||
<div>
|
||||
{{ slotProps?.applianceType?.text }}
|
||||
</div>
|
||||
</Ellipsis>
|
||||
</j-col>
|
||||
</j-row>
|
||||
|
@ -113,14 +122,21 @@
|
|||
@click="i.onClick"
|
||||
type="link"
|
||||
: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>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
target="category"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="tableRef"
|
||||
:columns="table.columns"
|
||||
|
@ -55,12 +56,15 @@
|
|||
style="padding: 0px"
|
||||
:danger="i.key === 'delete'"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<!-- 新增和编辑弹窗 -->
|
||||
<ModifyModal
|
||||
ref="modifyRef"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<SaveChild
|
||||
v-if="childVisible"
|
||||
@close-child-save="closeChildSave"
|
||||
|
@ -10,12 +9,16 @@
|
|||
:columns="columns"
|
||||
target="child-device"
|
||||
@search="handleSearch"
|
||||
class="child-device-search"
|
||||
class="device-child-device-search"
|
||||
/>
|
||||
<!-- <j-divider /> -->
|
||||
<JProTable
|
||||
ref="childDeviceRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
:bodyStyle="{
|
||||
padding: 0
|
||||
}"
|
||||
:defaultParams="{
|
||||
terms: [
|
||||
{
|
||||
|
@ -33,13 +36,12 @@
|
|||
:params="params"
|
||||
:model="'TABLE'"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<template #rightExtraRender>
|
||||
<j-space>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
v-if="
|
||||
detail?.accessProvider ===
|
||||
'official-edge-gateway'
|
||||
detail?.accessProvider === 'official-edge-gateway'
|
||||
"
|
||||
hasPermission="device/Instance:update"
|
||||
@click="
|
||||
|
@ -98,9 +100,7 @@
|
|||
style="padding: 0px"
|
||||
:hasPermission="'device/Instance:' + i.key"
|
||||
>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
|
@ -108,7 +108,6 @@
|
|||
</JProTable>
|
||||
<BindChildDevice v-if="visible" @change="closeBindDevice" />
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -147,10 +146,10 @@ const columns = [
|
|||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
ellipsis: true,
|
||||
search:{
|
||||
type:'string',
|
||||
defaultTermType: 'eq'
|
||||
}
|
||||
search: {
|
||||
type: 'string',
|
||||
defaultTermType: 'eq',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '设备名称',
|
||||
|
@ -303,12 +302,8 @@ const closeChildSave = () => {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.child-device-search {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
:deep(._jtable-body_1eyxz_1 ._jtable-body-header_1eyxz_6) {
|
||||
justify-content: flex-end;
|
||||
<style lang="less">
|
||||
.device-child-device-search {
|
||||
padding: 0px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<div class="diagnose">
|
||||
<div
|
||||
class="diagnose-header"
|
||||
|
@ -9,19 +8,11 @@
|
|||
<div class="diagnose-img">
|
||||
<div
|
||||
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;
|
||||
"
|
||||
style="height: 100%; position: absolute; z-index: 2"
|
||||
/>
|
||||
<img
|
||||
:src="getImage('/diagnose/loading-1.png')"
|
||||
|
@ -66,9 +57,7 @@
|
|||
"
|
||||
v-for="item in tabList"
|
||||
:key="item.key"
|
||||
:style="
|
||||
activeKey === item.key ? { ...activeStyle } : {}
|
||||
"
|
||||
:style="activeKey === item.key ? { ...activeStyle } : {}"
|
||||
@click="onTabChange(item.key)"
|
||||
>
|
||||
{{ item.text }}
|
||||
|
@ -90,7 +79,6 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -160,7 +148,7 @@ const countChange = (num: number) => {
|
|||
};
|
||||
|
||||
const init = () => {
|
||||
flag.value = true
|
||||
flag.value = true;
|
||||
activeKey.value = 'status';
|
||||
const provider = instanceStore.current?.accessProvider;
|
||||
if (provider === 'fixed-media' || provider === 'gb28181-2016') {
|
||||
|
@ -175,16 +163,16 @@ const init = () => {
|
|||
providerType.value = 'network';
|
||||
}
|
||||
topState.value = 'loading';
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
init()
|
||||
}, 500)
|
||||
init();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
flag.value = false
|
||||
flag.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
||||
<j-card>
|
||||
<j-card :bordered="false" style="padding: 0">
|
||||
<template #extra>
|
||||
<j-space>
|
||||
<j-button @click="visible = true">批量映射</j-button>
|
||||
|
@ -188,7 +188,7 @@
|
|||
:edgeId="instanceStore.current.parentId"
|
||||
/>
|
||||
</j-spin>
|
||||
<j-card v-else>
|
||||
<j-card v-else :bordered="false" style="padding: 0">
|
||||
<JEmpty description="暂无数据,请配置物模型" style="margin: 10% 0" />
|
||||
</j-card>
|
||||
</template>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<j-empty
|
||||
v-if="!metadata || (metadata && !metadata.functions.length)"
|
||||
style="margin-top: 50px"
|
||||
|
@ -17,7 +16,6 @@
|
|||
</j-tabs>
|
||||
<component :is="tabs[activeKey]" />
|
||||
</template>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<j-descriptions bordered>
|
||||
<template #title>
|
||||
设备信息
|
||||
|
@ -84,7 +83,6 @@
|
|||
@close="visible = false"
|
||||
@save="saveBtn"
|
||||
/>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<pro-search
|
||||
:columns="columns"
|
||||
target="device-instance-log"
|
||||
@search="handleSearch"
|
||||
type="simple"
|
||||
class="search"
|
||||
class="device-log-search"
|
||||
/>
|
||||
<JProTable
|
||||
ref="instanceRefLog"
|
||||
|
@ -22,9 +21,7 @@
|
|||
<template #timestamp="slotProps">
|
||||
{{
|
||||
slotProps.timestamp
|
||||
? moment(slotProps.timestamp).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
? moment(slotProps.timestamp).format('YYYY-MM-DD HH:mm:ss')
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
|
@ -45,7 +42,6 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -125,11 +121,7 @@ const getActions = (
|
|||
onClick: () => {
|
||||
let content = '';
|
||||
try {
|
||||
content = JSON.stringify(
|
||||
JSON.parse(data.content),
|
||||
null,
|
||||
2,
|
||||
);
|
||||
content = JSON.stringify(JSON.parse(data.content), null, 2);
|
||||
} catch (error) {
|
||||
content = data.content;
|
||||
}
|
||||
|
@ -139,7 +131,7 @@ const getActions = (
|
|||
content: h(Textarea, {
|
||||
bordered: false,
|
||||
rows: 15,
|
||||
value: content
|
||||
value: content,
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
@ -152,8 +144,8 @@ const handleSearch = (_params: any) => {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.search {
|
||||
<style lang="less">
|
||||
.device-log-search {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
|
@ -1,6 +1,5 @@
|
|||
|
||||
<template>
|
||||
<j-card>
|
||||
<div>
|
||||
<div class="top">
|
||||
<div class="top-left">
|
||||
|
@ -8,15 +7,23 @@
|
|||
<AIcon type="ExclamationCircleOutlined" />
|
||||
<template v-if="topTitle === 'rest'">
|
||||
当前数据解析内容已脱离产品影响,
|
||||
<PermissionButton type="link" hasPermission="device/Instance:update" @click="rest()">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
hasPermission="device/Instance:update"
|
||||
@click="rest()"
|
||||
>
|
||||
重置
|
||||
</PermissionButton>
|
||||
后将继承产品数据解析内容
|
||||
</template>
|
||||
<template v-else>
|
||||
当前数据解析内容继承自产品,
|
||||
<PermissionButton type="link" hasPermission="device/Instance:update" @click="readOnly = false"
|
||||
:style="color">
|
||||
<PermissionButton
|
||||
type="link"
|
||||
hasPermission="device/Instance:update"
|
||||
@click="readOnly = false"
|
||||
:style="color"
|
||||
>
|
||||
修改
|
||||
</PermissionButton>
|
||||
后将脱离产品影响。
|
||||
|
@ -25,163 +32,231 @@
|
|||
</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
|
||||
: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" />
|
||||
<AIcon
|
||||
type="ExpandOutlined"
|
||||
style="margin-left: 20px"
|
||||
@click="toggle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit" ref="el">
|
||||
<div v-show="readOnly" class="edit-only" @click="() => {
|
||||
<div
|
||||
v-show="readOnly"
|
||||
class="edit-only"
|
||||
@click="
|
||||
() => {
|
||||
message.warning({
|
||||
key: 1,
|
||||
content: () => '请点击上方修改字样,用以编辑脚本',
|
||||
style: {
|
||||
marginTop: '260px'
|
||||
marginTop: '260px',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
}"></div>
|
||||
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
"
|
||||
></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 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
|
||||
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>
|
||||
<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" />
|
||||
<j-textarea
|
||||
:rows="5"
|
||||
placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串"
|
||||
style="margin-top: 10px"
|
||||
v-model:value="simulation"
|
||||
/>
|
||||
</div>
|
||||
<div style="width: 49.5%;">
|
||||
<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" />
|
||||
<j-textarea
|
||||
:autoSize="{ minRows: 5 }"
|
||||
:style="resStyle"
|
||||
v-model:value="result"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px;margin-left: 10px;">
|
||||
<PermissionButton type="primary" hasPermission="device/Instance:update" :loading="loading"
|
||||
:disabled="isDisabled" @click="debug()" :tooltip="{
|
||||
<div style="margin-top: 10px; margin-left: 10px">
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
hasPermission="device/Instance:update"
|
||||
:loading="loading"
|
||||
:disabled="isDisabled"
|
||||
@click="debug()"
|
||||
:tooltip="{
|
||||
title: '需输入脚本和模拟数据后再点击',
|
||||
}">
|
||||
}"
|
||||
>
|
||||
调试
|
||||
</PermissionButton>
|
||||
<PermissionButton hasPermission="device/Instance:update" :loading="loading" :disabled="!isTest" @click="save()"
|
||||
:style="{ marginLeft: '10px' }" :tooltip="{
|
||||
<PermissionButton
|
||||
hasPermission="device/Instance:update"
|
||||
:loading="loading"
|
||||
:disabled="!isTest"
|
||||
@click="save()"
|
||||
:style="{ marginLeft: '10px' }"
|
||||
:tooltip="{
|
||||
title: isTest ? '' : '请先调试',
|
||||
}">
|
||||
}"
|
||||
>
|
||||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<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 { useFullscreen } from '@vueuse/core'
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import { useInstanceStore } from '@/store/instance';
|
||||
import {
|
||||
deviceCode,
|
||||
getProtocal,
|
||||
testCode,
|
||||
saveDeviceCode,
|
||||
delDeviceCode
|
||||
} from '@/api/device/instance'
|
||||
delDeviceCode,
|
||||
} from '@/api/device/instance';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isBoolean } from 'lodash';
|
||||
|
||||
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';
|
||||
|
||||
const el = ref<HTMLElement | null>(null)
|
||||
const { toggle } = useFullscreen(el)
|
||||
const el = ref<HTMLElement | null>(null);
|
||||
const { toggle } = useFullscreen(el);
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
|
||||
const topTitle = ref<string>('')
|
||||
const readOnly = ref<boolean>(true)
|
||||
const url = ref<string>('')
|
||||
const topic = ref<string>('')
|
||||
const topicList = ref([])
|
||||
const simulation = ref<string>('')
|
||||
const resultValue = ref<any>({})
|
||||
const loading = ref<boolean>(false)
|
||||
const isTest = ref<boolean>(false)
|
||||
const editorValue = ref<string>('')
|
||||
const topTitle = ref<string>('');
|
||||
const readOnly = ref<boolean>(true);
|
||||
const url = ref<string>('');
|
||||
const topic = ref<string>('');
|
||||
const topicList = ref([]);
|
||||
const simulation = ref<string>('');
|
||||
const resultValue = ref<any>({});
|
||||
const loading = ref<boolean>(false);
|
||||
const isTest = ref<boolean>(false);
|
||||
const editorValue = ref<string>('');
|
||||
|
||||
const color = computed(() => ({
|
||||
color: readOnly.value ? '#415ed1' : '#a6a6a6'
|
||||
}))
|
||||
const resStyle = computed(() => (isBoolean(resultValue.value.success) ? {
|
||||
color: readOnly.value ? '#415ed1' : '#a6a6a6',
|
||||
}));
|
||||
const resStyle = computed(() =>
|
||||
isBoolean(resultValue.value.success)
|
||||
? {
|
||||
'margin-top': '10px',
|
||||
'border-color': resultValue.value.success ? 'green' : 'red'
|
||||
} : {
|
||||
'border-color': resultValue.value.success ? 'green' : 'red',
|
||||
}
|
||||
: {
|
||||
'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 res = await delDeviceCode(instanceStore.current.productId, instanceStore.current.id)
|
||||
const res = await delDeviceCode(
|
||||
instanceStore.current.productId,
|
||||
instanceStore.current.id,
|
||||
);
|
||||
if (res.status === 200) {
|
||||
getDeviceCode();
|
||||
message.success('操作成功')
|
||||
message.success('操作成功');
|
||||
}
|
||||
};
|
||||
//获取topic
|
||||
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) {
|
||||
const item = res.result.routes?.map((items: any) => ({
|
||||
value: items.topic,
|
||||
}));
|
||||
// setTopicList(item);
|
||||
topicList.value = item
|
||||
topicList.value = item;
|
||||
}
|
||||
};
|
||||
//获取设备解析规则
|
||||
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) {
|
||||
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) {
|
||||
readOnly.value = false
|
||||
topTitle.value = 'rest'
|
||||
editorValue.value = item
|
||||
readOnly.value = false;
|
||||
topTitle.value = 'rest';
|
||||
editorValue.value = item;
|
||||
} else {
|
||||
readOnly.value = true
|
||||
topTitle.value = 'edit'
|
||||
editorValue.value = item
|
||||
readOnly.value = true;
|
||||
topTitle.value = 'edit';
|
||||
editorValue.value = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
//调试
|
||||
const test = async (dataTest: any) => {
|
||||
loading.value = true
|
||||
const res = await testCode(dataTest)
|
||||
loading.value = true;
|
||||
const res = await testCode(dataTest);
|
||||
if (res.status === 200) {
|
||||
loading.value = false
|
||||
resultValue.value = res?.result
|
||||
loading.value = false;
|
||||
resultValue.value = res?.result;
|
||||
} else {
|
||||
loading.value = false
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -193,15 +268,18 @@ const save = async () => {
|
|||
script: editorValue.value,
|
||||
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) {
|
||||
message.success('保存成功');
|
||||
getDeviceCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const debug = () => {
|
||||
if (instanceStore.current.transport === 'MQTT') {
|
||||
if (topic.value !== '') {
|
||||
|
@ -215,8 +293,8 @@ const debug = () => {
|
|||
},
|
||||
provider: 'jsr223',
|
||||
payload: simulation.value,
|
||||
})
|
||||
isTest.value = true
|
||||
});
|
||||
isTest.value = true;
|
||||
} else {
|
||||
message.error('请输入topic');
|
||||
}
|
||||
|
@ -233,19 +311,17 @@ const debug = () => {
|
|||
},
|
||||
payload: simulation.value,
|
||||
});
|
||||
isTest.value = true
|
||||
isTest.value = true;
|
||||
} else {
|
||||
message.error('请输入url');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDeviceCode()
|
||||
getTopic()
|
||||
})
|
||||
|
||||
getDeviceCode();
|
||||
getTopic();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<div class="property-box">
|
||||
<div class="property-box-left">
|
||||
<j-input-search
|
||||
|
@ -17,11 +16,7 @@
|
|||
:tabBarStyle="{ width: '200px' }"
|
||||
@change="tabChange"
|
||||
>
|
||||
<j-tab-pane
|
||||
v-for="i in tabList"
|
||||
:key="i.key"
|
||||
:tab="i.tab"
|
||||
/>
|
||||
<j-tab-pane v-for="i in tabList" :key="i.key" :tab="i.tab" />
|
||||
</j-tabs>
|
||||
<JEmpty v-else style="margin: 180px 0" />
|
||||
</div>
|
||||
|
@ -31,7 +26,6 @@
|
|||
<JEmpty v-else style="margin: 220px 0" />
|
||||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -51,28 +45,32 @@ const tabList = ref<{ key: string; tab: string; type: 'property' | 'event' }[]>(
|
|||
],
|
||||
);
|
||||
const type = ref<string>('property');
|
||||
const data = ref<Record<string, any>>({})
|
||||
const data = ref<Record<string, any>>({});
|
||||
const value = ref<string>('');
|
||||
const instanceStore = useInstanceStore()
|
||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}')
|
||||
const properties = metadata.properties
|
||||
const events = metadata.events
|
||||
const instanceStore = useInstanceStore();
|
||||
const metadata = JSON.parse(instanceStore.current?.metadata || '{}');
|
||||
const properties = metadata.properties;
|
||||
const events = metadata.events;
|
||||
|
||||
watch(() => events, (newVal) => {
|
||||
if(events && newVal.length){
|
||||
watch(
|
||||
() => events,
|
||||
(newVal) => {
|
||||
if (events && newVal.length) {
|
||||
newVal.map((item: any) => {
|
||||
tabList.value.push({
|
||||
...item,
|
||||
key: item.id,
|
||||
tab: item.name,
|
||||
type: 'event',
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true
|
||||
})
|
||||
immediate: true,
|
||||
},
|
||||
);
|
||||
|
||||
const onSearch = () => {
|
||||
const arr = [
|
||||
|
@ -87,33 +85,32 @@ const onSearch = () => {
|
|||
key: item.id,
|
||||
tab: item.name,
|
||||
type: 'event',
|
||||
}
|
||||
})
|
||||
]
|
||||
if(value.value){
|
||||
};
|
||||
}),
|
||||
];
|
||||
if (value.value) {
|
||||
const li = arr.filter((i: any) => {
|
||||
return i?.tab.indexOf(value.value) !== -1;
|
||||
})
|
||||
tabList.value = _.cloneDeep(li)
|
||||
});
|
||||
tabList.value = _.cloneDeep(li);
|
||||
} else {
|
||||
tabList.value = _.cloneDeep(arr)
|
||||
tabList.value = _.cloneDeep(arr);
|
||||
}
|
||||
const dt = tabList.value?.[0]
|
||||
const dt = tabList.value?.[0];
|
||||
if (dt) {
|
||||
data.value = dt
|
||||
data.value = dt;
|
||||
type.value = dt.type;
|
||||
} else {
|
||||
type.value = ''
|
||||
type.value = '';
|
||||
}
|
||||
};
|
||||
const tabChange = (key: string) => {
|
||||
const dt = tabList.value.find((i) => i.key === key);
|
||||
if (dt) {
|
||||
data.value = dt
|
||||
data.value = dt;
|
||||
type.value = dt.type;
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<j-spin :spinning="loading" v-if="metadata.properties.length">
|
||||
<j-card>
|
||||
<j-card :bordered="false" borderStyle="padding: 0">
|
||||
<template #extra>
|
||||
<j-space>
|
||||
<j-button @click="visible = true">批量映射</j-button>
|
||||
|
@ -107,7 +107,7 @@
|
|||
:metaData="modelRef.dataSource"
|
||||
/>
|
||||
</j-spin>
|
||||
<j-card v-else>
|
||||
<j-card v-else :bordered="false" borderStyle="padding: 0">
|
||||
<JEmpty description='暂无数据,请配置物模型' style="margin: 10% 0" />
|
||||
</j-card>
|
||||
</template>
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
<template #title>
|
||||
<div style="display: flex; align-items: center">
|
||||
<j-tooltip :title="instanceStore.current?.name">
|
||||
<div class="deviceDetailHead">{{ instanceStore.current?.name }}</div>
|
||||
<div class="deviceDetailHead">
|
||||
{{ instanceStore.current?.name }}
|
||||
</div>
|
||||
</j-tooltip>
|
||||
<j-divider type="vertical" />
|
||||
<j-space>
|
||||
|
@ -95,11 +97,15 @@
|
|||
style="margin-right: 20px; cursor: pointer"
|
||||
/>
|
||||
</template>
|
||||
<FullPage>
|
||||
<j-card :bordered="false">
|
||||
<component
|
||||
:is="tabs[instanceStore.tabActiveKey]"
|
||||
v-bind="{ type: 'device' }"
|
||||
@onJump="onTabChange"
|
||||
/>
|
||||
</j-card>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -121,12 +127,12 @@ import { message } from 'jetlinks-ui-components';
|
|||
import { getImage } from '@/utils/comm';
|
||||
import { getWebSocket } from '@/utils/websocket';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||
|
||||
const menuStory = useMenuStore();
|
||||
|
||||
const route = useRoute();
|
||||
const routerParams = useRouterParams()
|
||||
const routerParams = useRouterParams();
|
||||
const instanceStore = useInstanceStore();
|
||||
|
||||
const statusMap = new Map();
|
||||
|
@ -266,7 +272,7 @@ const getDetail = () => {
|
|||
// );
|
||||
|
||||
const getDetailFn = async () => {
|
||||
const _id = route.params?.id
|
||||
const _id = route.params?.id;
|
||||
if (_id) {
|
||||
await instanceStore.refresh(String(_id));
|
||||
getStatus(String(_id));
|
||||
|
@ -274,10 +280,10 @@ const getDetailFn = async () => {
|
|||
getDetail();
|
||||
}
|
||||
instanceStore.tabActiveKey = routerParams.params.value.tab || 'Info';
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getDetailFn()
|
||||
getDetailFn();
|
||||
});
|
||||
|
||||
const onBack = () => {
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
target="device-instance"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="instanceRef"
|
||||
:columns="columns"
|
||||
:request="query"
|
||||
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:rowSelection="
|
||||
isCheck
|
||||
? {
|
||||
|
@ -27,7 +30,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="device/Instance:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined"
|
||||
/></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
<BatchDropdown
|
||||
|
@ -159,7 +164,12 @@
|
|||
>
|
||||
<template #img>
|
||||
<img
|
||||
:src="getImage('/device/instance/device-card.png')"
|
||||
:width="88"
|
||||
:height="88"
|
||||
:src="
|
||||
slotProps?.photoUrl ||
|
||||
getImage('/device/instance/device-card.png')
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
|
@ -220,7 +230,11 @@
|
|||
</template>
|
||||
<template #createTime="slotProps">
|
||||
<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>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
|
@ -245,12 +259,15 @@
|
|||
: 'device/Instance:' + i.key
|
||||
"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
<Import
|
||||
v-if="importVisible"
|
||||
|
@ -867,7 +884,7 @@ const handleSearch = (_params: any) => {
|
|||
) {
|
||||
return {
|
||||
...item2,
|
||||
column: 'productId$product-info'
|
||||
column: 'productId$product-info',
|
||||
};
|
||||
}
|
||||
return item2;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<!-- 配置信息 -->
|
||||
<template>
|
||||
<j-card style="min-height: 100%">
|
||||
<j-descriptions bordered>
|
||||
<template #title>
|
||||
<div style="display: flex">
|
||||
|
@ -29,28 +28,29 @@
|
|||
}}</j-descriptions-item>
|
||||
|
||||
<j-descriptions-item label="接入方式">
|
||||
<j-button type="link" @click="changeTables">{{
|
||||
<PermissionButton
|
||||
type="link"
|
||||
@click="changeTables"
|
||||
hasPermission="device/Product:update"
|
||||
>{{
|
||||
productStore.current.accessName
|
||||
? productStore.current.accessName
|
||||
: '配置接入方式'
|
||||
}}</j-button>
|
||||
}}</PermissionButton
|
||||
>
|
||||
</j-descriptions-item>
|
||||
<j-descriptions-item label="创建时间">{{
|
||||
dayjs(productStore.current.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
dayjs(productStore.current.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</j-descriptions-item>
|
||||
<j-descriptions-item label="更新时间">{{
|
||||
dayjs(productStore.current.modifyTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
dayjs(productStore.current.modifyTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}</j-descriptions-item>
|
||||
|
||||
<j-descriptions-item label="说明" :span="3">
|
||||
{{ productStore.current.describe }}
|
||||
</j-descriptions-item>
|
||||
</j-descriptions>
|
||||
</j-card>
|
||||
|
||||
<!-- 编辑 -->
|
||||
<Save ref="saveRef" :isAdd="isAdd" :title="title" @success="refresh" />
|
||||
</template>
|
||||
|
@ -60,6 +60,8 @@ import { useProductStore } from '@/store/product';
|
|||
import Save from '../../Save/index.vue';
|
||||
import dayjs from 'dayjs';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useMenuStore } from '@/store/menu';
|
||||
const menuSotre = useMenuStore();
|
||||
const productStore = useProductStore();
|
||||
const route = useRoute();
|
||||
const saveRef = ref();
|
||||
|
|
|
@ -1,138 +1,193 @@
|
|||
|
||||
<template>
|
||||
<j-card>
|
||||
<div>
|
||||
<div class="top">
|
||||
<div>
|
||||
脚本语言:
|
||||
<j-select :defaultValue="'JavaScript'" style="width: 200;margin-left: 5px;">
|
||||
<j-select-option value="JavaScript">JavaScript(ECMAScript 5)</j-select-option>
|
||||
<j-select
|
||||
:defaultValue="'JavaScript'"
|
||||
style="width: 200; 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" />
|
||||
<AIcon
|
||||
type="ExpandOutlined"
|
||||
style="margin-left: 20px"
|
||||
@click="toggle"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit" ref="el">
|
||||
<j-monaco-editor language="javascript" style="height: 100%;" theme="vs" v-model:modelValue="editorValue" />
|
||||
<j-monaco-editor
|
||||
language="javascript"
|
||||
style="height: 100%"
|
||||
theme="vs"
|
||||
v-model:modelValue="editorValue"
|
||||
/>
|
||||
</div>
|
||||
<div class="bottom">
|
||||
<div style="width: 49.5%;">
|
||||
<div style="width: 49.5%">
|
||||
<div class="bottom-title">
|
||||
<div class="bottom-title-text">模拟输入</div>
|
||||
<div class="bottom-title-topic">
|
||||
<template v-if="productStore.current.transportProtocol === 'MQTT'">
|
||||
<div style="margin-right: 5px;">Topic:</div>
|
||||
<j-auto-complete placeholder="请输入Topic" style="width: 300px" :options="topicList"
|
||||
:allowClear="true" :filterOption="(inputValue: any, option: any) =>
|
||||
option!.value.indexOf(inputValue) !== -1" v-model:value="topic" />
|
||||
<template
|
||||
v-if="
|
||||
productStore.current.transportProtocol ===
|
||||
'MQTT'
|
||||
"
|
||||
>
|
||||
<div style="margin-right: 5px">Topic:</div>
|
||||
<j-auto-complete
|
||||
placeholder="请输入Topic"
|
||||
style="width: 300px"
|
||||
:options="topicList"
|
||||
:allowClear="true"
|
||||
:filterOption="(inputValue: any, option: any) =>
|
||||
option!.value.indexOf(inputValue) !== -1"
|
||||
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>
|
||||
<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" />
|
||||
<j-textarea
|
||||
:rows="5"
|
||||
placeholder="// 二进制数据以0x开头的十六进制输入,字符串数据输入原始字符串"
|
||||
style="margin-top: 10px"
|
||||
v-model:value="simulation"
|
||||
/>
|
||||
</div>
|
||||
<div style="width: 49.5%;">
|
||||
<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" />
|
||||
<j-textarea
|
||||
:autoSize="{ minRows: 5 }"
|
||||
:style="resStyle"
|
||||
v-model:value="result"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 10px;margin-left: 10px;">
|
||||
<PermissionButton type="primary" hasPermission="device/Instance:update" :loading="loading"
|
||||
:disabled="isDisabled" @click="debug()" :tooltip="{
|
||||
<div style="margin-top: 10px; margin-left: 10px">
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
hasPermission="device/Instance:update"
|
||||
:loading="loading"
|
||||
:disabled="isDisabled"
|
||||
@click="debug()"
|
||||
:tooltip="{
|
||||
title: '需输入脚本和模拟数据后再点击',
|
||||
}">
|
||||
}"
|
||||
>
|
||||
调试
|
||||
</PermissionButton>
|
||||
<PermissionButton hasPermission="device/Instance:update" :loading="loading" :disabled="!isTest" @click="save()"
|
||||
:style="{ marginLeft: '10px' }" :tooltip="{
|
||||
<PermissionButton
|
||||
hasPermission="device/Instance:update"
|
||||
:loading="loading"
|
||||
:disabled="!isTest"
|
||||
@click="save()"
|
||||
:style="{ marginLeft: '10px' }"
|
||||
:tooltip="{
|
||||
title: isTest ? '' : '请先调试',
|
||||
}">
|
||||
}"
|
||||
>
|
||||
保存
|
||||
</PermissionButton>
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts' name="DataAnalysis">
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue';
|
||||
// import MonacoEditor from '@/components/MonacoEditor/index.vue';
|
||||
import { useFullscreen } from '@vueuse/core'
|
||||
import { useFullscreen } from '@vueuse/core';
|
||||
import { useProductStore } from '@/store/product';
|
||||
import {
|
||||
productCode,
|
||||
getProtocal,
|
||||
testCode,
|
||||
saveProductCode,
|
||||
} from '@/api/device/instance'
|
||||
} from '@/api/device/instance';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import { isBoolean } from 'lodash';
|
||||
|
||||
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';
|
||||
|
||||
const el = ref<HTMLElement | null>(null)
|
||||
const { toggle } = useFullscreen(el)
|
||||
const productStore = useProductStore()
|
||||
const el = ref<HTMLElement | null>(null);
|
||||
const { toggle } = useFullscreen(el);
|
||||
const productStore = useProductStore();
|
||||
|
||||
const url = ref<string>('');
|
||||
const topic = ref<string>('');
|
||||
const topicList = ref([]);
|
||||
const simulation = ref<string>('');
|
||||
const resultValue = ref<any>({});
|
||||
const loading = ref<boolean>(false);
|
||||
const isTest = ref<boolean>(false);
|
||||
const editorValue = ref<string>('');
|
||||
|
||||
const url = ref<string>('')
|
||||
const topic = ref<string>('')
|
||||
const topicList = ref([])
|
||||
const simulation = ref<string>('')
|
||||
const resultValue = ref<any>({})
|
||||
const loading = ref<boolean>(false)
|
||||
const isTest = ref<boolean>(false)
|
||||
const editorValue = ref<string>('')
|
||||
|
||||
const resStyle = computed(() => (isBoolean(resultValue.value.success) ? {
|
||||
const resStyle = computed(() =>
|
||||
isBoolean(resultValue.value.success)
|
||||
? {
|
||||
'margin-top': '10px',
|
||||
'border-color': resultValue.value.success ? 'green' : 'red'
|
||||
} : {
|
||||
'border-color': resultValue.value.success ? 'green' : 'red',
|
||||
}
|
||||
: {
|
||||
'margin-top': '10px',
|
||||
}))
|
||||
},
|
||||
);
|
||||
|
||||
const isDisabled = computed(() => simulation.value === '')
|
||||
|
||||
const result = computed(() => resultValue.value.success ? JSON.stringify(resultValue.value.outputs?.[0]) : resultValue.value.reason)
|
||||
const isDisabled = computed(() => simulation.value === '');
|
||||
|
||||
const result = computed(() =>
|
||||
resultValue.value.success
|
||||
? JSON.stringify(resultValue.value.outputs?.[0])
|
||||
: resultValue.value.reason,
|
||||
);
|
||||
|
||||
//获取topic
|
||||
const getTopic = async () => {
|
||||
const res: any = await getProtocal(productStore.current.messageProtocol, productStore.current.transportProtocol)
|
||||
const res: any = await getProtocal(
|
||||
productStore.current.messageProtocol,
|
||||
productStore.current.transportProtocol,
|
||||
);
|
||||
if (res.status === 200) {
|
||||
const item = res.result.routes?.map((items: any) => ({
|
||||
value: items.topic,
|
||||
}));
|
||||
topicList.value = item
|
||||
topicList.value = item;
|
||||
}
|
||||
};
|
||||
//获取产品解析规则
|
||||
const getProductCode = async () => {
|
||||
const res: any = await productCode(productStore.current.id)
|
||||
const res: any = await productCode(productStore.current.id);
|
||||
if (res.status === 200) {
|
||||
if(res.result){
|
||||
editorValue.value = res.result?.configuration?.script
|
||||
}else{
|
||||
editorValue.value = defaultValue
|
||||
if (res.result) {
|
||||
editorValue.value = res.result?.configuration?.script;
|
||||
} else {
|
||||
editorValue.value = defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
//调试
|
||||
const test = async (dataTest: any) => {
|
||||
loading.value = true
|
||||
const res = await testCode(dataTest)
|
||||
loading.value = true;
|
||||
const res = await testCode(dataTest);
|
||||
if (res.status === 200) {
|
||||
loading.value = false
|
||||
resultValue.value = res?.result
|
||||
loading.value = false;
|
||||
resultValue.value = res?.result;
|
||||
} else {
|
||||
loading.value = false
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -144,15 +199,14 @@ const save = async () => {
|
|||
script: editorValue.value,
|
||||
lang: 'javascript',
|
||||
},
|
||||
}
|
||||
const res = await saveProductCode(productStore.current.id, item)
|
||||
};
|
||||
const res = await saveProductCode(productStore.current.id, item);
|
||||
if (res.status === 200) {
|
||||
message.success('保存成功');
|
||||
getProductCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const debug = () => {
|
||||
if (productStore.current.transportProtocol === 'MQTT') {
|
||||
if (topic.value !== '') {
|
||||
|
@ -166,8 +220,8 @@ const debug = () => {
|
|||
},
|
||||
provider: 'jsr223',
|
||||
payload: simulation.value,
|
||||
})
|
||||
isTest.value = true
|
||||
});
|
||||
isTest.value = true;
|
||||
} else {
|
||||
message.error('请输入topic');
|
||||
}
|
||||
|
@ -184,19 +238,17 @@ const debug = () => {
|
|||
},
|
||||
payload: simulation.value,
|
||||
});
|
||||
isTest.value = true
|
||||
isTest.value = true;
|
||||
} else {
|
||||
message.error('请输入url');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getProductCode()
|
||||
getTopic()
|
||||
})
|
||||
|
||||
getProductCode();
|
||||
getTopic();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang='less'>
|
||||
|
|
|
@ -1,24 +1,14 @@
|
|||
<!-- 设备接入 -->
|
||||
<template>
|
||||
<j-card style="min-height: 100%">
|
||||
<div v-if="productStore.current.accessId === undefined || null">
|
||||
<j-empty :image="simpleImage">
|
||||
<template #description>
|
||||
<span
|
||||
v-if="
|
||||
permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
)
|
||||
permissionStore.hasPermission('device/Product:update')
|
||||
"
|
||||
>
|
||||
请先<j-button type="link" @click="showModal"
|
||||
>选择</j-button
|
||||
请先<j-button type="link" @click="showModal">选择</j-button
|
||||
>设备接入网关,用以提供设备接入能力
|
||||
</span>
|
||||
<span v-else>请联系管理员配置产品接入方式</span>
|
||||
|
@ -60,35 +50,15 @@
|
|||
productStore.current?.count &&
|
||||
productStore.current?.count > 0
|
||||
? '产品下有设备实例时不能更换接入方式'
|
||||
: !(permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
))
|
||||
? '暂无权限,请联系管理员'
|
||||
: '',
|
||||
}"
|
||||
:disabled="
|
||||
(productStore.current?.count &&
|
||||
productStore.current?.count > 0) ||
|
||||
!(
|
||||
permissionStore.hasPermission(
|
||||
'device/Product:update',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:add',
|
||||
) &&
|
||||
permissionStore.hasPermission(
|
||||
'link/AccessConfig:update',
|
||||
)
|
||||
)
|
||||
productStore.current?.count &&
|
||||
productStore.current?.count > 0
|
||||
"
|
||||
ghost
|
||||
@click="showDevice"
|
||||
hasPermission="device/Product:update"
|
||||
>
|
||||
更换
|
||||
</PermissionButton>
|
||||
|
@ -113,10 +83,7 @@
|
|||
{{ access?.protocolDetail?.name }}
|
||||
</div>
|
||||
<!-- 显示md文件内容 -->
|
||||
<div
|
||||
v-if="config?.document"
|
||||
v-html="markdownToHtml"
|
||||
></div>
|
||||
<div v-if="config?.document" v-html="markdownToHtml"></div>
|
||||
</div>
|
||||
<div class="item-style">
|
||||
<Title data="连接信息"></Title>
|
||||
|
@ -126,9 +93,7 @@
|
|||
:key="item.address"
|
||||
>
|
||||
<j-badge
|
||||
:color="
|
||||
item.health === -1 ? 'red' : 'green'
|
||||
"
|
||||
:color="item.health === -1 ? 'red' : 'green'"
|
||||
:text="item.address"
|
||||
>
|
||||
</j-badge>
|
||||
|
@ -142,9 +107,7 @@
|
|||
class="config"
|
||||
>
|
||||
<template #extra>
|
||||
<j-tooltip
|
||||
title="此配置来自于产品接入方式所选择的协议"
|
||||
>
|
||||
<j-tooltip title="此配置来自于产品接入方式所选择的协议">
|
||||
<AIcon
|
||||
type="QuestionCircleOutlined"
|
||||
style="margin-left: 2px"
|
||||
|
@ -152,11 +115,7 @@
|
|||
</j-tooltip>
|
||||
</template>
|
||||
</Title>
|
||||
<j-form
|
||||
ref="formRef"
|
||||
:model="formData.data"
|
||||
layout="vertical"
|
||||
>
|
||||
<j-form ref="formRef" :model="formData.data" layout="vertical">
|
||||
<j-form-item
|
||||
:name="item.property"
|
||||
v-for="item in metadata.properties"
|
||||
|
@ -215,10 +174,7 @@
|
|||
</Title>
|
||||
<j-form layout="vertical">
|
||||
<j-form-item>
|
||||
<j-select
|
||||
ref="select"
|
||||
v-model:value="form.storePolicy"
|
||||
>
|
||||
<j-select ref="select" v-model:value="form.storePolicy">
|
||||
<j-select-option
|
||||
v-for="(item, index) in storageList"
|
||||
:key="index"
|
||||
|
@ -243,8 +199,7 @@
|
|||
<div>
|
||||
<div style="font-weight: 600; margin: 0 0 10 px 0">
|
||||
{{
|
||||
access?.provider ===
|
||||
'mqtt-server-gateway' ||
|
||||
access?.provider === 'mqtt-server-gateway' ||
|
||||
access?.provider === 'mqtt-client-gateway'
|
||||
? 'topic'
|
||||
: 'URL信息'
|
||||
|
@ -252,9 +207,7 @@
|
|||
</div>
|
||||
<j-table
|
||||
:columns="
|
||||
config.id === 'MQTT'
|
||||
? columnsMQTT
|
||||
: columnsHTTP
|
||||
config.id === 'MQTT' ? columnsMQTT : columnsHTTP
|
||||
"
|
||||
:data-source="config?.routes"
|
||||
:pagination="false"
|
||||
|
@ -274,9 +227,7 @@
|
|||
<template v-if="column.key === 'stream'">
|
||||
<div>{{ getStream(record) }}</div>
|
||||
</template>
|
||||
<template
|
||||
v-if="column.key === 'description'"
|
||||
>
|
||||
<template v-if="column.key === 'description'">
|
||||
<j-tooltip
|
||||
placement="topLeft"
|
||||
:title="text"
|
||||
|
@ -313,7 +264,6 @@
|
|||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
</j-card>
|
||||
<!-- 选择设备 -->
|
||||
<j-modal
|
||||
title="设备接入配置"
|
||||
|
@ -349,8 +299,11 @@
|
|||
:gridColumns="[2]"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<j-button type="primary" @click="add"
|
||||
><plus-outlined />新增</j-button
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
@click="add"
|
||||
hasPermission="link/AccessConfig:add"
|
||||
>新增</PermissionButton
|
||||
>
|
||||
</template>
|
||||
<template #deviceType="slotProps">
|
||||
|
@ -1010,7 +963,6 @@ const submitDevice = async () => {
|
|||
const result: any = {};
|
||||
flatObj(values, result);
|
||||
const { storePolicy, ...extra } = result;
|
||||
console.log({ ...extra });
|
||||
const id = productStore.current?.id;
|
||||
const resp = await modify(id || '', {
|
||||
id: id,
|
||||
|
@ -1046,7 +998,6 @@ const add = () => {
|
|||
if (url) {
|
||||
const tab: any = window.open(`${origin}/#${url}?view=false`);
|
||||
tab.onTabSaveSuccess = (value: any) => {
|
||||
console.log(value);
|
||||
if (value.status === 200) {
|
||||
tableRef.value.reload();
|
||||
handleClick(value.result);
|
||||
|
|
|
@ -90,11 +90,19 @@
|
|||
>应用配置</PermissionButton
|
||||
>
|
||||
</template>
|
||||
<FullPage>
|
||||
<j-card :bordered="false">
|
||||
<component
|
||||
:is="tabs[productStore.tabActiveKey]"
|
||||
:class="productStore.tabActiveKey === 'Metadata' ? 'metedata' : ''"
|
||||
:class="
|
||||
productStore.tabActiveKey === 'Metadata'
|
||||
? 'metedata'
|
||||
: ''
|
||||
"
|
||||
v-bind="{ type: 'product' }"
|
||||
/>
|
||||
</j-card>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="product-manage"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
:columns="columns"
|
||||
:request="queryProductList"
|
||||
|
@ -21,7 +22,9 @@
|
|||
@click="add"
|
||||
hasPermission="device/Product:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined"
|
||||
/></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
<j-upload
|
||||
|
@ -30,7 +33,8 @@
|
|||
:showUploadList="false"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<PermissionButton hasPermission="device/Product:import"
|
||||
<PermissionButton
|
||||
hasPermission="device/Product:import"
|
||||
>导入</PermissionButton
|
||||
>
|
||||
</j-upload>
|
||||
|
@ -103,7 +107,11 @@
|
|||
...item.tooltip,
|
||||
}"
|
||||
@click="item.onClick"
|
||||
:hasPermission="item.key ==='view' ? true : 'device/Product:' + item.key"
|
||||
:hasPermission="
|
||||
item.key === 'view'
|
||||
? true
|
||||
: 'device/Product:' + item.key
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
|
@ -136,7 +144,11 @@
|
|||
<PermissionButton
|
||||
:disabled="i.disabled"
|
||||
:popConfirm="i.popConfirm"
|
||||
:hasPermission="i.key === 'view' ? true : 'device/Product:' + i.key"
|
||||
:hasPermission="
|
||||
i.key === 'view'
|
||||
? true
|
||||
: 'device/Product:' + i.key
|
||||
"
|
||||
:tooltip="{
|
||||
...i.tooltip,
|
||||
}"
|
||||
|
@ -145,12 +157,15 @@
|
|||
style="padding: 0px"
|
||||
:danger="i.key === 'delete'"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<!-- 新增、编辑 -->
|
||||
<Save ref="saveRef" :isAdd="isAdd" :title="title" @success="refresh" />
|
||||
</page-container>
|
||||
|
@ -181,8 +196,8 @@ import { typeOptions } from '@/components/Search/util';
|
|||
import Save from './Save/index.vue';
|
||||
import { useMenuStore } from 'store/menu';
|
||||
import { useRoute } from 'vue-router';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { accessConfigTypeFilter } from '@/utils/setting'
|
||||
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||
import { accessConfigTypeFilter } from '@/utils/setting';
|
||||
/**
|
||||
* 表格数据
|
||||
*/
|
||||
|
@ -196,21 +211,21 @@ const columns = [
|
|||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
scopedSlots: true,
|
||||
width:200,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '产品名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width:220,
|
||||
width: 220,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '接入方式',
|
||||
dataIndex: 'accessName',
|
||||
key: 'accessName',
|
||||
width:220,
|
||||
width: 220,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
|
@ -219,7 +234,7 @@ const columns = [
|
|||
key: 'deviceType',
|
||||
scopedSlots: true,
|
||||
ellipsis: true,
|
||||
width:120,
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
|
@ -227,7 +242,7 @@ const columns = [
|
|||
key: 'state',
|
||||
scopedSlots: true,
|
||||
ellipsis: true,
|
||||
width:90,
|
||||
width: 90,
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
|
@ -434,7 +449,7 @@ const query = reactive({
|
|||
key: 'id',
|
||||
search: {
|
||||
type: 'string',
|
||||
defaultTermType: 'eq'
|
||||
defaultTermType: 'eq',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -446,8 +461,8 @@ const query = reactive({
|
|||
options: () => {
|
||||
return new Promise((resolve) => {
|
||||
getProviders().then((resp: any) => {
|
||||
const data = resp.result || []
|
||||
resolve(accessConfigTypeFilter(data))
|
||||
const data = resp.result || [];
|
||||
resolve(accessConfigTypeFilter(data));
|
||||
});
|
||||
});
|
||||
},
|
||||
|
@ -592,9 +607,9 @@ const saveRef = ref();
|
|||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
const routerParams = useRouterParams()
|
||||
const routerParams = useRouterParams();
|
||||
onMounted(() => {
|
||||
if(routerParams.params?.value.save){
|
||||
if (routerParams.params?.value.save) {
|
||||
add();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<template>
|
||||
<j-card>
|
||||
<div class='device-detail-metadata' style="position: relative;">
|
||||
<div class="tips">
|
||||
<j-tooltip :title="instanceStore.detail?.independentMetadata && type === 'device'
|
||||
|
@ -44,7 +43,6 @@
|
|||
<Import v-if="visible" v-model:visible="visible" :type="type" @close="visible = false" />
|
||||
<Cat v-model:visible="cat" @close="cat = false" :type="type" />
|
||||
</div>
|
||||
</j-card>
|
||||
</template>
|
||||
<script setup lang="ts" name="Metadata">
|
||||
import PermissionButton from '@/components/PermissionButton/index.vue'
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="edge-device"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="edgeDeviceRef"
|
||||
:columns="columns"
|
||||
|
@ -20,7 +21,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="edge/Device:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" /></template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined"
|
||||
/></template>
|
||||
新增
|
||||
</PermissionButton>
|
||||
<PermissionButton
|
||||
|
@ -48,7 +51,9 @@
|
|||
>
|
||||
<template #img>
|
||||
<img
|
||||
:src="getImage('/device/instance/device-card.png')"
|
||||
:src="
|
||||
getImage('/device/instance/device-card.png')
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
|
@ -112,7 +117,9 @@
|
|||
</template>
|
||||
<template #registryTime="slotProps">
|
||||
<span>{{
|
||||
dayjs(slotProps.registryTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
dayjs(slotProps.registryTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
|
@ -131,21 +138,33 @@
|
|||
type="link"
|
||||
style="padding: 0 5px"
|
||||
: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>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<Save
|
||||
v-if="visible"
|
||||
:data="current"
|
||||
@close="visible = false"
|
||||
@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>
|
||||
</template>
|
||||
|
||||
|
@ -192,18 +211,18 @@ const visible = ref<boolean>(false);
|
|||
const current = ref<Record<string, any>>({});
|
||||
|
||||
const transformData = (arr: any[]): any[] => {
|
||||
if(Array.isArray(arr) && arr.length){
|
||||
if (Array.isArray(arr) && arr.length) {
|
||||
return (arr || []).map((item: any) => {
|
||||
return {
|
||||
...item,
|
||||
id: `classifiedId is ${item.id}`,
|
||||
children: transformData(item.children)
|
||||
}
|
||||
})
|
||||
children: transformData(item.children),
|
||||
};
|
||||
});
|
||||
} else {
|
||||
return []
|
||||
return [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -471,9 +490,9 @@ const saveBtn = () => {
|
|||
};
|
||||
|
||||
const onRefresh = () => {
|
||||
importVisible.value = false
|
||||
importVisible.value = false;
|
||||
edgeDeviceRef.value?.reload();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="edge-resource"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="edgeResourceRef"
|
||||
:columns="columns"
|
||||
|
@ -26,7 +27,9 @@
|
|||
>
|
||||
<template #img>
|
||||
<img
|
||||
:src="getImage('/device/instance/device-card.png')"
|
||||
:src="
|
||||
getImage('/device/instance/device-card.png')
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
|
@ -42,7 +45,8 @@
|
|||
</div>
|
||||
<Ellipsis>{{
|
||||
options.find(
|
||||
(i) => i.value === slotProps.category,
|
||||
(i) =>
|
||||
i.value === slotProps.category,
|
||||
)?.label || slotProps.category
|
||||
}}</Ellipsis>
|
||||
</j-col>
|
||||
|
@ -99,7 +103,9 @@
|
|||
</template>
|
||||
<template #createTime="slotProps">
|
||||
<span>{{
|
||||
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
dayjs(slotProps.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}</span>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
|
@ -124,12 +130,16 @@
|
|||
: 'edge/Resource:' + i.key
|
||||
"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
|
||||
<Save
|
||||
v-if="visible"
|
||||
:data="current"
|
||||
|
|
|
@ -264,6 +264,7 @@ const saveCurrentData = () => {
|
|||
port: modalForm.port,
|
||||
publicHost: modalForm.publicHost,
|
||||
publicPort: modalForm.publicPort,
|
||||
maxMessageSize:8192,
|
||||
},
|
||||
});
|
||||
// 保存协议
|
||||
|
|
|
@ -652,8 +652,14 @@ const saveData = () => {
|
|||
|
||||
if (resp?.status === 200) {
|
||||
onlyMessage('操作成功', 'success');
|
||||
if (route.query.save) {
|
||||
// @ts-ignore
|
||||
window?.onSaveSuccess(resp.result);
|
||||
window.close();
|
||||
} else {
|
||||
history.back();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<pro-search :columns="columns" target="media" @search="handleSearch" />
|
||||
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="listRef"
|
||||
model="table"
|
||||
|
@ -91,7 +91,10 @@
|
|||
保存
|
||||
</j-button>
|
||||
</template>
|
||||
<j-button type="link" @click="slotProps.popVis = true">
|
||||
<j-button
|
||||
type="link"
|
||||
@click="slotProps.popVis = true"
|
||||
>
|
||||
<AIcon type="EditOutlined" />
|
||||
</j-button>
|
||||
</j-popover>
|
||||
|
@ -145,6 +148,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
|
||||
<BindChannel v-model:visible="bindVis" @submit="listRef.reload()" />
|
||||
</page-container>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
target="media-cascade"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="listRef"
|
||||
:columns="columns"
|
||||
|
@ -22,7 +22,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="media/Cascade:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" />新增</template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined" />新增</template
|
||||
>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
|
@ -42,7 +44,9 @@
|
|||
<slot name="img">
|
||||
<img
|
||||
:src="
|
||||
getImage('/device/instance/device-card.png')
|
||||
getImage(
|
||||
'/device/instance/device-card.png',
|
||||
)
|
||||
"
|
||||
/>
|
||||
</slot>
|
||||
|
@ -132,12 +136,15 @@
|
|||
style="padding: 0px"
|
||||
:hasPermission="'media/Cascade:' + i.key"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
|
||||
<Publish v-model:visible="publishVis" :data="currentData" />
|
||||
</page-container>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
target="channel"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="listRef"
|
||||
model="table"
|
||||
|
@ -45,9 +45,12 @@
|
|||
v-if="route?.query.type === 'gb28181-2016'"
|
||||
title="接入方式为GB/T28281时,不支持新增"
|
||||
>
|
||||
<j-button type="primary" disabled> 新增 </j-button>
|
||||
<j-button type="primary" disabled>
|
||||
新增
|
||||
</j-button>
|
||||
</j-tooltip>
|
||||
<PermissionButton
|
||||
v-else
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
hasPermission="media/Device:add"
|
||||
|
@ -77,7 +80,8 @@
|
|||
>
|
||||
<PermissionButton
|
||||
v-if="
|
||||
i.key !== 'play' && i.key !== 'backPlay'
|
||||
i.key !== 'play' &&
|
||||
i.key !== 'backPlay'
|
||||
"
|
||||
:danger="i.key === 'delete'"
|
||||
:disabled="i.disabled"
|
||||
|
@ -96,7 +100,10 @@
|
|||
</PermissionButton>
|
||||
<!-- 回放/播放不要权限控制 -->
|
||||
<template v-else>
|
||||
<j-tooltip :key="i.key" v-bind="i.tooltip">
|
||||
<j-tooltip
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<j-button
|
||||
style="padding: 0px"
|
||||
type="link"
|
||||
|
@ -119,6 +126,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<!-- 回放 -->
|
||||
<template>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<div class="playback-warp">
|
||||
<!-- 播放器/进度条 -->
|
||||
<div class="playback-left">
|
||||
|
@ -59,7 +60,9 @@
|
|||
<div>云端:存储在服务器中</div>
|
||||
<div>本地:存储在设备本地</div>
|
||||
</template>
|
||||
<div>类型: <AIcon type="QuestionCircleOutlined" /></div>
|
||||
<div>
|
||||
类型: <AIcon type="QuestionCircleOutlined" />
|
||||
</div>
|
||||
</j-tooltip>
|
||||
<RadioCard
|
||||
layout="horizontal"
|
||||
|
@ -152,7 +155,8 @@
|
|||
:item="item"
|
||||
:on-cloud-view="cloudView"
|
||||
:on-down-load="
|
||||
() => downloadClick(item)
|
||||
() =>
|
||||
downloadClick(item)
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
|
@ -181,6 +185,7 @@
|
|||
</j-spin>
|
||||
</div>
|
||||
</div>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="listRef"
|
||||
:columns="columns"
|
||||
|
@ -21,7 +22,9 @@
|
|||
@click="handleAdd"
|
||||
hasPermission="media/Device:add"
|
||||
>
|
||||
<template #icon><AIcon type="PlusOutlined" />新增</template>
|
||||
<template #icon
|
||||
><AIcon type="PlusOutlined" />新增</template
|
||||
>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
|
@ -32,7 +35,10 @@
|
|||
:showStatus="true"
|
||||
:status="slotProps.state.value"
|
||||
:statusText="slotProps.state.text"
|
||||
:statusNames="{ online: 'processing', offline: 'error' }"
|
||||
:statusNames="{
|
||||
online: 'processing',
|
||||
offline: 'error',
|
||||
}"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
|
@ -45,7 +51,9 @@
|
|||
</h3>
|
||||
<j-row>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">厂商</div>
|
||||
<div class="card-item-content-text">
|
||||
厂商
|
||||
</div>
|
||||
<div>{{ slotProps.manufacturer }}</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
|
@ -55,7 +63,9 @@
|
|||
<div>{{ slotProps.channelNumber }}</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">型号</div>
|
||||
<div class="card-item-content-text">
|
||||
型号
|
||||
</div>
|
||||
<div>{{ slotProps.model }}</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
|
@ -139,12 +149,15 @@
|
|||
: 'update')
|
||||
"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<j-card class="splitScreen">
|
||||
<div class="split-screen">
|
||||
<LeftTree @onSelect="mediaStart" />
|
||||
|
@ -8,9 +9,12 @@
|
|||
ref="player"
|
||||
:id="deviceId"
|
||||
:channelId="channelId"
|
||||
:onMouseUp="(id, cId) => channelApi.ptzStop(id, cId)"
|
||||
:onMouseUp="
|
||||
(id, cId) => channelApi.ptzStop(id, cId)
|
||||
"
|
||||
:onMouseDown="
|
||||
(id, cId, type) => channelApi.ptzTool(id, cId, type)
|
||||
(id, cId, type) =>
|
||||
channelApi.ptzTool(id, cId, type)
|
||||
"
|
||||
:historyHandle="(dId, cId) => getMediaUrl(dId, cId)"
|
||||
showScreen
|
||||
|
@ -18,6 +22,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</j-card>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
total: dataSource.length,
|
||||
current: current,
|
||||
pageSize: pageSize,
|
||||
pageSizeOptions: ['5', '10', '20', '50', '100'],
|
||||
pageSizeOptions: ['10', '20', '50', '100'],
|
||||
showSizeChanger: true,
|
||||
hideOnSinglePage: false,
|
||||
showTotal: (total: number, range: number) => `第 ${range[0]} - ${range[1]} 条/总共 ${total} 条`,
|
||||
|
@ -399,7 +399,7 @@ const getTableData = (terms?: any) => {
|
|||
* 前端分页
|
||||
*/
|
||||
const current = ref(1);
|
||||
const pageSize = ref(5);
|
||||
const pageSize = ref(10);
|
||||
const handleTableChange = (pagination: any) => {
|
||||
current.value = pagination.current;
|
||||
pageSize.value = pagination.pageSize;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="configRef"
|
||||
:columns="columns"
|
||||
|
@ -31,7 +32,9 @@
|
|||
:showUploadList="false"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<PermissionButton hasPermission="notice/Config:import">
|
||||
<PermissionButton
|
||||
hasPermission="notice/Config:import"
|
||||
>
|
||||
导入
|
||||
</PermissionButton>
|
||||
</j-upload>
|
||||
|
@ -41,7 +44,9 @@
|
|||
cancel-text="取消"
|
||||
@confirm="handleExport"
|
||||
>
|
||||
<PermissionButton hasPermission="notice/Config:export">
|
||||
<PermissionButton
|
||||
hasPermission="notice/Config:export"
|
||||
>
|
||||
导出
|
||||
</PermissionButton>
|
||||
</j-popconfirm>
|
||||
|
@ -58,7 +63,10 @@
|
|||
<slot name="img">
|
||||
<img
|
||||
:src="
|
||||
getLogo(slotProps.type, slotProps.provider)
|
||||
getLogo(
|
||||
slotProps.type,
|
||||
slotProps.provider,
|
||||
)
|
||||
"
|
||||
class="logo"
|
||||
/>
|
||||
|
@ -78,7 +86,9 @@
|
|||
</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<div class="card-item-content-text">
|
||||
说明
|
||||
</div>
|
||||
<Ellipsis>
|
||||
{{ slotProps.description }}
|
||||
</Ellipsis>
|
||||
|
@ -179,12 +189,15 @@
|
|||
style="padding: 0px"
|
||||
:hasPermission="'notice/Config:' + i.key"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
|
||||
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
||||
<Log v-model:visible="logVis" :data="currentConfig" />
|
||||
|
|
|
@ -783,6 +783,7 @@ import { LocalStore } from '@/utils/comm';
|
|||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { phoneRegEx } from '@/utils/validate';
|
||||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
@ -1005,7 +1006,8 @@ const formRules = ref({
|
|||
trigger: 'change',
|
||||
validator(_rule: Rule, value: string) {
|
||||
if (!value) return Promise.resolve();
|
||||
if (!phoneRegEx(value)) return Promise.reject('该字段不是有效的手机号');
|
||||
if (!phoneRegEx(value))
|
||||
return Promise.reject('该字段不是有效的手机号');
|
||||
return Promise.resolve();
|
||||
},
|
||||
},
|
||||
|
@ -1028,78 +1030,19 @@ const { resetFields, validate, validateInfos, clearValidate } = useForm(
|
|||
formRules.value,
|
||||
);
|
||||
|
||||
// 钉钉机器人markdown标题变量提取
|
||||
// 字段提取变量
|
||||
watch(
|
||||
[
|
||||
() => formData.value.template.markdown?.title,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
// 钉钉机器人link标题变量提取
|
||||
watch(
|
||||
() => formData.value.template.link?.title,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
// 邮件标题变量提取
|
||||
watch(
|
||||
() => formData.value.template.subject,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
// 模板内容变量提取
|
||||
watch(
|
||||
() => formData.value.template.message,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
// 模板内容变量提取
|
||||
watch(
|
||||
() => formData.value.template.ttsmessage,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
// webhook请求体变量提取
|
||||
watch(
|
||||
() => formData.value.template.body,
|
||||
(val) => {
|
||||
if (!val) {
|
||||
formData.value.variableDefinitions = [];
|
||||
return;
|
||||
}
|
||||
],
|
||||
() => {
|
||||
variableReg();
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -1176,7 +1119,7 @@ const handleMessageTypeChange = () => {
|
|||
content: formData.value.template.message as string,
|
||||
};
|
||||
}
|
||||
formData.value.variableDefinitions = [];
|
||||
// formData.value.variableDefinitions = [];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1186,7 +1129,10 @@ const getDetail = async () => {
|
|||
if (route.params.id !== ':id') {
|
||||
const res = await templateApi.detail(route.params.id as string);
|
||||
// formData.value = res.result;
|
||||
Object.assign(formData.value, res.result);
|
||||
// Object.assign(formData.value, res.result);
|
||||
console.log('res.result: ', res.result);
|
||||
formData.value = cloneDeep(res.result);
|
||||
console.log('formData.value: ', formData.value);
|
||||
}
|
||||
};
|
||||
getDetail();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
target="notice-config"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
ref="configRef"
|
||||
:columns="columns"
|
||||
|
@ -62,7 +63,10 @@
|
|||
<slot name="img">
|
||||
<img
|
||||
:src="
|
||||
getLogo(slotProps.type, slotProps.provider)
|
||||
getLogo(
|
||||
slotProps.type,
|
||||
slotProps.provider,
|
||||
)
|
||||
"
|
||||
class="logo"
|
||||
/>
|
||||
|
@ -82,7 +86,9 @@
|
|||
</div>
|
||||
</j-col>
|
||||
<j-col :span="12">
|
||||
<div class="card-item-content-text">说明</div>
|
||||
<div class="card-item-content-text">
|
||||
说明
|
||||
</div>
|
||||
<Ellipsis>
|
||||
{{ slotProps.description }}
|
||||
</Ellipsis>
|
||||
|
@ -183,12 +189,15 @@
|
|||
style="padding: 0px"
|
||||
:hasPermission="'notice/Template:' + i.key"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon" /></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
|
||||
<Debug v-model:visible="debugVis" :data="currentConfig" />
|
||||
<Log v-model:visible="logVis" :data="currentConfig" />
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
<template>
|
||||
<page-container :tabList="list" @tabChange="onTabChange" :tabActiveKey="tab">
|
||||
<div v-if="tab=='config'">
|
||||
<page-container
|
||||
:tabList="list"
|
||||
@tabChange="onTabChange"
|
||||
:tabActiveKey="tab"
|
||||
>
|
||||
<div v-if="tab == 'config'">
|
||||
<j-row :gutter="24">
|
||||
<j-col :span="14">
|
||||
<FullPage>
|
||||
<div class="alarm-level">
|
||||
<j-card
|
||||
:headStyle="{ borderBottom: 'none', padding: 0 }"
|
||||
:headStyle="{
|
||||
borderBottom: 'none',
|
||||
padding: 0,
|
||||
}"
|
||||
:bodyStyle="{ padding: 0 }"
|
||||
:bordered="false"
|
||||
>
|
||||
<template #title>
|
||||
<div class="alarmLevelTitle">告警级别配置</div>
|
||||
<div class="alarmLevelTitle">
|
||||
告警级别配置
|
||||
</div>
|
||||
</template>
|
||||
<div
|
||||
v-for="(item, i) in levels"
|
||||
|
@ -20,7 +30,9 @@
|
|||
<div>
|
||||
<img
|
||||
:src="
|
||||
getImage(`/alarm/alarm${i + 1}.png`)
|
||||
getImage(
|
||||
`/alarm/alarm${i + 1}.png`,
|
||||
)
|
||||
"
|
||||
alt=""
|
||||
/>
|
||||
|
@ -41,10 +53,18 @@
|
|||
@click="handleSaveLevel"
|
||||
>保存</j-button
|
||||
> -->
|
||||
<PermissionButton type="primary" size="middle" @click="handleSaveLevel" hasPermission="rule-engine/Alarm/Config:update">保存</PermissionButton>
|
||||
<PermissionButton
|
||||
type="primary"
|
||||
size="middle"
|
||||
@click="handleSaveLevel"
|
||||
hasPermission="rule-engine/Alarm/Config:update"
|
||||
>保存</PermissionButton
|
||||
>
|
||||
</div>
|
||||
</FullPage>
|
||||
</j-col>
|
||||
<j-col :span="10">
|
||||
<FullPage>
|
||||
<div class="description">
|
||||
<h1>功能说明</h1>
|
||||
<div>
|
||||
|
@ -53,6 +73,7 @@
|
|||
<div>2、告警级别将会在告警配置中被引用。</div>
|
||||
<div>3、最多可配置5个级别。</div>
|
||||
</div>
|
||||
</FullPage>
|
||||
</j-col>
|
||||
</j-row>
|
||||
</div>
|
||||
|
@ -65,7 +86,7 @@ import { getImage } from '@/utils/comm';
|
|||
import { queryLevel, saveLevel } from '@/api/rule-engine/config';
|
||||
import { LevelItem } from './typing';
|
||||
import { message } from 'jetlinks-ui-components';
|
||||
import Io from './Io/index.vue'
|
||||
import Io from './Io/index.vue';
|
||||
const list = ref([
|
||||
{
|
||||
key: 'config',
|
||||
|
@ -77,7 +98,7 @@ const list = ref([
|
|||
},
|
||||
]);
|
||||
let levels = ref<LevelItem[]>([]);
|
||||
let tab = ref<'io'|'config'|string>('config');
|
||||
let tab = ref<'io' | 'config' | string>('config');
|
||||
const getAlarmLevel = () => {
|
||||
queryLevel().then((res: any) => {
|
||||
if (res.status == 200) {
|
||||
|
@ -136,6 +157,7 @@ const onTabChange = (e: string) => {
|
|||
margin: 16px 0;
|
||||
color: rgba(#000, 0.85);
|
||||
font-weight: bold;
|
||||
font-size: 14px;}
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<FullPage>
|
||||
<div>
|
||||
<j-form layout="vertical" :rules="rule" :model="form" ref="formRef">
|
||||
<j-row :gutter="24">
|
||||
|
@ -20,7 +21,10 @@
|
|||
</j-col>
|
||||
</j-row>
|
||||
<j-form-item label="级别" name="level">
|
||||
<j-radio-group v-model:value="form.level" class="levelSelect">
|
||||
<j-radio-group
|
||||
v-model:value="form.level"
|
||||
class="levelSelect"
|
||||
>
|
||||
<j-radio-button
|
||||
v-for="(item, index) in levelOption"
|
||||
:key="index"
|
||||
|
@ -35,7 +39,9 @@
|
|||
"
|
||||
>
|
||||
<img
|
||||
:src="getImage(`/alarm/alarm${index + 1}.png`)"
|
||||
:src="
|
||||
getImage(`/alarm/alarm${index + 1}.png`)
|
||||
"
|
||||
style="height: 40px"
|
||||
alt=""
|
||||
/>{{ item.label }}
|
||||
|
@ -62,6 +68,7 @@
|
|||
>
|
||||
</j-form>
|
||||
</div>
|
||||
</FullPage>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<template>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
model="CARD"
|
||||
:request="query"
|
||||
|
@ -37,7 +38,9 @@
|
|||
:height="16"
|
||||
:src="typeMap.get(slotProps.triggerType)?.icon"
|
||||
style="margin-right: 5px"
|
||||
/>{{ typeMap.get(slotProps.triggerType)?.text }}</span
|
||||
/>{{
|
||||
typeMap.get(slotProps.triggerType)?.text
|
||||
}}</span
|
||||
>
|
||||
</template>
|
||||
<template #img>
|
||||
|
@ -81,6 +84,7 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<Save
|
||||
:id="id"
|
||||
:type="configurationData.current?.targetType"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
target="device-instance"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
:columns="columns"
|
||||
:request="queryList"
|
||||
|
@ -55,13 +56,20 @@
|
|||
<template #img>
|
||||
<slot name="img">
|
||||
<img
|
||||
:src="getImage('/alarm/alarm-config.png')"
|
||||
:src="
|
||||
getImage('/alarm/alarm-config.png')
|
||||
"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<Ellipsis style="width: calc(100% - 100px)">
|
||||
<span style="font-weight: 600; font-size: 16px">
|
||||
<span
|
||||
style="
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
|
@ -160,7 +168,8 @@
|
|||
type="link"
|
||||
style="padding: 0px"
|
||||
:hasPermission="
|
||||
'rule-engine/Alarm/Configuration:' + i.key
|
||||
'rule-engine/Alarm/Configuration:' +
|
||||
i.key
|
||||
"
|
||||
:danger="i.key === 'delete'"
|
||||
>
|
||||
|
@ -172,6 +181,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="alarm-log-detail"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
:columns="columns"
|
||||
model="TABLE"
|
||||
|
@ -34,19 +35,27 @@
|
|||
type="link"
|
||||
style="padding: 0px"
|
||||
>
|
||||
<template #icon><AIcon :type="i.icon"/></template>
|
||||
<template #icon
|
||||
><AIcon :type="i.icon"
|
||||
/></template>
|
||||
</PermissionButton>
|
||||
</template>
|
||||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
<Info v-if="visiable" :data="current" @close="close" :description="description"/>
|
||||
</FullPage>
|
||||
<Info
|
||||
v-if="visiable"
|
||||
:data="current"
|
||||
@close="close"
|
||||
:description="description"
|
||||
/>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { detail, queryHistoryList } from '@/api/rule-engine/log';
|
||||
import { detail as configurationDetail} from '@/api/rule-engine/configuration'
|
||||
import { detail as configurationDetail } from '@/api/rule-engine/configuration';
|
||||
import { useRoute } from 'vue-router';
|
||||
import dayjs from 'dayjs';
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
|
@ -54,10 +63,10 @@ import { message } from 'jetlinks-ui-components';
|
|||
import { useAlarmStore } from '@/store/alarm';
|
||||
import Info from './info.vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||
const route = useRoute();
|
||||
const id = route.params?.id;
|
||||
const { params: routerParams } = useRouterParams()
|
||||
const { params: routerParams } = useRouterParams();
|
||||
let visiable = ref(false);
|
||||
let description = ref<string>();
|
||||
const columns = [
|
||||
|
@ -170,11 +179,11 @@ watchEffect(async () => {
|
|||
key: 'targetName',
|
||||
});
|
||||
}
|
||||
configurationDetail(res.result?.alarmConfigId).then((res:any)=>{
|
||||
if(res.status === 200){
|
||||
configurationDetail(res.result?.alarmConfigId).then((res: any) => {
|
||||
if (res.status === 200) {
|
||||
description.value = res.result?.description;
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
const handleSearch = (_params: any) => {
|
||||
|
@ -185,15 +194,15 @@ const handleSearch = (_params: any) => {
|
|||
* 关闭模态弹窗
|
||||
*/
|
||||
const close = () => {
|
||||
visiable.value = false
|
||||
}
|
||||
visiable.value = false;
|
||||
};
|
||||
|
||||
watchEffect(()=>{
|
||||
watchEffect(() => {
|
||||
current.value = details.value;
|
||||
if(routerParams.value.detail && details.value){
|
||||
if (routerParams.value.detail && details.value) {
|
||||
visiable.value = true;
|
||||
}
|
||||
})
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
</style>
|
|
@ -5,6 +5,7 @@
|
|||
target="bind-channel"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
model="TABLE"
|
||||
:columns="columns"
|
||||
|
@ -33,11 +34,14 @@
|
|||
<template #alarmTime="slotProps">
|
||||
<span>
|
||||
{{
|
||||
dayjs(slotProps.alarmTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
dayjs(slotProps.alarmTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
v-if="props.type === 'org'"
|
||||
@search="search"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
:columns="columns"
|
||||
:request="handleSearch"
|
||||
|
@ -53,7 +54,10 @@
|
|||
}"
|
||||
>
|
||||
<template #img>
|
||||
<img :src="imgMap.get(slotProps.targetType)" alt="" />
|
||||
<img
|
||||
:src="imgMap.get(slotProps.targetType)"
|
||||
alt=""
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
<Ellipsis style="width: calc(100% - 100px)">
|
||||
|
@ -79,9 +83,9 @@
|
|||
<Ellipsis
|
||||
><div>
|
||||
{{
|
||||
dayjs(slotProps?.alarmTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
dayjs(
|
||||
slotProps?.alarmTime,
|
||||
).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}
|
||||
</div></Ellipsis
|
||||
>
|
||||
|
@ -131,6 +135,7 @@
|
|||
</CardBox>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<SolveComponent
|
||||
:data="data"
|
||||
v-if="data.solveVisible"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
target="device-instance"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
<FullPage>
|
||||
<JProTable
|
||||
:columns="columns"
|
||||
:request="queryList"
|
||||
|
@ -44,12 +45,19 @@
|
|||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/device-product.png')" />
|
||||
<img
|
||||
:src="getImage('/device-product.png')"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<Ellipsis style="width: calc(100% - 100px)">
|
||||
<span style="font-weight: 600; font-size: 16px">
|
||||
<span
|
||||
style="
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
"
|
||||
>
|
||||
{{ slotProps.name }}
|
||||
</span>
|
||||
</Ellipsis>
|
||||
|
@ -116,7 +124,9 @@
|
|||
@click="i.onClick"
|
||||
type="link"
|
||||
style="padding: 0px"
|
||||
:hasPermission="'rule-engine/Instance:' + i.key"
|
||||
:hasPermission="
|
||||
'rule-engine/Instance:' + i.key
|
||||
"
|
||||
:danger="i.key === 'delete'"
|
||||
>
|
||||
<template #icon
|
||||
|
@ -127,6 +137,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</JProTable>
|
||||
</FullPage>
|
||||
<!-- 新增、编辑 -->
|
||||
<Save
|
||||
:data="current"
|
||||
|
@ -151,11 +162,11 @@ import { getImage } from '@/utils/comm';
|
|||
import { message } from 'jetlinks-ui-components';
|
||||
import Save from './Save/index.vue';
|
||||
import { SystemConst } from '@/utils/consts';
|
||||
import {useRouterParams} from "@/utils/hooks/useParams";
|
||||
import { useRouterParams } from '@/utils/hooks/useParams';
|
||||
const params = ref<Record<string, any>>({});
|
||||
let visiable = ref(false);
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const { params: routeParams } = useRouterParams()
|
||||
const { params: routeParams } = useRouterParams();
|
||||
const query = {
|
||||
columns: [
|
||||
{
|
||||
|
|
|
@ -278,7 +278,7 @@ watch(
|
|||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true },
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
|
|
|
@ -154,7 +154,7 @@ const TypeList = [
|
|||
},
|
||||
{
|
||||
label: '按变量',
|
||||
value: 'variable',
|
||||
value: 'context',
|
||||
image: getImage('/scene/device-variable.png'),
|
||||
tip: '选择设备ID为上游变量值的设备',
|
||||
},
|
||||
|
@ -236,7 +236,7 @@ const filterType = async (newVal: any) => {
|
|||
!props.parallel &&
|
||||
props.name !== 0
|
||||
) {
|
||||
const array = TypeList.filter((item) => item.value === 'variable');
|
||||
const array = TypeList.filter((item) => item.value === 'context');
|
||||
_list.push(...array);
|
||||
}
|
||||
list.value = _list;
|
||||
|
@ -246,7 +246,7 @@ const filterType = async (newVal: any) => {
|
|||
!props.parallel &&
|
||||
props.name !== 0
|
||||
) {
|
||||
const array = TypeList.filter((item) => item.value === 'variable');
|
||||
const array = TypeList.filter((item) => item.value === 'context');
|
||||
_list.push(...array);
|
||||
}
|
||||
list.value = _list;
|
||||
|
@ -287,7 +287,12 @@ const onTagChange = (val: any[], arr: any[]) => {
|
|||
modelRef.source = 'fixed';
|
||||
}
|
||||
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}`;
|
||||
});
|
||||
emits('save', unref(modelRef), { tagName: tagName.join('') });
|
||||
|
@ -295,6 +300,8 @@ const onTagChange = (val: any[], arr: any[]) => {
|
|||
|
||||
const onVariableChange = (val: any, node: any) => {
|
||||
modelRef.deviceId = val;
|
||||
modelRef.source = 'upper';
|
||||
modelRef.upperKey = val;
|
||||
modelRef.selectorValues = [{ value: val, name: node.description }] as any;
|
||||
emits('save', unref(modelRef), { name: node.description });
|
||||
};
|
||||
|
@ -333,7 +340,7 @@ watch(
|
|||
return item.children.find((i: any) => i.id === param);
|
||||
});
|
||||
if (isVariable) {
|
||||
modelRef.selector = 'variable';
|
||||
modelRef.selector = 'context';
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -181,6 +181,7 @@ const onProductChange = (_val: any, bol: boolean) => {
|
|||
JSON.parse(_val.metadata || '{}'),
|
||||
DeviceModel?.message,
|
||||
);
|
||||
console.log(flag)
|
||||
if (!flag) {
|
||||
DeviceModel.message = {
|
||||
messageType: 'INVOKE_FUNCTION',
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -97,7 +97,9 @@
|
|||
<template #overlay>
|
||||
<j-menu>
|
||||
<j-menu-item
|
||||
v-for="(o, i) in item.children"
|
||||
v-for="(
|
||||
o, i
|
||||
) in item.children"
|
||||
:key="i"
|
||||
>
|
||||
<j-button
|
||||
|
@ -105,7 +107,9 @@
|
|||
@click="o.onClick"
|
||||
>
|
||||
<AIcon :type="o.icon" />
|
||||
<span>{{ o.text }}</span>
|
||||
<span>{{
|
||||
o.text
|
||||
}}</span>
|
||||
</j-button>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
|
@ -131,7 +135,9 @@
|
|||
<AIcon
|
||||
type="EyeOutlined"
|
||||
style="font-size: 24px"
|
||||
@click="() => table.toSave(slotProps.id, true)"
|
||||
@click="
|
||||
() => table.toSave(slotProps.id, true)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</CardBox>
|
||||
|
@ -153,7 +159,10 @@
|
|||
<template #action="slotProps">
|
||||
<j-space :size="16">
|
||||
<PermissionButton
|
||||
v-for="i in table.getActions(slotProps, 'table')"
|
||||
v-for="i in table.getActions(
|
||||
slotProps,
|
||||
'table',
|
||||
)"
|
||||
:hasPermission="i.permission"
|
||||
type="link"
|
||||
:tooltip="i.tooltip"
|
||||
|
@ -166,6 +175,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
</div>
|
||||
<div class="dialogs">
|
||||
<MenuDialog
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<FullPage>
|
||||
<div class="basis-container">
|
||||
<j-form
|
||||
layout="vertical"
|
||||
|
@ -33,7 +34,9 @@
|
|||
>
|
||||
<img
|
||||
class="img-style"
|
||||
:src="getImage('/init-home/mark.png')"
|
||||
:src="
|
||||
getImage('/init-home/mark.png')
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
|
@ -48,7 +51,9 @@
|
|||
<j-tooltip title="系统后台访问的url">
|
||||
<img
|
||||
class="img-style"
|
||||
:src="getImage('/init-home/mark.png')"
|
||||
:src="
|
||||
getImage('/init-home/mark.png')
|
||||
"
|
||||
/>
|
||||
</j-tooltip>
|
||||
</template>
|
||||
|
@ -61,7 +66,9 @@
|
|||
<j-col>
|
||||
<j-form-item label="系统logo">
|
||||
<div class="upload-image-warp-logo">
|
||||
<div class="upload-image-border-logo">
|
||||
<div
|
||||
class="upload-image-border-logo"
|
||||
>
|
||||
<j-upload
|
||||
name="file"
|
||||
:action="action"
|
||||
|
@ -73,14 +80,18 @@
|
|||
@change="
|
||||
uploader.handleChangeLogo
|
||||
"
|
||||
:accept="uploader.imageTypes"
|
||||
:accept="
|
||||
uploader.imageTypes
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="upload-image-content-logo"
|
||||
>
|
||||
<div
|
||||
class="loading-logo"
|
||||
v-if="form.logoLoading"
|
||||
v-if="
|
||||
form.logoLoading
|
||||
"
|
||||
>
|
||||
<AIcon
|
||||
type="LoadingOutlined"
|
||||
|
@ -89,7 +100,9 @@
|
|||
<div
|
||||
class="upload-image"
|
||||
style="height: 100%"
|
||||
v-if="formValue.logo"
|
||||
v-if="
|
||||
formValue.logo
|
||||
"
|
||||
:style="
|
||||
formValue.logo
|
||||
? `background-image: url(${formValue.logo});`
|
||||
|
@ -97,7 +110,9 @@
|
|||
"
|
||||
></div>
|
||||
<div
|
||||
v-if="formValue.logo"
|
||||
v-if="
|
||||
formValue.logo
|
||||
"
|
||||
class="upload-image-mask"
|
||||
>
|
||||
点击修改
|
||||
|
@ -151,7 +166,9 @@
|
|||
</j-tooltip>
|
||||
</template>
|
||||
<div class="upload-image-warp-logo">
|
||||
<div class="upload-image-border-logo">
|
||||
<div
|
||||
class="upload-image-border-logo"
|
||||
>
|
||||
<j-upload
|
||||
name="file"
|
||||
:action="action"
|
||||
|
@ -169,7 +186,9 @@
|
|||
class="upload-image-content-logo"
|
||||
>
|
||||
<div
|
||||
v-if="form.iconLoading"
|
||||
v-if="
|
||||
form.iconLoading
|
||||
"
|
||||
class="loading-icon"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -203,8 +222,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="upload-tips">推荐尺寸64*64</div>
|
||||
<div class="upload-tips">支持ico格式</div>
|
||||
<div class="upload-tips">
|
||||
推荐尺寸64*64
|
||||
</div>
|
||||
<div class="upload-tips">
|
||||
支持ico格式
|
||||
</div>
|
||||
</j-form-item>
|
||||
</j-col>
|
||||
</j-row>
|
||||
|
@ -224,12 +247,16 @@
|
|||
@change="uploader.changeBackUpload"
|
||||
:accept="uploader.imageTypes"
|
||||
>
|
||||
<div class="upload-image-content-back">
|
||||
<div
|
||||
class="upload-image-content-back"
|
||||
>
|
||||
<div
|
||||
v-if="form.backLoading"
|
||||
class="loading-back"
|
||||
>
|
||||
<AIcon type="LoadingOutlined" />
|
||||
<AIcon
|
||||
type="LoadingOutlined"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="upload-image"
|
||||
|
@ -280,6 +307,7 @@
|
|||
保存
|
||||
</j-button>
|
||||
</div>
|
||||
</FullPage>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -133,6 +133,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<EditDialog
|
||||
v-if="dialog.visible"
|
||||
|
@ -283,13 +284,13 @@ const table = {
|
|||
// 刷新列表
|
||||
refresh: () => {
|
||||
tableRef.value.reload();
|
||||
dialog.visible = false
|
||||
dialog.selectItem = {}
|
||||
dialog.visible = false;
|
||||
dialog.selectItem = {};
|
||||
},
|
||||
cancel: () => {
|
||||
dialog.visible = false
|
||||
dialog.selectItem = {}
|
||||
}
|
||||
dialog.visible = false;
|
||||
dialog.selectItem = {};
|
||||
},
|
||||
};
|
||||
table.getTypeOption();
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:request="table.requestFun"
|
||||
|
@ -49,7 +50,9 @@
|
|||
:hasPermission="`${permission}:assert`"
|
||||
@click="table.clickEdit()"
|
||||
>
|
||||
<AIcon type="EditOutlined" />批量编辑
|
||||
<AIcon
|
||||
type="EditOutlined"
|
||||
/>批量编辑
|
||||
</PermissionButton>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
|
@ -127,7 +130,8 @@
|
|||
:hasPermission="`${permission}:bind`"
|
||||
:popConfirm="{
|
||||
title: `是否解除绑定`,
|
||||
onConfirm: () => table.clickUnBind(slotProps),
|
||||
onConfirm: () =>
|
||||
table.clickUnBind(slotProps),
|
||||
}"
|
||||
>
|
||||
<AIcon type="DisconnectOutlined" />
|
||||
|
@ -169,6 +173,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddDeviceOrProductDialog
|
||||
|
@ -471,7 +476,7 @@ const table = {
|
|||
},
|
||||
clickAdd: (type?: string) => {
|
||||
// 设备资产分配弹窗操作类型: type = 'handle': 手动点击资产分配按钮, !type产品资产分配后, 自动弹出设备资产分配
|
||||
departmentStore.setType(type)
|
||||
departmentStore.setType(type);
|
||||
dialogs.addShow = true;
|
||||
},
|
||||
clickEdit: (row?: any) => {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:request="table.requestFun"
|
||||
|
@ -49,7 +50,9 @@
|
|||
:hasPermission="`${permission}:assert`"
|
||||
@click="() => table.clickEdit()"
|
||||
>
|
||||
<AIcon type="EditOutlined" />批量编辑
|
||||
<AIcon
|
||||
type="EditOutlined"
|
||||
/>批量编辑
|
||||
</PermissionButton>
|
||||
</j-menu-item>
|
||||
</j-menu>
|
||||
|
@ -63,7 +66,9 @@
|
|||
:value="slotProps"
|
||||
:actions="table.getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
:active="tableData._selectedRowKeys.includes(slotProps.id)"
|
||||
:active="
|
||||
tableData._selectedRowKeys.includes(slotProps.id)
|
||||
"
|
||||
@click="table.onSelectChange"
|
||||
:status="slotProps.state?.value"
|
||||
:statusText="slotProps.state?.text"
|
||||
|
@ -192,6 +197,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddDeviceOrProductDialog
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
target="category"
|
||||
@search="handleParams"
|
||||
/>
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -71,6 +72,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<div class="dialogs">
|
||||
<AddBindUserDialog
|
||||
|
@ -150,8 +152,8 @@ const columns = [
|
|||
const queryParams = ref({});
|
||||
|
||||
const handleParams = (params: any) => {
|
||||
queryParams.value = params
|
||||
}
|
||||
queryParams.value = params;
|
||||
};
|
||||
|
||||
// 表格
|
||||
const tableRef = ref<Record<string, any>>({}); // 表格实例
|
||||
|
@ -174,7 +176,7 @@ const table = reactive({
|
|||
value: props.parentId,
|
||||
},
|
||||
],
|
||||
type: 'and'
|
||||
type: 'and',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -32,7 +32,9 @@
|
|||
</template>
|
||||
<template #createTime="slotProps">
|
||||
{{
|
||||
dayjs(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
dayjs(slotProps.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
|
@ -70,6 +72,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="system-permission"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -100,7 +100,8 @@
|
|||
title: `确定要${
|
||||
slotProps.status ? '禁用' : '启用'
|
||||
}吗?`,
|
||||
onConfirm: () => table.changeStatus(slotProps),
|
||||
onConfirm: () =>
|
||||
table.changeStatus(slotProps),
|
||||
}"
|
||||
:tooltip="{
|
||||
title: slotProps.status ? '禁用' : '启用',
|
||||
|
@ -134,6 +135,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<EditDialog
|
||||
v-if="dialog.visible"
|
||||
|
|
|
@ -37,6 +37,9 @@ import {
|
|||
} from '@/api/system/apiPage';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { modeType } from '../typing';
|
||||
import { useDepartmentStore } from '@/store/department';
|
||||
|
||||
const department = useDepartmentStore();
|
||||
const emits = defineEmits([
|
||||
'refresh',
|
||||
'update:clickApi',
|
||||
|
@ -64,11 +67,6 @@ const columns = [
|
|||
dataIndex: 'summary',
|
||||
key: 'summary',
|
||||
},
|
||||
// {
|
||||
// title: 'ID',
|
||||
// dataIndex: 'id',
|
||||
// key: 'id',
|
||||
// },
|
||||
];
|
||||
const rowSelection = {
|
||||
// onSelect: (record: any) => {
|
||||
|
@ -95,7 +93,7 @@ const rowSelection = {
|
|||
props.sourceKeys.includes(key),
|
||||
);
|
||||
// 除当前表格之外, 勾选上的数据
|
||||
const otherSelectedKeys = props.sourceKeys.filter(
|
||||
const otherSelectedKeys = department.crossPageKeys.filter(
|
||||
(key) => !currenTableKeys.includes(key),
|
||||
);
|
||||
|
||||
|
@ -103,6 +101,7 @@ const rowSelection = {
|
|||
const removeKeys = oldSelectedKeys.filter((key) => !keys.includes(key));
|
||||
// 新增选择的项
|
||||
const addKeys = keys.filter((key) => !oldSelectedKeys.includes(key));
|
||||
// 缓存当前表格和其他表格改变的数据
|
||||
emits('update:selectedRowKeys', [...otherSelectedKeys, ...keys]);
|
||||
|
||||
// 新增选中/取消选中的数据
|
||||
|
@ -111,37 +110,21 @@ const rowSelection = {
|
|||
changed[key] = props.tableData.find((f: any) => f.id === key);
|
||||
});
|
||||
if (props.mode === 'appManger') {
|
||||
emits('update:changedApis', changed);
|
||||
// 缓存当前表格和其他表格改变的数据
|
||||
emits('update:changedApis', {
|
||||
...department.changedApis,
|
||||
...changed,
|
||||
});
|
||||
}
|
||||
},
|
||||
selectedRowKeys: ref<string[]>([]),
|
||||
};
|
||||
const save = async () => {
|
||||
// fix: #bug10828
|
||||
// 当前节点表格数据id
|
||||
// const currenTableKeys = props.tableData.map((m: any) => m.id);
|
||||
// // 当前表格选中的id
|
||||
// const currentSelectedKeys = rowSelection.selectedRowKeys.value.filter(
|
||||
// (key: string) => currenTableKeys.includes(key),
|
||||
// );
|
||||
// // 当前表格, 原有选中的id
|
||||
// const oldSelectedKeys = currenTableKeys.filter((key) =>
|
||||
// props.sourceKeys.includes(key),
|
||||
// );
|
||||
|
||||
const keys = props.selectedRowKeys;
|
||||
// 移除的key
|
||||
const removeKeys = props.sourceKeys.filter((key) => !keys.includes(key));
|
||||
// 新选中的key
|
||||
const addKeys = keys.filter((key) => !props.sourceKeys.includes(key));
|
||||
// console.log('addKeys: ', addKeys);
|
||||
// console.log('removeKeys: ', removeKeys);
|
||||
// 取消选择的数据项
|
||||
// const removeKeys = oldSelectedKeys.filter(
|
||||
// (key) => !currentSelectedKeys.includes(key),
|
||||
// );
|
||||
// // 新增选择的项
|
||||
// const addKeys = currentSelectedKeys.filter(
|
||||
// (key) => !oldSelectedKeys.includes(key),
|
||||
// );
|
||||
|
||||
if (props.mode === 'api') {
|
||||
// 此时是api配置
|
||||
|
@ -163,14 +146,10 @@ const save = async () => {
|
|||
const removeItems = removeKeys.map((key) => ({
|
||||
id: key,
|
||||
permissions: props.changedApis[key]?.security,
|
||||
// permissions: props.tableData.find((f: any) => f.id === key)
|
||||
// ?.security,
|
||||
}));
|
||||
const addItems = addKeys.map((key) => ({
|
||||
id: key,
|
||||
permissions: props.changedApis[key]?.security,
|
||||
// permissions: props.tableData.find((f: any) => f.id === key)
|
||||
// ?.security,
|
||||
}));
|
||||
Promise.all([
|
||||
updateOperations_api(code, '_delete', { operations: removeItems }),
|
||||
|
|
|
@ -76,6 +76,9 @@ import LeftTree from './components/LeftTree.vue';
|
|||
import ChooseApi from './components/ChooseApi.vue';
|
||||
import ApiDoes from './components/ApiDoes.vue';
|
||||
import ApiTest from './components/ApiTest.vue';
|
||||
import { useDepartmentStore } from '@/store/department';
|
||||
|
||||
const department = useDepartmentStore();
|
||||
|
||||
const props = defineProps<{
|
||||
mode: modeType;
|
||||
|
@ -157,12 +160,20 @@ function getSelectKeys() {
|
|||
}
|
||||
}
|
||||
|
||||
// watch(
|
||||
// () => changedApis.value,
|
||||
// (val: any) => {
|
||||
// console.log('changedApis: ', val);
|
||||
// },
|
||||
// );
|
||||
watch(
|
||||
() => selectedKeys.value,
|
||||
(val: any) => {
|
||||
// console.log('selectedKeys: ', val);
|
||||
department.setSelectedKeys(val);
|
||||
},
|
||||
);
|
||||
watch(
|
||||
() => changedApis.value,
|
||||
(val: any) => {
|
||||
// console.log('changedApis: ', val);
|
||||
department.setChangedApis(val);
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -60,6 +60,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<EditDialog
|
||||
v-if="dialog.visible"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="(params:any)=>queryParams = {...params}"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -65,6 +65,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<AddDialog v-if="dialogVisible" v-model:visible="dialogVisible" />
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
target="category"
|
||||
@search="handleParams"
|
||||
/>
|
||||
|
||||
<FullPage>
|
||||
<j-pro-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
|
@ -60,13 +60,16 @@
|
|||
:hasPermission="`${permission}:action`"
|
||||
type="link"
|
||||
:tooltip="{
|
||||
title: `${slotProps.status ? '禁用' : '启用'}`,
|
||||
title: `${
|
||||
slotProps.status ? '禁用' : '启用'
|
||||
}`,
|
||||
}"
|
||||
:popConfirm="{
|
||||
title: `确定${
|
||||
slotProps.status ? '禁用' : '启用'
|
||||
}吗?`,
|
||||
onConfirm: () => table.changeStatus(slotProps),
|
||||
onConfirm: () =>
|
||||
table.changeStatus(slotProps),
|
||||
}"
|
||||
>
|
||||
<AIcon
|
||||
|
@ -97,7 +100,8 @@
|
|||
}"
|
||||
:popConfirm="{
|
||||
title: `确认删除`,
|
||||
onConfirm: () => table.clickDel(slotProps.id),
|
||||
onConfirm: () =>
|
||||
table.clickDel(slotProps.id),
|
||||
}"
|
||||
:disabled="slotProps.status"
|
||||
>
|
||||
|
@ -106,6 +110,7 @@
|
|||
</j-space>
|
||||
</template>
|
||||
</j-pro-table>
|
||||
</FullPage>
|
||||
|
||||
<EditUserDialog
|
||||
v-if="dialog.visible"
|
||||
|
@ -263,22 +268,21 @@ type dictType = {
|
|||
};
|
||||
type modalType = '' | 'add' | 'edit' | 'reset';
|
||||
|
||||
const handleParams = (params: any)=> {
|
||||
|
||||
const newParams = (params?.terms as any[])?.map(item1 => {
|
||||
const handleParams = (params: any) => {
|
||||
const newParams = (params?.terms as any[])?.map((item1) => {
|
||||
item1.terms = item1.terms.map((item2: any) => {
|
||||
if (['telephone', 'email'].includes(item2.column)) {
|
||||
return {
|
||||
column: 'id$user-detail',
|
||||
value: [item2]
|
||||
value: [item2],
|
||||
};
|
||||
}
|
||||
}
|
||||
return item2
|
||||
})
|
||||
return item1
|
||||
})
|
||||
queryParams.value = { terms: newParams || [] }
|
||||
}
|
||||
return item2;
|
||||
});
|
||||
return item1;
|
||||
});
|
||||
queryParams.value = { terms: newParams || [] };
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
|
Loading…
Reference in New Issue