feat: 设备接入网关 接口调试 加入权限

This commit is contained in:
jackhoo_98 2023-02-28 21:15:54 +08:00
parent 568afdb69e
commit 7143af3ff1
14 changed files with 1077 additions and 1867 deletions

View File

@ -9,8 +9,10 @@
></Provider>
</div>
<div v-else>
<div v-if="!id"><a @click="goBack">返回</a></div>
<AccessNetwork
<div class="go-back" v-if="id === ':id'">
<a @click="goBack">返回</a>
</div>
<Network
v-if="showType === 'network'"
:provider="provider"
:data="data"
@ -42,18 +44,15 @@
</template>
<script lang="ts" setup name="AccessConfigDetail">
import { getImage } from '@/utils/comm';
import AccessNetwork from '../components/Network.vue';
import Network from '../components/Network/index.vue';
import Provider from '../components/Provider/index.vue';
import { getProviders, detail } from '@/api/link/accessConfig';
import Media from '../components/Media/index.vue';
import Channel from '../components/Channel/index.vue';
import Edge from '../components/Edge/index.vue';
import Cloud from '../components/Cloud/index.vue';
import { getProviders, detail } from '@/api/link/accessConfig';
const route = useRoute();
const view = route.query.view as string;
const id = route.params.id as string;
const dataSource = ref([]);
@ -74,7 +73,7 @@ const goBack = () => {
type.value = true;
};
const getTypeList = (result: any[]) => {
const getTypeList = (result: Record<string, any>) => {
const list = [];
const media: any[] = [];
const network: any[] = [];
@ -184,76 +183,7 @@ onMounted(() => {
</script>
<style lang="less" scoped>
.provider {
position: relative;
width: 100%;
padding: 20px;
background: url('/public/images/access/background.png') no-repeat;
background-size: 100% 100%;
border: 1px solid #e6e6e6;
&::before {
position: absolute;
top: 0;
left: 40px;
display: block;
width: 15%;
min-width: 64px;
height: 2px;
background-image: url('/public/images/access/rectangle.png');
background-repeat: no-repeat;
background-size: 100% 100%;
// border: 1px #8da1f4 solid;
// border-bottom-left-radius: 10%;
// border-bottom-right-radius: 10%;
content: ' ';
}
&:hover {
box-shadow: 0 0 24px rgba(#000, 0.1);
}
}
.box {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
.left {
display: flex;
width: calc(100% - 70px);
.images {
width: 64px;
height: 64px;
img {
width: 100%;
}
}
.context {
width: calc(100% - 84px);
margin: 10px;
.title {
font-weight: 600;
}
.desc {
width: 100%;
margin-top: 10px;
overflow: hidden;
color: rgba(0, 0, 0, 0.55);
font-weight: 400;
font-size: 13px;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
.right {
width: 70px;
}
.go-back {
margin: 0 0 20px 0;
}
</style>

View File

@ -39,12 +39,16 @@
/>
</a-form-item>
<a-form-item>
<a-button
<PermissionButton
v-if="view === 'false'"
type="primary"
html-type="submit"
>保存</a-button
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</PermissionButton>
</a-form-item>
</a-form>
</div>
@ -86,10 +90,9 @@
</template>
<script lang="ts" setup name="AccessChannel">
import { message, Form } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import { update, save } from '@/api/link/accessConfig';
import { ProtocolMapping } from '../../Detail/data';
import { ProtocolMapping } from '../../data';
interface FormState {
name: string;
@ -129,16 +132,7 @@ const onFinish = async (values: any) => {
id === ':id' ? await save(params) : await update({ ...params, id });
if (resp.status === 200) {
message.success('操作成功!');
// if (params.get('save')) {
// if ((window as any).onTabSaveSuccess) {
// if (resp.result) {
// (window as any).onTabSaveSuccess(resp.result);
// setTimeout(() => window.close(), 300);
// }
// }
// } else {
history.back();
// }
}
};
@ -164,8 +158,6 @@ onMounted(() => {
}
.config-right {
padding: 20px;
// color: rgba(0, 0, 0, 0.8);
// background: rgba(0, 0, 0, 0.04);
.config-right-item {
margin-bottom: 10px;

View File

@ -6,7 +6,7 @@
<div class="steps-content">
<div class="steps-box" v-if="current === 0">
<div class="alert">
<info-circle-outlined />
<AIcon type="InfoCircleOutlined" />
通过CTWing平台的HTTP推送服务进行数据接入
</div>
<div style="margin-top: 15px">
@ -160,7 +160,7 @@
<div class="steps-content">
<div class="steps-box" v-if="current === 1">
<div class="alert">
<info-circle-outlined />
<AIcon type="InfoCircleOutlined" />
只能选择HTTP通信方式的协议
</div>
<div class="search">
@ -170,9 +170,14 @@
style="width: 300px"
@search="procotolSearch"
/>
<a-button type="primary" @click="addProcotol"
>新增</a-button
<PermissionButton
type="primary"
@click="addProcotol"
hasPermission="link/Protocol:add"
>
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</div>
<div class="card-item">
<a-row :gutter="[24, 24]" v-if="procotolList.length > 0">
@ -282,96 +287,39 @@
>
下一步
</a-button>
<a-button
<PermissionButton
v-if="current === 2 && view === 'false'"
type="primary"
style="margin-right: 8px"
@click="saveData"
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</a-button>
</PermissionButton>
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
</div>
</div>
</template>
<script lang="ts" setup name="AccessCloudCtwing">
import { message, Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import { update, save, getNetworkList } from '@/api/link/accessConfig';
import { ProtocolMapping, NetworkTypeMapping } from '../../Detail/data';
import { InfoCircleOutlined } from '@ant-design/icons-vue';
import { update, save, getProtocolList } from '@/api/link/accessConfig';
import { ProtocolMapping } from '../../data';
import AccessCard from '../AccessCard/index.vue';
import { randomString } from '@/utils/utils';
import { getImage } from '@/utils/comm';
import { useMenuStore } from 'store/menu';
const menuStory = useMenuStore();
const origin = window.location.origin;
const img1 = getImage('/network/01.png');
const img2 = getImage('/network/02.jpg');
const img3 = getImage('/network/03.png');
const img4 = getImage('/network/04.jpg');
//1{
const resultList1 = [
{
id: '1612354213444087808',
name: '大华烟感协议',
},
{
id: '1610475299002855424',
name: '宇视摄像头协议',
},
{
id: '1610466717670780928',
name: '官方协议',
},
{
id: '1610205217785524224',
name: 'demo协议',
},
{
id: '1610204985806958592',
name: '水压协议',
},
{
id: '1605459961693745152',
name: '测试设备诊断日志显示',
},
{
id: '1582302200020783104',
name: 'demo',
},
{
id: '1581839391887794176',
name: '海康闸机协议',
},
{
id: '1567062365030637568',
name: '协议20220906160914',
},
{
id: '1561650927208628224',
name: 'local',
},
{
id: '1552881998413754368',
name: '官方协议V3-支持固件升级3',
},
{
id: '2b283b28a16d61e5fc2bdf39ceff34f8',
name: 'JetLinks官方协议',
description: 'JetLinks官方协议包',
},
{
id: '1551510679466844160',
name: '官方协议3.1',
},
{
id: '1551509716811161600',
name: '官方协议3.0',
},
];
interface FormState {
apiAddress: string;
appKey: string;
@ -397,7 +345,6 @@ const props = defineProps({
},
});
const channel = ref(props.provider.channel);
const formRef1 = ref<FormInstance>();
const formRef2 = ref<FormInstance>();
@ -459,37 +406,24 @@ const saveData = async () => {
});
if (resp.status === 200) {
message.success('操作成功!');
//
// if (window.onTabSaveSuccess) {
// window.onTabSaveSuccess(resp);
// setTimeout(() => window.close(), 300);
// } else {
// // this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] })
// }
history.back();
}
// onFinish(data);
};
const queryProcotolList = async (id: string, params = {}) => {
// const resp = await getProtocolList(ProtocolMapping.get(id), {
// ...params,
// 'sorts[0].name': 'createTime',
// 'sorts[0].order': 'desc',
// });
// if (resp.status === 200) {
// procotolList.value = resp.result;
// allProcotolList.value = resp.result;
// }
//使1
procotolList.value = resultList1;
allProcotolList.value = resultList1;
const resp = await getProtocolList(ProtocolMapping.get(id), {
...params,
'sorts[0].name': 'createTime',
'sorts[0].order': 'desc',
});
if (resp.status === 200) {
procotolList.value = resp.result;
allProcotolList.value = resp.result;
}
};
const addProcotol = () => {
// const url = this.$store.state.permission.routes['Link/Protocol']
const url = '/iot/link/protocol';
const url = menuStory.menus['link/Protocol']?.path;
const tab = window.open(
`${window.location.origin + window.location.pathname}#${url}?save=true`,
);
@ -503,7 +437,7 @@ const addProcotol = () => {
const next = async () => {
if (current.value === 0) {
let data1: any = await formRef1.value?.validate();
await formRef1.value?.validate();
queryProcotolList(props.provider.id);
current.value = current.value + 1;
} else if (current.value === 1) {
@ -514,9 +448,11 @@ const next = async () => {
}
}
};
const prev = () => {
current.value = current.value - 1;
};
onMounted(() => {
if (id !== ':id') {
formState.value = props.data.configuration;
@ -527,6 +463,7 @@ onMounted(() => {
};
}
});
watch(
current,
(v) => {
@ -590,9 +527,6 @@ watch(
}
.config-right {
padding: 20px;
// color: rgba(0, 0, 0, 0.8);
// background: rgba(0, 0, 0, 0.04);
.config-right-item {
margin-bottom: 10px;

View File

@ -6,7 +6,7 @@
<div class="steps-content">
<div class="steps-box" v-if="current === 0">
<div class="alert">
<info-circle-outlined />
<AIcon type="InfoCircleOutlined" />
通过OneNet平台的HTTP推送服务进行数据接入
</div>
<div style="margin-top: 15px">
@ -41,7 +41,9 @@
同步物联网平台设备数据到OneNet
</p>
</template>
<question-circle-outlined />
<AIcon
type="QuestionCircleOutlined"
/>
</a-tooltip>
</div>
<a-input
@ -105,7 +107,9 @@
接收OneNet推送的Token地址
</p>
</template>
<question-circle-outlined />
<AIcon
type="QuestionCircleOutlined"
/>
</a-tooltip>
</div>
<a-input
@ -136,7 +140,9 @@
端生成的消息加密key
</p>
</template>
<question-circle-outlined />
<AIcon
type="QuestionCircleOutlined"
/>
</a-tooltip>
</div>
<a-input
@ -253,7 +259,7 @@
<div class="steps-content">
<div class="steps-box" v-if="current === 1">
<div class="alert">
<info-circle-outlined />
<AIcon type="InfoCircleOutlined" />
只能选择HTTP通信方式的协议
</div>
<div class="search">
@ -263,9 +269,14 @@
style="width: 300px"
@search="procotolSearch"
/>
<a-button type="primary" @click="addProcotol"
>新增</a-button
<PermissionButton
type="primary"
@click="addProcotol"
hasPermission="link/Protocol:add"
>
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</div>
<div class="card-item">
<a-row :gutter="[24, 24]" v-if="procotolList.length > 0">
@ -375,98 +386,38 @@
>
下一步
</a-button>
<a-button
<PermissionButton
style="margin-right: 8px"
v-if="current === 2 && view === 'false'"
type="primary"
@click="saveData"
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</a-button>
</PermissionButton>
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
</div>
</div>
</template>
<script lang="ts" setup name="AccessCloudOneNet">
import { message, Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import { update, save, getNetworkList } from '@/api/link/accessConfig';
import { ProtocolMapping, NetworkTypeMapping } from '../../Detail/data';
import {
InfoCircleOutlined,
QuestionCircleOutlined,
} from '@ant-design/icons-vue';
import { update, save, getProtocolList } from '@/api/link/accessConfig';
import AccessCard from '../AccessCard/index.vue';
import { randomString } from '@/utils/utils';
import { getImage } from '@/utils/comm';
import { ProtocolMapping } from '../../data';
import { useMenuStore } from 'store/menu';
const menuStory = useMenuStore();
const origin = window.location.origin;
const img5 = getImage('/network/05.jpg');
const img6 = getImage('/network/06.jpg');
const img = getImage('/network/OneNet.jpg');
//1{
const resultList1 = [
{
id: '1612354213444087808',
name: '大华烟感协议',
},
{
id: '1610475299002855424',
name: '宇视摄像头协议',
},
{
id: '1610466717670780928',
name: '官方协议',
},
{
id: '1610205217785524224',
name: 'demo协议',
},
{
id: '1610204985806958592',
name: '水压协议',
},
{
id: '1605459961693745152',
name: '测试设备诊断日志显示',
},
{
id: '1582302200020783104',
name: 'demo',
},
{
id: '1581839391887794176',
name: '海康闸机协议',
},
{
id: '1567062365030637568',
name: '协议20220906160914',
},
{
id: '1561650927208628224',
name: 'local',
},
{
id: '1552881998413754368',
name: '官方协议V3-支持固件升级3',
},
{
id: '2b283b28a16d61e5fc2bdf39ceff34f8',
name: 'JetLinks官方协议',
description: 'JetLinks官方协议包',
},
{
id: '1551510679466844160',
name: '官方协议3.1',
},
{
id: '1551509716811161600',
name: '官方协议3.0',
},
];
interface FormState {
apiAddress: string;
apiKey: string;
@ -478,9 +429,6 @@ interface Form {
name: string;
description: string;
}
const route = useRoute();
const view = route.query.view as string;
const id = route.params.id as string;
const props = defineProps({
provider: {
@ -493,7 +441,10 @@ const props = defineProps({
},
});
const channel = ref(props.provider.channel);
const route = useRoute();
const view = route.query.view as string;
const id = route.params.id as string;
const formRef1 = ref<FormInstance>();
const formRef2 = ref<FormInstance>();
@ -557,36 +508,24 @@ const saveData = async () => {
if (resp.status === 200) {
message.success('操作成功!');
//
// if (window.onTabSaveSuccess) {
// window.onTabSaveSuccess(resp);
// setTimeout(() => window.close(), 300);
// } else {
// // this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] })
// }
history.back();
}
};
const queryProcotolList = async (id: string, params = {}) => {
// const resp = await getProtocolList(ProtocolMapping.get(id), {
// ...params,
// 'sorts[0].name': 'createTime',
// 'sorts[0].order': 'desc',
// });
// if (resp.status === 200) {
// procotolList.value = resp.result;
// allProcotolList.value = resp.result;
// }
//使1
procotolList.value = resultList1;
allProcotolList.value = resultList1;
const resp = await getProtocolList(ProtocolMapping.get(id), {
...params,
'sorts[0].name': 'createTime',
'sorts[0].order': 'desc',
});
if (resp.status === 200) {
procotolList.value = resp.result;
allProcotolList.value = resp.result;
}
};
const addProcotol = () => {
// const url = this.$store.state.permission.routes['Link/Protocol']
const url = '/iot/link/protocol';
const url = menuStory.menus['link/Protocol']?.path;
const tab = window.open(
`${window.location.origin + window.location.pathname}#${url}?save=true`,
);
@ -689,9 +628,6 @@ watch(
}
.config-right {
padding: 20px;
// color: rgba(0, 0, 0, 0.8);
// background: rgba(0, 0, 0, 0.04);
.config-right-item {
margin-bottom: 10px;

View File

@ -10,7 +10,7 @@
<div v-if="channel !== 'edge-child-device'" class="steps-content">
<div class="steps-box" v-if="current === 0">
<div class="alert">
<question-circle-outlined />
<AIcon type="InfoCircleOutlined" />
选择与设备通信的网络组件
</div>
<div class="search">
@ -20,7 +20,14 @@
style="width: 300px"
@search="networkSearch"
/>
<a-button type="primary" @click="addNetwork">新增</a-button>
<PermissionButton
type="primary"
@click="addNetwork"
hasPermission="link/Type:add"
>
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</div>
<div class="card-item">
<a-row :gutter="[24, 24]" v-if="networkList.length > 0">
@ -103,7 +110,6 @@
<a-row :gutter="[24, 24]">
<a-col :span="12">
<title-component data="基本信息" />
<div>
<a-form
:model="formState"
name="basic"
@ -139,15 +145,18 @@
/>
</a-form-item>
<a-form-item>
<a-button
<PermissionButton
v-if="current !== 1 && view === 'false'"
type="primary"
html-type="submit"
>保存</a-button
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</PermissionButton>
</a-form-item>
</a-form>
</div>
</a-col>
<a-col :span="12">
<div class="config-right">
@ -178,119 +187,35 @@
>
下一步
</a-button>
<a-button
<PermissionButton
v-if="current === 1 && view === 'false'"
type="primary"
style="margin-right: 8px"
@click="saveData"
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</a-button>
</PermissionButton>
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
</div>
</div>
</template>
<script lang="ts" setup name="AccessEdge">
import { message, Form } from 'ant-design-vue';
import { message } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import { update, save, getNetworkList } from '@/api/link/accessConfig';
import {
descriptionList,
ProtocolMapping,
NetworkTypeMapping,
} from '../../Detail/data';
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
} from '../../data';
import AccessCard from '../AccessCard/index.vue';
import { useMenuStore } from 'store/menu';
//1
const networkListTest = {
message: 'success',
result: [
{
id: '1585192878304051200',
name: 'MQTT网络组件',
addresses: [
{
address: 'mqtt://120.77.179.54:8101',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1583268266806009856',
name: '我的第一个MQTT服务组件',
description: '',
addresses: [
{
address: 'mqtt://120.77.179.54:8100',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1570335308902912000',
name: '0915MQTT网络组件_勿动',
description: '测试,勿动!',
addresses: [
{
address: 'mqtt://120.77.179.54:8083',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1567062350140858368',
name: '网络组件20220906160907',
addresses: [
{
address: 'mqtt://120.77.179.54:8083',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1556563257890742272',
name: 'MQTT网络组件',
addresses: [
{
address: 'mqtt://0.0.0.0:8104',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1534774770408108032',
name: 'MQTT',
addresses: [
{
address: 'mqtt://120.77.179.54:8088',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
],
status: 200,
timestamp: 1674960624150,
};
const menuStory = useMenuStore();
interface FormState {
name: string;
@ -327,6 +252,7 @@ const stepCurrent = ref(0);
const steps = ref(['网络组件', '完成']);
const networkCurrent = ref('');
const networkList = ref([]);
const allNetworkList = ref([]);
const onFinish = async (values: any) => {
const providerId = props.provider.id;
@ -341,16 +267,7 @@ const onFinish = async (values: any) => {
id === ':id' ? await save(params) : await update({ ...params, id });
if (resp.status === 200) {
message.success('操作成功!');
// if (params.get('save')) {
// if ((window as any).onTabSaveSuccess) {
// if (resp.result) {
// (window as any).onTabSaveSuccess(resp.result);
// setTimeout(() => window.close(), 300);
// }
// }
// } else {
history.back();
// }
}
};
@ -359,28 +276,27 @@ const checkedChange = (id: string) => {
};
const queryNetworkList = async (id: string, include: string, data = {}) => {
// const resp = await getNetworkList(
// NetworkTypeMapping.get(id),
// include,
// data,
// );
// if (resp.status === 200) {
// networkList.value = resp.result;
// }
//使1
networkList.value = networkListTest.result;
const resp = await getNetworkList(
NetworkTypeMapping.get(id),
include,
data,
);
if (resp.status === 200) {
networkList.value = resp.result;
allNetworkList.value = resp.result;
}
};
const networkSearch = (value: string) => {
queryNetworkList(props.provider.id, networkCurrent.value || '', {
terms: [
{
column: 'name$LIKE',
value: `%${value}%`,
},
],
});
if (value) {
networkList.value = allNetworkList.value.filter(
(i: any) =>
i.name &&
i.name.toLocaleLowerCase().includes(value.toLocaleLowerCase()),
);
} else {
networkList.value = allNetworkList.value;
}
};
const saveData = async () => {
@ -389,8 +305,7 @@ const saveData = async () => {
};
const addNetwork = () => {
// const url = this.$store.state.permission.routes['Link/Type/Detail']
const url = '/iot/link/type/detail/:id';
const url = menuStory.menus['link/Type/Detail']?.path;
const tab = window.open(
`${window.location.origin + window.location.pathname}#${url}?type=${
NetworkTypeMapping.get(props.provider?.id) || ''
@ -426,7 +341,7 @@ onMounted(() => {
};
networkCurrent.value = props.data.channelId;
}
}),
});
watch(
current,
(v) => {

View File

@ -6,7 +6,7 @@
<div class="steps-content">
<div class="steps-box" v-if="current === 0">
<div class="alert">
<info-circle-outlined />
<AIcon type="InfoCircleOutlined" />
配置设备信令参数
</div>
<div>
@ -85,7 +85,7 @@
独立配置:集群下不同节点使用不同配置
</p>
</template>
<question-circle-outlined />
<AIcon type="QuestionCircleOutlined" />
</a-tooltip>
</div>
@ -218,9 +218,7 @@
:header="`#${index + 1}.节点`"
>
<template #extra>
<delete-outlined
@click="removeCluster(cluster)"
/>
<AIcon type="DeleteOutlined" />
</template>
<a-row :gutter="[24, 24]">
<a-col :span="8">
@ -274,7 +272,9 @@
绑定到服务器上的网卡地址,绑定到所有网卡:0.0.0.0
</p>
</template>
<question-circle-outlined />
<AIcon
type="QuestionCircleOutlined"
/>
</a-tooltip>
</div>
@ -363,7 +363,9 @@
监听指定端口的请求
</p>
</template>
<question-circle-outlined />
<AIcon
type="QuestionCircleOutlined"
/>
</a-tooltip>
</div>
<a-input
@ -417,7 +419,7 @@
block
@click="addCluster"
>
<PlusOutlined />
<AIcon type="PlusOutlined" />
新增
</a-button>
</a-form-item>
@ -502,14 +504,17 @@
>
下一步
</a-button>
<a-button
<PermissionButton
v-if="current === 1 && view === 'false'"
type="primary"
style="margin-right: 8px"
@click="saveData"
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</a-button>
</PermissionButton>
<a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
</div>
</div>
@ -519,12 +524,6 @@
import { message, Form } from 'ant-design-vue';
import type { FormInstance } from 'ant-design-vue';
import { getResourcesCurrent, getClusters } from '@/api/link/accessConfig';
import {
DeleteOutlined,
PlusOutlined,
QuestionCircleOutlined,
InfoCircleOutlined,
} from '@ant-design/icons-vue';
import { update, save } from '@/api/link/accessConfig';
interface Form2 {

View File

@ -39,12 +39,16 @@
/>
</a-form-item>
<a-form-item>
<a-button
<PermissionButton
v-if="view === 'false'"
type="primary"
html-type="submit"
>保存</a-button
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</PermissionButton>
</a-form-item>
</a-form>
</div>
@ -122,16 +126,7 @@ const onFinish = async (values: any) => {
id === ':id' ? await save(params) : await update({ ...params, id });
if (resp.status === 200) {
message.success('操作成功!');
// if (params.get('save')) {
// if ((window as any).onTabSaveSuccess) {
// if (resp.result) {
// (window as any).onTabSaveSuccess(resp.result);
// setTimeout(() => window.close(), 300);
// }
// }
// } else {
history.back();
// }
}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,701 @@
<template>
<div>
<a-steps :current="stepCurrent">
<a-step v-for="item in steps" :key="item" :title="item" />
</a-steps>
<div class="steps-content">
<div class="steps-box" v-if="current === 0">
<div class="alert">
<AIcon type="InfoCircleOutlined" />
选择与设备通信的网络组件
</div>
<div class="search">
<a-input-search
allowClear
placeholder="请输入"
style="width: 300px"
@search="networkSearch"
/>
<PermissionButton
type="primary"
@click="addNetwork"
hasPermission="link/Type:add"
>
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</div>
<div class="card-item">
<a-row :gutter="[24, 24]" v-if="networkList.length > 0">
<a-col
:span="8"
v-for="item in networkList"
:key="item.id"
>
<access-card
@checkedChange="checkedChange"
:checked="networkCurrent"
:data="{
...item,
description: item.description
? item.description
: descriptionList[provider.id],
}"
>
<template #other>
<div class="other">
<a-tooltip placement="topLeft">
<div
v-if="
(item.addresses || [])
.length > 1
"
>
<div
v-for="i in item.addresses ||
[]"
:key="i.address"
class="item"
>
<a-badge
:color="getColor(i)"
/>{{ i.address }}
</div>
</div>
<div
v-for="i in (
item.addresses || []
).slice(0, 1)"
:key="i.address"
class="item"
>
<a-badge
:color="getColor(i)"
:text="i.address"
/>
<span
v-if="
(item.addresses || [])
.length > 1
"
>...</span
>
</div>
</a-tooltip>
</div>
</template>
</access-card>
</a-col>
</a-row>
<a-empty v-else description="暂无数据" />
</div>
</div>
<div class="steps-box" v-else-if="current === 1">
<div class="alert">
<AIcon type="InfoCircleOutlined" />
使用选择的消息协议对网络组件通信数据进行编解码认证等操作
</div>
<div class="search">
<a-input-search
allowClear
placeholder="请输入"
style="width: 300px"
@search="procotolSearch"
/>
<PermissionButton
type="primary"
@click="addProcotol"
hasPermission="link/Protocol:add"
>
<template #icon><AIcon type="PlusOutlined" /></template>
新增
</PermissionButton>
</div>
<div class="card-item">
<a-row :gutter="[24, 24]" v-if="procotolList.length > 0">
<a-col
:span="8"
v-for="item in procotolList"
:key="item?.id"
>
<access-card
@checkedChange="procotolChange"
:checked="procotolCurrent"
:data="item"
>
</access-card>
</a-col>
</a-row>
<a-empty v-else description="暂无数据" />
</div>
</div>
<div class="steps-box" v-else>
<div
class="card-last"
:style="`max-height:${
clientHeight > 900 ? 750 : clientHeight * 0.7
}px`"
>
<a-row :gutter="[24, 24]">
<a-col :span="12">
<title-component data="基本信息" />
<div>
<a-form
ref="formRef"
:model="formData"
layout="vertical"
>
<a-form-item
label="名称"
v-bind="validateInfos.name"
>
<a-input
v-model:value="formData.name"
allowClear
placeholder="请输入名称"
/>
</a-form-item>
<a-form-item
label="说明"
v-bind="validateInfos.description"
>
<a-textarea
placeholder="请输入说明"
:rows="4"
v-model:value="formData.description"
show-count
:maxlength="200"
/>
</a-form-item>
</a-form>
</div>
</a-col>
<a-col :span="12">
<div class="config-right">
<div class="config-right-item">
<div class="config-right-item-title">
接入方式
</div>
<div class="config-right-item-context">
{{ provider.name }}
</div>
<div class="config-right-item-context">
{{ provider.description }}
</div>
</div>
<div class="config-right-item">
<div class="config-right-item-title">
消息协议
</div>
<div class="config-right-item-context">
{{
procotolList.find(
(i) => i.id === procotolCurrent,
).name
}}
</div>
<div
class="config-right-item-context"
v-if="config.document"
>
<Markdown :source="config.document" />
</div>
</div>
<div
class="config-right-item"
v-if="getNetworkCurrent()"
>
<div class="config-right-item-title">
网络组件
</div>
<div
v-for="i in getNetworkCurrentData()"
:key="i.address"
>
<a-badge
:color="getColor(i)"
:text="i.address"
/>
</div>
</div>
<div
class="config-right-item"
v-if="
config.routes &&
config.routes.length > 0
"
>
<div class="config-right-item-title">
{{
data.provider ===
'mqtt-server-gateway' ||
data.provider ===
'mqtt-client-gateway'
? 'topic'
: 'URL信息'
}}
</div>
<a-table
:pagination="false"
:rowKey="generateUUID()"
:data-source="config.routes || []"
bordered
:columns="
config.id === 'MQTT'
? columnsMQTT
: columnsHTTP
"
:scroll="{ y: 300 }"
>
<template
#bodyCell="{ column, text, record }"
>
<template
v-if="
column.dataIndex ===
'stream'
"
>
<span>{{
getStream(record)
}}</span>
</template>
</template>
</a-table>
</div>
</div>
</a-col>
</a-row>
</div>
</div>
</div>
<div class="steps-action">
<a-button
v-if="[0, 1].includes(current)"
type="primary"
style="margin-right: 8px"
@click="next"
>
下一步
</a-button>
<PermissionButton
v-if="current === 2 && view === 'false'"
type="primary"
style="margin-right: 8px"
@click="saveData"
:hasPermission="`link/AccessConfig:${
id === ':id' ? 'add' : 'update'
}`"
>
保存
</PermissionButton>
<a-button
v-if="type === 'child-device' ? current > 1 : current > 0"
@click="prev"
>
上一步
</a-button>
</div>
</div>
</template>
<script lang="ts" setup name="AccessNetwork">
import {
getNetworkList,
getProtocolList,
getConfigView,
save,
update,
getChildConfigView,
} from '@/api/link/accessConfig';
import {
descriptionList,
NetworkTypeMapping,
ProtocolMapping,
ColumnsMQTT,
ColumnsHTTP,
} from '../../data';
import AccessCard from '../AccessCard/index.vue';
import { message, Form } from 'ant-design-vue';
import type { FormInstance, TableColumnType } from 'ant-design-vue';
import Markdown from 'vue3-markdown-it';
import { useMenuStore } from 'store/menu';
const menuStory = useMenuStore();
function generateUUID() {
var d = new Date().getTime();
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
},
);
}
const props = defineProps({
provider: {
type: Object,
default: () => {},
},
data: {
type: Object,
default: () => {},
},
});
const clientHeight = document.body.clientHeight;
const type = props.provider.channel;
const route = useRoute();
const view = route.query.view as string;
const id = route.params.id as string;
const formRef = ref<FormInstance>();
const useForm = Form.useForm;
const current = ref(0);
const stepCurrent = ref(0);
const steps = ref(['网络组件', '消息协议', '完成']);
const networkList: any = ref([]);
const allNetworkList: any = ref([]);
const procotolList = ref([]);
const allProcotolList = ref([]);
const networkCurrent: any = ref('');
const procotolCurrent: any = ref('');
const config: any = ref({});
const columnsMQTT = ref(<TableColumnType>[]);
const columnsHTTP = ref(<TableColumnType>[]);
const formData = ref({
name: '',
description: '',
});
const { resetFields, validate, validateInfos } = useForm(
formData,
reactive({
name: [
{ required: true, message: '请输入名称', trigger: 'blur' },
{ max: 64, message: '最多可输入64个字符' },
],
description: [{ max: 200, message: '最多可输入200个字符' }],
}),
);
const queryNetworkList = async (id: string, include: string, data = {}) => {
const resp = await getNetworkList(
NetworkTypeMapping.get(id),
include,
data,
);
if (resp.status === 200) {
networkList.value = resp.result;
}
};
const queryProcotolList = async (id: string, params = {}) => {
const resp = await getProtocolList(ProtocolMapping.get(id), {
...params,
'sorts[0].name': 'createTime',
'sorts[0].order': 'desc',
});
if (resp.status === 200) {
procotolList.value = resp.result;
allProcotolList.value = resp.result;
}
};
const addNetwork = () => {
const url = menuStory.menus['link/Type/Detail']?.path;
const tab = window.open(
`${window.location.origin + window.location.pathname}#${url}?type=${
NetworkTypeMapping.get(props.provider?.id) || ''
}`,
);
tab.onTabSaveSuccess = (value) => {
if (value.success) {
networkCurrent.value = value.result.id;
queryNetworkList(props.provider?.id, networkCurrent.value || '');
}
};
};
const addProcotol = () => {
const url = menuStory.menus['link/Protocol']?.path;
const tab = window.open(
`${window.location.origin + window.location.pathname}#${url}?save=true`,
);
tab.onTabSaveSuccess = (value) => {
if (value.success) {
procotolCurrent.value = value.result?.id;
queryProcotolList(props.provider?.id);
}
};
};
const getNetworkCurrent = () =>
networkList.value.find((i) => i.id === networkCurrent) &&
(networkList.value.find((i) => i.id === networkCurrent).addresses || [])
.length > 0;
const getNetworkCurrentData = () =>
getNetworkCurrent()
? networkList.value.find((i) => i.id === networkCurrent).addresses
: [];
const getColor = (i) => (i.health === -1 ? 'red' : 'green');
const getStream = (record: any) => {
let stream = '';
if (record.upstream && record.downstream) stream = '上行、下行';
else if (record.upstream) stream = '上行';
else if (record.downstream) stream = '下行';
return stream;
};
const checkedChange = (id: string) => {
networkCurrent.value = id;
};
const networkSearch = (value: string) => {
if (value) {
networkList.value = allNetworkList.value.filter(
(i: any) =>
i.name &&
i.name.toLocaleLowerCase().includes(value.toLocaleLowerCase()),
);
} else {
networkList.value = allNetworkList.value;
}
};
const procotolChange = (id: string) => {
if (!props.data.id) {
procotolCurrent.value = id;
}
};
const procotolSearch = (value: string) => {
if (value) {
const list = allProcotolList.value.filter((i: any) => {
return (
i.name &&
i.name.toLocaleLowerCase().includes(value.toLocaleLowerCase())
);
});
procotolList.value = list;
} else {
procotolList.value = allProcotolList.value;
}
};
const saveData = () => {
validate()
.then(async (values) => {
const params = {
...props.data,
...values,
protocol: procotolCurrent.value,
channel: 'network', //
channelId: networkCurrent.value,
};
const resp =
id === ':id'
? await save(params)
: await update({
...params,
id,
provider: props.provider.id,
transport:
props.provider?.id === 'child-device'
? 'Gateway'
: ProtocolMapping.get(props.provider.id),
});
if (resp.status === 200) {
message.success('操作成功!');
history.back();
}
})
.catch((err) => {});
};
const next = async () => {
if (current.value === 0) {
if (!networkCurrent.value) {
message.error('请选择网络组件!');
} else {
queryProcotolList(props.provider.id);
current.value = current.value + 1;
}
} else if (current.value === 1) {
if (!procotolCurrent.value) {
message.error('请选择消息协议!');
} else {
const resp =
type !== 'child-device'
? await getConfigView(
procotolCurrent.value,
ProtocolMapping.get(props.provider.id),
)
: await getChildConfigView(procotolCurrent.value);
if (resp.status === 200) {
config.value = resp.result;
console.log(222, config.value);
current.value = current.value + 1;
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 prev = () => {
current.value = current.value - 1;
};
onMounted(() => {
if (props.data && props.data.id) {
if (props.data.provider !== 'child-device') {
procotolCurrent.value = props.data.protocol;
current.value = 0;
networkCurrent.value = props.data.channelId;
queryNetworkList(props.provider.id, networkCurrent.value);
procotolCurrent.value = props.data.protocol;
steps.value = ['网络组件', '消息协议', '完成'];
} else {
steps.value = ['消息协议', '完成'];
current.value = 1;
queryProcotolList(props.provider.id);
}
} else {
if (props.provider?.id) {
if (type !== 'child-device') {
queryNetworkList(props.provider.id, '');
steps.value = ['网络组件', '消息协议', '完成'];
current.value = 0;
} else {
steps.value = ['消息协议', '完成'];
current.value = 1;
queryProcotolList(props.provider.id);
}
}
}
});
onMounted(() => {
if (id !== ':id') {
procotolCurrent.value = props.data.protocol;
formData.value = {
name: props.data.name,
description: props.data.description,
};
}
});
watch(
current,
(v) => {
stepCurrent.value = type === 'child-device' ? v - 1 : v;
},
{
deep: true,
immediate: true,
},
);
</script>
<style lang="less" scoped>
.steps-content {
margin: 20px;
}
.steps-box {
min-height: 400px;
.card-item {
padding-right: 5px;
max-height: 480px;
overflow-y: auto;
overflow-x: hidden;
}
.card-last {
padding-right: 5px;
overflow-y: auto;
overflow-x: hidden;
}
}
.steps-action {
width: 100%;
margin-top: 24px;
margin-left: 20px;
}
.alert {
height: 40px;
padding-left: 10px;
color: rgba(0, 0, 0, 0.55);
line-height: 40px;
background-color: #f6f6f6;
}
.search {
display: flex;
margin: 15px 0;
justify-content: space-between;
}
.other {
width: 100%;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
.item {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.config-right {
padding: 20px;
color: rgba(0, 0, 0, 0.8);
background: rgba(0, 0, 0, 0.04);
.config-right-item {
margin-bottom: 10px;
.config-right-item-title {
width: 100%;
margin-bottom: 10px;
font-weight: 600;
}
.config-right-item-context {
margin: 5px 0;
color: rgba(0, 0, 0, 0.8);
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div v-for="items in dataSource" :key="items.type">
<a-card class="card-items">
<div v-for="items in dataSource" :key="items.type" class="card-items">
<div class="card-items-container">
<TitleComponent :data="items.title"></TitleComponent>
<a-row :gutter="[24, 24]">
<a-col :span="12" v-for="item in items.list" :key="item.id">
@ -8,7 +8,7 @@
<div class="box">
<div class="left">
<div class="images">
<img :src="backMap.get(item.id)" />
<img :src="BackMap.get(item.id)" />
</div>
<div class="context">
<div class="title">
@ -30,13 +30,13 @@
</div>
</a-col>
</a-row>
</a-card>
</div>
</div>
</template>
<script lang="ts" setup name="AccessConfigProvider">
import TitleComponent from '@/components/TitleComponent/index.vue';
import { getImage } from '@/utils/comm';
import { BackMap } from '../../data';
const props = defineProps({
dataSource: {
@ -47,24 +47,6 @@ const props = defineProps({
const emit = defineEmits(['onClick']);
const backMap = new Map();
backMap.set('mqtt-server-gateway', getImage('/access/mqtt.png'));
backMap.set('websocket-server', getImage('/access/websocket.png'));
backMap.set('modbus-tcp', getImage('/access/modbus.png'));
backMap.set('coap-server-gateway', getImage('/access/coap.png'));
backMap.set('tcp-server-gateway', getImage('/access/tcp.png'));
backMap.set('Ctwing', getImage('/access/ctwing.png'));
backMap.set('child-device', getImage('/access/child-device.png'));
backMap.set('opc-ua', getImage('/access/opc-ua.png'));
backMap.set('http-server-gateway', getImage('/access/http.png'));
backMap.set('fixed-media', getImage('/access/video-device.png'));
backMap.set('udp-device-gateway', getImage('/access/udp.png'));
backMap.set('OneNet', getImage('/access/onenet.png'));
backMap.set('gb28181-2016', getImage('/access/gb28181.png'));
backMap.set('mqtt-client-gateway', getImage('/access/mqtt-broke.png'));
backMap.set('edge-child-device', getImage('/access/child-device.png'));
backMap.set('official-edge-gateway', getImage('/access/edge.png'));
const click = (value: object) => {
emit('onClick', value);
};
@ -73,6 +55,8 @@ const click = (value: object) => {
<style lang="less" scoped>
.card-items {
margin-bottom: 24px;
.card-items-container {
}
}
.provider {
position: relative;
@ -93,9 +77,6 @@ const click = (value: object) => {
background-image: url('/public/images/access/rectangle.png');
background-repeat: no-repeat;
background-size: 100% 100%;
// border: 1px #8da1f4 solid;
// border-bottom-left-radius: 10%;
// border-bottom-right-radius: 10%;
content: ' ';
}
@ -109,7 +90,6 @@ const click = (value: object) => {
align-items: center;
justify-content: space-between;
width: 100%;
.left {
display: flex;
width: calc(100% - 70px);

View File

@ -1,3 +1,4 @@
import { getImage } from '@/utils/comm';
const ProtocolMapping = new Map();
ProtocolMapping.set('websocket-server', 'WebSocket');
@ -25,6 +26,23 @@ NetworkTypeMapping.set('mqtt-server-gateway', 'MQTT_SERVER');
NetworkTypeMapping.set('tcp-server-gateway', 'TCP_SERVER');
NetworkTypeMapping.set('official-edge-gateway', 'MQTT_SERVER');
const BackMap = new Map();
BackMap.set('mqtt-server-gateway', getImage('/access/mqtt.png'));
BackMap.set('websocket-server', getImage('/access/websocket.png'));
BackMap.set('modbus-tcp', getImage('/access/modbus.png'));
BackMap.set('coap-server-gateway', getImage('/access/coap.png'));
BackMap.set('tcp-server-gateway', getImage('/access/tcp.png'));
BackMap.set('Ctwing', getImage('/access/ctwing.png'));
BackMap.set('child-device', getImage('/access/child-device.png'));
BackMap.set('opc-ua', getImage('/access/opc-ua.png'));
BackMap.set('http-server-gateway', getImage('/access/http.png'));
BackMap.set('fixed-media', getImage('/access/video-device.png'));
BackMap.set('udp-device-gateway', getImage('/access/udp.png'));
BackMap.set('OneNet', getImage('/access/onenet.png'));
BackMap.set('gb28181-2016', getImage('/access/gb28181.png'));
BackMap.set('mqtt-client-gateway', getImage('/access/mqtt-broke.png'));
BackMap.set('edge-child-device', getImage('/access/child-device.png'));
BackMap.set('official-edge-gateway', getImage('/access/edge.png'));
const descriptionList = {
'udp-device-gateway':
@ -43,21 +61,21 @@ const descriptionList = {
'CoAP是针对只有少量的内存空间和有限的计算能力提供的一种基于UDP的协议。便于低功耗或网络受限的设备与平台通信仅支持设备和平台之间单对单的请求-响应模式。',
};
const columnsMQTT = [
{
title: '分组',
dataIndex: 'group',
key: 'group',
ellipsis: true,
align: 'center',
width: 100,
scopedSlots: { customRender: 'group' },
},
const ColumnsMQTT = [
// {
// title: '分组',
// dataIndex: 'group',
// key: 'group',
// ellipsis: true,
// align: 'center',
// width: 100,
// scopedSlots: { customRender: 'group' },
// },
{
title: 'topic',
dataIndex: 'topic',
key: 'topic',
scopedSlots: { customRender: 'topic' },
ellipsis: true,
},
{
title: '上下行',
@ -72,37 +90,58 @@ const columnsMQTT = [
title: '说明',
dataIndex: 'description',
key: 'description',
scopedSlots: { customRender: 'description' },
},
]
const columnsHTTP = [
{
title: '分组',
dataIndex: 'group',
key: 'group',
ellipsis: true,
width: 100,
scopedSlots: { customRender: 'group' },
},
];
const ColumnsHTTP = [
// {
// title: '分组',
// dataIndex: 'group',
// key: 'group',
// ellipsis: true,
// width: 100,
// scopedSlots: { customRender: 'group' },
// },
{
title: '地址',
dataIndex: 'address',
key: 'address',
scopedSlots: { customRender: 'address' },
ellipsis: true,
// scopedSlots: { customRender: 'address' },
},
{
title: '示例',
dataIndex: 'example',
key: 'example',
scopedSlots: { customRender: 'example' },
ellipsis: true,
// scopedSlots: { customRender: 'example' },
},
{
title: '说明',
dataIndex: 'description',
key: 'description',
scopedSlots: { customRender: 'description' }
ellipsis: true,
// scopedSlots: { customRender: 'description' },
},
]
];
export { NetworkTypeMapping, ProtocolMapping, descriptionList, columnsMQTT, columnsHTTP };
const TiTlePermissionButtonStyle = {
padding: 0,
color: ' #1890ff !important',
'font-weight': 700,
'font-size': '16px',
overflow: 'hidden',
'text-overflow': 'ellipsis',
'white-space': 'nowrap',
};
export {
NetworkTypeMapping,
ProtocolMapping,
BackMap,
descriptionList,
ColumnsMQTT,
ColumnsHTTP,
TiTlePermissionButtonStyle,
};

View File

@ -11,12 +11,23 @@
:defaultParams="{
sorts: [{ name: 'createTime', order: 'desc' }],
}"
gridColumn="2"
gridColumns="[2]"
:params="params"
>
<template #headerTitle>
<a-button type="primary" @click="handlAdd"
><AIcon type="PlusOutlined" />新增</a-button
<a-space>
<PermissionButton
type="primary"
@click="handlAdd"
hasPermission="link/AccessConfig:add"
>
<template #icon
><AIcon type="PlusOutlined"
/></template>
新增
</PermissionButton>
</a-space>
</template>
<template #card="slotProps">
<CardBox
@ -43,12 +54,15 @@
</template>
<template #content>
<div class="card-item-content">
<h3
<PermissionButton
type="link"
@click="handlEye(slotProps.id)"
class="card-item-content-title card-item-content-title-a"
hasPermission="link/AccessConfig:view"
:style="TiTlePermissionButtonStyle"
>
{{ slotProps.name }}
</h3>
</PermissionButton>
<a-row class="card-item-content-box">
<a-col
:span="12"
@ -65,13 +79,7 @@
"
>
<a-badge
:status="
slotProps.channelInfo
.addresses[0].health ===
-1
? 'error'
: 'success'
"
:status="getStatus(slotProps)"
/>
<a-tooltip>
<template #title>{{
@ -112,24 +120,12 @@
<a-tooltip>
<template #title>
{{
slotProps.description
? slotProps.description
: providersList.find(
(item) =>
item.id ===
slotProps.provider,
)?.description
getDescription(
slotProps,
)
}}
</template>
{{
slotProps.description
? slotProps.description
: providersList.find(
(item) =>
item.id ===
slotProps.provider,
)?.description
}}
{{ getDescription(slotProps) }}
</a-tooltip>
</div>
</a-col>
@ -138,30 +134,14 @@
</template>
<template #actions="item">
<a-tooltip
v-bind="item.tooltip"
:title="item.disabled && item.tooltip.title"
>
<a-popconfirm
v-if="item.popConfirm"
v-bind="item.popConfirm"
:disabled="item.disabled"
>
<a-button :disabled="item.disabled">
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
</template>
</a-button>
</a-popconfirm>
<template v-else>
<a-button
<PermissionButton
:disabled="item.disabled"
:popConfirm="item.popConfirm"
:tooltip="{
...item.tooltip,
}"
@click="item.onClick"
:hasPermission="'link/AccessConfig:' + item.key"
>
<AIcon
type="DeleteOutlined"
@ -169,11 +149,9 @@
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item.text }}</span>
<span>{{ item?.text }}</span>
</template>
</a-button>
</template>
</a-tooltip>
</PermissionButton>
</template>
</CardBox>
</template>
@ -198,12 +176,14 @@ import {
deploy,
} from '@/api/link/accessConfig';
import { message } from 'ant-design-vue';
import { useMenuStore } from 'store/menu';
import { TiTlePermissionButtonStyle } from './data';
const menuStory = useMenuStore();
const tableRef = ref<Record<string, any>>({});
const router = useRouter();
const params = ref<Record<string, any>>({});
let providersList = ref([]);
let providersList = ref<Record<string, any>>([]);
const statusMap = new Map();
statusMap.set('enabled', 'success');
@ -225,8 +205,6 @@ const columns = [
key: 'provider',
search: {
type: 'select',
// options: providersList,
// options: getProvidersList
options: async () => {
const res = await getProviders();
return (res?.result || []).map((item) => ({
@ -275,9 +253,10 @@ const columns = [
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
if (!data) return [];
const state = data.state.value;
const stateText = state === 'enabled' ? '禁用' : '启用';
return [
{
key: 'edit',
key: 'update',
text: '编辑',
tooltip: {
title: '编辑',
@ -289,13 +268,13 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
},
{
key: 'action',
text: state === 'enabled' ? '禁用' : '启用',
text: stateText,
tooltip: {
title: state === 'enabled' ? '禁用' : '启用',
title: stateText,
},
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
popConfirm: {
title: `确认${state === 'enabled' ? '禁用' : '启用'}?`,
title: `确认${stateText}?`,
onConfirm: async () => {
let res =
state === 'enabled'
@ -342,27 +321,29 @@ const getProvidersList = async () => {
getProvidersList();
const handlAdd = () => {
// router.push('/link/accessConfig/detail/add/new');
router.push({
path: `/iot/link/accessConfig/detail/:id`,
query: { view: false },
});
menuStory.jumpPage(
`link/AccessConfig/Detail`,
{ id: ':id' },
{ view: false },
);
};
const handlEdit = (id: string) => {
// router.push(`/link/accessConfig/detail/edit/${id}`);
router.push({
path: `/iot/link/accessConfig/detail/${id}`,
query: { view: false },
});
menuStory.jumpPage(`link/AccessConfig/Detail`, { id }, { view: false });
};
const handlEye = (id: string) => {
// router.push(`/link/accessConfig/detail/view/${id}`);
router.push({
path: `/iot/link/accessConfig/detail/${id}`,
query: { view: true },
});
menuStory.jumpPage(`link/AccessConfig/Detail`, { id }, { view: true });
};
const getDescription = (slotProps: Record<string, any>) =>
slotProps.description
? slotProps.description
: providersList?.find(
(item: Record<string, any>) => item.id === slotProps.provider,
)?.description;
const getStatus = (slotProps: Record<string, any>) =>
slotProps.channelInfo.addresses[0].health === -1 ? 'error' : 'success';
/**
* 搜索
* @param params
@ -370,18 +351,6 @@ const handlEye = (id: string) => {
const handleSearch = (e: any) => {
params.value = e;
};
// const handlAdd = () => {
// router.push({
// path: '/link/accessConfig/detail/add',
// query: {
// id: '1610475400026861568',
// },
// });
// };
// const handlAdd = () => {
// router.push('/link/accessConfig/detail/add');
// }
</script>
<style lang="less" scoped>
.tableCardDisabled {

View File

@ -159,7 +159,7 @@ import _ from 'lodash';
const tableRef = ref<Record<string, any>>({});
const params = ref<Record<string, any>>({});
const route = useRoute();
const visible = ref(false);
const current = ref({});
@ -276,6 +276,14 @@ const saveChange = (value: object) => {
}
};
watch(
() => route.query?.save,
(value) => {
value === 'true' && handlAdd();
},
{ deep: true, immediate: true },
);
/**
* 搜索
* @param params

View File

@ -1032,11 +1032,10 @@ import { Store } from 'jetlinks-store';
import MonacoEditor from '@/components/MonacoEditor/index.vue';
const route = useRoute();
const view = route.query.view as string;
const NetworkType = route.query.type as string;
const view = NetworkType ? 'false' : (route.query.view as string);
const id = route.params.id as string;
const activeKey = ref(['1']);
const loading = ref(false);
const formRef1 = ref<FormInstance>();
const formRef2 = ref<FormInstance>();
@ -1250,7 +1249,6 @@ watch(
}
},
{ deep: true },
// { deep: true, immediate: true },
);
watch(
@ -1263,7 +1261,6 @@ watch(
updateClustersListIndex();
},
{ deep: true },
// { deep: true, immediate: true },
);
watch(
() => dynamicValidateForm.cluster?.length,
@ -1272,6 +1269,17 @@ watch(
},
{ deep: true, immediate: true },
);
watch(
() => NetworkType,
(value) => {
if (value) {
const { cluster } = dynamicValidateForm;
formData.value.type = value;
cluster[0].configuration.host = '0.0.0.0';
}
},
{ deep: true, immediate: true },
);
</script>
<style lang="less" scoped>