feat: 设备接入网关 接入第一步部分功能
This commit is contained in:
parent
a703709123
commit
8ac810bfb5
|
@ -0,0 +1,33 @@
|
||||||
|
import server from '@/utils/request';
|
||||||
|
|
||||||
|
export const getProviders = () => server.get(`/gateway/device/providers`);
|
||||||
|
|
||||||
|
export const detail = (id) => server.get(`/gateway/device/${id}`);
|
||||||
|
|
||||||
|
export const getNetworkList = (networkType, data, params) =>
|
||||||
|
server.get(
|
||||||
|
`/network/config/${networkType}/_alive?include=${params.include}`,
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getProtocolList = (transport, params) =>
|
||||||
|
server.get(`/protocol/supports/${transport ? transport : ''}`, params);
|
||||||
|
|
||||||
|
export const getConfigView = (id, transport) =>
|
||||||
|
server.get(`/protocol/${id}/transport/${transport}`);
|
||||||
|
|
||||||
|
export const getChildConfigView = (id) =>
|
||||||
|
server.get(`/protocol/${id}/transports`);
|
||||||
|
|
||||||
|
export const save = (data) => server.post(`/gateway/device`, data);
|
||||||
|
|
||||||
|
export const update = (data) => server.patch(`/gateway/device`, data);
|
||||||
|
|
||||||
|
export const list = (data) =>
|
||||||
|
server.post(`/gateway/device/detail/_query`, data);
|
||||||
|
|
||||||
|
export const undeploy = (id) => server.post(`/gateway/device/${id}/_shutdown`);
|
||||||
|
|
||||||
|
export const deploy = (id) => server.post(`/gateway/device/${id}/_startup`);
|
||||||
|
|
||||||
|
export const del = (id) => server.remove(`/gateway/device/${id}`);
|
|
@ -59,6 +59,10 @@ export default [
|
||||||
path: '/link/certificate/detail/add',
|
path: '/link/certificate/detail/add',
|
||||||
component: () => import('@/views/link/Certificate/Detail/index.vue')
|
component: () => import('@/views/link/Certificate/Detail/index.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/link/accessConfig',
|
||||||
|
component: () => import('@/views/link/AccessConfig/index.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/link/accessConfig/detail/add',
|
path: '/link/accessConfig/detail/add',
|
||||||
component: () => import('@/views/link/AccessConfig/Detail/index.vue')
|
component: () => import('@/views/link/AccessConfig/Detail/index.vue')
|
||||||
|
|
|
@ -1,21 +1,30 @@
|
||||||
const MetworkTypeMapping = new Map();
|
|
||||||
MetworkTypeMapping.set('websocket-server', 'WEB_SOCKET_SERVER');
|
|
||||||
MetworkTypeMapping.set('http-server-gateway', 'HTTP_SERVER');
|
|
||||||
MetworkTypeMapping.set('udp-device-gateway', 'UDP');
|
|
||||||
MetworkTypeMapping.set('coap-server-gateway', 'COAP_SERVER');
|
|
||||||
MetworkTypeMapping.set('mqtt-client-gateway', 'MQTT_CLIENT');
|
|
||||||
MetworkTypeMapping.set('mqtt-server-gateway', 'MQTT_SERVER');
|
|
||||||
MetworkTypeMapping.set('tcp-server-gateway', 'TCP_SERVER');
|
|
||||||
|
|
||||||
const ProcotoleMapping = new Map();
|
const ProtocolMapping = new Map();
|
||||||
ProcotoleMapping.set('websocket-server', 'WebSocket');
|
ProtocolMapping.set('websocket-server', 'WebSocket');
|
||||||
ProcotoleMapping.set('http-server-gateway', 'HTTP');
|
ProtocolMapping.set('http-server-gateway', 'HTTP');
|
||||||
ProcotoleMapping.set('udp-device-gateway', 'UDP');
|
ProtocolMapping.set('udp-device-gateway', 'UDP');
|
||||||
ProcotoleMapping.set('coap-server-gateway', 'CoAP');
|
ProtocolMapping.set('coap-server-gateway', 'CoAP');
|
||||||
ProcotoleMapping.set('mqtt-client-gateway', 'MQTT');
|
ProtocolMapping.set('mqtt-client-gateway', 'MQTT');
|
||||||
ProcotoleMapping.set('mqtt-server-gateway', 'MQTT');
|
ProtocolMapping.set('mqtt-server-gateway', 'MQTT');
|
||||||
ProcotoleMapping.set('tcp-server-gateway', 'TCP');
|
ProtocolMapping.set('tcp-server-gateway', 'TCP');
|
||||||
ProcotoleMapping.set('child-device', '');
|
ProtocolMapping.set('child-device', '');
|
||||||
|
ProtocolMapping.set('OneNet', 'HTTP');
|
||||||
|
ProtocolMapping.set('Ctwing', 'HTTP');
|
||||||
|
ProtocolMapping.set('modbus-tcp', 'MODBUS_TCP');
|
||||||
|
ProtocolMapping.set('opc-ua', 'OPC_UA');
|
||||||
|
ProtocolMapping.set('edge-child-device', 'EdgeGateway');
|
||||||
|
ProtocolMapping.set('official-edge-gateway', 'MQTT');
|
||||||
|
|
||||||
|
const NetworkTypeMapping = new Map();
|
||||||
|
NetworkTypeMapping.set('websocket-server', 'WEB_SOCKET_SERVER');
|
||||||
|
NetworkTypeMapping.set('http-server-gateway', 'HTTP_SERVER');
|
||||||
|
NetworkTypeMapping.set('udp-device-gateway', 'UDP');
|
||||||
|
NetworkTypeMapping.set('coap-server-gateway', 'COAP_SERVER');
|
||||||
|
NetworkTypeMapping.set('mqtt-client-gateway', 'MQTT_CLIENT');
|
||||||
|
NetworkTypeMapping.set('mqtt-server-gateway', 'MQTT_SERVER');
|
||||||
|
NetworkTypeMapping.set('tcp-server-gateway', 'TCP_SERVER');
|
||||||
|
NetworkTypeMapping.set('official-edge-gateway', 'MQTT_SERVER');
|
||||||
|
|
||||||
|
|
||||||
const descriptionList = {
|
const descriptionList = {
|
||||||
'udp-device-gateway':
|
'udp-device-gateway':
|
||||||
|
@ -96,4 +105,4 @@ const columnsHTTP = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export { MetworkTypeMapping, ProcotoleMapping, descriptionList, columnsMQTT, columnsHTTP };
|
export { NetworkTypeMapping, ProtocolMapping, descriptionList, columnsMQTT, columnsHTTP };
|
||||||
|
|
|
@ -1,62 +1,93 @@
|
||||||
<template>
|
<template>
|
||||||
<a-card :bordered="false">
|
<a-spin :spinning="loading">
|
||||||
<TitleComponent data="自定义设备接入"></TitleComponent>
|
<a-card :bordered="false">
|
||||||
<div>
|
<div v-if="type">
|
||||||
<a-row :gutter="[24, 24]">
|
<Provider
|
||||||
<a-col :span="12" v-for="item in items" :key="item.id">
|
@onClick="goProviders"
|
||||||
<div class="provider">
|
:dataSource="dataSource"
|
||||||
<div class="box">
|
></Provider>
|
||||||
<div class="left">
|
</div>
|
||||||
<div class="images">
|
<div v-else>
|
||||||
<img :src="backMap.get(item.id)" />
|
<div v-if="!id"><a @click="goBack">返回</a></div>
|
||||||
</div>
|
<AccessNetwork :provider="provider" :data="data" />
|
||||||
<div class="context">
|
</div>
|
||||||
<div class="title">{{ item.name }}</div>
|
</a-card>
|
||||||
<div class="desc">
|
</a-spin>
|
||||||
<a-tooltip :title="item.description">
|
|
||||||
{{ item.description || '' }}
|
|
||||||
</a-tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right">
|
|
||||||
<a-button
|
|
||||||
type="primary"
|
|
||||||
@click="goProviders(item)"
|
|
||||||
>接入</a-button
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</div>
|
|
||||||
</a-card>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="AccessConfigDetail">
|
<script lang="ts" setup name="AccessConfigDetail">
|
||||||
import { getImage } from '@/utils/comm';
|
import { getImage } from '@/utils/comm';
|
||||||
import TitleComponent from '@/components/TitleComponent/index.vue';
|
import TitleComponent from '@/components/TitleComponent/index.vue';
|
||||||
|
import AccessNetwork from '../components/Network.vue';
|
||||||
|
import Provider from '../components/Provider/index.vue';
|
||||||
|
import { getProviders, detail } from '@/api/link/accessConfig';
|
||||||
|
|
||||||
const items = [
|
// const router = useRouter();
|
||||||
{ id: 'mqtt-server-gateway', name: '测试1', description: '测试1' },
|
const route = useRoute();
|
||||||
{ id: 'websocket-server', name: '测试2', description: '测试' },
|
|
||||||
{ id: 'coap-server-gateway', name: '测试3', description: '测试' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const backMap = new Map();
|
const id = route.query.id;
|
||||||
backMap.set('mqtt-server-gateway', getImage('/access/mqtt.png'));
|
|
||||||
backMap.set('websocket-server', getImage('/access/websocket.png'));
|
|
||||||
backMap.set('coap-server-gateway', getImage('/access/coap.png'));
|
|
||||||
backMap.set('tcp-server-gateway', getImage('/access/tcp.png'));
|
|
||||||
backMap.set('child-device', getImage('/access/child-device.png'));
|
|
||||||
backMap.set('http-server-gateway', getImage('/access/http.png'));
|
|
||||||
backMap.set('udp-device-gateway', getImage('/access/udp.png'));
|
|
||||||
backMap.set('mqtt-client-gateway', getImage('/access/mqtt-broke.png'));
|
|
||||||
|
|
||||||
const goProviders = (value: object) => {
|
const dataSource = ref([]);
|
||||||
console.log(111, value);
|
const type = ref(false);
|
||||||
|
const loading = ref(true);
|
||||||
|
const provider = ref({});
|
||||||
|
const data = ref({});
|
||||||
|
|
||||||
|
const goProviders = (param: object) => {
|
||||||
|
provider.value = param;
|
||||||
|
type.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
provider.value = {};
|
||||||
|
type.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryProviders = async () => {
|
||||||
|
const resp = await getProviders();
|
||||||
|
if (resp.status === 200) {
|
||||||
|
dataSource.value = resp.result.filter(
|
||||||
|
(item) =>
|
||||||
|
item.channel === 'network' || item.channel === 'child-device',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getProvidersData = async () => {
|
||||||
|
if (id) {
|
||||||
|
getProviders().then((response) => {
|
||||||
|
if (response.status === 200) {
|
||||||
|
dataSource.value = response.result.filter(
|
||||||
|
(item) =>
|
||||||
|
item.channel === 'network' ||
|
||||||
|
item.channel === 'child-device',
|
||||||
|
);
|
||||||
|
detail(id).then((resp) => {
|
||||||
|
if (resp.status === 200) {
|
||||||
|
const dt = response.result.find(
|
||||||
|
(item) => item?.id === resp.result.provider,
|
||||||
|
);
|
||||||
|
provider.value = dt;
|
||||||
|
data.value = resp.result;
|
||||||
|
type.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
loading.value = false;
|
||||||
|
} else {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
type.value = true;
|
||||||
|
queryProviders();
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loading.value = true;
|
||||||
|
getProvidersData();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<a-card hoverable :class="['card-render', checked === data.id ? 'checked' : '']" @click="checkedChange(data.id)">
|
||||||
|
<div class="title">
|
||||||
|
<a-tooltip placement="topLeft" :title="data.name">{{ data.name }}</a-tooltip>
|
||||||
|
</div>
|
||||||
|
<slot name="other"></slot>
|
||||||
|
<div class="desc">
|
||||||
|
<a-tooltip placement="topLeft" :title="data.description">{{ data.description }}</a-tooltip>
|
||||||
|
</div>
|
||||||
|
<div class="checked-icon">
|
||||||
|
<div><a-icon type="check" /></div>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "AccessCard",
|
||||||
|
props: ['data', 'checked'],
|
||||||
|
methods: {
|
||||||
|
checkedChange(id){
|
||||||
|
this.$emit('checkedChange', id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.card-render {
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background: url("/public/images/access/access.png") no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
min-height: 105px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: calc(100% - 88px);
|
||||||
|
overflow: hidden;
|
||||||
|
font-weight: 800;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: rgba(0, 0, 0, 0.55);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 13px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.checked-icon {
|
||||||
|
position: absolute;
|
||||||
|
right: -22px;
|
||||||
|
bottom: -22px;
|
||||||
|
z-index: 2;
|
||||||
|
display: none;
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: red;
|
||||||
|
background-color: #2f54eb;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
|
||||||
|
> div {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 0 0 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.checked {
|
||||||
|
position: relative;
|
||||||
|
color: #2f54eb;
|
||||||
|
border-color: #2f54eb;
|
||||||
|
|
||||||
|
.checked-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,733 @@
|
||||||
|
<template>
|
||||||
|
<div style="margin-top: 10px">
|
||||||
|
<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">
|
||||||
|
<a-icon type="info-circle" style="margin-right: 10px" />
|
||||||
|
选择与设备通信的网络组件
|
||||||
|
</div>
|
||||||
|
<div class="search">
|
||||||
|
<a-input-search
|
||||||
|
allowClear
|
||||||
|
placeholder="请输入"
|
||||||
|
style="width: 300px"
|
||||||
|
@search="networkSearch"
|
||||||
|
/>
|
||||||
|
<a-button type="primary" @click="addNetwork">新增</a-button>
|
||||||
|
</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],
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div slot="other" class="other">
|
||||||
|
<a-tooltip placement="topLeft">
|
||||||
|
<div
|
||||||
|
slot="title"
|
||||||
|
v-if="
|
||||||
|
(item.addresses || []).length >
|
||||||
|
1
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="i in item.addresses ||
|
||||||
|
[]"
|
||||||
|
:key="i.address"
|
||||||
|
class="item"
|
||||||
|
>
|
||||||
|
<a-badge
|
||||||
|
:color="
|
||||||
|
i.health === -1
|
||||||
|
? 'red'
|
||||||
|
: 'green'
|
||||||
|
"
|
||||||
|
/>{{ i.address }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="i in (
|
||||||
|
item.addresses || []
|
||||||
|
).slice(0, 1)"
|
||||||
|
:key="i.address"
|
||||||
|
class="item"
|
||||||
|
>
|
||||||
|
<a-badge
|
||||||
|
:color="
|
||||||
|
i.health === -1
|
||||||
|
? 'red'
|
||||||
|
: 'green'
|
||||||
|
"
|
||||||
|
:text="i.address"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-if="
|
||||||
|
(item.addresses || [])
|
||||||
|
.length > 1
|
||||||
|
"
|
||||||
|
>...</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</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">
|
||||||
|
<a-icon type="info-circle" style="margin-right: 10px" />
|
||||||
|
使用选择的消息协议,对网络组件通信数据进行编解码、认证等操作
|
||||||
|
</div>
|
||||||
|
<div class="search">
|
||||||
|
<a-input-search
|
||||||
|
allowClear
|
||||||
|
placeholder="请输入"
|
||||||
|
style="width: 300px"
|
||||||
|
@search="procotolSearch"
|
||||||
|
/>
|
||||||
|
<a-button type="primary" @click="addProcotol"
|
||||||
|
>新增</a-button
|
||||||
|
>
|
||||||
|
</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">
|
||||||
|
<a-row :gutter="[24, 24]">
|
||||||
|
<a-col :span="12">
|
||||||
|
<title-component data="基本信息" />
|
||||||
|
<div>
|
||||||
|
<a-form :form="form" layout="vertical">
|
||||||
|
<a-form-item label="名称">
|
||||||
|
<a-input
|
||||||
|
allowClear
|
||||||
|
placeholder="请输入名称"
|
||||||
|
v-decorator="[
|
||||||
|
'name',
|
||||||
|
{
|
||||||
|
initialValue: data.name,
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message:
|
||||||
|
'请输入名称!',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="说明">
|
||||||
|
<a-textarea
|
||||||
|
placeholder="请输入说明"
|
||||||
|
:rows="4"
|
||||||
|
v-decorator="[
|
||||||
|
'description',
|
||||||
|
{
|
||||||
|
initialValue:
|
||||||
|
data.description,
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
</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"
|
||||||
|
>
|
||||||
|
{{ config.document }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="config-right-item"
|
||||||
|
v-if="
|
||||||
|
networkList.find(
|
||||||
|
(i) => i.id === networkCurrent,
|
||||||
|
) &&
|
||||||
|
(
|
||||||
|
networkList.find(
|
||||||
|
(i) => i.id === networkCurrent,
|
||||||
|
).addresses || []
|
||||||
|
).length > 0
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="config-right-item-title">
|
||||||
|
网络组件
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-for="i in (networkList.find(
|
||||||
|
(i) => i.id === networkCurrent,
|
||||||
|
) &&
|
||||||
|
networkList.find(
|
||||||
|
(i) => i.id === networkCurrent,
|
||||||
|
).addresses) ||
|
||||||
|
[]"
|
||||||
|
:key="i.address"
|
||||||
|
>
|
||||||
|
<a-badge
|
||||||
|
:color="
|
||||||
|
i.health === -1
|
||||||
|
? 'red'
|
||||||
|
: 'green'
|
||||||
|
"
|
||||||
|
: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="columnsMQTT"
|
||||||
|
:scroll="{ y: 300 }"
|
||||||
|
>
|
||||||
|
<template
|
||||||
|
slot="stream"
|
||||||
|
slot-scope="text, record"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
v-if="
|
||||||
|
record.upstream &&
|
||||||
|
record.downstream
|
||||||
|
"
|
||||||
|
>上行、下行</span
|
||||||
|
>
|
||||||
|
<span v-else-if="record.upstream"
|
||||||
|
>上行</span
|
||||||
|
>
|
||||||
|
<span v-else-if="record.downstream"
|
||||||
|
>下行</span
|
||||||
|
>
|
||||||
|
</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"
|
||||||
|
@click="next"
|
||||||
|
>
|
||||||
|
下一步
|
||||||
|
</a-button>
|
||||||
|
<a-button v-if="current === 2" type="primary" @click="save">
|
||||||
|
保存
|
||||||
|
</a-button>
|
||||||
|
<a-button v-if="current > 0" style="margin-left: 8px" @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,
|
||||||
|
} from '../Detail/data';
|
||||||
|
import AccessCard from './AccessCard/index.vue';
|
||||||
|
import TitleComponent from '@/components/TitleComponent/index.vue';
|
||||||
|
import { message, Form } from 'ant-design-vue';
|
||||||
|
|
||||||
|
function generateUUID() {
|
||||||
|
var d = new Date().getTime();
|
||||||
|
if (
|
||||||
|
typeof performance !== 'undefined' &&
|
||||||
|
typeof performance.now === 'function'
|
||||||
|
) {
|
||||||
|
d += performance.now(); //use high-precision timer if available
|
||||||
|
}
|
||||||
|
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 current = ref(0);
|
||||||
|
const stepCurrent = ref(0);
|
||||||
|
const steps = ref(['网络组件', '消息协议', '完成']);
|
||||||
|
const networkList = ref([]);
|
||||||
|
const procotolList = ref([]);
|
||||||
|
const allProcotolList = ref([]);
|
||||||
|
const networkCurrent = ref('');
|
||||||
|
const procotolCurrent = ref('');
|
||||||
|
let config = ref({});
|
||||||
|
let columnsMQTT = ref([]);
|
||||||
|
const form = reactive({
|
||||||
|
name: 'access',
|
||||||
|
description: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
const queryNetworkList = async (id: string, params: object, data = {}) => {
|
||||||
|
console.log('queryNetworkList',NetworkTypeMapping.get(id), data, params);
|
||||||
|
|
||||||
|
const resp = await getNetworkList(NetworkTypeMapping.get(id), data, params);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
networkList.value = resp.result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// const queryProcotolList=async(id:string, params:object) =>{
|
||||||
|
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 = this.$store.state.permission.routes['Link/Type/Detail']
|
||||||
|
const url = '/demo';
|
||||||
|
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, {
|
||||||
|
include: networkCurrent.value || '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const addProcotol = () => {
|
||||||
|
// const url = this.$store.state.permission.routes['Link/Protocol']
|
||||||
|
const url = '/demo';
|
||||||
|
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 checkedChange = (id: string) => {
|
||||||
|
networkCurrent.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const networkSearch = (value: string) => {
|
||||||
|
console.log('networkSearch',
|
||||||
|
props.provider.id,
|
||||||
|
{
|
||||||
|
include: networkCurrent.value || '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
column: 'name$LIKE',
|
||||||
|
value: `%${value}%`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
queryNetworkList(
|
||||||
|
props.provider.id,
|
||||||
|
{
|
||||||
|
include: networkCurrent.value || '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
terms: [
|
||||||
|
{
|
||||||
|
column: 'name$LIKE',
|
||||||
|
value: `%${value}%`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const procotolChange = (id: string) => {
|
||||||
|
if (!props.data.id) {
|
||||||
|
procotolCurrent.value = id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const procotolSearch = (value: string) => {
|
||||||
|
if (value) {
|
||||||
|
const list = allProcotolList.value.filter((i) => {
|
||||||
|
return (
|
||||||
|
i.name &&
|
||||||
|
i.name.toLocaleLowerCase().includes(value.toLocaleLowerCase())
|
||||||
|
);
|
||||||
|
});
|
||||||
|
procotolList.value = list;
|
||||||
|
} else {
|
||||||
|
procotolList.value = allProcotolList.value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const saveData = () => {
|
||||||
|
form.validateFields(async (err, values) => {
|
||||||
|
if (!err) {
|
||||||
|
let resp = undefined;
|
||||||
|
if (props.data && props.data.id) {
|
||||||
|
resp = await update({
|
||||||
|
...props.data,
|
||||||
|
name: values.name,
|
||||||
|
description: values.description,
|
||||||
|
protocol: procotolCurrent.value,
|
||||||
|
channel: 'network', // 网络组件
|
||||||
|
channelId: networkCurrent.value,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resp = await save({
|
||||||
|
name: values.name,
|
||||||
|
description: values.description,
|
||||||
|
provider: props.provider.id,
|
||||||
|
protocol: procotolCurrent.value,
|
||||||
|
transport:
|
||||||
|
props.provider?.id === 'child-device'
|
||||||
|
? 'Gateway'
|
||||||
|
: ProtocolMapping.get(props.provider.id),
|
||||||
|
channel: 'network', // 网络组件
|
||||||
|
channelId: networkCurrent.value,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
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'] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const next = async () => {
|
||||||
|
if (current.value === 0) {
|
||||||
|
if (!networkCurrent.value) {
|
||||||
|
message.error('请选择网络组件!');
|
||||||
|
} else {
|
||||||
|
queryProcotolList(props.provider.id);
|
||||||
|
current.value -= current.value;
|
||||||
|
}
|
||||||
|
} else if (current.value === 1) {
|
||||||
|
if (!procotolCurrent.value) {
|
||||||
|
message.error('请选择消息协议!');
|
||||||
|
} else {
|
||||||
|
const resp =
|
||||||
|
props.provider.channel !== 'child-device'
|
||||||
|
? await getConfigView(
|
||||||
|
procotolCurrent.value,
|
||||||
|
ProtocolMapping.get(props.provider.id),
|
||||||
|
)
|
||||||
|
: await getChildConfigView(procotolCurrent.value);
|
||||||
|
if (resp.status === 200) {
|
||||||
|
config.value = resp.result;
|
||||||
|
current.value += current.value;
|
||||||
|
columnsMQTT = [
|
||||||
|
{
|
||||||
|
title: '分组',
|
||||||
|
dataIndex: 'group',
|
||||||
|
key: 'group',
|
||||||
|
ellipsis: true,
|
||||||
|
align: 'center',
|
||||||
|
width: 100,
|
||||||
|
customRender: (value, row, index) => {
|
||||||
|
const obj = {
|
||||||
|
children: value,
|
||||||
|
attrs: {},
|
||||||
|
};
|
||||||
|
const list = (config && config.routes) || [];
|
||||||
|
const arr = list.filter((res) => {
|
||||||
|
return res.group == row.group;
|
||||||
|
});
|
||||||
|
if (
|
||||||
|
index == 0 ||
|
||||||
|
list[index - 1].group !== row.group
|
||||||
|
) {
|
||||||
|
obj.attrs.rowSpan = arr.length;
|
||||||
|
} else {
|
||||||
|
obj.attrs.rowSpan = 0;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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 prev = () => {
|
||||||
|
const currentValue = current.value;
|
||||||
|
current.value -= currentValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
console.log(11111111,props.provider.id, {
|
||||||
|
include: networkCurrent.value,
|
||||||
|
});
|
||||||
|
|
||||||
|
queryNetworkList(props.provider.id, {
|
||||||
|
include: 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 (props.provider.channel !== 'child-device') {
|
||||||
|
console.log(3333333, props.provider.id, {
|
||||||
|
include: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
queryNetworkList(props.provider.id, {
|
||||||
|
include: '',
|
||||||
|
});
|
||||||
|
steps.value = ['网络组件', '消息协议', '完成'];
|
||||||
|
current.value = 0;
|
||||||
|
} else {
|
||||||
|
console.log(444444,props.provider.id);
|
||||||
|
|
||||||
|
steps.value = ['消息协议', '完成'];
|
||||||
|
current.value = 1;
|
||||||
|
queryProcotolList(props.provider.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// watch(
|
||||||
|
// () => props.modelValue,
|
||||||
|
// (v) => {
|
||||||
|
// keystoreBase64.value = v;
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// deep: true,
|
||||||
|
// immediate: true,
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// watch: {
|
||||||
|
// current(val) {
|
||||||
|
// if (this.provider.channel !== 'child-device') {
|
||||||
|
// this.stepCurrent = val
|
||||||
|
// } else {
|
||||||
|
// this.stepCurrent = val - 1
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
</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;
|
||||||
|
max-height: 580px;
|
||||||
|
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>
|
|
@ -0,0 +1,145 @@
|
||||||
|
<template>
|
||||||
|
<TitleComponent data="自定义设备接入"></TitleComponent>
|
||||||
|
<div>
|
||||||
|
<a-row :gutter="[24, 24]">
|
||||||
|
<a-col :span="12" v-for="item in dataSource" :key="item.id">
|
||||||
|
<div class="provider">
|
||||||
|
<div class="box">
|
||||||
|
<div class="left">
|
||||||
|
<div class="images">
|
||||||
|
<img :src="backMap.get(item.id)" />
|
||||||
|
</div>
|
||||||
|
<div class="context">
|
||||||
|
<div class="title">
|
||||||
|
{{ item.name }}
|
||||||
|
</div>
|
||||||
|
<div class="desc">
|
||||||
|
<a-tooltip :title="item.description">
|
||||||
|
{{ item.description || '' }}
|
||||||
|
</a-tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="right">
|
||||||
|
<a-button type="primary" @click="click(item)"
|
||||||
|
>接入</a-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="AccessConfigProvider">
|
||||||
|
import TitleComponent from '@/components/TitleComponent/index.vue';
|
||||||
|
import { getImage } from '@/utils/comm';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataSource: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,11 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<a-button type="primary" @click="handlAdd">新增</a-button>
|
<a-button type="primary" @click="handlAdd">新增</a-button>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup name="AccessConfigPage">
|
<script lang="ts" setup name="AccessConfigPage">
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
const handlAdd = (e: any) => {
|
// const handlAdd = () => {
|
||||||
console.log(111,e);
|
// router.push({
|
||||||
|
// path: '/link/accessConfig/detail/add',
|
||||||
|
// query: {
|
||||||
|
// id: '1610475400026861568',
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// };
|
||||||
|
const handlAdd = () => {
|
||||||
|
router.push('/link/accessConfig/detail/add');
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in New Issue