Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
xieyonghong 2023-02-01 10:10:43 +08:00
commit 419f5ff4a2
15 changed files with 867 additions and 444 deletions

View File

@ -36,7 +36,7 @@ export const undeploy = (id: string) =>
export const deploy = (id: string) => export const deploy = (id: string) =>
server.post(`/gateway/device/${id}/_startup`); server.post(`/gateway/device/${id}/_startup`);
export const del = (id: string) => server.remove(`/gateway/device/${id}`); export const remove = (id: string) => server.remove(`/gateway/device/${id}`);
export const getResourcesCurrent = () => export const getResourcesCurrent = () =>
server.get(`/network/resources/alive/_current`); server.get(`/network/resources/alive/_current`);

View File

@ -10,17 +10,23 @@
.jtable-body-header-right { .jtable-body-header-right {
display: flex; display: flex;
gap: 8px; gap: 8px;
.jtable-setting-item { align-items: center;
color: rgba(0, 0, 0, 0.75); .jtable-body-header-right-button {
font-size: 16px; display: flex;
cursor: pointer; margin-left: 10px;
gap: 8px;
.jtable-setting-item {
color: rgba(0, 0, 0, 0.75);
font-size: 16px;
cursor: pointer;
&:hover { &:hover {
color: @primary-color-hover; color: @primary-color-hover;
} }
&.active { &.active {
color: @primary-color-active; color: @primary-color-active;
}
} }
} }
} }

View File

@ -73,6 +73,7 @@ const JTable = defineComponent<JTableProps>({
slots: [ slots: [
'headerTitle', // 顶部左边插槽 'headerTitle', // 顶部左边插槽
'card', // 卡片内容 'card', // 卡片内容
'rightExtraRender'
], ],
emits: [ emits: [
'modelChange', // 切换卡片和表格 'modelChange', // 切换卡片和表格
@ -254,16 +255,22 @@ const JTable = defineComponent<JTableProps>({
{slots.headerTitle && slots.headerTitle()} {slots.headerTitle && slots.headerTitle()}
</div> </div>
<div class={styles["jtable-body-header-right"]}> <div class={styles["jtable-body-header-right"]}>
<div class={[styles["jtable-setting-item"], ModelEnum.CARD === _model.value ? styles['active'] : '']} onClick={() => { {/* 顶部右边插槽 */}
_model.value = ModelEnum.CARD {slots.rightExtraRender && slots.rightExtraRender()}
}}> {
<AppstoreOutlined /> !props.model && <div class={styles["jtable-body-header-right-button"]}>
</div> <div class={[styles["jtable-setting-item"], ModelEnum.CARD === _model.value ? styles['active'] : '']} onClick={() => {
<div class={[styles["jtable-setting-item"], ModelEnum.TABLE === _model.value ? styles['active'] : '']} onClick={() => { _model.value = ModelEnum.CARD
_model.value = ModelEnum.TABLE }}>
}}> <AppstoreOutlined />
<UnorderedListOutlined /> </div>
</div> <div class={[styles["jtable-setting-item"], ModelEnum.TABLE === _model.value ? styles['active'] : '']} onClick={() => {
_model.value = ModelEnum.TABLE
}}>
<UnorderedListOutlined />
</div>
</div>
}
</div> </div>
</div> </div>
{/* content */} {/* content */}

View File

@ -1,222 +1,234 @@
<template> <template>
<Search :columns="columns" target="device-instance" /> <page-container>
<JTable <Search :columns="columns" target="device-instance" />
ref="instanceRef" <JTable
:columns="columns" ref="instanceRef"
:request="query" :columns="columns"
:defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }" :request="query"
:rowSelection="{ :defaultParams="{ sorts: [{ name: 'createTime', order: 'desc' }] }"
selectedRowKeys: _selectedRowKeys, :rowSelection="{
onChange: onSelectChange, selectedRowKeys: _selectedRowKeys,
}" onChange: onSelectChange,
@cancelSelect="cancelSelect" }"
:params="params" @cancelSelect="cancelSelect"
> :params="params"
<template #headerTitle> >
<a-space> <template #headerTitle>
<a-button type="primary" @click="handleAdd">新增</a-button> <a-space>
<a-dropdown> <a-button type="primary" @click="handleAdd">新增</a-button>
<a-button>批量操作 <AIcon type="DownOutlined" /></a-button> <a-dropdown>
<template #overlay> <a-button
<a-menu> >批量操作 <AIcon type="DownOutlined"
<a-menu-item> /></a-button>
<a-button @click="exportVisible = true" <template #overlay>
><AIcon <a-menu>
type="ExportOutlined" <a-menu-item>
/></a-button <a-button @click="exportVisible = true"
>
</a-menu-item>
<a-menu-item>
<a-button @click="importVisible = true"
><AIcon
type="ImportOutlined"
/></a-button
>
</a-menu-item>
<a-menu-item>
<a-popconfirm
@confirm="activeAllDevice"
title="确认激活全部设备?"
>
<a-button type="primary" ghost
><AIcon ><AIcon
type="CheckCircleOutlined" type="ExportOutlined"
/></a-button /></a-button
> >
</a-popconfirm> </a-menu-item>
</a-menu-item> <a-menu-item>
<a-menu-item> <a-button @click="importVisible = true"
<a-button
@click="syncDeviceStatus"
type="primary"
><AIcon
type="SyncOutlined"
/></a-button
>
</a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length">
<a-popconfirm
@confirm="delSelectedDevice"
title="已启用的设备无法删除,确认删除选中的禁用状态设备?"
>
<a-button type="primary" danger
><AIcon ><AIcon
type="DeleteOutlined" type="ImportOutlined"
/></a-button /></a-button
> >
</a-popconfirm> </a-menu-item>
</a-menu-item> <a-menu-item>
<a-menu-item <a-popconfirm
v-if="_selectedRowKeys.length" @confirm="activeAllDevice"
title="确认激活选中设备?" title="确认激活全部设备?"
> >
<a-popconfirm @confirm="activeSelectedDevice"> <a-button type="primary" ghost
<a-button type="primary" ><AIcon
type="CheckCircleOutlined"
/></a-button
>
</a-popconfirm>
</a-menu-item>
<a-menu-item>
<a-button
@click="syncDeviceStatus"
type="primary"
><AIcon ><AIcon
type="CheckOutlined" type="SyncOutlined"
/></a-button /></a-button
> >
</a-popconfirm> </a-menu-item>
</a-menu-item> <a-menu-item v-if="_selectedRowKeys.length">
<a-menu-item v-if="_selectedRowKeys.length"> <a-popconfirm
<a-popconfirm @confirm="delSelectedDevice"
@confirm="disabledSelectedDevice" title="已启用的设备无法删除,确认删除选中的禁用状态设备?"
title="确认禁用选中设备?" >
<a-button type="primary" danger
><AIcon
type="DeleteOutlined"
/></a-button
>
</a-popconfirm>
</a-menu-item>
<a-menu-item
v-if="_selectedRowKeys.length"
title="确认激活选中设备?"
> >
<a-button type="primary" danger <a-popconfirm
><AIcon @confirm="activeSelectedDevice"
type="StopOutlined"
/></a-button
> >
</a-popconfirm> <a-button type="primary"
</a-menu-item> ><AIcon
</a-menu> type="CheckOutlined"
/></a-button
>
</a-popconfirm>
</a-menu-item>
<a-menu-item v-if="_selectedRowKeys.length">
<a-popconfirm
@confirm="disabledSelectedDevice"
title="确认禁用选中设备?"
>
<a-button type="primary" danger
><AIcon
type="StopOutlined"
/></a-button
>
</a-popconfirm>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</a-space>
</template>
<template #card="slotProps">
<CardBox
:value="slotProps"
@click="handleClick"
:actions="getActions(slotProps, 'card')"
v-bind="slotProps"
:active="_selectedRowKeys.includes(slotProps.id)"
:status="slotProps.state?.value"
:statusText="slotProps.state?.text"
:statusNames="{
online: 'success',
offline: 'error',
notActive: 'warning',
}"
>
<template #img>
<slot name="img">
<img
:src="
getImage('/device/instance/device-card.png')
"
/>
</slot>
</template> </template>
</a-dropdown> <template #content>
</a-space> <h3
</template> class="card-item-content-title"
<template #card="slotProps"> @click.stop="handleView(slotProps.id)"
<CardBox >
:value="slotProps" {{ slotProps.name }}
@click="handleClick" </h3>
:actions="getActions(slotProps, 'card')" <a-row>
v-bind="slotProps" <a-col :span="12">
:active="_selectedRowKeys.includes(slotProps.id)" <div class="card-item-content-text">
:status="slotProps.state?.value" 设备类型
:statusText="slotProps.state?.text" </div>
:statusNames="{ <div>{{ slotProps.deviceType?.text }}</div>
online: 'success', </a-col>
offline: 'error', <a-col :span="12">
notActive: 'warning', <div class="card-item-content-text">
}" 产品名称
> </div>
<template #img> <div>{{ slotProps.productName }}</div>
<slot name="img"> </a-col>
<img </a-row>
:src="getImage('/device/instance/device-card.png')" </template>
/> <template #actions="item">
</slot> <a-tooltip
</template> v-bind="item.tooltip"
<template #content> :title="item.disabled && item.tooltip.title"
<h3 >
class="card-item-content-title" <a-popconfirm
@click.stop="handleView(slotProps.id)" v-if="item.popConfirm"
> v-bind="item.popConfirm"
{{ slotProps.name }} :disabled="item.disabled"
</h3> >
<a-row> <a-button :disabled="item.disabled">
<a-col :span="12"> <AIcon
<div class="card-item-content-text">设备类型</div> type="DeleteOutlined"
<div>{{ slotProps.deviceType?.text }}</div> v-if="item.key === 'delete'"
</a-col> />
<a-col :span="12"> <template v-else>
<div class="card-item-content-text">产品名称</div> <AIcon :type="item.icon" />
<div>{{ slotProps.productName }}</div> <span>{{ item?.text }}</span>
</a-col> </template>
</a-row> </a-button>
</template> </a-popconfirm>
<template #actions="item"> <template v-else>
<a-button
:disabled="item.disabled"
@click="item.onClick"
>
<AIcon
type="DeleteOutlined"
v-if="item.key === 'delete'"
/>
<template v-else>
<AIcon :type="item.icon" />
<span>{{ item?.text }}</span>
</template>
</a-button>
</template>
</a-tooltip>
</template>
</CardBox>
</template>
<template #state="slotProps">
<a-badge
:text="slotProps.state?.text"
:status="statusMap.get(slotProps.state?.value)"
/>
</template>
<template #action="slotProps">
<a-space :size="16">
<a-tooltip <a-tooltip
v-bind="item.tooltip" v-for="i in getActions(slotProps, 'table')"
:title="item.disabled && item.tooltip.title" :key="i.key"
v-bind="i.tooltip"
> >
<a-popconfirm <a-popconfirm
v-if="item.popConfirm" v-if="i.popConfirm"
v-bind="item.popConfirm" v-bind="i.popConfirm"
:disabled="item.disabled" :disabled="i.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 <a-button
:disabled="item.disabled" :disabled="i.disabled"
@click="item.onClick" style="padding: 0"
> type="link"
<AIcon ><AIcon :type="i.icon"
type="DeleteOutlined" /></a-button>
v-if="item.key === 'delete'" </a-popconfirm>
/> <a-button
<template v-else> style="padding: 0"
<AIcon :type="item.icon" /> type="link"
<span>{{ item?.text }}</span> v-else
</template> @click="i.onClick && i.onClick(slotProps)"
</a-button> >
</template> <a-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip> </a-tooltip>
</template> </a-space>
</CardBox> </template>
</template> </JTable>
<template #state="slotProps"> </page-container>
<a-badge
:text="slotProps.state?.text"
:status="statusMap.get(slotProps.state?.value)"
/>
</template>
<template #action="slotProps">
<a-space :size="16">
<a-tooltip
v-for="i in getActions(slotProps, 'table')"
:key="i.key"
v-bind="i.tooltip"
>
<a-popconfirm
v-if="i.popConfirm"
v-bind="i.popConfirm"
:disabled="i.disabled"
>
<a-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-popconfirm>
<a-button
style="padding: 0"
type="link"
v-else
@click="i.onClick && i.onClick(slotProps)"
>
<a-button
:disabled="i.disabled"
style="padding: 0"
type="link"
><AIcon :type="i.icon"
/></a-button>
</a-button>
</a-tooltip>
</a-space>
</template>
</JTable>
<Import v-if="importVisible" @close="importVisible = false" /> <Import v-if="importVisible" @close="importVisible = false" />
<Export <Export
v-if="exportVisible" v-if="exportVisible"
@ -229,7 +241,12 @@
:api="api" :api="api"
:type="type" :type="type"
/> />
<Save v-if="visible" :data="current" @close="visible = false" @save="saveBtn" /> <Save
v-if="visible"
:data="current"
@close="visible = false"
@save="saveBtn"
/>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@ -368,8 +385,8 @@ const handleAdd = () => {
* 查看 * 查看
*/ */
const handleView = (id: string) => { const handleView = (id: string) => {
router.push('/device/instance/detail/' + id) router.push('/device/instance/detail/' + id);
} };
const getActions = ( const getActions = (
data: Partial<Record<string, any>>, data: Partial<Record<string, any>>,
@ -520,10 +537,10 @@ const disabledSelectedDevice = async () => {
_selectedRowKeys.value = []; _selectedRowKeys.value = [];
instanceRef.value?.reload(); instanceRef.value?.reload();
} }
} };
const saveBtn = () => { const saveBtn = () => {
visible.value = false visible.value = false;
instanceRef.value?.reload() instanceRef.value?.reload();
} };
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<a-spin :spinning="loading"> <a-spin :spinning="loading">
<a-card :bordered="false"> <a-card :bordered="false">
<div v-if="type"> <div v-if="type && modeType === 'add'">
<Provider <Provider
@onClick="goProviders" @onClick="goProviders"
:dataSource="dataSource" :dataSource="dataSource"
@ -14,9 +14,21 @@
:provider="provider" :provider="provider"
:data="data" :data="data"
/> />
<Media v-if="showType === 'media'" :provider="provider" /> <Media
<Channel v-if="showType === 'channel'" :provider="provider" /> v-if="showType === 'media'"
<Edge v-if="showType === 'edge'" :provider="provider" /> :provider="provider"
:data="data"
/>
<Channel
v-if="showType === 'channel'"
:provider="provider"
:data="data"
/>
<Edge
v-if="showType === 'edge'"
:provider="provider"
:data="data"
/>
<Cloud <Cloud
v-if="showType === 'cloud'" v-if="showType === 'cloud'"
:provider="provider" :provider="provider"
@ -37,10 +49,10 @@ import Channel from '../components/Channel/index.vue';
import Edge from '../components/Edge/index.vue'; import Edge from '../components/Edge/index.vue';
import Cloud from '../components/Cloud/index.vue'; import Cloud from '../components/Cloud/index.vue';
// const router = useRouter();
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const dataSource = ref([]); const dataSource = ref([]);
const type = ref(false); const type = ref(false);
@ -53,7 +65,6 @@ const goProviders = (param: object) => {
showType.value = param.type; showType.value = param.type;
provider.value = param; provider.value = param;
type.value = false; type.value = false;
console.log(1123, showType.value, param);
}; };
const goBack = () => { const goBack = () => {
@ -61,80 +72,77 @@ const goBack = () => {
type.value = true; type.value = true;
}; };
const getTypeList = (result: any[]) => {
const list = [];
const media: any[] = [];
const network: any[] = [];
const cloud: any[] = [];
const channel: any[] = [];
const edge: any[] = [];
result.map((item) => {
if (item.id === 'fixed-media' || item.id === 'gb28181-2016') {
item.type = 'media';
media.push(item);
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
item.type = 'cloud';
cloud.push(item);
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua') {
item.type = 'channel';
channel.push(item);
} else if (
item.id === 'official-edge-gateway' ||
item.id === 'edge-child-device'
) {
item.type = 'edge';
edge.push(item);
} else {
item.type = 'network';
network.push(item);
}
});
network.length &&
list.push({
list: [...network],
title: '自定义设备接入',
});
media.length &&
list.push({
list: [...media],
title: '视频类设备接入',
});
cloud.length &&
list.push({
list: [...cloud],
title: '云平台接入',
});
channel.length &&
list.push({
list: [...channel],
title: '通道类设备接入',
});
edge.length &&
list.push({
list: [...edge],
title: '官方接入',
});
return list;
};
const queryProviders = async () => { const queryProviders = async () => {
const resp = await getProviders(); const resp = await getProviders();
if (resp.status === 200) { if (resp.status === 200) {
const media: any[] = []; dataSource.value = getTypeList(resp.result);
const network: any[] = [];
const cloud: any[] = [];
const channel: any[] = [];
const edge: any[] = [];
resp.result.map((item) => {
if (item.id === 'fixed-media' || item.id === 'gb28181-2016') {
item.type = 'media';
media.push(item);
} else if (item.id === 'OneNet' || item.id === 'Ctwing') {
item.type = 'cloud';
cloud.push(item);
} else if (item.id === 'modbus-tcp' || item.id === 'opc-ua') {
item.type = 'channel';
channel.push(item);
} else if (
item.id === 'official-edge-gateway' ||
item.id === 'edge-child-device'
) {
item.type = 'edge';
edge.push(item);
} else {
item.type = 'network';
network.push(item);
}
});
const list = [];
if (network.length) {
list.push({
// type: 'network',
list: [...network],
title: '自定义设备接入',
});
}
if (media.length) {
list.push({
// type: 'media',
list: [...media],
title: '视频类设备接入',
});
}
if (cloud.length) {
list.push({
// type: 'cloud',
list: [...cloud],
title: '云平台接入',
});
}
if (channel.length) {
list.push({
// type: 'channel',
list: [...channel],
title: '通道类设备接入',
});
}
if (edge.length) {
list.push({
// type: 'edge',
list: [...edge],
title: '官方接入',
});
}
dataSource.value = list;
} }
}; };
const getProvidersData = async () => { const getProvidersData = async () => {
if (id) { if (id && modeType !== 'add') {
getProviders().then((response) => { getProviders().then((response) => {
if (response.status === 200) { if (response.status === 200) {
dataSource.value = response.result.filter( const list = getTypeList(response.result);
dataSource.value = list.filter(
(item) => (item) =>
item.channel === 'network' || item.channel === 'network' ||
item.channel === 'child-device', item.channel === 'child-device',
@ -144,15 +152,21 @@ const getProvidersData = async () => {
const dt = response.result.find( const dt = response.result.find(
(item) => item?.id === resp.result.provider, (item) => item?.id === resp.result.provider,
); );
response.result.forEach((item) => {
if (item.id === resp.result.provider) {
resp.result.type = item.type;
showType.value = item.type;
}
});
provider.value = dt; provider.value = dt;
data.value = resp.result; data.value = resp.result;
type.value = false; type.value = false;
} }
}); });
loading.value = false;
} else {
loading.value = false;
} }
loading.value = false;
}); });
} else { } else {
type.value = true; type.value = true;

View File

@ -39,7 +39,10 @@
/> />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button type="primary" html-type="submit" <a-button
v-if="modeType !== 'view'"
type="primary"
html-type="submit"
>保存</a-button >保存</a-button
> >
</a-form-item> </a-form-item>
@ -93,18 +96,23 @@ interface FormState {
description: string; description: string;
} }
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const props = defineProps({ const props = defineProps({
provider: { provider: {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
data: {
type: Object,
default: () => {},
},
}); });
const type = ref(props.provider.type); const type = ref(props.provider.type);
const formState = reactive<FormState>({ const formState = ref<FormState>({
name: '', name: '',
description: '', description: '',
}); });
@ -117,7 +125,10 @@ const onFinish = async (values: any) => {
transport: ProtocolMapping.get(providerId), transport: ProtocolMapping.get(providerId),
channel: providerId === 'modbus-tcp' ? 'modbus' : 'opc-ua', channel: providerId === 'modbus-tcp' ? 'modbus' : 'opc-ua',
}; };
const resp = !!id ? await update({ ...params, id }) : await save(params); const resp =
!!id && modeType !== 'add'
? await update({ ...params, id })
: await save(params);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
// if (params.get('save')) { // if (params.get('save')) {
@ -132,6 +143,15 @@ const onFinish = async (values: any) => {
// } // }
} }
}; };
onMounted(() => {
if (modeType !== 'add') {
formState.value = {
name: props.data.name,
description: props.data?.description || '',
};
}
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -199,7 +199,7 @@
<title-component data="基本信息" /> <title-component data="基本信息" />
<div> <div>
<a-form <a-form
:model="form" :model="formData"
name="basic" name="basic"
autocomplete="off" autocomplete="off"
layout="vertical" layout="vertical"
@ -219,14 +219,14 @@
> >
<a-input <a-input
placeholder="请输入名称" placeholder="请输入名称"
v-model:value="form.name" v-model:value="formData.name"
/> />
</a-form-item> </a-form-item>
<a-form-item label="说明" name="description"> <a-form-item label="说明" name="description">
<a-textarea <a-textarea
placeholder="请输入说明" placeholder="请输入说明"
:rows="4" :rows="4"
v-model:value="form.description" v-model:value="formData.description"
show-count show-count
:maxlength="200" :maxlength="200"
/> />
@ -277,16 +277,20 @@
<a-button <a-button
v-if="[0, 1].includes(current)" v-if="[0, 1].includes(current)"
type="primary" type="primary"
style="margin-right: 8px"
@click="next" @click="next"
> >
下一步 下一步
</a-button> </a-button>
<a-button v-if="current === 2" type="primary" @click="saveData"> <a-button
v-if="current === 2 && modeType !== 'view'"
type="primary"
style="margin-right: 8px"
@click="saveData"
>
保存 保存
</a-button> </a-button>
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev"> <a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
上一步
</a-button>
</div> </div>
</div> </div>
</template> </template>
@ -379,7 +383,8 @@ interface Form {
description: string; description: string;
} }
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const props = defineProps({ const props = defineProps({
provider: { provider: {
@ -396,13 +401,13 @@ const channel = ref(props.provider.channel);
const formRef1 = ref<FormInstance>(); const formRef1 = ref<FormInstance>();
const formRef2 = ref<FormInstance>(); const formRef2 = ref<FormInstance>();
const formState = reactive<FormState>({ const formState = ref<FormState>({
apiAddress: 'https://ag-api.ctwing.cn/', apiAddress: 'https://ag-api.ctwing.cn/',
appKey: '', appKey: '',
appSecret: '', appSecret: '',
description: '', description: '',
}); });
const form = reactive<Form>({ const formData = ref<Form>({
name: '', name: '',
description: '', description: '',
}); });
@ -415,9 +420,7 @@ const allProcotolList = ref([]);
const procotolCurrent = ref(''); const procotolCurrent = ref('');
const procotolChange = (id: string) => { const procotolChange = (id: string) => {
if (!props.data?.id) { procotolCurrent.value = id;
procotolCurrent.value = id;
}
}; };
const procotolSearch = (value: string) => { const procotolSearch = (value: string) => {
@ -439,7 +442,7 @@ const saveData = async () => {
const params = { const params = {
...data, ...data,
configuration: { configuration: {
...formState, ...formState.value,
protocol: procotolCurrent.value, protocol: procotolCurrent.value,
}, },
protocol: procotolCurrent.value, protocol: procotolCurrent.value,
@ -447,7 +450,7 @@ const saveData = async () => {
transport: 'HTTP_SERVER', transport: 'HTTP_SERVER',
}; };
const resp = const resp =
props.data && props.data.id !!id && modeType !== 'add'
? await update({ ? await update({
...props.data, ...props.data,
...params, ...params,
@ -514,7 +517,16 @@ const next = async () => {
const prev = () => { const prev = () => {
current.value = current.value - 1; current.value = current.value - 1;
}; };
onMounted(() => {
if (modeType !== 'add') {
formState.value = props.data.configuration;
procotolCurrent.value = props.data.protocol;
formData.value = {
name: props.data.name,
description: props.data.description,
};
}
});
watch( watch(
current, current,
(v) => { (v) => {

View File

@ -292,7 +292,7 @@
<title-component data="基本信息" /> <title-component data="基本信息" />
<div> <div>
<a-form <a-form
:model="form" :model="formData"
name="basic" name="basic"
autocomplete="off" autocomplete="off"
layout="vertical" layout="vertical"
@ -312,26 +312,18 @@
> >
<a-input <a-input
placeholder="请输入名称" placeholder="请输入名称"
v-model:value="form.name" v-model:value="formData.name"
/> />
</a-form-item> </a-form-item>
<a-form-item label="说明" name="description"> <a-form-item label="说明" name="description">
<a-textarea <a-textarea
placeholder="请输入说明" placeholder="请输入说明"
:rows="4" :rows="4"
v-model:value="form.description" v-model:value="formData.description"
show-count show-count
:maxlength="200" :maxlength="200"
/> />
</a-form-item> </a-form-item>
<!-- <a-form-item>
<a-button
v-if="current !== 1"
type="primary"
html-type="submit"
>保存</a-button
>
</a-form-item> -->
</a-form> </a-form>
</div> </div>
</a-col> </a-col>
@ -378,16 +370,20 @@
<a-button <a-button
v-if="[0, 1].includes(current)" v-if="[0, 1].includes(current)"
type="primary" type="primary"
style="margin-right: 8px"
@click="next" @click="next"
> >
下一步 下一步
</a-button> </a-button>
<a-button v-if="current === 2" type="primary" @click="saveData"> <a-button
style="margin-right: 8px"
v-if="current === 2 && modeType !== 'view'"
type="primary"
@click="saveData"
>
保存 保存
</a-button> </a-button>
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev"> <a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
上一步
</a-button>
</div> </div>
</div> </div>
</template> </template>
@ -483,7 +479,8 @@ interface Form {
description: string; description: string;
} }
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const props = defineProps({ const props = defineProps({
provider: { provider: {
@ -500,14 +497,14 @@ const channel = ref(props.provider.channel);
const formRef1 = ref<FormInstance>(); const formRef1 = ref<FormInstance>();
const formRef2 = ref<FormInstance>(); const formRef2 = ref<FormInstance>();
const formState = reactive<FormState>({ const formState = ref<FormState>({
apiAddress: 'https://api.heclouds.com/', apiAddress: 'https://api.heclouds.com/',
apiKey: '', apiKey: '',
validateToken: '', validateToken: '',
aesKey: '', aesKey: '',
description: '', description: '',
}); });
const form = reactive<Form>({ const formData = ref<Form>({
name: '', name: '',
description: '', description: '',
}); });
@ -520,9 +517,7 @@ const allProcotolList = ref([]);
const procotolCurrent = ref(''); const procotolCurrent = ref('');
const procotolChange = (id: string) => { const procotolChange = (id: string) => {
if (!props.data?.id) { procotolCurrent.value = id;
procotolCurrent.value = id;
}
}; };
const procotolSearch = (value: string) => { const procotolSearch = (value: string) => {
@ -544,7 +539,7 @@ const saveData = async () => {
const params = { const params = {
...data, ...data,
configuration: { configuration: {
...formState, ...formState.value,
protocol: procotolCurrent.value, protocol: procotolCurrent.value,
}, },
protocol: procotolCurrent.value, protocol: procotolCurrent.value,
@ -552,7 +547,7 @@ const saveData = async () => {
transport: 'HTTP_SERVER', transport: 'HTTP_SERVER',
}; };
const resp = const resp =
props.data && props.data.id !!id && modeType !== 'add'
? await update({ ? await update({
...props.data, ...props.data,
...params, ...params,
@ -619,6 +614,17 @@ const prev = () => {
current.value = current.value - 1; current.value = current.value - 1;
}; };
onMounted(() => {
if (modeType !== 'add') {
formState.value = props.data.configuration;
procotolCurrent.value = props.data.protocol;
formData.value = {
name: props.data.name,
description: props.data.description,
};
}
});
watch( watch(
current, current,
(v) => { (v) => {

View File

@ -17,9 +17,6 @@
import Ctwing from './Ctwing.vue'; import Ctwing from './Ctwing.vue';
import OneNet from './OneNet.vue'; import OneNet from './OneNet.vue';
const route = useRoute();
const id = route.query.id;
const props = defineProps({ const props = defineProps({
provider: { provider: {
type: Object, type: Object,

View File

@ -140,7 +140,7 @@
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button <a-button
v-if="current !== 1" v-if="current !== 1 && modeType !== 'view'"
type="primary" type="primary"
html-type="submit" html-type="submit"
>保存</a-button >保存</a-button
@ -171,15 +171,22 @@
v-if="channel !== 'edge-child-device'" v-if="channel !== 'edge-child-device'"
:class="current !== 1 ? 'steps-action' : 'steps-action-save'" :class="current !== 1 ? 'steps-action' : 'steps-action-save'"
> >
<a-button v-if="[0].includes(current)" @click="next"> <a-button
v-if="[0].includes(current)"
style="margin-right: 8px"
@click="next"
>
下一步 下一步
</a-button> </a-button>
<a-button v-if="current === 1" type="primary" @click="saveData"> <a-button
v-if="current === 1 && modeType !== 'view'"
type="primary"
style="margin-right: 8px"
@click="saveData"
>
保存 保存
</a-button> </a-button>
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev"> <a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
上一步
</a-button>
</div> </div>
</div> </div>
</template> </template>
@ -290,19 +297,25 @@ interface FormState {
description: string; description: string;
} }
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const props = defineProps({ const props = defineProps({
provider: { provider: {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
data: {
type: Object,
default: () => {},
},
}); });
const type = ref(props.provider.type); const type = props.provider.type;
const channel = ref(props.provider.channel); const channel = ref(props.provider.channel);
const formState = reactive<FormState>({ const formState = ref<FormState>({
name: '', name: '',
description: '', description: '',
}); });
@ -324,9 +337,10 @@ const onFinish = async (values: any) => {
transport: ProtocolMapping.get(providerId), transport: ProtocolMapping.get(providerId),
}; };
if (networkCurrent.value) params.channelId = networkCurrent.value; if (networkCurrent.value) params.channelId = networkCurrent.value;
console.log(1112, networkCurrent.value, params); const resp =
!!id && modeType !== 'add'
const resp = !!id ? await update({ ...params, id }) : await save(params); ? await update({ ...params, id })
: await save(params);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
// if (params.get('save')) { // if (params.get('save')) {
@ -407,6 +421,13 @@ onMounted(() => {
if (props.provider.id === 'official-edge-gateway') { if (props.provider.id === 'official-edge-gateway') {
queryNetworkList(props.provider.id, ''); queryNetworkList(props.provider.id, '');
} }
if (modeType !== 'add') {
formState.value = {
name: props.data.name,
description: props.data?.description || '',
};
networkCurrent.value = props.data.channelId;
}
}), }),
watch( watch(
current, current,

View File

@ -436,17 +436,18 @@
<a-col :span="12"> <a-col :span="12">
<title-component data="基本信息" /> <title-component data="基本信息" />
<div> <div>
<a-form :model="form" layout="vertical"> <a-form :model="formData" layout="vertical">
<a-form-item <a-form-item
label="名称" label="名称"
v-bind="validateInfos.name" v-bind="validateInfos.name"
> >
<a-input <a-input
v-model:value="form.name" v-model:value="formData.name"
allowClear allowClear
placeholder="请输入名称" placeholder="请输入名称"
/> />
</a-form-item> </a-form-item>
<a-form-item <a-form-item
label="说明" label="说明"
v-bind="validateInfos.description" v-bind="validateInfos.description"
@ -454,7 +455,7 @@
<a-textarea <a-textarea
placeholder="请输入说明" placeholder="请输入说明"
:rows="4" :rows="4"
v-model:value="form.description" v-model:value="formData.description"
show-count show-count
:maxlength="200" :maxlength="200"
/> />
@ -494,15 +495,22 @@
</div> </div>
</div> </div>
<div class="steps-action"> <div class="steps-action">
<a-button v-if="[0].includes(current)" @click="next"> <a-button
v-if="[0].includes(current)"
style="margin-right: 8px"
@click="next"
>
下一步 下一步
</a-button> </a-button>
<a-button v-if="current === 1" type="primary" @click="saveData"> <a-button
v-if="current === 1 && modeType !== 'view'"
type="primary"
style="margin-right: 8px"
@click="saveData"
>
保存 保存
</a-button> </a-button>
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev"> <a-button v-if="current > 0" @click="prev"> 上一步 </a-button>
上一步
</a-button>
</div> </div>
</div> </div>
</template> </template>
@ -544,10 +552,15 @@ const props = defineProps({
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
data: {
type: Object,
default: () => {},
},
}); });
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const activeKey: any = ref([]); const activeKey: any = ref([]);
const clientHeight = document.body.clientHeight; const clientHeight = document.body.clientHeight;
@ -559,11 +572,11 @@ const useForm = Form.useForm;
const current = ref(0); const current = ref(0);
const stepCurrent = ref(0); const stepCurrent = ref(0);
const steps = ref(['信令配置', '完成']); const steps = ref(['信令配置', '完成']);
const form = reactive({ const formData = ref({
name: '', name: '',
description: '', description: '',
}); });
const formState = reactive<FormState>({ let formState = ref<FormState>({
domain: '', domain: '',
sipId: '', sipId: '',
shareCluster: true, shareCluster: true,
@ -574,6 +587,7 @@ const formState = reactive<FormState>({
publicHost: '', publicHost: '',
}, },
}); });
let params = { let params = {
configuration: {}, configuration: {},
}; };
@ -628,12 +642,13 @@ const handleChangeForm2Sip = (index: number) => {
}; };
const { resetFields, validate, validateInfos } = useForm( const { resetFields, validate, validateInfos } = useForm(
form, formData,
reactive({ reactive({
name: [ name: [
{ required: true, message: '请输入名称', trigger: 'blur' }, { required: true, message: '请输入名称', trigger: 'blur' },
{ max: 64, message: '最多可输入64个字符' }, { max: 64, message: '最多可输入64个字符' },
], ],
description: [{ max: 200, message: '最多可输入200个字符' }],
}), }),
); );
@ -646,9 +661,11 @@ const saveData = () => {
transport: 'SIP', transport: 'SIP',
channel: 'gb28181', channel: 'gb28181',
}; };
const resp = !!id
? await update({ ...params, id }) const resp =
: await save(params); !!id && modeType !== 'add'
? await update({ ...params, id })
: await save(params);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
// if (params.get('save')) { // if (params.get('save')) {
@ -723,6 +740,14 @@ onMounted(() => {
clustersList.value = list; clustersList.value = list;
} }
}); });
if (modeType !== 'add') {
formState.value = props.data.configuration;
formData.value = {
name: props.data.name,
description: props.data?.description || '',
};
}
}); });
watch( watch(

View File

@ -39,7 +39,10 @@
/> />
</a-form-item> </a-form-item>
<a-form-item> <a-form-item>
<a-button type="primary" html-type="submit" <a-button
v-if="modeType !== 'view'"
type="primary"
html-type="submit"
>保存</a-button >保存</a-button
> >
</a-form-item> </a-form-item>
@ -72,7 +75,7 @@
</a-row> </a-row>
</div> </div>
<div v-else-if="channel === 'gb28181'"> <div v-else-if="channel === 'gb28181'">
<GB28181 :provider="props.provider"></GB28181> <GB28181 :provider="props.provider" :data="props.data"></GB28181>
</div> </div>
</div> </div>
</template> </template>
@ -88,18 +91,23 @@ interface FormState {
description: string; description: string;
} }
const route = useRoute(); const route = useRoute();
const id = route.query.id; const modeType = route.params.type as string;
const id = route.params.id as string;
const props = defineProps({ const props = defineProps({
provider: { provider: {
type: Object, type: Object,
default: () => {}, default: () => {},
}, },
data: {
type: Object,
default: () => {},
},
}); });
const channel = ref(props.provider.channel); const channel = ref(props.provider.channel);
const formState = reactive<FormState>({ const formState = ref<FormState>({
name: '', name: '',
description: '', description: '',
}); });
@ -110,7 +118,10 @@ const onFinish = async (values: any) => {
transport: 'URL', transport: 'URL',
channel: 'fixed-media', channel: 'fixed-media',
}; };
const resp = !!id ? await update({ ...params, id }) : await save(params); const resp =
!!id && modeType !== 'add'
? await update({ ...params, id })
: await save(params);
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
// if (params.get('save')) { // if (params.get('save')) {
@ -125,6 +136,15 @@ const onFinish = async (values: any) => {
// } // }
} }
}; };
onMounted(() => {
if (modeType !== 'add') {
formState.value = {
name: props.data.name,
description: props.data?.description || '',
};
}
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -138,7 +138,7 @@
<div> <div>
<a-form <a-form
ref="formRef" ref="formRef"
:model="form" :model="formData"
layout="vertical" layout="vertical"
> >
<a-form-item <a-form-item
@ -146,7 +146,7 @@
v-bind="validateInfos.name" v-bind="validateInfos.name"
> >
<a-input <a-input
v-model:value="form.name" v-model:value="formData.name"
allowClear allowClear
placeholder="请输入名称" placeholder="请输入名称"
/> />
@ -158,7 +158,7 @@
<a-textarea <a-textarea
placeholder="请输入说明" placeholder="请输入说明"
:rows="4" :rows="4"
v-model:value="form.description" v-model:value="formData.description"
show-count show-count
:maxlength="200" :maxlength="200"
/> />
@ -295,13 +295,26 @@
</div> </div>
</div> </div>
<div class="steps-action"> <div class="steps-action">
<a-button v-if="[0, 1].includes(current)" @click="next"> <a-button
v-if="[0, 1].includes(current)"
type="primary"
style="margin-right: 8px"
@click="next"
>
下一步 下一步
</a-button> </a-button>
<a-button v-if="current === 2" type="primary" @click="saveData"> <a-button
v-if="current === 2 && modeType !== 'view'"
type="primary"
style="margin-right: 8px"
@click="saveData"
>
保存 保存
</a-button> </a-button>
<a-button v-if="current > 0" style="margin-left: 8px" @click="prev"> <a-button
v-if="type === 'child-device' ? current > 1 : current > 0"
@click="prev"
>
上一步 上一步
</a-button> </a-button>
</div> </div>
@ -524,7 +537,204 @@ const result2 = {
'### 认证说明\r\n\r\nCONNECT报文:\r\n```text\r\nclientId: 设备ID\r\nusername: secureId+"|"+timestamp\r\npassword: md5(secureId+"|"+timestamp+"|"+secureKey)\r\n ```\r\n\r\n说明: secureId以及secureKey在创建设备产品或设备实例时进行配置. \r\ntimestamp为当前时间戳(毫秒),与服务器时间不能相差5分钟.\r\nmd5为32位,不区分大小写.', '### 认证说明\r\n\r\nCONNECT报文:\r\n```text\r\nclientId: 设备ID\r\nusername: secureId+"|"+timestamp\r\npassword: md5(secureId+"|"+timestamp+"|"+secureKey)\r\n ```\r\n\r\n说明: secureId以及secureKey在创建设备产品或设备实例时进行配置. \r\ntimestamp为当前时间戳(毫秒),与服务器时间不能相差5分钟.\r\nmd5为32位,不区分大小写.',
metadata: '', metadata: '',
}; };
//
const networkData = {
COAP_SERVER: [
{
id: '1620352949679960064',
name: '前端测试1',
description: '前端测试1',
addresses: [
{
address: 'coap://111.0.0:88',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1613071630619607040',
name: '1',
addresses: [
{
address: 'coap://120.77.179.54:9000',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
],
UDP: [
{
id: '1590553821093437440',
name: '194',
addresses: [
{
address: 'udp://139.217.130.194:1883',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1585831257204301824',
name: '测试隐藏集群',
description: '111',
addresses: [
{
address: 'udp://127.0.0.1:8080',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1584825665263149056',
name: '1',
addresses: [
{
address: 'udp://120.77.179.54:9000',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
{
id: '1551761481741672448',
name: '0726UDP',
description: '测试',
addresses: [
{
address: 'udp://120.77.179.54:8088',
health: 1,
ok: true,
bad: false,
disabled: false,
},
],
},
],
TCP_SERVER: [
{
id: '1603206069979918336',
name: '测试A',
addresses: [
{
address: 'tcp://120.77.179.54:8106',
health: -1,
ok: false,
bad: false,
disabled: true,
},
],
},
{
id: '1603206069979918330',
name: '测试AA',
addresses: [
{
address: 'tcp://120.77.179.54:8106',
health: -1,
ok: false,
bad: false,
disabled: true,
},
],
},
],
MQTT_SERVER: [
{
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,
},
],
},
],
};
function generateUUID() { function generateUUID() {
var d = new Date().getTime(); var d = new Date().getTime();
if ( if (
@ -555,6 +765,10 @@ const props = defineProps({
}); });
const clientHeight = document.body.clientHeight; const clientHeight = document.body.clientHeight;
const type = props.provider.channel;
const route = useRoute();
const modeType = route.params.type as string;
const id = route.params.id as string;
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const useForm = Form.useForm; const useForm = Form.useForm;
@ -569,29 +783,40 @@ const networkCurrent = ref('');
const procotolCurrent = ref(''); const procotolCurrent = ref('');
let config = ref({}); let config = ref({});
let columnsMQTT = ref(<TableColumnType>[]); let columnsMQTT = ref(<TableColumnType>[]);
const form = reactive({ const formData = ref({
name: '', name: '',
description: '', description: '',
}); });
const { resetFields, validate, validateInfos } = useForm( const { resetFields, validate, validateInfos } = useForm(
form, formData,
reactive({ reactive({
name: [ name: [
{ required: true, message: '请输入名称', trigger: 'blur' }, { required: true, message: '请输入名称', trigger: 'blur' },
{ max: 64, message: '最多可输入64个字符' }, { max: 64, message: '最多可输入64个字符' },
], ],
description: [{ max: 200, message: '最多可输入200个字符' }],
}), }),
); );
const queryNetworkList = async (id: string, include: string, data = {}) => { const queryNetworkList = async (id: string, include: string, data = {}) => {
if (NetworkTypeMapping.get(id) === 'MQTT_SERVER') {
//使
networkList.value = networkData[NetworkTypeMapping.get(id)];
// return;
}
const resp = await getNetworkList( const resp = await getNetworkList(
NetworkTypeMapping.get(id), NetworkTypeMapping.get(id),
include, include,
data, data,
); );
if (resp.status === 200) { if (resp.status === 200) {
networkList.value = resp.result; //使
// networkList.value = resp.result;
networkList.value =
resp.result.length === 0
? networkData[NetworkTypeMapping.get(id)]
: resp.result;
} }
}; };
@ -686,7 +911,7 @@ const saveData = () => {
channel: 'network', // channel: 'network', //
channelId: networkCurrent.value, channelId: networkCurrent.value,
}; };
if (props.data && props.data.id) { if (!!id && modeType !== 'add') {
resp = await update(params); resp = await update(params);
} else { } else {
params = { params = {
@ -702,12 +927,13 @@ const saveData = () => {
if (resp.status === 200) { if (resp.status === 200) {
message.success('操作成功!'); message.success('操作成功!');
// //
if (window.onTabSaveSuccess) { // if (window.onTabSaveSuccess) {
window.onTabSaveSuccess(resp); // window.onTabSaveSuccess(resp);
setTimeout(() => window.close(), 300); // setTimeout(() => window.close(), 300);
} else { // } else {
// this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] }) // // this.$store.dispatch('jumpPathByKey', { key: MenuKeys['Link/AccessConfig'] })
} // }
history.back();
} }
}) })
.catch((err) => {}); .catch((err) => {});
@ -781,7 +1007,7 @@ const next = async () => {
]; ];
// const resp = // const resp =
// props.provider.channel !== 'child-device' // type !== 'child-device'
// ? await getConfigView( // ? await getConfigView(
// procotolCurrent.value, // procotolCurrent.value,
// ProtocolMapping.get(props.provider.id), // ProtocolMapping.get(props.provider.id),
@ -864,7 +1090,7 @@ onMounted(() => {
} }
} else { } else {
if (props.provider?.id) { if (props.provider?.id) {
if (props.provider.channel !== 'child-device') { if (type !== 'child-device') {
queryNetworkList(props.provider.id, ''); queryNetworkList(props.provider.id, '');
steps.value = ['网络组件', '消息协议', '完成']; steps.value = ['网络组件', '消息协议', '完成'];
current.value = 0; current.value = 0;
@ -877,14 +1103,20 @@ onMounted(() => {
} }
}); });
onMounted(() => {
if (modeType !== 'add') {
procotolCurrent.value = props.data.protocol;
formData.value = {
name: props.data.name,
description: props.data.description,
};
}
});
watch( watch(
current, current,
(v) => { (v) => {
if (props.provider.channel !== 'child-device') { stepCurrent.value = type === 'child-device' ? v - 1 : v;
stepCurrent.value = v;
} else {
stepCurrent.value = v - 1;
}
}, },
{ {
deep: true, deep: true,

View File

@ -44,8 +44,13 @@
</template> </template>
<template #content> <template #content>
<div class="card-item-content"> <div class="card-item-content">
<h3 class="card-item-content-title"> <h3
<a href="">{{ slotProps.name }}</a> @click="handlEye(slotProps.id)"
class="card-item-content-title"
>
<a class="card-item-content-title-a">{{
slotProps.name
}}</a>
</h3> </h3>
<a-row class="card-item-content-box"> <a-row class="card-item-content-box">
<a-col <a-col
@ -110,19 +115,23 @@
<a-tooltip> <a-tooltip>
<template #title> <template #title>
{{ {{
providersList.find( slotProps.description
(item) => ? slotProps.description
item.id === : providersList.find(
slotProps.provider, (item) =>
)?.description item.id ===
}}</template slotProps.provider,
> )?.description
}}
</template>
{{ {{
providersList.find( slotProps.description
(item) => ? slotProps.description
item.id === : providersList.find(
slotProps.provider, (item) =>
)?.description item.id ===
slotProps.provider,
)?.description
}} }}
</a-tooltip> </a-tooltip>
</div> </div>
@ -184,7 +193,13 @@
<script lang="ts" setup name="AccessConfigPage"> <script lang="ts" setup name="AccessConfigPage">
import type { ActionsType } from '@/components/Table/index.vue'; import type { ActionsType } from '@/components/Table/index.vue';
import { getImage } from '@/utils/comm'; import { getImage } from '@/utils/comm';
import { list, getProviders } from '@/api/link/accessConfig'; import {
list,
getProviders,
remove,
undeploy,
deploy,
} from '@/api/link/accessConfig';
import { message } from 'ant-design-vue'; import { message } from 'ant-design-vue';
const tableRef = ref<Record<string, any>>({}); const tableRef = ref<Record<string, any>>({});
@ -261,9 +276,8 @@ const columns = [
]; ];
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => { const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
if (!data) { if (!data) return [];
return []; const state = data.state.value;
}
return [ return [
{ {
key: 'edit', key: 'edit',
@ -276,15 +290,47 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
handlEdit(data.id); handlEdit(data.id);
}, },
}, },
{
key: 'action',
text: state === 'enabled' ? '禁用' : '启用',
tooltip: {
title: state === 'enabled' ? '禁用' : '启用',
},
icon: state === 'enabled' ? 'StopOutlined' : 'CheckCircleOutlined',
popConfirm: {
title: `确认${state === 'enabled' ? '禁用' : '启用'}?`,
onConfirm: async () => {
let res =
state === 'enabled'
? await undeploy(data.id)
: await deploy(data.id);
if (res.success) {
message.success('操作成功');
tableRef.value?.reload();
} else {
message.error('操作失败!');
}
},
},
},
{ {
key: 'delete', key: 'delete',
text: '删除', text: '删除',
disabled: state === 'enabled',
tooltip: {
title: state === 'enabled' ? '已启用的设备不能删除' : '删除',
},
popConfirm: { popConfirm: {
title: '确认删除?', title: '确认删除?',
okText: ' 确定',
cancelText: '取消',
onConfirm: async () => { onConfirm: async () => {
handlDelete(data.id); const res = await remove(data.id);
if (res.success) {
message.success('操作成功');
tableRef.value.reload();
} else {
message.error('操作失败!');
}
}, },
}, },
icon: 'DeleteOutlined', icon: 'DeleteOutlined',
@ -299,21 +345,13 @@ const getProvidersList = async () => {
getProvidersList(); getProvidersList();
const handlAdd = () => { const handlAdd = () => {
router.push('/link/accessConfig/detail/add'); router.push('/link/accessConfig/detail/add/new');
// router.push('/link/certificate/detail/add/new');
}; };
const handlEdit = (id: string) => { const handlEdit = (id: string) => {
router.push(`/link/certificate/detail/edit/${id}`); router.push(`/link/accessConfig/detail/edit/${id}`);
}; };
const handlEye = (id: string) => {
const handlDelete = async (id: string) => { router.push(`/link/accessConfig/detail/view/${id}`);
const res = await remove(id);
if (res.success) {
message.success('操作成功');
tableRef.value.reload();
}
}; };
/** /**
@ -356,6 +394,14 @@ const handleSearch = (e: any) => {
.card-item-content { .card-item-content {
min-height: 100px; min-height: 100px;
.card-item-content-title-a {
// color: #000 !important;
font-weight: 700;
font-size: 18px;
overflow: hidden; //
text-overflow: ellipsis; //
white-space: nowrap; //
}
.card-item-content-box { .card-item-content-box {
min-height: 50px; min-height: 50px;
} }

View File

@ -60,7 +60,7 @@
<a-form-item> <a-form-item>
<a-button <a-button
v-if="type !== 'view'" v-if="modeType !== 'view'"
class="form-submit" class="form-submit"
html-type="submit" html-type="submit"
type="primary" type="primary"
@ -103,7 +103,7 @@ import { FormDataType, TypeObjType } from '../type';
const router = useRouter(); const router = useRouter();
const route = useRoute(); const route = useRoute();
const type = route.params.type as string; const modeType = route.params.type as string;
const id = route.params.id as string; const id = route.params.id as string;
const useForm = Form.useForm; const useForm = Form.useForm;
@ -145,7 +145,7 @@ const onSubmit = () => {
const params = toRaw(formData.value); const params = toRaw(formData.value);
loading.value = true; loading.value = true;
const response = const response =
type === 'edit' ? await update(params) : await save(params); modeType === 'edit' ? await update(params) : await save(params);
if (response.status === 200) { if (response.status === 200) {
message.success('操作成功'); message.success('操作成功');
router.push('/link/certificate'); router.push('/link/certificate');
@ -168,7 +168,7 @@ const handleChange = (info: UploadChangeParam) => {
}; };
const detail = async (id: string) => { const detail = async (id: string) => {
if (type !== 'add') { if (modeType !== 'add') {
loading.value = true; loading.value = true;
const res = await queryDetail(id); const res = await queryDetail(id);
if (res.success) { if (res.success) {