Merge branch 'dev-hub' into dev
This commit is contained in:
commit
011f289262
|
@ -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',
|
||||
component: () => import('@/views/link/Certificate/Detail/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/link/accessConfig',
|
||||
component: () => import('@/views/link/AccessConfig/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/link/accessConfig/detail/add',
|
||||
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();
|
||||
ProcotoleMapping.set('websocket-server', 'WebSocket');
|
||||
ProcotoleMapping.set('http-server-gateway', 'HTTP');
|
||||
ProcotoleMapping.set('udp-device-gateway', 'UDP');
|
||||
ProcotoleMapping.set('coap-server-gateway', 'CoAP');
|
||||
ProcotoleMapping.set('mqtt-client-gateway', 'MQTT');
|
||||
ProcotoleMapping.set('mqtt-server-gateway', 'MQTT');
|
||||
ProcotoleMapping.set('tcp-server-gateway', 'TCP');
|
||||
ProcotoleMapping.set('child-device', '');
|
||||
const ProtocolMapping = new Map();
|
||||
ProtocolMapping.set('websocket-server', 'WebSocket');
|
||||
ProtocolMapping.set('http-server-gateway', 'HTTP');
|
||||
ProtocolMapping.set('udp-device-gateway', 'UDP');
|
||||
ProtocolMapping.set('coap-server-gateway', 'CoAP');
|
||||
ProtocolMapping.set('mqtt-client-gateway', 'MQTT');
|
||||
ProtocolMapping.set('mqtt-server-gateway', 'MQTT');
|
||||
ProtocolMapping.set('tcp-server-gateway', 'TCP');
|
||||
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 = {
|
||||
'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>
|
||||
<a-card :bordered="false">
|
||||
<TitleComponent data="自定义设备接入"></TitleComponent>
|
||||
<div>
|
||||
<a-row :gutter="[24, 24]">
|
||||
<a-col :span="12" v-for="item in items" :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="goProviders(item)"
|
||||
>接入</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-card>
|
||||
<a-spin :spinning="loading">
|
||||
<a-card :bordered="false">
|
||||
<div v-if="type">
|
||||
<Provider
|
||||
@onClick="goProviders"
|
||||
:dataSource="dataSource"
|
||||
></Provider>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!id"><a @click="goBack">返回</a></div>
|
||||
<AccessNetwork :provider="provider" :data="data" />
|
||||
</div>
|
||||
</a-card>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="AccessConfigDetail">
|
||||
import { getImage } from '@/utils/comm';
|
||||
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 = [
|
||||
{ id: 'mqtt-server-gateway', name: '测试1', description: '测试1' },
|
||||
{ id: 'websocket-server', name: '测试2', description: '测试' },
|
||||
{ id: 'coap-server-gateway', name: '测试3', description: '测试' },
|
||||
];
|
||||
// const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const backMap = new Map();
|
||||
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 id = route.query.id;
|
||||
|
||||
const goProviders = (value: object) => {
|
||||
console.log(111, value);
|
||||
const dataSource = ref([]);
|
||||
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>
|
||||
|
||||
<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>
|
||||
<a-button type="primary" @click="handlAdd">新增</a-button>
|
||||
<a-button type="primary" @click="handlAdd">新增</a-button>
|
||||
</template>
|
||||
<script lang="ts" setup name="AccessConfigPage">
|
||||
const router = useRouter();
|
||||
|
||||
const handlAdd = (e: any) => {
|
||||
console.log(111,e);
|
||||
|
||||
// const handlAdd = () => {
|
||||
// router.push({
|
||||
// path: '/link/accessConfig/detail/add',
|
||||
// query: {
|
||||
// id: '1610475400026861568',
|
||||
// },
|
||||
// });
|
||||
// };
|
||||
const handlAdd = () => {
|
||||
router.push('/link/accessConfig/detail/add');
|
||||
}
|
||||
|
||||
</script>
|
||||
|
|
|
@ -64,16 +64,14 @@ const handleChange = (info: UploadChangeParam) => {
|
|||
message.success('上传成功!');
|
||||
const result = info.file.response?.result;
|
||||
keystoreBase64.value = result;
|
||||
console.log(1114, result);
|
||||
loading.value = false;
|
||||
emit('change', result);
|
||||
emit('update:modelValue', result);
|
||||
}
|
||||
};
|
||||
const textChange = (val: any) => {
|
||||
val.name = props.name;
|
||||
emit('change', val);
|
||||
// emit('update:modelValue', val);
|
||||
emit('change', keystoreBase64.value);
|
||||
emit('update:modelValue', keystoreBase64.value);
|
||||
};
|
||||
|
||||
watch(
|
||||
|
|
|
@ -10,10 +10,8 @@
|
|||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
@finish="onFinish"
|
||||
:rules="formRules"
|
||||
>
|
||||
<a-form-item label="证书标准" name="type">
|
||||
<a-form-item label="证书标准" v-bind="validateInfos.type">
|
||||
<a-radio-group v-model:value="formData.type">
|
||||
<a-radio-button
|
||||
class="form-radio-button"
|
||||
|
@ -24,25 +22,29 @@
|
|||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="证书名称" name="name">
|
||||
<a-form-item label="证书名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
placeholder="请输入证书名称"
|
||||
v-model:value="formData.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="证书文件" name="cert">
|
||||
<a-form-item
|
||||
label="证书文件"
|
||||
v-bind="validateInfos['configs.cert']"
|
||||
>
|
||||
<CertificateFile
|
||||
name="cert"
|
||||
v-model:modelValue="formData.cert"
|
||||
@change="changeFileValue"
|
||||
v-model:modelValue="formData.configs.cert"
|
||||
placeholder='证书格式以"-----BEGIN CERTIFICATE-----"开头,以"-----END CERTIFICATE-----"结尾"'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="证书私钥" name="key">
|
||||
<a-form-item
|
||||
label="证书私钥"
|
||||
v-bind="validateInfos['configs.key']"
|
||||
>
|
||||
<CertificateFile
|
||||
name="key"
|
||||
v-model:modelValue="formData.key"
|
||||
@change="changeFileValue"
|
||||
v-model:modelValue="formData.configs.key"
|
||||
placeholder='证书私钥格式以"-----BEGIN (RSA|EC) PRIVATE KEY-----"开头,以"-----END(RSA|EC) PRIVATE KEY-----"结尾。'
|
||||
/>
|
||||
</a-form-item>
|
||||
|
@ -61,6 +63,8 @@
|
|||
class="form-submit"
|
||||
html-type="submit"
|
||||
type="primary"
|
||||
@click.prevent="onSubmit"
|
||||
:loading="loading"
|
||||
>保存</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
|
@ -89,7 +93,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts" setup name="CertificateDetail">
|
||||
import { message } from 'ant-design-vue';
|
||||
import { message, Form } from 'ant-design-vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import CertificateFile from './CertificateFile.vue';
|
||||
import type { UploadChangeParam } from 'ant-design-vue';
|
||||
|
@ -101,57 +105,65 @@ import {
|
|||
} from '@/utils/variable';
|
||||
import { save } from '@/api/link/certificate';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const fileLoading = ref(false);
|
||||
const loading = ref(false);
|
||||
|
||||
const formData = reactive({
|
||||
type: 'common',
|
||||
name: '',
|
||||
cert: '',
|
||||
key: '',
|
||||
// configs: {
|
||||
// cert: '',
|
||||
// key: '',
|
||||
// },
|
||||
configs: {
|
||||
cert: '',
|
||||
key: '',
|
||||
},
|
||||
description: '',
|
||||
});
|
||||
|
||||
const formRules = {
|
||||
type: [{ required: true, message: '请选择证书标准', trigger: 'blur' }],
|
||||
name: [
|
||||
{ required: true, message: '请输入证书名称', trigger: 'blur' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
cert: [{ required: true, message: '请输入或上传文件', trigger: 'blur' }],
|
||||
key: [{ required: true, message: '请输入或上传文件', trigger: 'blur' }],
|
||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||
};
|
||||
const { resetFields, validate, validateInfos } = useForm(
|
||||
formData,
|
||||
reactive({
|
||||
type: [{ required: true, message: '请选择证书标准', trigger: 'blur' }],
|
||||
name: [
|
||||
{ required: true, message: '请输入证书名称', trigger: 'blur' },
|
||||
{ max: 64, message: '最多可输入64个字符' },
|
||||
],
|
||||
'configs.cert': [
|
||||
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||
],
|
||||
'configs.key': [
|
||||
{ required: true, message: '请输入或上传文件', trigger: 'blur' },
|
||||
],
|
||||
description: [{ max: 200, message: '最多可输入200个字符' }],
|
||||
}),
|
||||
);
|
||||
|
||||
const onFinish = async (values: any) => {
|
||||
values.configs = {
|
||||
cert: formData.cert,
|
||||
key: formData.key,
|
||||
};
|
||||
delete values.cert;
|
||||
delete values.key;
|
||||
|
||||
const response = await save(values)
|
||||
if (response.status === 200) {
|
||||
message.success('操作成功')
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
const changeFileValue = (v: any) => {
|
||||
formData[v.name] = v.data;
|
||||
const onSubmit = () => {
|
||||
validate()
|
||||
.then(async (res) => {
|
||||
const params = toRaw(formData);
|
||||
loading.value = true;
|
||||
const response = await save(params);
|
||||
if (response.status === 200) {
|
||||
message.success('操作成功');
|
||||
router.push('/link/certificate');
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const handleChange = (info: UploadChangeParam) => {
|
||||
loading.value = true;
|
||||
fileLoading.value = true;
|
||||
if (info.file.status === 'done') {
|
||||
message.success('上传成功!');
|
||||
const result = info.file.response?.result;
|
||||
formData.cert = result;
|
||||
loading.value = false;
|
||||
formData.configs.cert = result;
|
||||
fileLoading.value = false;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
</template>
|
||||
<script lang="ts" setup name="CertificatePage">
|
||||
|
||||
const handlAdd = (e: any) => {
|
||||
console.log(111,e);
|
||||
const router = useRouter();
|
||||
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push('/link/certificate/detail/add');
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue