💥 feat(网关): 添加网关配置模块

This commit is contained in:
fhysy 2024-12-13 11:05:19 +08:00
parent 4847600a47
commit a385d889c3
19 changed files with 2289 additions and 117 deletions

4
.env
View File

@ -1,5 +1,5 @@
# port 端口号
VITE_PORT = 8888
VITE_PORT = 4466
# open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = false
@ -8,4 +8,4 @@ VITE_OPEN = false
VITE_OPEN_CDN = false
# public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
VITE_PUBLIC_PATH =
VITE_PUBLIC_PATH =

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ pnpm-debug.log*
*.njsproj
*.sln
*.sw?
!/yarn.lock

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
<title>网关采集配置器</title>
<script src="./config.js"></script>
<script src="./js/config.js"></script>
</head>
<body>
<div id="app"></div>

View File

@ -12,8 +12,10 @@
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"axios": "^1.3.5",
"dayjs": "^1.11.13",
"echarts": "^5.4.2",
"element-plus": "^2.5.0",
"element-plus": "^2.9.0",
"file-saver": "^2.0.5",
"js-cookie": "^3.0.1",
"mitt": "^3.0.0",
"nprogress": "^0.2.0",
@ -26,7 +28,8 @@
"vue-clipboard3": "^2.0.0",
"vue-demi": "^0.13.11",
"vue-next-admin-template-js": "file:",
"vue-router": "^4.1.6"
"vue-router": "^4.1.6",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.1.0",

View File

@ -1,8 +0,0 @@
// 手动配置的地址
window.baseConfig = {
ip: 'digital-core.drgyen.com',
port: '',
prodApi: '',
protocol: 'https://',
wsProtocol: 'wss://'
}

16
public/js/config.js Normal file
View File

@ -0,0 +1,16 @@
// 手动配置的地址
// window.baseConfig = {
// ip: 'digital-core.drgyen.com',
// port: '',
// prodApi: '',
// protocol: 'https://',
// wsProtocol: 'wss://'
// }
window.baseConfig = {
ip: '192.168.1.17',
port: '8000',
prodApi: '',
protocol: 'http://',
wsProtocol: 'ws://'
}

View File

@ -0,0 +1,30 @@
import request from '/@/utils/request';
export function getDeviceCollectli(id) {
return request({
url: '/data/collect?equipId='+id,
method: 'get',
});
}
export function getDeviceEquipli(data) {
return request({
url: '/data/equip/list',
method: 'get',
data,
});
}
export function startDeviceCollect(id) {
return request({
url: '/data/collect/start?equipId='+id,
method: 'get',
});
}
export function endDeviceCollect(id) {
return request({
url: '/data/collect/end?equipId='+id,
method: 'get',
});
}

View File

@ -0,0 +1,17 @@
import request from '/@/utils/request';
export function getPlatformConf(data) {
return request({
url: '/config/platform/query',
method: 'get',
data,
});
}
export function setPlatformConf(data) {
return request({
url: '/config/platform/add',
method: 'post',
data,
});
}

View File

@ -0,0 +1,25 @@
import request from '/@/utils/request';
export function getDeviceConf(data) {
return request({
url: '/config/equip/query',
method: 'get',
data,
});
}
export function setDeviceConf(data) {
return request({
url: '/config/equip/add',
method: 'post',
data,
});
}
export function getSerialPortDataList(data) {
return request({
url: '/config/serials',
method: 'get',
data,
});
}

View File

@ -3,7 +3,7 @@
<router-view v-slot="{ Component }">
<transition :name="setTransitionName" mode="out-in">
<keep-alive :include="getKeepAliveNames">
<component :is="Component" :key="state.refreshRouterViewKey" class="w100" v-show="!isIframePage" />
<component style="padding: 10px" :is="Component" :key="state.refreshRouterViewKey" class="w100" v-show="!isIframePage" />
</keep-alive>
</transition>
</router-view>

View File

@ -108,7 +108,7 @@ router.beforeEach(async (to, from, next) => {
Session.clear();
NProgress.done();
} else if (token && to.path === '/login') {
next('/home');
next('/');
NProgress.done();
} else {
const storesRoutesList = useRoutesList(pinia);

View File

@ -23,119 +23,164 @@ export const dynamicRoutes = [
path: '/',
name: '/',
component: () => import('/@/layout/index.vue'),
redirect: '/home',
redirect: '/southdirection',
meta: {
isKeepAlive: true,
},
children: [
// {
// path: '/home',
// name: 'home',
// component: () => import('/@/views/home/index.vue'),
// meta: {
// title: '首页',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: true,
// isIframe: false,
// roles: ['admin', 'common'],
// icon: 'iconfont icon-shouye',
// },
// },
{
path: '/home',
name: 'home',
component: () => import('/@/views/home/index.vue'),
path: '/southdirection',
name: 'southdirection',
component: () => import('/@/views/gateway/southdirection.vue'),
meta: {
title: '首页',
title: '南向采集配置',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
roles: ['admin', 'common'],
icon: 'iconfont icon-shouye',
icon: 'ele-Bottom',
},
},
{
path: '/system',
name: 'system',
component: () => import('/@/layout/routerView/parent.vue'),
redirect: '/system/menu',
path: '/northboundtask',
name: 'northboundtask',
component: () => import('/@/views/gateway/northboundtask.vue'),
meta: {
title: '系统设置',
title: '北向任务配置',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isAffix: true,
isIframe: false,
roles: ['admin'],
icon: 'iconfont icon-xitongshezhi',
roles: ['admin', 'common'],
icon: 'ele-Top',
},
children: [
{
path: '/system/menu',
name: 'systemMenu',
component: () => import('/@/views/system/menu/index.vue'),
meta: {
title: '菜单管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'iconfont icon-caidan',
},
},
{
path: '/system/role',
name: 'systemRole',
component: () => import('/@/views/system/role/index.vue'),
meta: {
title: '角色管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-ColdDrink',
},
},
{
path: '/system/user',
name: 'systemUser',
component: () => import('/@/views/system/user/index.vue'),
meta: {
title: '用户管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'iconfont icon-icon-',
},
},
{
path: '/system/dept',
name: 'systemDept',
component: () => import('/@/views/system/dept/index.vue'),
meta: {
title: '部门管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-OfficeBuilding',
},
},
{
path: '/system/dic',
name: 'systemDic',
component: () => import('/@/views/system/dic/index.vue'),
meta: {
title: '字典管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
roles: ['admin'],
icon: 'ele-SetUp',
},
},
],
},
{
path: '/collectdatamonitor',
name: 'collectdatamonitor',
component: () => import('/@/views/gateway/collectdatamonitor.vue'),
meta: {
title: '采集数据监视',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
roles: ['admin', 'common'],
icon: 'ele-Tickets',
},
},
// {
// path: '/system',
// name: 'system',
// component: () => import('/@/layout/routerView/parent.vue'),
// redirect: '/system/menu',
// meta: {
// title: '系统设置',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'iconfont icon-xitongshezhi',
// },
// children: [
// {
// path: '/system/menu',
// name: 'systemMenu',
// component: () => import('/@/views/system/menu/index.vue'),
// meta: {
// title: '菜单管理',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'iconfont icon-caidan',
// },
// },
// {
// path: '/system/role',
// name: 'systemRole',
// component: () => import('/@/views/system/role/index.vue'),
// meta: {
// title: '角色管理',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'ele-ColdDrink',
// },
// },
// {
// path: '/system/user',
// name: 'systemUser',
// component: () => import('/@/views/system/user/index.vue'),
// meta: {
// title: '用户管理',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'iconfont icon-icon-',
// },
// },
// {
// path: '/system/dept',
// name: 'systemDept',
// component: () => import('/@/views/system/dept/index.vue'),
// meta: {
// title: '部门管理',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'ele-OfficeBuilding',
// },
// },
// {
// path: '/system/dic',
// name: 'systemDic',
// component: () => import('/@/views/system/dic/index.vue'),
// meta: {
// title: '字典管理',
// isLink: '',
// isHide: false,
// isKeepAlive: true,
// isAffix: false,
// isIframe: false,
// roles: ['admin'],
// icon: 'ele-SetUp',
// },
// },
// ],
// },
],
},
];

View File

@ -82,7 +82,7 @@ export const useThemeConfig = defineStore('themeConfig', {
// 初始化变量,用于 el-scrollbar 的高度更新,请勿删除
isShowLogoChange: false,
// 是否开启 Breadcrumb强制经典、横向布局不显示
isBreadcrumb: false,
isBreadcrumb: true,
// 是否开启 Tagsview
isTagsview: false,
// 是否开启 Breadcrumb 图标
@ -145,7 +145,7 @@ export const useThemeConfig = defineStore('themeConfig', {
// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn
globalI18n: 'zh-cn',
// 默认全局组件大小,可选值"<large|'default'|small>",默认 'large'
globalComponentSize: 'large',
globalComponentSize: 'default',
},
}),
actions: {

6
src/utils/function.js Normal file
View File

@ -0,0 +1,6 @@
export function guidGenerator() {
var S4 = function() {
return ((1 + Math.random())*0X10000|0).toString(16).substring(1);
};
return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}

View File

@ -0,0 +1,263 @@
<template>
<div id="southdirection-box">
<div class="device-config">
<h2>设备状态</h2>
<div class="btn-list">
<div class="btn-list-left"></div>
<div class="btn-list-right">
<el-button type="primary" @click="getDeviceList">刷新</el-button>
</div>
</div>
<div class="table-box">
<el-table
ref="deviceConfigTableRef"
highlight-current-row
:data="deviceList"
border
height="187"
:style="{ width: tabelBox + 'px', background: '#f2f2f2' }"
empty-text="配置为空"
@row-click="deviceConfigClick"
>
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column prop="equipId" label="设备ID" align="center" />
<el-table-column prop="quality" label="通讯质量" align="center" />
<el-table-column prop="status" label="运行状态" align="center" />
<el-table-column prop="status" label="开启状态" align="center">
<template #default="scope">
<el-switch v-model="scope.row.status" :before-change="handleBeforeChange.bind(this, scope.$index)" />
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="data-config">
<h2>数据源配置 {{ activeDeviceConfig.equipId || '' }}</h2>
<div class="btn-list">
<div class="btn-list-left"></div>
<div class="btn-list-right">
<el-button type="primary" @click="getDeviceConfig">刷新</el-button>
</div>
</div>
<div class="table-box">
<el-table ref="deviceDataTableRef" :data="activeDeviceConfig.result" border size="small" height="100%" :style="{ width: tabelBox + 'px' }" empty-text="配置为空">
<el-table-column type="index" label="序号" align="center" width="60" fixed />
<el-table-column prop="id" label="设备ID_数据ID" align="center">
<template #default="scope">
{{ activeDeviceConfig.equipId + '_' + scope.row.id }}
</template>
</el-table-column>
<el-table-column prop="dataName" label="数据名" align="center" />
<el-table-column prop="dataValue" label="当前值" align="center" />
<el-table-column prop="dataUnit" label="单位" align="center" />
<el-table-column prop="time" label="时间" align="center" />
<!-- <el-table-column label="操作" width="55" fixed="right" align="center">-->
<!-- <template #default="scope">-->
<!-- <el-button link type="danger" size="small" @click.stop="delDeviceDataConfig(scope.$index)">删除</el-button>-->
<!-- </template>-->
<!-- </el-table-column>-->
</el-table>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import {
endDeviceCollect,
getDeviceCollectli,
getDeviceEquipli,
startDeviceCollect
} from "/@/api/gateway/collectdatamonitor";
const deviceConfigTableRef = ref();
const deviceDataTableRef = ref();
const tabelBox = ref(884);
const deviceList = ref([]);
//
const ActiveRowIndex = ref(0);
const activeDeviceConfig = ref({
equipId: '',
status: false,
result: []
});
const getDeviceDataList = id => {
// console.log('')
getDeviceCollectli(id)
.then(response => {
//
if (response.code == 0) {
//
activeDeviceConfig.value = {
equipId: response.data.equipId || '',
status: response.data.status || false,
result: response.data.result || []
};
// activeDeviceResult.value = response.data.result || []
} else {
ElMessage.error(response.message);
}
})
.catch(error => {
//
console.error(error); //
ElMessage.error(error);
});
};
const getDeviceList = () => {
// console.log('')
getDeviceEquipli({})
.then(response => {
//
if (response.code == 0) {
//
deviceList.value = response.data.equips || [];
if (deviceList.value.length > ActiveRowIndex.value) {
getDeviceDataList(deviceList.value[ActiveRowIndex.value].equipId);
} else if (deviceList.value.length > 0) {
getDeviceDataList(deviceList.value[0].equipId);
} else {
activeDeviceConfig.value = {
equipId: '',
starus: false,
result: []
};
// activeDeviceResult.value = []
}
} else {
ElMessage.error(response.message);
}
})
.catch(error => {
//
console.error(error); //
ElMessage.error(error);
});
};
const getDeviceConfig = () => {
getDeviceDataList(deviceList.value[ActiveRowIndex.value].equipId);
};
const handleBeforeChange = index => {
console.log('e', index);
return new Promise((resolve, reject) => {
let deviceObj = deviceList.value[index];
console.log('deviceObj', deviceObj.status);
if (deviceObj.status) {
endDeviceCollect(deviceObj.equipId).then(response => {
console.log('response', response);
if (response.code === 0) {
// ok
if (deviceObj.status) {
ElMessage.success('关闭成功');
} else {
ElMessage.success('开启成功');
}
deviceList.value[index].status = !deviceList.value[index].status;
getDeviceList();
resolve();
} else {
// ok
ElMessage.error(response.message);
reject();
}
})
.catch(error => {
//
ElMessage.error(error.data.message);
reject();
});
}else{
startDeviceCollect(deviceObj.equipId).then(response => {
console.log('response', response);
if (response.code === 0) {
// ok
if (deviceObj.status) {
ElMessage.success('关闭成功');
} else {
ElMessage.success('开启成功');
}
deviceList.value[index].status = !deviceList.value[index].status;
getDeviceList();
resolve();
} else {
// ok
ElMessage.error(response.message);
reject();
}
})
.catch(error => {
//
ElMessage.error(error.data.message);
reject();
});
}
});
};
//
const deviceConfigClick = e => {
getDeviceDataList(e.equipId);
deviceConfigTableRef.value.toggleRowSelection(e);
ActiveRowIndex.value = deviceList.value.indexOf(e);
};
//
const handleResize = () => {
deviceDataTableRef.value.doLayout();
tabelBox.value = window.innerWidth - 180 - 10;
};
onMounted(() => {
window.addEventListener('resize', handleResize);
getDeviceList();
handleResize();
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
</script>
<style scoped lang="scss">
.el-table .double-clicked-row {
background-color: #f0f9eb;
}
:deep(.el-table .el-scrollbar) {
background: #fff;
}
#southdirection-box {
position: absolute;
width: 100%;
height: 100%;
.btn-list {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
}
.device-config {
position: relative;
overflow-y: auto;
}
.data-config {
position: relative;
height: calc(100% - 278px);
.table-box {
position: absolute;
width: 100%;
height: calc(100% - 162px);
}
}
.table-box {
//position: absolute;
//width: 100%;
}
}
</style>

View File

@ -0,0 +1,655 @@
<template>
<div id="southdirection-box">
<div class="plat-config">
<h2>平台配置</h2>
<div class="btn-list">
<div class="btn-list-left">
<el-button type="primary" @click="addDeviceConfig">新增配置</el-button>
<!-- <el-button type="danger" @click="getDeviceConfig">删除</el-button>-->
</div>
<div class="btn-list-right">
<!-- <el-button type="primary" @click="getDeviceConfig">导出</el-button>-->
<!-- <el-button type="primary" @click="getDeviceConfig">导入</el-button>-->
<el-button type="primary" @click="getDeviceConfig">获取配置</el-button>
<el-button type="primary" @click="setDeviceConfig">设置配置</el-button>
</div>
</div>
<div class="table-box">
<el-table
ref="platConfigTableRef"
highlight-current-row
:data="platConfigList"
border
height="187"
:row-class-name="tableRowClassName"
:style="{ width: tabelBox + 'px',background:'#f2f2f2' }"
empty-text="配置为空"
>
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column prop="PlatformIp" label="平台地址" >
<template #default="scope">
<el-input v-model="scope.row.PlatformIp" placeholder="请输入平台地址" />
</template>
</el-table-column>
<el-table-column prop="type" label="上报格式" >
<template #default="scope">
<el-select v-model="scope.row.type" placeholder="请选择上报格式">
<el-option
v-for="item in uploadType"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
</el-table-column>
<el-table-column prop="mqtt.user" label="用户名" >
<template #default="scope">
<el-input v-model="scope.row.mqtt.user" placeholder="请输入用户名" />
</template>
</el-table-column>
<el-table-column prop="mqtt.passwd" label="密码" >
<template #default="scope">
<el-input type="password" show-password v-model="scope.row.mqtt.passwd" placeholder="请输入密码" />
</template>
</el-table-column>
<el-table-column prop="mqtt.isUseSsl" label="ssl" >
<template #default="scope">
<el-switch v-model="scope.row.mqtt.isUseSsl" />
</template>
</el-table-column>
<el-table-column prop="mqtt.isUseSslConf" label="ssl文件" >
<template #default="scope">
<el-switch v-model="scope.row.mqtt.isUseSslConf" />
</template>
</el-table-column>
<el-table-column prop="pushConf.isUseResumeBrokenTransfer" label="断点续存" >
<template #default="scope">
<el-switch v-model="scope.row.pushConf.isUseResumeBrokenTransfer" />
</template>
</el-table-column>
<el-table-column prop="tasks" label="任务ID" >
<template #default="scope">
{{scope.row.tasks?scope.row.tasks.join():''}}
</template>
</el-table-column>
<el-table-column label="操作" width="140" align="center">
<template #default="scope">
<el-button link type="primary" size="small" @click="openCollectionModel(scope.row)">加解密配置</el-button>
<el-button link type="danger" size="small" @click="delDeviceConfig(scope.$index)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="plat-config">
<h2>任务配置</h2>
<div class="table-box">
<el-table
ref="platConfigTableRef"
highlight-current-row
:data="taskList"
border
height="187"
:row-class-name="tableRowClassName"
@row-click="taskConfigClick"
:style="{ width: tabelBox + 'px',background:'#f2f2f2' }"
empty-text="配置为空"
>
<el-table-column type="index" label="序号" align="center" width="60" />
<el-table-column prop="taskId" label="任务ID" align="center">
<template #default="scope">
{{scope.row.taskId}}
<!-- <el-input v-model="scope.row.taskId" placeholder="请输入任务ID" />-->
</template>
</el-table-column>
<el-table-column prop="uploadMode" label="上报策略" >
<template #default="scope">
<el-autocomplete
v-model="scope.row.uploadMode"
:fetch-suggestions="querySearch"
clearable
class="inline-input w-50"
placeholder="请选择上报策略"
/>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div class="data-config">
<h2>上报测点 {{activeDeviceConfig.taskId}}</h2>
<div class="table-box">
<el-table
:data="activeDeviceConfig.dataIdEntire"
border
size="small"
height="100%"
ref="deviceDataTableRef"
:style="{ width: tabelBox + 'px' }"
empty-text="配置为空"
>
<el-table-column type="index" label="序号" align="center" width="60" fixed />
<el-table-column prop="equipId" label="设备ID" align="center"/>
<el-table-column prop="idInfo[0].id" label="数据ID" align="center"/>
<el-table-column prop="idInfo[0].uploadMode" label="上报策略" align="center"/>
</el-table>
</div>
</div>
<el-dialog
v-model="collectionModelShow"
title="加解密配置"
width="500"
:before-close="handleClose"
>
<el-form ref="collectionRef" :model="collectionForm" label-width="auto" status-icon>
<h3>加密算法配置</h3>
<el-form-item label="启动">
<el-switch v-model="collectionForm.encrypt_1.enable" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="加密算法">
<el-select v-model="collectionForm.encrypt_1.algorithm" placeholder="选择加密算法">
<el-option label="AES" value="AES" />
<el-option label="DES" value="DES" />
<el-option label="SM4" value="SM4" />
<el-option label="RSA" value="RSA" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="text-center">
<el-form-item label="加密key值">
<el-input v-model="collectionForm.encrypt_1.param.key" placeholder="请输入加密key值" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="加密模式">
<el-select v-model="collectionForm.encrypt_1.mode" placeholder="选择加密模式">
<el-option label="ECB" value="ECB" />
<el-option label="CBC" value="CBC" />
<el-option label="CTR" value="CTR" />
<el-option label="CFB" value="CFB" />
<el-option label="CFB1" value="CFB1" />
<el-option label="CFB8" value="CFB8" />
<el-option label="CFB128" value="CFB128" />
<el-option label="OFB" value="OFB" />
<el-option label="OFB128" value="OFB128" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="text-center">
<el-form-item label="加密向量表">
<el-input v-model="collectionForm.encrypt_1.param.ivec" placeholder="请输入加密向量表" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="加密位数">
<el-select v-model="collectionForm.encrypt_1.bits" placeholder="选择加密位数">
<el-option label="128" value="128" />
<el-option label="192" value="192" />
<el-option label="256" value="256" />
</el-select>
</el-form-item>
<h3>解密算法配置</h3>
<el-form-item label="启动">
<el-switch v-model="collectionForm.decrypt_1.enable" />
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="加密算法">
<el-select v-model="collectionForm.decrypt_1.algorithm" placeholder="选择加密算法">
<el-option label="AES" value="AES" />
<el-option label="DES" value="DES" />
<el-option label="SM4" value="SM4" />
<el-option label="RSA" value="RSA" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="text-center">
<el-form-item label="加密key值">
<el-input v-model="collectionForm.decrypt_1.param.key" placeholder="请输入加密key值" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="加密模式">
<el-select v-model="collectionForm.decrypt_1.mode" placeholder="选择加密模式">
<el-option label="ECB" value="ECB" />
<el-option label="CBC" value="CBC" />
<el-option label="CTR" value="CTR" />
<el-option label="CFB" value="CFB" />
<el-option label="CFB1" value="CFB1" />
<el-option label="CFB8" value="CFB8" />
<el-option label="CFB128" value="CFB128" />
<el-option label="OFB" value="OFB" />
<el-option label="OFB128" value="OFB128" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="text-center">
<el-form-item label="加密向量表">
<el-input v-model="collectionForm.decrypt_1.param.ivec" placeholder="请输入加密向量表" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="加密位数">
<el-select v-model="collectionForm.decrypt_1.bits" placeholder="选择加密位数">
<el-option label="128" value="128" />
<el-option label="192" value="192" />
<el-option label="256" value="256" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="collectionModelShow = false">取消</el-button>
<el-button type="primary" @click="editCollection">
确认
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { reactive, ref, onMounted, onUnmounted, computed, watch } from "vue"
import { ElMessage, ElMessageBox } from "element-plus"
import {getPlatformConf, setPlatformConf} from "/@/api/gateway/northboundtask";
//
const uploadModeList = ref([
{ value: 'timer 10', link: 'timer 10' },
{ value: 'change 10', link: 'change 10' },
{ value: 'timer 10 || change 10', link: 'timer 10 || change 10' },
{ value: 'label LD200 up', link: 'label LD200 up' },
])
const querySearch = (queryString, cb) => {
const results = queryString
? uploadModeList.value.filter(createFilter(queryString))
: uploadModeList.value
// call callback function to return suggestions
cb(results)
}
const createFilter = (queryString) => {
return (restaurant) => {
return (
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
)
}
}
//
const taskList = ref([
]);
const platConfigTableRef = ref();
const deviceDataTableRef = ref();
const tabelBox = ref(884)
const platConfigList = ref([])
const uploadType = ref([
{ label: 'DT-MQTT-DEFAULT', value: 'DT-MQTT-DEFAULT'},
{ label: 'DT-MQTT-DEBUG', value: 'DT-MQTT-DEBUG'},
{ label: 'HN-MQTT-BJ', value: 'HN-MQTT-BJ'},
{ label: 'SC-MQTT-DEFAULT', value: 'SC-MQTT-DEFAULT'},
{ label: 'WG-MQTT-PuPu', value: 'WG-MQTT-PuPu'},
{ label: 'WG-MQTT-TengSheng', value: 'WG-MQTT-TengSheng'},
])
//
const addDeviceConfig = () => {
let newDeviceConfig = {
"PlatformIp": "",
"tasks": ["T1", "T2", "T3", "T4", "T5"],
"type": "",
"mqtt": {
"user": "",
"passwd": "",
"isUseSsl": false,
"isUseSslConf": false,
"sslConf": {
"localCertificate_file": "/etc/custom/sslConf/pupu_core_3501000001.pem",
"privateKey_file": "/etc/custom/sslConf/pupu_core_3501000001.prv"
}
},
"pushConf": {
"isRun": true,
"isUseResumeBrokenTransfer": false,
"broken": {
"resume": { "intervalTime_ms": 1000 },
"filter": {
"filter_s": 600,
"relevanceTaskId": ["T1", "T2", "T3", "T4", "T5"]
}
}
},
"encrypt_decrypt": {
"encrypt_1": {
"algorithm": "AES",
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
"enable": false
},
"decrypt_1": {
"algorithm": "AES",
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
"enable": false
}
}
};
console.log("platConfigList.value",platConfigTableRef.value)
platConfigList.value.push(newDeviceConfig);
}
//
const delDeviceConfig = (index) => {
console.log("当前点击的行号", index);
ElMessageBox.confirm(
'确认要删除该设备配置吗?',
'告警',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
platConfigList.value.splice(index, 1);
ElMessage({
type: 'success',
message: '删除成功',
})
})
.catch(() => {
ElMessage({
type: 'info',
message: '取消删除',
})
})
}
const getDeviceConfig = () => {
console.log('获取配置')
getPlatformConf({})
.then(response => {
//
console.log(response); //
if (response.code == 0) {
//
platConfigList.value = response.data.PlatformPar || [];
taskList.value = response.data.tasks.map(item=>{
if(item.dataIdEntire!=[]){
let dataIdEntireList = [];
item.dataIdEntire.forEach(val=>{
val.idInfo.forEach(info=>{
dataIdEntireList.push({
equipId: val.equipId,
idInfo:[info]
})
})
})
item.dataIdEntire = dataIdEntireList;
}
return item;
}) || [];
// taskList.value = taskDataList;
console.log("格式化后数据",taskList.value)
if(!platConfigList.value.length){
addDeviceConfig()
}
if(platConfigList.value.length){
if(platConfigList.value.length>ActiveRowIndex.value){
activeDeviceConfig.value = platConfigList.value[ActiveRowIndex.value];
}else{
activeDeviceConfig.value = platConfigList.value[0];
}
}
} else {
ElMessage.error(response.message);
}
})
.catch(error => {
//
console.error(error); //
ElMessage.error(error);
});
}
const setDeviceConfig = () => {
console.log('提交配置',platConfigList.value)
setPlatformConf({PlatformPar: platConfigList.value,tasks:taskList.value})
.then(response => {
//
console.log(response); //
if (response.code == 0) {
ElMessage.success('保存成功');
} else {
ElMessage.error(response.message);
}
})
.catch(error => {
//
console.error(error); //
ElMessage.error(error);
});
}
//
const ActiveRowIndex = ref(0);
const collectionModelShow = ref(false);
const collectionRef = ref();
const collectionForm = ref({
//
"encrypt_1": {
//
"algorithm": "AES",
//
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
//
"enable": false
},
//
"decrypt_1": {
//
"algorithm": "AES",
//
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
//
"enable": false
}
})
//
const openCollectionModel = (row) => {
console.log("当前采集",row)
collectionForm.value = {
"encrypt_1": row.encrypt_decrypt.encrypt_1,
"decrypt_1": row.encrypt_decrypt.decrypt_1
};
collectionModelShow.value = true;
}
const editCollection = () => {
platConfigList.value[ActiveRowIndex.value].encrypt_decrypt.encrypt_1 = collectionForm.value.encrypt_1;
platConfigList.value[ActiveRowIndex.value].encrypt_decrypt.decrypt_1 = collectionForm.value.decrypt_1;
collectionModelShow.value = false;
}
const activeDeviceConfig = ref({
"PlatformIp": "",
"tasks": ["T1", "T2", "T3", "T4", "T5"],
"type": "",
"mqtt": {
"user": "",
"passwd": "",
"isUseSsl": false,
"isUseSslConf": false,
"sslConf": {
"localCertificate_file": "/etc/custom/sslConf/pupu_core_3501000001.pem",
"privateKey_file": "/etc/custom/sslConf/pupu_core_3501000001.prv"
}
},
"pushConf": {
"isRun": true,
"isUseResumeBrokenTransfer": false,
"broken": {
"resume": { "intervalTime_ms": 1000 },
"filter": {
"filter_s": 600,
"relevanceTaskId": ["T1", "T2", "T3", "T4", "T5"]
}
}
},
"encrypt_decrypt": {
"encrypt_1": {
"algorithm": "AES",
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
"enable": false
},
"decrypt_1": {
"algorithm": "AES",
"param": {
"mode": "CBC",
"key": "0123456789abcdef",
"ivec": "0123456789abcdef",
"bits": 128
},
"enable": false
}
}
})
watch(
() => ({ ...activeDeviceConfig.value }),
(newVal) => {
console.log("数据变化",newVal)
platConfigList.value[ActiveRowIndex.value] = newVal;
},
{ deep: true }
);
// const saveDeviceDataConfig = () => {
// platConfigList.value[ActiveRowIndex.value] = activeDeviceConfig.value;
// }
const tableRowClassName = ({ row, rowIndex }) => {
if (rowIndex === ActiveRowIndex.value) {
return 'selected-row';
}
return '';
};
//
const taskConfigClick = (e) => {
console.log(`current page:`,e)
activeDeviceConfig.value = e;
platConfigTableRef.value.toggleRowSelection(e);
ActiveRowIndex.value = platConfigList.value.indexOf(e);
// e.isDoubleClicked = !e.isDoubleClicked;
}
//
const handleResize = () => {
deviceDataTableRef.value.doLayout();
tabelBox.value = window.innerWidth - 180 - 10 ;
}
onMounted(() => {
window.addEventListener('resize', handleResize);
getDeviceConfig()
handleResize()
// if(platConfigList.value[0]){
// activeDeviceConfig.value = platConfigList.value[0];
// platConfigTableRef.value.toggleRowSelection(platConfigList.value[0]);
// ActiveRowIndex.value = 0;
// }
});
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
});
</script>
<style scoped lang="scss">
.el-table .double-clicked-row {
background-color: #f0f9eb;
}
:deep(.el-table .el-scrollbar) {
background: #fff;
}
#southdirection-box{
position: absolute;
width: 100%;
height: 100%;
.btn-list{
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
}
.plat-config{
position: relative;
overflow-y: auto;
}
.data-config{
position: relative;
height: calc(100% - 278px - 226px);
.table-box{
position: absolute;
width: 100%;
height: calc(100% - 120px);
}
}
.table-box{
//position: absolute;
//width: 100%;
}
}
</style>
<style>
.selected-row {
background-color: #55e800;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -29,12 +29,17 @@ const viteConfig = defineConfig((mode) => {
open: JSON.parse(env.VITE_OPEN),
hmr: true,
proxy: {
'/gitee': {
target: 'https://gitee.com',
ws: true,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/gitee/, ''),
},
// '/gitee': {
// target: 'https://gitee.com',
// ws: true,
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/gitee/, ''),
// },
// '/config': {
// target: 'http://192.168.1.17:8000',
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/config/, ''),
// },
},
},
build: {

View File

@ -383,6 +383,11 @@ acorn@^8.8.0:
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz"
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
adler-32@~1.3.0:
version "1.3.1"
resolved "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2"
integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==
ajv@^6.10.0, ajv@^6.12.4:
version "6.12.6"
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
@ -480,6 +485,14 @@ callsites@^3.0.0:
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
cfb@~1.2.1:
version "1.2.2"
resolved "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44"
integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==
dependencies:
adler-32 "~1.3.0"
crc-32 "~1.2.0"
chalk@^4.0.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
@ -512,6 +525,11 @@ clipboard@^2.0.6:
select "^1.1.2"
tiny-emitter "^2.0.0"
codepage@~1.15.0:
version "1.15.0"
resolved "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab"
integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
@ -536,6 +554,11 @@ concat-map@0.0.1:
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
crc-32@~1.2.0, crc-32@~1.2.1:
version "1.2.2"
resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz"
@ -597,7 +620,7 @@ echarts@^5.4.2:
tslib "2.3.0"
zrender "5.4.3"
element-plus@^2.5.0:
element-plus@^2.7.6, element-plus@^2.9.0:
version "2.9.0"
resolved "https://registry.npmmirror.com/element-plus/-/element-plus-2.9.0.tgz#76a16566ab6dbadb555a40704bde870a02c306bc"
integrity sha512-ccOFXKsauo2dtokAr4OX7gZsb7TuAoVxA2zGRZo5o2yyDDBLBaZxOoFQPoxITSLcHbBfQuNDGK5Iag5hnyKkZA==
@ -795,6 +818,11 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"
file-saver@^2.0.5:
version "2.0.5"
resolved "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz"
@ -837,6 +865,11 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
frac@~1.1.2:
version "1.1.2"
resolved "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
fs-extra@^10.0.0:
version "10.1.0"
resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz"
@ -1433,6 +1466,13 @@ sourcemap-codec@^1.4.8:
resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz"
integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
ssf@~0.11.2:
version "0.11.2"
resolved "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c"
integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==
dependencies:
frac "~1.1.2"
strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
@ -1571,8 +1611,10 @@ vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.1.1:
dependencies:
"@element-plus/icons-vue" "^2.1.0"
axios "^1.3.5"
dayjs "^1.11.13"
echarts "^5.4.2"
element-plus "^2.5.0"
element-plus "^2.7.6"
file-saver "^2.0.5"
js-cookie "^3.0.1"
mitt "^3.0.0"
nprogress "^0.2.0"
@ -1584,8 +1626,9 @@ vue-eslint-parser@^9.0.1, vue-eslint-parser@^9.1.1:
vue "^3.2.47"
vue-clipboard3 "^2.0.0"
vue-demi "^0.13.11"
vue-next-admin-template-js "file:C:/Users/Administrator/AppData/Local/Yarn/Cache/v6/npm-vue-next-admin-template-js-2.4.33-7ca98d43-7ddc-421a-a897-166f94ead9bb-1733975867024/node_modules/vue-next-admin-template-js"
vue-next-admin-template-js "file:C:/Users/Administrator/AppData/Local/Yarn/Cache/v6/npm-vue-next-admin-template-js-2.4.33-d6f20349-ce84-4f4c-b83e-27e36d4b1985-1733992643913/node_modules/vue-next-admin-template-js"
vue-router "^4.1.6"
xlsx "^0.18.5"
vue-router@^4.1.6:
version "4.1.6"
@ -1612,16 +1655,39 @@ which@^2.0.1:
dependencies:
isexe "^2.0.0"
wmf@~1.0.1:
version "1.0.2"
resolved "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da"
integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==
word-wrap@^1.2.3:
version "1.2.3"
resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
word@~0.3.0:
version "0.3.0"
resolved "https://registry.npmmirror.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961"
integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==
wrappy@1:
version "1.0.2"
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
xlsx@^0.18.5:
version "0.18.5"
resolved "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0"
integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==
dependencies:
adler-32 "~1.3.0"
cfb "~1.2.1"
codepage "~1.15.0"
crc-32 "~1.2.1"
ssf "~0.11.2"
wmf "~1.0.1"
word "~0.3.0"
xml-name-validator@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz"