Merge branch 'dev-hub' into dev
This commit is contained in:
commit
c384fd6f6c
|
@ -0,0 +1,7 @@
|
|||
import server from '@/utils/request';
|
||||
|
||||
export const queryAccess = (data: object) =>
|
||||
server.post(`/logger/access/_query`, data);
|
||||
|
||||
export const querySystem = (data: object) =>
|
||||
server.post(`/logger/system/_query`, data);
|
|
@ -0,0 +1,10 @@
|
|||
import server from '@/utils/request';
|
||||
|
||||
export const detail = (id: string) => server.get(`/gateway/device/${id}`);
|
||||
|
||||
export const save = (data: Object) => server.post(`/gateway/device`, data);
|
||||
|
||||
export const list = (data: Object) =>
|
||||
server.post(`/protocol/_query`, data);
|
||||
|
||||
export const remove = (id: string) => server.remove(`/gateway/device/${id}`);
|
|
@ -76,3 +76,23 @@ export function getSlotVNode<T>(slots: Slots, props: Record<string, unknown>, pr
|
|||
}
|
||||
return (props[prop] || slots[prop]?.()) as T;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改Select参数column的值
|
||||
* @param e // 查询参数 e
|
||||
* @param column {Object} {需要修改的值: 修改后的值}
|
||||
* {
|
||||
username: 'context.username',
|
||||
}
|
||||
*/
|
||||
export const modifySearchColumnValue = (e: any, column: object) => {
|
||||
e.terms.forEach((item: any) => {
|
||||
item.terms.forEach((t: any) => {
|
||||
if (column[t.column]) {
|
||||
t.column = column[t.column];
|
||||
}
|
||||
});
|
||||
});
|
||||
return e;
|
||||
};
|
|
@ -0,0 +1,255 @@
|
|||
<template>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
<JTable
|
||||
ref="tableRef"
|
||||
model="TABLE"
|
||||
:columns="columns"
|
||||
:request="queryAccess"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'responseTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #requestTime="slotProps">
|
||||
{{
|
||||
moment(slotProps.requestTime).format('YYYY-MM-DD HH:mm:ss')
|
||||
}}
|
||||
</template>
|
||||
<template #responseTime="slotProps">
|
||||
<a-tag color="purple">
|
||||
{{ slotProps.responseTime - slotProps.requestTime }} ms
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #username="slotProps">
|
||||
<a-tag color="geekblue">
|
||||
{{ slotProps.context.userName }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
|
||||
<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>
|
||||
</div>
|
||||
<a-modal
|
||||
:width="1100"
|
||||
v-model:visible="visible"
|
||||
title="详情"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<a-descriptions :data="descriptionsData" title="" bordered :column="2">
|
||||
<a-descriptions-item label="URL">
|
||||
{{ descriptionsData?.url }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求方法">
|
||||
{{ descriptionsData?.httpMethod }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="动作">
|
||||
{{ descriptionsData?.action }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="类名">
|
||||
{{ descriptionsData?.target }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="方法名">
|
||||
{{ descriptionsData?.method }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="IP">
|
||||
{{ descriptionsData?.ip }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求时间">
|
||||
{{
|
||||
moment(descriptionsData?.requestTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求耗时">
|
||||
{{
|
||||
descriptionsData?.responseTime -
|
||||
descriptionsData?.requestTime +
|
||||
'ms'
|
||||
}}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求头" :span="2">
|
||||
{{ descriptionsData?.httpHeaders }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="请求参数" :span="2">
|
||||
{{ descriptionsData?.parameters }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="异常信息" :span="2">
|
||||
<a-textarea
|
||||
v-model:value="descriptionsData.exception"
|
||||
placeholder="暂无数据"
|
||||
:auto-size="{ minRows: 3, maxRows: 20 }"
|
||||
/>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script lang="ts" setup name="AccessLog">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import type { AccessLogItem } from '../typings';
|
||||
import { queryAccess } from '@/api/link/log';
|
||||
import moment from 'moment';
|
||||
|
||||
import { modifySearchColumnValue } from '@/utils/comm';
|
||||
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'IP',
|
||||
dataIndex: 'ip',
|
||||
key: 'ip',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
scopedSlots: true,
|
||||
width: 150,
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: '请求路径',
|
||||
dataIndex: 'url',
|
||||
key: 'url',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
// width: 200,
|
||||
},
|
||||
{
|
||||
title: '请求方法',
|
||||
dataIndex: 'httpMethod',
|
||||
key: 'httpMethod',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: 'POST',
|
||||
value: 'POST',
|
||||
},
|
||||
{
|
||||
label: 'GET',
|
||||
value: 'GET',
|
||||
},
|
||||
{
|
||||
label: 'PATCH',
|
||||
value: 'PATCH',
|
||||
},
|
||||
{
|
||||
label: 'DELETE',
|
||||
value: 'DELETE',
|
||||
},
|
||||
{
|
||||
label: 'PUT',
|
||||
value: 'PUT',
|
||||
},
|
||||
],
|
||||
},
|
||||
scopedSlots: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '请求时间',
|
||||
dataIndex: 'requestTime',
|
||||
key: 'requestTime',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '请求耗时',
|
||||
dataIndex: 'responseTime',
|
||||
key: 'responseTime',
|
||||
scopedSlots: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '请求用户',
|
||||
dataIndex: 'username',
|
||||
key: 'username',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
width: 150,
|
||||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 150,
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const descriptionsData = ref<AccessLogItem>();
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
const handleOk = (e: MouseEvent) => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
key: 'eye',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: (data: AccessLogItem) => {
|
||||
descriptionsData.value = data;
|
||||
visible.value = true;
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const column = {
|
||||
username: 'context.username',
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = modifySearchColumnValue(e, column);
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,246 @@
|
|||
<template>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
<JTable
|
||||
ref="tableRef"
|
||||
model="TABLE"
|
||||
:columns="columns"
|
||||
:request="querySystem"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #level="slotProps">
|
||||
<a-tag
|
||||
:color="
|
||||
slotProps.level === 'WARN'
|
||||
? 'orange'
|
||||
: slotProps.level === 'ERROR'
|
||||
? 'red'
|
||||
: slotProps.level === 'DEBUG'
|
||||
? 'blue'
|
||||
: 'green'
|
||||
"
|
||||
>
|
||||
{{ slotProps.level }}
|
||||
</a-tag>
|
||||
</template>
|
||||
<template #createTime="slotProps">
|
||||
{{ moment(slotProps.createTime).format('YYYY-MM-DD HH:mm:ss') }}
|
||||
</template>
|
||||
<template #server="slotProps">
|
||||
{{ slotProps.context.server }}
|
||||
</template>
|
||||
|
||||
<template #action="slotProps">
|
||||
<a-space :size="16">
|
||||
<a-tooltip
|
||||
v-for="i in getActions(slotProps)"
|
||||
:key="i.key"
|
||||
v-bind="i.tooltip"
|
||||
>
|
||||
<a-popconfirm v-if="i.popConfirm" v-bind="i.popConfirm">
|
||||
<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>
|
||||
</div>
|
||||
<a-modal
|
||||
:width="1100"
|
||||
v-model:visible="visible"
|
||||
title="详情"
|
||||
@ok="handleOk"
|
||||
>
|
||||
<div>
|
||||
<span class="mr-10">[{{ descriptionsData?.threadName }}]</span>
|
||||
<span class="mr-10">{{
|
||||
moment(descriptionsData?.createTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss',
|
||||
)
|
||||
}}</span>
|
||||
<span>{{ descriptionsData?.className }}</span>
|
||||
</div>
|
||||
<div class="mb-10">
|
||||
<a-tag
|
||||
:color="
|
||||
descriptionsData?.level === 'WARN'
|
||||
? 'orange'
|
||||
: descriptionsData?.level === 'ERROR'
|
||||
? 'red'
|
||||
: descriptionsData?.level === 'DEBUG'
|
||||
? 'blue'
|
||||
: 'green'
|
||||
"
|
||||
>
|
||||
{{ descriptionsData?.level }}
|
||||
</a-tag>
|
||||
<span>{{ descriptionsData?.message }}</span>
|
||||
</div>
|
||||
<a-textarea
|
||||
v-model:value="descriptionsData.exceptionStack"
|
||||
placeholder="暂无数据"
|
||||
:auto-size="{ minRows: 24, maxRows: 28 }"
|
||||
/>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script lang="ts" setup name="SystemLog">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import type { SystemLogItem } from '../typings';
|
||||
import { querySystem } from '@/api/link/log';
|
||||
import moment from 'moment';
|
||||
|
||||
import { modifySearchColumnValue } from '@/utils/comm';
|
||||
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
scopedSlots: true,
|
||||
width: 400,
|
||||
fixed: 'left',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '日志级别',
|
||||
dataIndex: 'level',
|
||||
key: 'level',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: 'ERROR',
|
||||
value: 'ERROR',
|
||||
},
|
||||
{
|
||||
label: 'INFO',
|
||||
value: 'INFO',
|
||||
},
|
||||
{
|
||||
label: 'DEBUG',
|
||||
value: 'DEBUG',
|
||||
},
|
||||
{
|
||||
label: 'WARN',
|
||||
value: 'WARN',
|
||||
},
|
||||
],
|
||||
},
|
||||
scopedSlots: true,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '日志内容',
|
||||
dataIndex: 'message',
|
||||
key: 'message',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
scopedSlots: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '服务名',
|
||||
dataIndex: 'server',
|
||||
key: 'server',
|
||||
scopedSlots: true,
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
search: {
|
||||
type: 'date',
|
||||
},
|
||||
scopedSlots: true,
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 150,
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const descriptionsData = ref<SystemLogItem>();
|
||||
const visible = ref<boolean>(false);
|
||||
|
||||
const handleOk = (e: MouseEvent) => {
|
||||
visible.value = false;
|
||||
};
|
||||
|
||||
const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
||||
if (!data) {
|
||||
return [];
|
||||
}
|
||||
return [
|
||||
{
|
||||
key: 'eye',
|
||||
text: '查看',
|
||||
tooltip: {
|
||||
title: '查看',
|
||||
},
|
||||
icon: 'EyeOutlined',
|
||||
onClick: (data: SystemLogItem) => {
|
||||
descriptionsData.value = data;
|
||||
visible.value = true;
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
const column = {
|
||||
server: 'context.server',
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = modifySearchColumnValue(e, column);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.mr-10 {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb-10 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<page-container :tabList="list" @tabChange="onTabChange">
|
||||
<AccessLog v-if="activeKey === '1'" />
|
||||
<SystemLog v-else />
|
||||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="LogPage">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import AccessLog from './Access/index.vue';
|
||||
import SystemLog from './System/index.vue';
|
||||
|
||||
const activeKey = ref('1');
|
||||
|
||||
const list = [
|
||||
{
|
||||
key: '1',
|
||||
tab: '访问日志',
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
tab: '系统日志',
|
||||
},
|
||||
];
|
||||
|
||||
const onTabChange = (e: string) => {
|
||||
activeKey.value = e;
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,31 @@
|
|||
export type AccessLogItem = {
|
||||
id: string;
|
||||
context: any;
|
||||
describe: string;
|
||||
exception: string;
|
||||
httpHeaders: any;
|
||||
httpMethod: string;
|
||||
ip: string;
|
||||
method: string;
|
||||
parameters: any;
|
||||
requestTime: number;
|
||||
responseTime: number;
|
||||
target: string;
|
||||
url: string;
|
||||
action: string;
|
||||
};
|
||||
|
||||
export type SystemLogItem = {
|
||||
id: string;
|
||||
className: string;
|
||||
context: any;
|
||||
createTime: number;
|
||||
exceptionStack: string;
|
||||
level: string;
|
||||
lineNumber: number;
|
||||
message: string;
|
||||
methodName: string;
|
||||
name: string;
|
||||
threadId: string;
|
||||
threadName: string;
|
||||
};
|
|
@ -1,42 +1,44 @@
|
|||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
<a-card :bordered="false">
|
||||
<div v-if="type && modeType === 'add'">
|
||||
<Provider
|
||||
@onClick="goProviders"
|
||||
:dataSource="dataSource"
|
||||
></Provider>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!id"><a @click="goBack">返回</a></div>
|
||||
<AccessNetwork
|
||||
v-if="showType === 'network'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Media
|
||||
v-if="showType === 'media'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Channel
|
||||
v-if="showType === 'channel'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Edge
|
||||
v-if="showType === 'edge'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Cloud
|
||||
v-if="showType === 'cloud'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-spin>
|
||||
<page-container>
|
||||
<a-spin :spinning="loading">
|
||||
<a-card :bordered="false">
|
||||
<div v-if="type && id === ':id'">
|
||||
<Provider
|
||||
@onClick="goProviders"
|
||||
:dataSource="dataSource"
|
||||
></Provider>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="!id"><a @click="goBack">返回</a></div>
|
||||
<AccessNetwork
|
||||
v-if="showType === 'network'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Media
|
||||
v-if="showType === 'media'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Channel
|
||||
v-if="showType === 'channel'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Edge
|
||||
v-if="showType === 'edge'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
<Cloud
|
||||
v-if="showType === 'cloud'"
|
||||
:provider="provider"
|
||||
:data="data"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-spin>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="AccessConfigDetail">
|
||||
|
@ -51,7 +53,7 @@ import Cloud from '../components/Cloud/index.vue';
|
|||
|
||||
const route = useRoute();
|
||||
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const dataSource = ref([]);
|
||||
|
@ -138,7 +140,7 @@ const queryProviders = async () => {
|
|||
};
|
||||
|
||||
const getProvidersData = async () => {
|
||||
if (id && modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
getProviders().then((response) => {
|
||||
if (response.status === 200) {
|
||||
const list = getTypeList(response.result);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
v-if="modeType !== 'view'"
|
||||
v-if="view === 'false'"
|
||||
type="primary"
|
||||
html-type="submit"
|
||||
>保存</a-button
|
||||
|
@ -96,7 +96,7 @@ interface FormState {
|
|||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -126,9 +126,7 @@ const onFinish = async (values: any) => {
|
|||
channel: providerId === 'modbus-tcp' ? 'modbus' : 'opc-ua',
|
||||
};
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({ ...params, id })
|
||||
: await save(params);
|
||||
id === ':id' ? await save(params) : await update({ ...params, id });
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
|
@ -145,7 +143,7 @@ const onFinish = async (values: any) => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (modeType !== 'add') {
|
||||
if (id === ':id') {
|
||||
formState.value = {
|
||||
name: props.data.name,
|
||||
description: props.data?.description || '',
|
||||
|
|
|
@ -283,7 +283,7 @@
|
|||
下一步
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="current === 2 && modeType !== 'view'"
|
||||
v-if="current === 2 && view === 'false'"
|
||||
type="primary"
|
||||
style="margin-right: 8px"
|
||||
@click="saveData"
|
||||
|
@ -383,7 +383,7 @@ interface Form {
|
|||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -450,13 +450,13 @@ const saveData = async () => {
|
|||
transport: 'HTTP_SERVER',
|
||||
};
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({
|
||||
id === ':id'
|
||||
? await save(params)
|
||||
: await update({
|
||||
...props.data,
|
||||
...params,
|
||||
})
|
||||
: await save(params);
|
||||
|
||||
id,
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// 回到列表页面
|
||||
|
@ -489,7 +489,7 @@ const queryProcotolList = async (id: string, params = {}) => {
|
|||
|
||||
const addProcotol = () => {
|
||||
// const url = this.$store.state.permission.routes['Link/Protocol']
|
||||
const url = '/demo';
|
||||
const url = '/iot/link/protocol';
|
||||
const tab = window.open(
|
||||
`${window.location.origin + window.location.pathname}#${url}?save=true`,
|
||||
);
|
||||
|
@ -518,7 +518,7 @@ const prev = () => {
|
|||
current.value = current.value - 1;
|
||||
};
|
||||
onMounted(() => {
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
formState.value = props.data.configuration;
|
||||
procotolCurrent.value = props.data.protocol;
|
||||
formData.value = {
|
||||
|
|
|
@ -377,7 +377,7 @@
|
|||
</a-button>
|
||||
<a-button
|
||||
style="margin-right: 8px"
|
||||
v-if="current === 2 && modeType !== 'view'"
|
||||
v-if="current === 2 && view === 'false'"
|
||||
type="primary"
|
||||
@click="saveData"
|
||||
>
|
||||
|
@ -479,7 +479,7 @@ interface Form {
|
|||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -547,12 +547,13 @@ const saveData = async () => {
|
|||
transport: 'HTTP_SERVER',
|
||||
};
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({
|
||||
id === ':id'
|
||||
? await save(params)
|
||||
: await update({
|
||||
...props.data,
|
||||
...params,
|
||||
})
|
||||
: await save(params);
|
||||
id,
|
||||
});
|
||||
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
|
@ -585,7 +586,7 @@ const queryProcotolList = async (id: string, params = {}) => {
|
|||
|
||||
const addProcotol = () => {
|
||||
// const url = this.$store.state.permission.routes['Link/Protocol']
|
||||
const url = '/demo';
|
||||
const url = '/iot/link/protocol';
|
||||
const tab = window.open(
|
||||
`${window.location.origin + window.location.pathname}#${url}?save=true`,
|
||||
);
|
||||
|
@ -615,7 +616,7 @@ const prev = () => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
formState.value = props.data.configuration;
|
||||
procotolCurrent.value = props.data.protocol;
|
||||
formData.value = {
|
||||
|
|
|
@ -140,7 +140,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
v-if="current !== 1 && modeType !== 'view'"
|
||||
v-if="current !== 1 && view === 'false'"
|
||||
type="primary"
|
||||
html-type="submit"
|
||||
>保存</a-button
|
||||
|
@ -179,7 +179,7 @@
|
|||
下一步
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="current === 1 && modeType !== 'view'"
|
||||
v-if="current === 1 && view === 'false'"
|
||||
type="primary"
|
||||
style="margin-right: 8px"
|
||||
@click="saveData"
|
||||
|
@ -297,7 +297,7 @@ interface FormState {
|
|||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -338,9 +338,7 @@ const onFinish = async (values: any) => {
|
|||
};
|
||||
if (networkCurrent.value) params.channelId = networkCurrent.value;
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({ ...params, id })
|
||||
: await save(params);
|
||||
id === ':id' ? await save(params) : await update({ ...params, id });
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
|
@ -392,7 +390,7 @@ const saveData = async () => {
|
|||
|
||||
const addNetwork = () => {
|
||||
// const url = this.$store.state.permission.routes['Link/Type/Detail']
|
||||
const url = '/demo';
|
||||
const url = '/iot/link/type/detail/:id';
|
||||
const tab = window.open(
|
||||
`${window.location.origin + window.location.pathname}#${url}?type=${
|
||||
NetworkTypeMapping.get(props.provider?.id) || ''
|
||||
|
@ -421,7 +419,7 @@ onMounted(() => {
|
|||
if (props.provider.id === 'official-edge-gateway') {
|
||||
queryNetworkList(props.provider.id, '');
|
||||
}
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
formState.value = {
|
||||
name: props.data.name,
|
||||
description: props.data?.description || '',
|
||||
|
|
|
@ -503,7 +503,7 @@
|
|||
下一步
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="current === 1 && modeType !== 'view'"
|
||||
v-if="current === 1 && view === 'false'"
|
||||
type="primary"
|
||||
style="margin-right: 8px"
|
||||
@click="saveData"
|
||||
|
@ -559,7 +559,7 @@ const props = defineProps({
|
|||
});
|
||||
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const activeKey: any = ref([]);
|
||||
|
@ -663,9 +663,7 @@ const saveData = () => {
|
|||
};
|
||||
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({ ...params, id })
|
||||
: await save(params);
|
||||
id === ':id' ? await save(params) : await update({ ...params, id });
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
|
@ -741,7 +739,7 @@ onMounted(() => {
|
|||
}
|
||||
});
|
||||
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
formState.value = props.data.configuration;
|
||||
formData.value = {
|
||||
name: props.data.name,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button
|
||||
v-if="modeType !== 'view'"
|
||||
v-if="view === 'false'"
|
||||
type="primary"
|
||||
html-type="submit"
|
||||
>保存</a-button
|
||||
|
@ -91,7 +91,7 @@ interface FormState {
|
|||
description: string;
|
||||
}
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const props = defineProps({
|
||||
|
@ -119,9 +119,7 @@ const onFinish = async (values: any) => {
|
|||
channel: 'fixed-media',
|
||||
};
|
||||
const resp =
|
||||
!!id && modeType !== 'add'
|
||||
? await update({ ...params, id })
|
||||
: await save(params);
|
||||
id === ':id' ? await save(params) : await update({ ...params, id });
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// if (params.get('save')) {
|
||||
|
@ -138,7 +136,7 @@ const onFinish = async (values: any) => {
|
|||
};
|
||||
|
||||
onMounted(() => {
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
formState.value = {
|
||||
name: props.data.name,
|
||||
description: props.data?.description || '',
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div style="margin-top: 10px">
|
||||
<div>
|
||||
<a-steps :current="stepCurrent">
|
||||
<a-step v-for="item in steps" :key="item" :title="item" />
|
||||
</a-steps>
|
||||
|
@ -304,7 +304,7 @@
|
|||
下一步
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="current === 2 && modeType !== 'view'"
|
||||
v-if="current === 2 && view === 'false'"
|
||||
type="primary"
|
||||
style="margin-right: 8px"
|
||||
@click="saveData"
|
||||
|
@ -767,7 +767,7 @@ const props = defineProps({
|
|||
const clientHeight = document.body.clientHeight;
|
||||
const type = props.provider.channel;
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
@ -839,7 +839,7 @@ const queryProcotolList = async (id: string, params = {}) => {
|
|||
|
||||
const addNetwork = () => {
|
||||
// const url = this.$store.state.permission.routes['Link/Type/Detail']
|
||||
const url = '/demo';
|
||||
const url = '/iot/link/type/detail/:id';
|
||||
const tab = window.open(
|
||||
`${window.location.origin + window.location.pathname}#${url}?type=${
|
||||
NetworkTypeMapping.get(props.provider?.id) || ''
|
||||
|
@ -854,7 +854,7 @@ const addNetwork = () => {
|
|||
};
|
||||
const addProcotol = () => {
|
||||
// const url = this.$store.state.permission.routes['Link/Protocol']
|
||||
const url = '/demo';
|
||||
const url = '/iot/link/protocol';
|
||||
const tab = window.open(
|
||||
`${window.location.origin + window.location.pathname}#${url}?save=true`,
|
||||
);
|
||||
|
@ -903,27 +903,25 @@ const procotolSearch = (value: string) => {
|
|||
const saveData = () => {
|
||||
validate()
|
||||
.then(async (values) => {
|
||||
let resp = undefined;
|
||||
let params = {
|
||||
const params = {
|
||||
...props.data,
|
||||
...values,
|
||||
protocol: procotolCurrent.value,
|
||||
channel: 'network', // 网络组件
|
||||
channelId: networkCurrent.value,
|
||||
};
|
||||
if (!!id && modeType !== 'add') {
|
||||
resp = await update(params);
|
||||
} else {
|
||||
params = {
|
||||
...params,
|
||||
provider: props.provider.id,
|
||||
transport:
|
||||
props.provider?.id === 'child-device'
|
||||
? 'Gateway'
|
||||
: ProtocolMapping.get(props.provider.id),
|
||||
};
|
||||
resp = await save(params);
|
||||
}
|
||||
const resp =
|
||||
id === ':id'
|
||||
? await save(params)
|
||||
: await update({
|
||||
...params,
|
||||
id,
|
||||
provider: props.provider.id,
|
||||
transport:
|
||||
props.provider?.id === 'child-device'
|
||||
? 'Gateway'
|
||||
: ProtocolMapping.get(props.provider.id),
|
||||
});
|
||||
if (resp.status === 200) {
|
||||
message.success('操作成功!');
|
||||
// 回到列表页面
|
||||
|
@ -1104,7 +1102,7 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
onMounted(() => {
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
procotolCurrent.value = props.data.protocol;
|
||||
formData.value = {
|
||||
name: props.data.name,
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<div class="page-container">
|
||||
<a-card style="margin-bottom: 20px">
|
||||
<page-container>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
</a-card>
|
||||
<a-card>
|
||||
|
||||
<JTable
|
||||
ref="tableRef"
|
||||
model="CARD"
|
||||
|
@ -187,8 +186,8 @@
|
|||
/>
|
||||
</template>
|
||||
</JTable>
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="AccessConfigPage">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
|
@ -345,13 +344,25 @@ const getProvidersList = async () => {
|
|||
getProvidersList();
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push('/link/accessConfig/detail/add/new');
|
||||
// router.push('/link/accessConfig/detail/add/new');
|
||||
router.push({
|
||||
path: `/iot/link/accessConfig/detail/:id`,
|
||||
query: { view: false },
|
||||
});
|
||||
};
|
||||
const handlEdit = (id: string) => {
|
||||
router.push(`/link/accessConfig/detail/edit/${id}`);
|
||||
// router.push(`/link/accessConfig/detail/edit/${id}`);
|
||||
router.push({
|
||||
path: `/iot/link/accessConfig/detail/${id}`,
|
||||
query: { view: false },
|
||||
});
|
||||
};
|
||||
const handlEye = (id: string) => {
|
||||
router.push(`/link/accessConfig/detail/view/${id}`);
|
||||
// router.push(`/link/accessConfig/detail/view/${id}`);
|
||||
router.push({
|
||||
path: `/iot/link/accessConfig/detail/${id}`,
|
||||
query: { view: true },
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -375,10 +386,6 @@ const handleSearch = (e: any) => {
|
|||
// }
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.page-container {
|
||||
background: #f0f2f5;
|
||||
padding: 24px;
|
||||
}
|
||||
.tableCardDisabled {
|
||||
width: 100%;
|
||||
background: url('/images/access-config-diaabled.png') no-repeat;
|
||||
|
|
|
@ -1,96 +1,104 @@
|
|||
<template>
|
||||
<a-card>
|
||||
<a-row :gutter="[24, 24]" style="padding: 24px">
|
||||
<a-col :span="12">
|
||||
<a-form
|
||||
class="form"
|
||||
layout="vertical"
|
||||
:model="formData"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
>
|
||||
<a-form-item label="证书标准" v-bind="validateInfos.type">
|
||||
<a-radio-group v-model:value="formData.type">
|
||||
<a-radio-button
|
||||
class="form-radio-button"
|
||||
value="common"
|
||||
>
|
||||
<img :src="getImage('/certificate.png')" />
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item label="证书名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
placeholder="请输入证书名称"
|
||||
v-model:value="formData.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="证书文件"
|
||||
v-bind="validateInfos['configs.cert']"
|
||||
<page-container>
|
||||
<a-card>
|
||||
<a-row :gutter="[24, 24]" style="padding: 24px">
|
||||
<a-col :span="12">
|
||||
<a-form
|
||||
class="form"
|
||||
layout="vertical"
|
||||
:model="formData"
|
||||
name="basic"
|
||||
:label-col="{ span: 8 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
autocomplete="off"
|
||||
>
|
||||
<CertificateFile
|
||||
name="cert"
|
||||
v-model:modelValue="formData.configs.cert"
|
||||
placeholder='证书格式以"-----BEGIN CERTIFICATE-----"开头,以"-----END CERTIFICATE-----"结尾"'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="证书私钥"
|
||||
v-bind="validateInfos['configs.key']"
|
||||
>
|
||||
<CertificateFile
|
||||
name="key"
|
||||
v-model:modelValue="formData.configs.key"
|
||||
placeholder='证书私钥格式以"-----BEGIN (RSA|EC) PRIVATE KEY-----"开头,以"-----END(RSA|EC) PRIVATE KEY-----"结尾。'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="description">
|
||||
<a-textarea
|
||||
placeholder="请输入说明"
|
||||
v-model:value="formData.description"
|
||||
:maxlength="200"
|
||||
:rows="3"
|
||||
showCount
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button
|
||||
v-if="modeType !== 'view'"
|
||||
class="form-submit"
|
||||
html-type="submit"
|
||||
type="primary"
|
||||
@click.prevent="onSubmit"
|
||||
:loading="loading"
|
||||
>保存</a-button
|
||||
<a-form-item
|
||||
label="证书标准"
|
||||
v-bind="validateInfos.type"
|
||||
>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="doc">
|
||||
<h1>1. 概述</h1>
|
||||
<div>
|
||||
证书由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能,保障设备与平台间的数据传输安全。配置后可被网络组件引用。
|
||||
<a-radio-group v-model:value="formData.type">
|
||||
<a-radio-button
|
||||
class="form-radio-button"
|
||||
value="common"
|
||||
>
|
||||
<img :src="getImage('/certificate.png')" />
|
||||
</a-radio-button>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item
|
||||
label="证书名称"
|
||||
v-bind="validateInfos.name"
|
||||
>
|
||||
<a-input
|
||||
placeholder="请输入证书名称"
|
||||
v-model:value="formData.name"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="证书文件"
|
||||
v-bind="validateInfos['configs.cert']"
|
||||
>
|
||||
<CertificateFile
|
||||
name="cert"
|
||||
v-model:modelValue="formData.configs.cert"
|
||||
placeholder='证书格式以"-----BEGIN CERTIFICATE-----"开头,以"-----END CERTIFICATE-----"结尾"'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="证书私钥"
|
||||
v-bind="validateInfos['configs.key']"
|
||||
>
|
||||
<CertificateFile
|
||||
name="key"
|
||||
v-model:modelValue="formData.configs.key"
|
||||
placeholder='证书私钥格式以"-----BEGIN (RSA|EC) PRIVATE KEY-----"开头,以"-----END(RSA|EC) PRIVATE KEY-----"结尾。'
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="说明" name="description">
|
||||
<a-textarea
|
||||
placeholder="请输入说明"
|
||||
v-model:value="formData.description"
|
||||
:maxlength="200"
|
||||
:rows="3"
|
||||
showCount
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
<a-form-item>
|
||||
<a-button
|
||||
v-if="view === 'false'"
|
||||
class="form-submit"
|
||||
html-type="submit"
|
||||
type="primary"
|
||||
@click.prevent="onSubmit"
|
||||
:loading="loading"
|
||||
>保存</a-button
|
||||
>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="doc">
|
||||
<h1>1. 概述</h1>
|
||||
<div>
|
||||
证书由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能,保障设备与平台间的数据传输安全。配置后可被网络组件引用。
|
||||
</div>
|
||||
<h1>2. 配置说明</h1>
|
||||
<h2>1、证书文件</h2>
|
||||
<div>
|
||||
您可以使用文本编辑工具打开PEM或者CRT格式的证书文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传,并选择存储在本地计算机的证书文件,将文件内容上传到文本框。
|
||||
</div>
|
||||
<h2>2、证书私钥</h2>
|
||||
<div>
|
||||
填写证书私钥内容的PEM编码。
|
||||
您可以使用文本编辑工具打开KEY格式的证书私钥文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传并选择存储在本地计算机的证书私钥文件,将文件内容上传到文本框。
|
||||
</div>
|
||||
</div>
|
||||
<h1>2. 配置说明</h1>
|
||||
<h2>1、证书文件</h2>
|
||||
<div>
|
||||
您可以使用文本编辑工具打开PEM或者CRT格式的证书文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传,并选择存储在本地计算机的证书文件,将文件内容上传到文本框。
|
||||
</div>
|
||||
<h2>2、证书私钥</h2>
|
||||
<div>
|
||||
填写证书私钥内容的PEM编码。
|
||||
您可以使用文本编辑工具打开KEY格式的证书私钥文件,复制其中的内容并粘贴到该文本框,或者单击该文本框下的上传并选择存储在本地计算机的证书私钥文件,将文件内容上传到文本框。
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="CertificateDetail">
|
||||
|
@ -103,7 +111,7 @@ import { FormDataType, TypeObjType } from '../type';
|
|||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const modeType = route.params.type as string;
|
||||
const view = route.query.view as string;
|
||||
const id = route.params.id as string;
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
@ -145,10 +153,12 @@ const onSubmit = () => {
|
|||
const params = toRaw(formData.value);
|
||||
loading.value = true;
|
||||
const response =
|
||||
modeType === 'edit' ? await update(params) : await save(params);
|
||||
id === ':id'
|
||||
? await save(params)
|
||||
: await update({ ...params, id });
|
||||
if (response.status === 200) {
|
||||
message.success('操作成功');
|
||||
router.push('/link/certificate');
|
||||
router.push('/iot/link/certificate');
|
||||
}
|
||||
loading.value = false;
|
||||
})
|
||||
|
@ -168,7 +178,7 @@ const handleChange = (info: UploadChangeParam) => {
|
|||
};
|
||||
|
||||
const detail = async (id: string) => {
|
||||
if (modeType !== 'add') {
|
||||
if (id !== ':id') {
|
||||
loading.value = true;
|
||||
const res = await queryDetail(id);
|
||||
if (res.success) {
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<template>
|
||||
<div class="page-container">
|
||||
<a-card style="margin-bottom: 20px">
|
||||
<Search
|
||||
:columns="columns"
|
||||
target="search"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
</a-card>
|
||||
<a-card>
|
||||
<page-container>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
<JTable
|
||||
ref="tableRef"
|
||||
model="TABLE"
|
||||
|
@ -61,8 +55,8 @@
|
|||
</a-space>
|
||||
</template>
|
||||
</JTable>
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="CertificatePage">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
|
@ -158,15 +152,24 @@ const getActions = (data: Partial<Record<string, any>>): ActionsType[] => {
|
|||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
router.push('/link/certificate/detail/add/new');
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/:id`,
|
||||
query: { view: false },
|
||||
});
|
||||
};
|
||||
|
||||
const handlEye = (id: string) => {
|
||||
router.push(`/link/certificate/detail/view/${id}`);
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/${id}`,
|
||||
query: { view: true },
|
||||
});
|
||||
};
|
||||
|
||||
const handlEdit = (id: string) => {
|
||||
router.push(`/link/certificate/detail/edit/${id}`);
|
||||
router.push({
|
||||
path: `/iot/link/certificate/detail/${id}`,
|
||||
query: { view: false },
|
||||
});
|
||||
};
|
||||
|
||||
const handlDelete = async (id: string) => {
|
||||
|
@ -182,15 +185,8 @@ const handlDelete = async (id: string) => {
|
|||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
console.log(1211, e);
|
||||
|
||||
params.value = e;
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.page-container {
|
||||
background: #f0f2f5;
|
||||
padding: 24px;
|
||||
}
|
||||
</style>
|
||||
<style lang="less" scoped></style>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<template>
|
||||
<div>访问日志</div>
|
||||
</template>
|
||||
<script lang="ts" setup name="SystemLog">
|
||||
|
||||
</script>
|
|
@ -1,6 +0,0 @@
|
|||
<template>
|
||||
<div>系统日志</div>
|
||||
</template>
|
||||
<script lang="ts" setup name="AccessLog">
|
||||
|
||||
</script>
|
|
@ -1,17 +0,0 @@
|
|||
<template>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="访问日志">
|
||||
<AccessLog />
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="系统日志" force-render>
|
||||
<SystemLog />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</template>
|
||||
<script lang="ts" setup name="LogPage">
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import AccessLog from './Access/index.vue';
|
||||
import SystemLog from './System/index.vue';
|
||||
|
||||
const activeKey = ref('1');
|
||||
</script>
|
|
@ -0,0 +1,37 @@
|
|||
<template lang="">
|
||||
<a-modal
|
||||
:title="data.id ? '编辑' : '新增'"
|
||||
ok-text="确认"
|
||||
cancel-text="取消"
|
||||
:visible="true"
|
||||
width="600px"
|
||||
:confirm-loading="loading"
|
||||
@cancel="handleCancel"
|
||||
@ok="handleOk"
|
||||
>
|
||||
123
|
||||
</a-modal>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
const loading = ref(false);
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
const handleOk = () => {
|
||||
console.log(2);
|
||||
emit('change', true);
|
||||
};
|
||||
const handleCancel = () => {
|
||||
console.log(1);
|
||||
emit('change', false);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang=""></style>
|
|
@ -0,0 +1,327 @@
|
|||
<template>
|
||||
<page-container>
|
||||
<div>
|
||||
<Search :columns="columns" target="search" @search="handleSearch" />
|
||||
|
||||
<JTable
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:request="list"
|
||||
:defaultParams="{
|
||||
sorts: [{ name: 'createTime', order: 'desc' }],
|
||||
}"
|
||||
:params="params"
|
||||
>
|
||||
<template #headerTitle>
|
||||
<a-button type="primary" @click="handlAdd"
|
||||
><plus-outlined />新增</a-button
|
||||
>
|
||||
</template>
|
||||
<template #card="slotProps">
|
||||
<CardBox
|
||||
:showStatus="false"
|
||||
:value="slotProps"
|
||||
:actions="getActions(slotProps, 'card')"
|
||||
v-bind="slotProps"
|
||||
>
|
||||
<template #img>
|
||||
<slot name="img">
|
||||
<img :src="getImage('/device-access.png')" />
|
||||
</slot>
|
||||
</template>
|
||||
<template #content>
|
||||
<div class="card-item-content">
|
||||
<h3 class="card-item-content-title-a">
|
||||
{{ slotProps.name }}
|
||||
</h3>
|
||||
<a-row class="card-item-content-box">
|
||||
<a-col
|
||||
:span="12"
|
||||
class="card-item-content-text"
|
||||
>
|
||||
<div class="card-item-content-text">
|
||||
ID
|
||||
</div>
|
||||
<div class="card-item-content-text">
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.id
|
||||
}}</template>
|
||||
{{ slotProps.id }}
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<div class="card-item-content-text">
|
||||
类型
|
||||
</div>
|
||||
<div class="card-item-content-text">
|
||||
<a-tooltip>
|
||||
<template #title>{{
|
||||
slotProps.type
|
||||
}}</template>
|
||||
{{ slotProps.type }}
|
||||
</a-tooltip>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions="item">
|
||||
<a-tooltip
|
||||
v-bind="item.tooltip"
|
||||
:title="item.disabled && item.tooltip.title"
|
||||
>
|
||||
<a-popconfirm
|
||||
v-if="item.popConfirm"
|
||||
v-bind="item.popConfirm"
|
||||
:disabled="item.disabled"
|
||||
>
|
||||
<a-button :disabled="item.disabled">
|
||||
<AIcon
|
||||
type="DeleteOutlined"
|
||||
v-if="item.key === 'delete'"
|
||||
/>
|
||||
<template v-else>
|
||||
<AIcon :type="item.icon" />
|
||||
<span>{{ item.text }}</span>
|
||||
</template>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<template v-else>
|
||||
<a-button
|
||||
: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 #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>
|
||||
</div>
|
||||
<Save v-if="visible" :data="current" @change="saveChange" />
|
||||
</page-container>
|
||||
</template>
|
||||
<script lang="ts" setup name="AccessConfigPage">
|
||||
import type { ActionsType } from '@/components/Table/index.vue';
|
||||
import { getImage } from '@/utils/comm';
|
||||
import { list, remove } from '@/api/link/protocol';
|
||||
import { message } from 'ant-design-vue';
|
||||
import Save from './Save/index.vue';
|
||||
|
||||
const tableRef = ref<Record<string, any>>({});
|
||||
const router = useRouter();
|
||||
const params = ref<Record<string, any>>({});
|
||||
|
||||
const visible = ref(false);
|
||||
const current = ref({});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'ID',
|
||||
dataIndex: 'id',
|
||||
key: 'id',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
width: 200,
|
||||
fixed: 'left',
|
||||
// scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
dataIndex: 'type',
|
||||
key: 'type',
|
||||
search: {
|
||||
type: 'select',
|
||||
options: [
|
||||
{
|
||||
label: 'jar',
|
||||
value: 'jar',
|
||||
},
|
||||
{
|
||||
label: 'local',
|
||||
value: 'local',
|
||||
},
|
||||
],
|
||||
},
|
||||
scopedSlots: true,
|
||||
},
|
||||
{
|
||||
title: '说明',
|
||||
dataIndex: 'description',
|
||||
key: 'description',
|
||||
search: {
|
||||
type: 'string',
|
||||
},
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
width: 200,
|
||||
scopedSlots: true,
|
||||
},
|
||||
];
|
||||
|
||||
const getActions = (
|
||||
data: Partial<Record<string, any>>,
|
||||
type: 'card' | 'table',
|
||||
): ActionsType[] => {
|
||||
if (!data) return [];
|
||||
const actions = [
|
||||
{
|
||||
key: 'edit',
|
||||
text: '编辑',
|
||||
tooltip: {
|
||||
title: '编辑',
|
||||
},
|
||||
icon: 'EditOutlined',
|
||||
onClick: () => {
|
||||
handlEdit(data.id);
|
||||
},
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
text: '删除',
|
||||
popConfirm: {
|
||||
title: '确认删除?',
|
||||
onConfirm: async () => {
|
||||
console.log(11, data.id);
|
||||
|
||||
// const res = await remove(data.id);
|
||||
// if (res.success) {
|
||||
// message.success('操作成功');
|
||||
// tableRef.value.reload();
|
||||
// } else {
|
||||
// message.error('操作失败!');
|
||||
// }
|
||||
},
|
||||
},
|
||||
icon: 'DeleteOutlined',
|
||||
},
|
||||
];
|
||||
return actions;
|
||||
};
|
||||
|
||||
const handlAdd = () => {
|
||||
console.log(11);
|
||||
visible.value = true;
|
||||
};
|
||||
const handlEdit = (id: string) => {
|
||||
// router.push(`/link/accessConfig/detail/edit/${id}`);
|
||||
// router.push({
|
||||
// path: `/iot/link/accessConfig/detail/${id}`,
|
||||
// query: { view: false },
|
||||
// });
|
||||
console.log(id);
|
||||
visible.value = true;
|
||||
};
|
||||
|
||||
const saveChange = (value: object) => {
|
||||
visible.value = false;
|
||||
current.value = {};
|
||||
if (value) {
|
||||
message.success('操作成功');
|
||||
tableRef.value.reload();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
* @param params
|
||||
*/
|
||||
const handleSearch = (e: any) => {
|
||||
params.value = e;
|
||||
};
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.tableCardDisabled {
|
||||
width: 100%;
|
||||
background: url('/images/access-config-diaabled.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.tableCardEnabled {
|
||||
width: 100%;
|
||||
background: url('/images/access-config-enabled.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.card-item-content {
|
||||
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 {
|
||||
min-height: 50px;
|
||||
}
|
||||
.card-item-content-text {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
font-size: 12px;
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis; //溢出用省略号显示
|
||||
white-space: nowrap; //溢出不换行
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,7 @@
|
|||
import type { BaseItem } from '@/utils/typings';
|
||||
|
||||
type ProtocolItem = {
|
||||
state: number;
|
||||
type: string;
|
||||
configuration: Record<string, any>;
|
||||
} & BaseItem;
|
Loading…
Reference in New Issue