934 lines
29 KiB
Vue
934 lines
29 KiB
Vue
<!-- 设备接入 -->
|
||
<template>
|
||
<div v-if="access.id === undefined || null" style='margin-top: 20%; transform: translateY(-50%);'>
|
||
<j-empty :image="simpleImage">
|
||
<template #description>
|
||
<span
|
||
v-if="
|
||
permissionStore.hasPermission('device/Product:update')
|
||
"
|
||
>
|
||
请先<j-button type="link" @click="showModal">选择</j-button
|
||
>设备接入网关,用以提供设备接入能力
|
||
</span>
|
||
<span v-else>请联系管理员配置产品接入方式</span>
|
||
</template>
|
||
</j-empty>
|
||
</div>
|
||
<div v-else>
|
||
<j-row :gutter="24">
|
||
<j-col :span="12">
|
||
<Title data="接入方式">
|
||
<template #extra>
|
||
<PermissionButton
|
||
style="margin: 0 0 0 20px"
|
||
type="primary"
|
||
size="small"
|
||
:tooltip="{
|
||
title: tooltip
|
||
}"
|
||
:disabled="checkDisabled"
|
||
ghost
|
||
@click="showDevice"
|
||
hasPermission="device/Product:update"
|
||
>
|
||
更换
|
||
</PermissionButton>
|
||
</template>
|
||
</Title>
|
||
<div>
|
||
<div>
|
||
{{ access?.name }}
|
||
</div>
|
||
<div>
|
||
{{
|
||
access?.description ||
|
||
dataSource.find(
|
||
(item) => item?.id === access?.provider,
|
||
)?.description
|
||
}}
|
||
</div>
|
||
</div>
|
||
<div class="item-style">
|
||
<Title data="消息协议"></Title>
|
||
<div>
|
||
{{ access?.protocolDetail?.name }}
|
||
</div>
|
||
<!-- 显示md文件内容 -->
|
||
<div v-if="config?.document" v-html="markdownToHtml"></div>
|
||
</div>
|
||
<div class="item-style">
|
||
<Title data="连接信息"></Title>
|
||
<div v-if="access?.channelInfo?.addresses.length > 0">
|
||
<div
|
||
v-for="item in access?.channelInfo?.addresses"
|
||
:key="item.address"
|
||
>
|
||
<j-badge
|
||
:color="item.health === -1 ? 'red' : 'green'"
|
||
:text="item.address"
|
||
>
|
||
</j-badge>
|
||
</div>
|
||
</div>
|
||
<div v-else>{{ '暂无连接信息' }}</div>
|
||
</div>
|
||
<!-- 产品类型 -->
|
||
<j-form ref="pluginFormRef" :model="productData" layout="vertical" v-if='productTypes.length'>
|
||
<j-form-item name='id' label='产品类型' :rules='[{ required: true, message: "请选择产品类型"}]'>
|
||
<j-select
|
||
v-model:value='productData.id'
|
||
:options='productTypes'
|
||
@change='productTypeChange'
|
||
placeholder='请选择产品类型'
|
||
/>
|
||
</j-form-item>
|
||
|
||
</j-form>
|
||
<!-- 其它接入配置 -->
|
||
<Title
|
||
v-if="metadata?.name"
|
||
:data="metadata?.name"
|
||
class="config"
|
||
>
|
||
<template #extra>
|
||
<j-tooltip title="此配置来自于产品接入方式所选择的协议">
|
||
<AIcon
|
||
type="QuestionCircleOutlined"
|
||
style="margin-left: 2px"
|
||
/>
|
||
</j-tooltip>
|
||
</template>
|
||
</Title>
|
||
<j-form ref="formRef" :model="formData.data" layout="vertical">
|
||
<j-form-item
|
||
:name="item.property"
|
||
v-for="item in metadata?.properties || []"
|
||
:key="item"
|
||
:label="item.name"
|
||
:rules="[
|
||
{
|
||
required: !!item?.type?.expands?.required,
|
||
message: `${
|
||
item.type.type === 'enum' || 'boolean'
|
||
? '请选择'
|
||
: '请输入'
|
||
}${item.name}`,
|
||
},
|
||
]"
|
||
>
|
||
<j-input
|
||
placeholder="请输入"
|
||
v-if="item.type.type === 'string'"
|
||
v-model:value="formData.data[item.property]"
|
||
></j-input>
|
||
<j-input-password
|
||
placeholder="请输入"
|
||
v-if="item.type.type === 'password'"
|
||
v-model:value="formData.data[item.property]"
|
||
></j-input-password>
|
||
<j-select
|
||
placeholder="请选择"
|
||
v-if="item.type.type === 'enum' || item.type.type === 'boolean'"
|
||
v-model:value="formData.data[item.property]"
|
||
:options="getOptions(item)"
|
||
>
|
||
<!-- <j-select-option
|
||
v-for="el in item?.type?.type === 'enum' &&
|
||
item?.type?.elements
|
||
? item?.type?.elements
|
||
: []"
|
||
:key="el"
|
||
:value="el.value"
|
||
>
|
||
{{ el.text }}
|
||
</j-select-option> -->
|
||
</j-select>
|
||
<j-input-number v-if="['int','float','double','long'].includes(item.type.type)" v-model:value="formData.data[item.property]" placeholder="请输入"></j-input-number>
|
||
</j-form-item>
|
||
</j-form>
|
||
<Title data="存储策略">
|
||
<template #extra>
|
||
<j-tooltip
|
||
title="若修改存储策略,需要手动做数据迁移,平台只能搜索最新存储策略中的数据"
|
||
>
|
||
<AIcon
|
||
type="QuestionCircleOutlined"
|
||
style="margin-left: 2px"
|
||
/>
|
||
</j-tooltip>
|
||
</template>
|
||
</Title>
|
||
<j-form layout="vertical">
|
||
<j-form-item>
|
||
<j-select ref="select" v-model:value="form.storePolicy">
|
||
<j-select-option
|
||
v-for="(item, index) in storageList"
|
||
:key="index"
|
||
:value="item.id"
|
||
>{{ item.name }}</j-select-option
|
||
>
|
||
</j-select>
|
||
</j-form-item>
|
||
</j-form>
|
||
<PermissionButton
|
||
type="primary"
|
||
@click="submitDevice"
|
||
hasPermission="device/Instance:update"
|
||
:loading='submitLoading'
|
||
>保存</PermissionButton
|
||
>
|
||
</j-col>
|
||
<j-col
|
||
:span="12"
|
||
v-if="config?.routes && config?.routes?.length > 0"
|
||
>
|
||
<div class="info">
|
||
<div>
|
||
<div style="font-weight: 600; margin: 0 0 10px 0">
|
||
{{
|
||
access?.provider === 'mqtt-server-gateway' ||
|
||
access?.provider === 'mqtt-client-gateway'
|
||
? 'topic'
|
||
: 'URL信息'
|
||
}}
|
||
</div>
|
||
<j-table
|
||
:columns="
|
||
config.id === 'MQTT' ? columnsMQTT : columnsHTTP
|
||
"
|
||
:data-source="config?.routes"
|
||
:pagination="false"
|
||
:scroll="{ y: 500 }"
|
||
>
|
||
<template #bodyCell="{ text, column, record }">
|
||
<template v-if="column?.key === 'topic'">
|
||
<j-tooltip
|
||
placement="topLeft"
|
||
:title="text"
|
||
>
|
||
<div class="ellipsis-style">
|
||
{{ text }}
|
||
</div>
|
||
</j-tooltip>
|
||
</template>
|
||
<template v-if="column?.key === 'stream'">
|
||
<div>{{ getStream(record) }}</div>
|
||
</template>
|
||
<template v-if="column.key === 'description'">
|
||
<j-tooltip
|
||
placement="topLeft"
|
||
:title="text"
|
||
>
|
||
<div class="ellipsis-style">
|
||
{{ text }}
|
||
</div>
|
||
</j-tooltip>
|
||
</template>
|
||
<template v-if="column?.key === 'address'">
|
||
<j-tooltip
|
||
placement="topLeft"
|
||
:title="text"
|
||
>
|
||
<div class="ellipsis-style">
|
||
{{ text }}
|
||
</div>
|
||
</j-tooltip>
|
||
</template>
|
||
<template v-if="column?.key === 'example'">
|
||
<j-tooltip
|
||
placement="topLeft"
|
||
:title="text"
|
||
>
|
||
<div class="ellipsis-style">
|
||
{{ text }}
|
||
</div>
|
||
</j-tooltip>
|
||
</template>
|
||
</template>
|
||
</j-table>
|
||
</div>
|
||
</div>
|
||
</j-col>
|
||
</j-row>
|
||
</div>
|
||
<!-- 选择设备 -->
|
||
<AccessModal
|
||
v-if='visible'
|
||
:product-id='productStore.current.id'
|
||
:deviceType='productStore.current.deviceType'
|
||
:accessId='accessId'
|
||
:providersList='dataSource'
|
||
@cancel=' visible = false'
|
||
@submit='checkAccess'
|
||
/>
|
||
<!-- 物模型处理方式 -->
|
||
<MetaDataModal
|
||
v-if='metadataVisible'
|
||
:metadata='productData.metadata'
|
||
:access='access'
|
||
:data='metadataModalCacheData'
|
||
@cancel=' () => { metadataVisible = false, metadataModalCacheData = {}}'
|
||
@submit='MetaDataModalSubmit'
|
||
/>
|
||
</template>
|
||
|
||
<script lang="ts" setup name='AccessConfig'>
|
||
import { useProductStore } from '@/store/product';
|
||
import { ConfigMetadata } from '@/views/device/Product/typings';
|
||
import { Empty } from 'jetlinks-ui-components';
|
||
import Title from '../Title/index.vue';
|
||
import { usePermissionStore } from '@/store/permission';
|
||
import { steps, steps1 } from './util';
|
||
import './index.less';
|
||
import {
|
||
getProviders,
|
||
_deploy,
|
||
_undeploy,
|
||
queryList,
|
||
getConfigView,
|
||
getConfigMetadata,
|
||
productGuide,
|
||
productGuideSave,
|
||
getStoragList,
|
||
saveDevice,
|
||
updateDevice,
|
||
detail,
|
||
modify, getAccessConfig
|
||
} from '@/api/device/product'
|
||
|
||
import Driver from 'driver.js';
|
||
import 'driver.js/dist/driver.min.css';
|
||
import { marked } from 'marked';
|
||
import type { TableColumnType } from 'ant-design-vue';
|
||
import { useMenuStore } from '@/store/menu';
|
||
import _ from 'lodash-es';
|
||
import { accessConfigTypeFilter } from '@/utils/setting';
|
||
import AccessModal from './accessModal.vue'
|
||
import MetaDataModal from './metadataModal.vue'
|
||
import { getPluginData, getProductByPluginId, savePluginData } from '@/api/link/plugin'
|
||
import { detail as queryPluginAccessDetail } from '@/api/link/accessConfig'
|
||
import { onlyMessage } from '@/utils/comm';
|
||
|
||
const productStore = useProductStore();
|
||
const tableRef = ref();
|
||
const formRef = ref();
|
||
const menuStore = useMenuStore();
|
||
const permissionStore = usePermissionStore();
|
||
const render = new marked.Renderer();
|
||
marked.setOptions({
|
||
renderer: render,
|
||
gfm: true,
|
||
pedantic: false,
|
||
snaitize: false,
|
||
});
|
||
const simpleImage = ref(Empty.PRESENTED_IMAGE_SIMPLE);
|
||
const visible = ref<boolean>(false);
|
||
const access = ref<Record<string, any>>({});
|
||
const accessId = ref<string>(productStore.current.accessId)
|
||
const config = ref<any>({});
|
||
const metadata = ref<ConfigMetadata>({ properties: [] });
|
||
const dataSource = ref<string[]>([]);
|
||
const storageList = ref<any[]>([]);
|
||
const markdownToHtml = shallowRef('');
|
||
const current = ref({
|
||
id: productStore.current?.accessId,
|
||
name: productStore.current?.accessName,
|
||
protocol: productStore.current?.messageProtocol,
|
||
transport: productStore.current?.transportProtocol,
|
||
protocolDetail: {
|
||
name: productStore.current?.protocolName,
|
||
},
|
||
});
|
||
//存储数据
|
||
const form = reactive<Record<string, any>>({
|
||
storePolicy: 'default-row' || productStore.current?.storePolicy || '',
|
||
});
|
||
// 表单数据
|
||
const formData = reactive<Record<string, any>>({
|
||
data: productStore.current?.configuration || {},
|
||
});
|
||
//获取物模型下拉选项
|
||
const getOptions = (i:any) =>{
|
||
if (i.type.type === 'enum') {
|
||
return (i.type?.elements || []).map((item) => {
|
||
return {
|
||
label: item?.text,
|
||
value: item?.value,
|
||
};
|
||
});
|
||
} else if (i.type.type === 'boolean') {
|
||
return [
|
||
{
|
||
label: i.type?.falseText,
|
||
value: i.type?.falseValue,
|
||
},
|
||
{
|
||
label: i.type?.trueText,
|
||
value: i.type?.trueValue,
|
||
}
|
||
];
|
||
}
|
||
return undefined;
|
||
}
|
||
const fun = () =>{
|
||
console.log(formData.data,productStore.current?.configuration)
|
||
}
|
||
fun()
|
||
// 产品类型
|
||
const productTypes = ref([])
|
||
const productData = reactive({
|
||
id: undefined,
|
||
metadata: {} // 物模型
|
||
})
|
||
const pluginFormRef = ref()
|
||
const metadataVisible = ref(false)
|
||
const metadataModalCacheData = ref()
|
||
|
||
const submitLoading = ref(false)
|
||
/**
|
||
* 显示弹窗
|
||
*/
|
||
const showModal = () => {
|
||
visible.value = true;
|
||
};
|
||
|
||
/**
|
||
* 关闭弹窗
|
||
*/
|
||
const cancel = () => {
|
||
queryParams.value = {};
|
||
visible.value = false;
|
||
};
|
||
/**
|
||
* 打开设备弹窗
|
||
*/
|
||
const showDevice = () => {
|
||
visible.value = true;
|
||
};
|
||
|
||
const param = ref<Record<string, any>>({
|
||
pageSize: 4,
|
||
terms: [],
|
||
});
|
||
const queryParams = ref<Record<string, any>>({});
|
||
|
||
const currentForm = ref({});
|
||
|
||
const search = (e: any) => {
|
||
queryParams.value = {
|
||
...e,
|
||
};
|
||
};
|
||
|
||
const stepsRef = reactive({ current: 0 });
|
||
|
||
/**
|
||
* 保存引导页数据
|
||
*/
|
||
const guide = (data: any) => {
|
||
productGuideSave(data);
|
||
};
|
||
/**
|
||
* 显示引导页
|
||
*/
|
||
const driver = new Driver({
|
||
allowClose: false,
|
||
doneBtnText: '我知道了',
|
||
closeBtnText: '不再提示',
|
||
nextBtnText: '下一步',
|
||
prevBtnText: '上一步',
|
||
onNext: () => {
|
||
stepsRef.current = stepsRef.current + 1;
|
||
},
|
||
onPrevious: () => {
|
||
stepsRef.current = stepsRef.current - 1;
|
||
},
|
||
onReset: () => {
|
||
if (stepsRef.current !== 3) {
|
||
guide({
|
||
name: 'guide',
|
||
content: 'skip',
|
||
});
|
||
}
|
||
stepsRef.current = 0;
|
||
},
|
||
});
|
||
|
||
const driver1 = new Driver({
|
||
allowClose: false,
|
||
doneBtnText: '我知道了',
|
||
closeBtnText: '不再提示',
|
||
nextBtnText: '下一步',
|
||
prevBtnText: '上一步',
|
||
onNext: () => {
|
||
stepsRef.current = stepsRef.current + 1;
|
||
},
|
||
onPrevious: () => {
|
||
stepsRef.current = stepsRef.current - 1;
|
||
},
|
||
onReset: () => {
|
||
if (stepsRef.current !== 4) {
|
||
guide({
|
||
name: 'guide',
|
||
content: 'skip',
|
||
});
|
||
}
|
||
stepsRef.current = 0;
|
||
},
|
||
});
|
||
|
||
let columnsMQTT = ref(<TableColumnType>[]);
|
||
const ColumnsMQTT = [
|
||
{
|
||
title: 'topic',
|
||
dataIndex: 'topic',
|
||
key: 'topic',
|
||
ellipsis: true,
|
||
},
|
||
{
|
||
title: '上下行',
|
||
dataIndex: 'stream',
|
||
key: 'stream',
|
||
ellipsis: true,
|
||
align: 'center',
|
||
width: 100,
|
||
scopedSlots: { customRender: 'stream' },
|
||
},
|
||
{
|
||
title: '说明',
|
||
dataIndex: 'description',
|
||
key: 'description',
|
||
ellipsis: true,
|
||
},
|
||
];
|
||
const columnsHTTP = ref(<TableColumnType>[]);
|
||
const ColumnsHTTP = [
|
||
{
|
||
title: '地址',
|
||
dataIndex: 'address',
|
||
key: 'address',
|
||
ellipsis: true,
|
||
// scopedSlots: { customRender: 'address' },
|
||
},
|
||
{
|
||
title: '示例',
|
||
dataIndex: 'example',
|
||
key: 'example',
|
||
ellipsis: true,
|
||
// scopedSlots: { customRender: 'example' },
|
||
},
|
||
{
|
||
title: '说明',
|
||
dataIndex: 'description',
|
||
key: 'description',
|
||
ellipsis: true,
|
||
// scopedSlots: { customRender: 'description' },
|
||
},
|
||
];
|
||
/**
|
||
* 获取上下行数据
|
||
*/
|
||
const getStream = (record: any) => {
|
||
const list = [];
|
||
if (record?.upstream) {
|
||
list.push('上行');
|
||
}
|
||
if (record?.downstream) {
|
||
list.push('下行');
|
||
}
|
||
return `${list.join(',')}`;
|
||
};
|
||
/**
|
||
* 查询接入方式
|
||
*/
|
||
const queryAccessDetail = async (id: string) => {
|
||
const res = await queryList({
|
||
terms: [
|
||
{
|
||
column: 'id',
|
||
value: id,
|
||
},
|
||
],
|
||
}).then((res: any) => {
|
||
if (res.status === 200) {
|
||
access.value = res.result.data[0];
|
||
if (access.value?.transportDetail?.metadata) {
|
||
productData.metadata = JSON.parse(access.value?.transportDetail?.metadata)
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleColumns = () => {
|
||
const Group = {
|
||
title: '分组',
|
||
dataIndex: 'group',
|
||
key: 'group',
|
||
ellipsis: true,
|
||
align: 'center',
|
||
width: 100,
|
||
customCell: (record: any, rowIndex: number) => {
|
||
const obj = {
|
||
children: record,
|
||
rowSpan: 0,
|
||
};
|
||
const list = config.value?.routes || [];
|
||
|
||
const arr = list.filter(
|
||
(res: any) => res.group === record.group,
|
||
);
|
||
|
||
const isRowIndex =
|
||
rowIndex === 0 ||
|
||
list[rowIndex - 1].group !== record.group;
|
||
isRowIndex && (obj.rowSpan = arr.length);
|
||
|
||
return obj;
|
||
},
|
||
};
|
||
columnsMQTT.value = [Group, ...ColumnsMQTT];
|
||
columnsHTTP.value = [Group, ...ColumnsHTTP];
|
||
}
|
||
|
||
/**
|
||
* 查询协议信息
|
||
*/
|
||
const getConfigDetail = (
|
||
messageProtocol: string,
|
||
transportProtocol: string,
|
||
) => {
|
||
getConfigView(messageProtocol, transportProtocol).then((resp) => {
|
||
if (resp.status === 200) {
|
||
config.value = resp.result;
|
||
handleColumns()
|
||
if (config.value?.document) {
|
||
markdownToHtml.value = marked(config.value.document);
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const modifyArray = (oldData: any[], newData: any[]) => {
|
||
newData.map((item) => {
|
||
if (!_.map(oldData, 'id').includes(item.id)) {
|
||
oldData.push(item);
|
||
}
|
||
});
|
||
return oldData.map((item, index) => {
|
||
return { ...item, sortsIndex: index };
|
||
});
|
||
};
|
||
/**
|
||
*
|
||
*/
|
||
const getGuide = async (isDriver1: boolean = false) => {
|
||
const res: any = await productGuide();
|
||
if (res.result && res.result?.content === 'skip') {
|
||
return;
|
||
} else {
|
||
if (isDriver1) {
|
||
driver1.defineSteps(steps1);
|
||
driver1.start();
|
||
} else {
|
||
driver.defineSteps(steps);
|
||
driver.start();
|
||
}
|
||
}
|
||
};
|
||
|
||
const checkAccess = async (data: any) => {
|
||
visible.value = false
|
||
accessId.value = data.access.id
|
||
access.value = data.access
|
||
config.value = data.access?.transportDetail || {}
|
||
productTypes.value = []
|
||
productData.id = undefined
|
||
productData.metadata = {}
|
||
metadata.value = data.metadata?.[0] || {
|
||
properties: []
|
||
}
|
||
if (data.access.channel === 'plugin') { // 插件设备
|
||
markdownToHtml.value = ''
|
||
productTypes.value = data.productTypes.map(item => ({ ...item, label: item.name, value: item.id}))
|
||
} else {
|
||
handleColumns()
|
||
markdownToHtml.value = config.value?.document ? marked(config.value.document) : '';
|
||
getGuide(!!data.metadata.length); //
|
||
|
||
if (data.access?.transportDetail?.metadata) {
|
||
productData.metadata = JSON.parse(data.access?.transportDetail?.metadata)
|
||
}
|
||
}
|
||
}
|
||
|
||
const productTypeChange = (id: string, items: any) => {
|
||
productData.metadata = items?.metadata || {}
|
||
}
|
||
|
||
/**
|
||
* 获取协议类型名称
|
||
*/
|
||
const getProvidersList = async () => {
|
||
const res: any = await getProviders();
|
||
dataSource.value = res.result;
|
||
};
|
||
|
||
/**
|
||
* 查询保存数据信息
|
||
*/
|
||
const getData = async (accessId?: string) => {
|
||
const _accessId = accessId || productStore.current?.accessId;
|
||
if (productStore.current?.id) {
|
||
getConfigMetadata(productStore.current?.id).then((resp: any) => {
|
||
metadata.value = (resp?.result[0] as ConfigMetadata) || {
|
||
properties: [],
|
||
};
|
||
// 流传输模式 初始为udp模式
|
||
if (metadata.value?.properties) {
|
||
metadata.value?.properties.forEach((item) => {
|
||
if (
|
||
item.name === '流传输模式' &&
|
||
(!productStore.current?.configuration ||
|
||
!productStore.current?.configuration.hasOwnProperty(
|
||
item.property,
|
||
))
|
||
) {
|
||
formData.data[item.property] =
|
||
item.type.expands?.defaultValue;
|
||
}
|
||
});
|
||
}
|
||
if (accessId) {
|
||
// 切换接入方式之后获取是否显示引导
|
||
getGuide(resp?.result.length); //
|
||
}
|
||
});
|
||
}
|
||
if (_accessId) {
|
||
// 有设备接入
|
||
// const metadataResp = await getConfigMetadata(productStore.current!.id)
|
||
// if (metadataResp.success) {
|
||
// metadata.value = (metadataResp.result?.[0] as ConfigMetadata[]) || [];
|
||
// }
|
||
queryAccessDetail(_accessId);
|
||
if (productStore.current?.accessProvider === 'plugin_gateway') {
|
||
queryPluginAccessDetail(_accessId).then(async res => { //
|
||
if (res.success) {
|
||
const pluginRes = await getPluginData('product', _accessId, productStore.current?.id)
|
||
const resp = await getProductByPluginId(res.result.channelId).catch(() => ({ success: false, result: []}))
|
||
if (resp.success) {
|
||
productTypes.value = resp.result.map(item => {
|
||
if (pluginRes?.result?.externalId === item.id) {
|
||
productData.id = pluginRes?.result?.externalId
|
||
productData.metadata = item.metadata
|
||
}
|
||
return { ...item, label: item.name, value: item.id }
|
||
})
|
||
}
|
||
}
|
||
})
|
||
|
||
} else {
|
||
getConfigDetail(
|
||
productStore.current?.messageProtocol || '',
|
||
productStore.current?.transportProtocol || '',
|
||
);
|
||
}
|
||
|
||
}
|
||
getStoragList().then((resp: any) => {
|
||
if (resp.status === 200) {
|
||
storageList.value = resp.result;
|
||
}
|
||
});
|
||
};
|
||
|
||
/**
|
||
* 保存设备接入
|
||
*/
|
||
const submitDevice = async () => {
|
||
if (pluginFormRef.value) { // 插件
|
||
const pluginRef = await pluginFormRef.value.validate();
|
||
if (!pluginRef) return
|
||
}
|
||
|
||
const res = await formRef.value.validate();
|
||
if (!res) return
|
||
const values = { storePolicy: form.storePolicy, ...formData.data };
|
||
const id = productStore.current?.id;
|
||
// 该产品是否有物模型,有则弹窗进行处理
|
||
const _metadata = JSON.parse(productStore.current?.metadata || '{}')
|
||
console.log(_metadata.properties, productData.metadata)
|
||
if (
|
||
(_metadata.properties?.length ||
|
||
_metadata.events?.length ||
|
||
_metadata.functions?.length ||
|
||
_metadata.tags?.length
|
||
) &&
|
||
(
|
||
productData.metadata?.properties?.length ||
|
||
productData.metadata?.events?.length ||
|
||
productData.metadata?.functions?.length ||
|
||
productData.metadata?.tags?.length
|
||
)
|
||
) {
|
||
metadataModalCacheData.value = {
|
||
id,
|
||
values,
|
||
productTypeId: productData.id
|
||
}
|
||
metadataVisible.value = true
|
||
} else {
|
||
updateAccessData(id, values)
|
||
}
|
||
};
|
||
|
||
const updateAccessData = async (id: string, values: any) => {
|
||
const result: any = {};
|
||
flatObj(values, result);
|
||
const { storePolicy, ...extra } = result;
|
||
// 产品有物模型,设备接入没有,取产品物模型;设备接入有物模型,产品没有,取设备接入的物模型;否则取空字符串;不能为undefined或者null
|
||
let _metadata = ''
|
||
if (productStore.current?.metadata) {
|
||
_metadata = productStore.current?.metadata
|
||
} else if (productData.metadata && Object.keys(productData.metadata).length) {
|
||
_metadata = JSON.stringify(productData.metadata)
|
||
}
|
||
// 更新选择设备(设备接入)
|
||
const accessObj = {
|
||
...productStore.current,
|
||
metadata: _metadata,
|
||
transportProtocol: access.value?.transport,
|
||
protocolName: access.value?.protocolDetail?.name,
|
||
accessId: access.value?.id,
|
||
accessName: access.value?.name,
|
||
accessProvider: access.value?.provider,
|
||
messageProtocol: access.value?.protocol,
|
||
}
|
||
submitLoading.value = true
|
||
const updateDeviceResp = await updateDevice(accessObj).catch(() => { success: false})
|
||
|
||
if (!updateDeviceResp.success) {
|
||
submitLoading.value = false
|
||
}
|
||
|
||
if (access.value?.provider === "plugin_gateway" && productData.id) {
|
||
await savePluginData(
|
||
'product',
|
||
access.value?.id,
|
||
productStore.current.id,
|
||
productData.id
|
||
).catch(() => ({}))
|
||
}
|
||
// 更新产品配置信息
|
||
const resp = await modify(id || '', {
|
||
id: id,
|
||
configuration: { ...extra },
|
||
storePolicy: storePolicy,
|
||
});
|
||
submitLoading.value = false
|
||
if (resp.status === 200) {
|
||
onlyMessage('操作成功!');
|
||
productStore.current!.storePolicy = storePolicy;
|
||
if ((window as any).onTabSaveSuccess) {
|
||
if (resp.result) {
|
||
(window as any).onTabSaveSuccess(resp);
|
||
setTimeout(() => window.close(), 300);
|
||
}
|
||
} else {
|
||
getDetailInfo();
|
||
}
|
||
}
|
||
}
|
||
|
||
const flatObj = (obj: any, result: any) => {
|
||
Object.keys(obj).forEach((key: string) => {
|
||
if (typeof obj[key] === 'string') {
|
||
result[key] = obj[key];
|
||
} else {
|
||
flatObj(obj[key], result);
|
||
}
|
||
});
|
||
};
|
||
|
||
const getDetailInfo = async () => {
|
||
await productStore.getDetail(productStore.detail.id)
|
||
MetaDataModalSubmit()
|
||
};
|
||
|
||
const MetaDataModalSubmit = () => {
|
||
// 跳转物模型标签
|
||
productStore.tabActiveKey = 'Metadata'
|
||
}
|
||
|
||
getProvidersList()
|
||
/**
|
||
* 初始化
|
||
*/
|
||
watchEffect(() => {
|
||
if (productStore.current?.storePolicy) {
|
||
form.storePolicy = productStore.current!.storePolicy;
|
||
}
|
||
});
|
||
|
||
const tooltip = computed(() => {
|
||
if (productStore.current?.count > 0) {
|
||
return '产品下有设备实例时不能更换接入方式'
|
||
}
|
||
if (productStore.current.state === 1) {
|
||
return '停用产品后才可更换接入方式'
|
||
}
|
||
return ''
|
||
})
|
||
|
||
const checkDisabled = computed(() => {
|
||
if (productStore.current?.count > 0 || productStore.current.state === 1) {
|
||
return true
|
||
}
|
||
return false
|
||
})
|
||
|
||
nextTick(() => {
|
||
getData();
|
||
});
|
||
watch(
|
||
() => productStore.current,
|
||
() => {
|
||
getData();
|
||
formData.data = productStore.current?.configuration || {};
|
||
},
|
||
);
|
||
</script>
|
||
<style lang="less" scoped>
|
||
:deep(
|
||
._jtable-body_1eyxz_1
|
||
._jtable-body-header_1eyxz_6
|
||
._jtable-body-header-right_1eyxz_12
|
||
._jtable-body-header-right-button_1eyxz_17
|
||
) {
|
||
display: none;
|
||
margin-left: 10px;
|
||
gap: 8px;
|
||
}
|
||
|
||
.item-style {
|
||
margin-bottom: 10px;
|
||
}
|
||
.ellipsis-style {
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.context-access {
|
||
margin-right: 10px;
|
||
color: #666;
|
||
font-weight: 400;
|
||
font-size: 12px;
|
||
}
|
||
.changeBtn {
|
||
margin: 0 0 0 20px;
|
||
}
|
||
</style>
|