修改测试用例
This commit is contained in:
@@ -56,6 +56,7 @@
|
|||||||
"mathjax": "^3.2.2",
|
"mathjax": "^3.2.2",
|
||||||
"min-dash": "^4.2.1",
|
"min-dash": "^4.2.1",
|
||||||
"mitt": "^3.0.1",
|
"mitt": "^3.0.1",
|
||||||
|
"mqtt": "^5.13.3",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 21 KiB |
BIN
public/favicon1.ico
Normal file
BIN
public/favicon1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
@@ -88,8 +88,8 @@ export const updateStatistical = (data: any) => {
|
|||||||
// 单位绑定
|
// 单位绑定
|
||||||
export function codeDicTree(data: any) {
|
export function codeDicTree(data: any) {
|
||||||
return createAxios({
|
return createAxios({
|
||||||
url: '/system-boot/dicTree/codeDicTree',
|
url: '/system-boot/dictTree/queryByCodeList',
|
||||||
method: 'get',
|
method: 'post',
|
||||||
params: data
|
params: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,15 +134,29 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
backbxlb() {
|
backbxlb() {
|
||||||
this.waveDatas = []
|
this.waveDatas = []
|
||||||
if(this.myChartess){this.myChartess.dispose(); this.myChartess=null; }
|
|
||||||
if(this.myChartess1){this.myChartess1.dispose(); this.myChartess1=null; }
|
|
||||||
if(this.myChartess2){this.myChartess2.dispose(); this.myChartess2=null; }
|
|
||||||
if(this.myChartess3){this.myChartess3.dispose(); this.myChartess3=null; }
|
|
||||||
if(this.myChartess4){this.myChartess4.dispose(); this.myChartess4=null; }
|
|
||||||
if(this.myChartess5){this.myChartess5.dispose(); this.myChartess5=null; }
|
|
||||||
|
|
||||||
echarts.disconnect([this.myChartess,this.myChartess1,this.myChartess2,this.myChartess3,this.myChartess4,this.myChartess5])
|
// 清理所有可能的 echarts 实例
|
||||||
|
const chartNames = ['myChartess', 'myChartess1', 'myChartess2', 'myChartess3', 'myChartess4', 'myChartess5']
|
||||||
|
|
||||||
|
chartNames.forEach(name => {
|
||||||
|
if (this[name]) {
|
||||||
|
this[name].dispose()
|
||||||
|
this[name] = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 断开 echarts 实例连接
|
||||||
|
echarts.disconnect(chartNames.map(name => this[name]).filter(Boolean))
|
||||||
|
// this.waveDatas = []
|
||||||
|
// if(this.myChartess){this.myChartess.dispose(); this.myChartess=null; }
|
||||||
|
// if(this.myChartess1){this.myChartess1.dispose(); this.myChartess1=null; }
|
||||||
|
// if(this.myChartess2){this.myChartess2.dispose(); this.myChartess2=null; }
|
||||||
|
// if(this.myChartess3){this.myChartess3.dispose(); this.myChartess3=null; }
|
||||||
|
// if(this.myChartess4){this.myChartess4.dispose(); this.myChartess4=null; }
|
||||||
|
// if(this.myChartess5){this.myChartess5.dispose(); this.myChartess5=null; }
|
||||||
|
|
||||||
|
// echarts.disconnect([this.myChartess,this.myChartess1,this.myChartess2,this.myChartess3,this.myChartess4,this.myChartess5])
|
||||||
|
|
||||||
// if (this.echartlist.length > 0) {
|
// if (this.echartlist.length > 0) {
|
||||||
|
|
||||||
|
|||||||
@@ -122,16 +122,20 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
backbxlb() {
|
backbxlb() {
|
||||||
this.waveDatas = []
|
this.waveDatas = []
|
||||||
if(this.myChartess){this.myChartess.dispose(); this.myChartess=null; }
|
|
||||||
if(this.myChartess1){this.myChartess1.dispose(); this.myChartess1=null; }
|
|
||||||
if(this.myChartess2){this.myChartess2.dispose(); this.myChartess2=null; }
|
|
||||||
if(this.myChartess3){this.myChartess3.dispose(); this.myChartess3=null; }
|
|
||||||
if(this.myChartess4){this.myChartess4.dispose(); this.myChartess4=null; }
|
|
||||||
if(this.myChartess5){this.myChartess5.dispose(); this.myChartess5=null; }
|
|
||||||
|
|
||||||
echarts.disconnect([this.myChartess,this.myChartess1,this.myChartess2,this.myChartess3,this.myChartess4,this.myChartess5])
|
// 清理所有可能的 echarts 实例
|
||||||
|
const chartNames = ['myChartess', 'myChartess1', 'myChartess2', 'myChartess3', 'myChartess4', 'myChartess5']
|
||||||
|
|
||||||
|
chartNames.forEach(name => {
|
||||||
|
if (this[name]) {
|
||||||
|
this[name].dispose()
|
||||||
|
this[name] = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 断开 echarts 实例连接
|
||||||
|
echarts.disconnect(chartNames.map(name => this[name]).filter(Boolean))
|
||||||
|
|
||||||
// this.echartlist.forEach(item => {
|
// this.echartlist.forEach(item => {
|
||||||
// if (item) {
|
// if (item) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export const defaultAttribute: VxeTableProps = {
|
|||||||
align: 'center',
|
align: 'center',
|
||||||
headerCellClassName: 'table-header-cell',
|
headerCellClassName: 'table-header-cell',
|
||||||
border: true,
|
border: true,
|
||||||
// stripe: true,
|
|
||||||
size: 'small',
|
size: 'small',
|
||||||
columnConfig: { resizable: true },
|
columnConfig: { resizable: true },
|
||||||
rowConfig: { isCurrent: true, isHover: true },
|
rowConfig: { isCurrent: true, isHover: true },
|
||||||
|
|||||||
91
src/layouts/admin/components/globalPopUp.vue
Normal file
91
src/layouts/admin/components/globalPopUp.vue
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- 全局暂降事件 -->
|
||||||
|
<el-drawer v-model="drawer" title="暂降事件" size="1000px" :before-close="handleClose">
|
||||||
|
<div :style="height">
|
||||||
|
<vxe-table
|
||||||
|
v-bind="defaultAttribute"
|
||||||
|
v-loading="isLoading"
|
||||||
|
height="100%"
|
||||||
|
ref="xTable1Ref"
|
||||||
|
:data="eventList"
|
||||||
|
>
|
||||||
|
<vxe-column type="seq" width="70px" title="序号"></vxe-column>
|
||||||
|
<vxe-column field="time" width="180px" sortable title="发生时刻"></vxe-column>
|
||||||
|
<vxe-column field="lineName" title="监测点"></vxe-column>
|
||||||
|
<vxe-column field="powerCompany" title="变电站"></vxe-column>
|
||||||
|
<vxe-column field="powerCompany" title="供电公司"></vxe-column>
|
||||||
|
<vxe-column field="persistTime" width="120px" sortable title="持续时间(s)"></vxe-column>
|
||||||
|
<vxe-column field="eventValue" width="160px" sortable title="暂降(骤升)幅值(%)">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ Math.floor(row.eventValue * 10000) / 100 }}
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
<vxe-column field="eventReason" width="110px" title="暂降类型">
|
||||||
|
<template #default="{ row }">
|
||||||
|
{{ eventType.filter(item => item.id == row.eventReason)[0]?.name || '/' }}
|
||||||
|
</template>
|
||||||
|
</vxe-column>
|
||||||
|
</vxe-table>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { defaultAttribute } from '@/components/table/defaultAttribute'
|
||||||
|
import { mainHeight } from '@/utils/layout'
|
||||||
|
import { useDictData } from '@/stores/dictData'
|
||||||
|
import MQTT from '@/utils/mqtt'
|
||||||
|
const dictData = useDictData()
|
||||||
|
const eventType = dictData.getBasicData('Event_Type')
|
||||||
|
import { useAdminInfo } from '@/stores/adminInfo'
|
||||||
|
const adminInfo = useAdminInfo()
|
||||||
|
const height = mainHeight(-20)
|
||||||
|
const drawer = ref(false)
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const eventList = ref([])
|
||||||
|
const open = () => {
|
||||||
|
drawer.value = true
|
||||||
|
}
|
||||||
|
const handleClose = (done: any) => {
|
||||||
|
drawer.value = false
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
const init = async () => {
|
||||||
|
const mqttClient = new MQTT('/sendEvent')
|
||||||
|
// 设置消息接收回调
|
||||||
|
try {
|
||||||
|
await mqttClient.init()
|
||||||
|
|
||||||
|
// 订阅主题
|
||||||
|
await mqttClient.subscribe()
|
||||||
|
// 设置消息接收回调
|
||||||
|
mqttClient.onMessage((topic, message) => {
|
||||||
|
const msg = JSON.parse(message.toString())
|
||||||
|
if (msg.deptList.includes(adminInfo.$state.deptId)) {
|
||||||
|
drawer.value = true
|
||||||
|
isLoading.value = true
|
||||||
|
eventList.value.unshift(msg)
|
||||||
|
setTimeout(() => {
|
||||||
|
isLoading.value = false
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('MQTT 初始化失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
// startMqtt('/sendEvent', (topic, message) => {
|
||||||
|
// const msg = JSON.parse(message.toString())
|
||||||
|
// console.log(msg)
|
||||||
|
// })
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
eventList
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -1,29 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nav-menus" :class="configStore.layout.layoutMode">
|
<div class="nav-menus" :class="configStore.layout.layoutMode">
|
||||||
<div @click="savePng" class="nav-menu-item">
|
<el-tooltip effect="dark" content="暂降事件" placement="bottom">
|
||||||
<Icon
|
<div @click="temporaryLandingEvent" class="nav-menu-item">
|
||||||
:color="configStore.getColorVal('headerBarTabColor')"
|
<Icon
|
||||||
class="nav-menu-icon"
|
:color="configStore.getColorVal('headerBarTabColor')"
|
||||||
name="el-icon-Camera"
|
class="nav-menu-icon"
|
||||||
size="18"
|
name="el-icon-BellFilled"
|
||||||
/>
|
size="18"
|
||||||
</div>
|
/>
|
||||||
<div @click="onFullScreen" class="nav-menu-item" :class="state.isFullScreen ? 'hover' : ''">
|
<span class="nav-menu-text" v-if="globalPopUpRef?.eventList.length != 0">
|
||||||
<Icon
|
{{ globalPopUpRef?.eventList.length || 0 }}
|
||||||
:color="configStore.getColorVal('headerBarTabColor')"
|
</span>
|
||||||
class="nav-menu-icon"
|
</div>
|
||||||
v-if="state.isFullScreen"
|
</el-tooltip>
|
||||||
name="fa-solid fa-compress"
|
<el-tooltip effect="dark" content="截图" placement="bottom">
|
||||||
size="18"
|
<div @click="savePng" class="nav-menu-item">
|
||||||
/>
|
<Icon
|
||||||
<Icon
|
:color="configStore.getColorVal('headerBarTabColor')"
|
||||||
:color="configStore.getColorVal('headerBarTabColor')"
|
class="nav-menu-icon"
|
||||||
class="nav-menu-icon"
|
name="el-icon-Camera"
|
||||||
v-else
|
size="18"
|
||||||
name="fa-solid fa-expand"
|
/>
|
||||||
size="18"
|
</div>
|
||||||
/>
|
</el-tooltip>
|
||||||
</div>
|
<el-tooltip effect="dark" :content="state.isFullScreen ? '缩小' : '放大'" placement="bottom">
|
||||||
|
<div @click="onFullScreen" class="nav-menu-item" :class="state.isFullScreen ? 'hover' : ''">
|
||||||
|
<Icon
|
||||||
|
:color="configStore.getColorVal('headerBarTabColor')"
|
||||||
|
class="nav-menu-icon"
|
||||||
|
v-if="state.isFullScreen"
|
||||||
|
name="fa-solid fa-compress"
|
||||||
|
size="18"
|
||||||
|
/>
|
||||||
|
<Icon
|
||||||
|
:color="configStore.getColorVal('headerBarTabColor')"
|
||||||
|
class="nav-menu-icon"
|
||||||
|
v-else
|
||||||
|
name="fa-solid fa-expand"
|
||||||
|
size="18"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-tooltip>
|
||||||
<el-dropdown style="height: 100%" @command="handleCommand">
|
<el-dropdown style="height: 100%" @command="handleCommand">
|
||||||
<div class="admin-info" :class="state.currentNavMenu == 'adminInfo' ? 'hover' : ''">
|
<div class="admin-info" :class="state.currentNavMenu == 'adminInfo' ? 'hover' : ''">
|
||||||
<el-avatar :size="25" fit="fill">
|
<el-avatar :size="25" fit="fill">
|
||||||
@@ -51,6 +68,8 @@
|
|||||||
<PopupPwd ref="popupPwd" />
|
<PopupPwd ref="popupPwd" />
|
||||||
<AdminInfo ref="popupAdminInfo" />
|
<AdminInfo ref="popupAdminInfo" />
|
||||||
<!-- <TerminalVue /> -->
|
<!-- <TerminalVue /> -->
|
||||||
|
<!-- 全局暂降事件 -->
|
||||||
|
<globalPopUp ref="globalPopUpRef" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -62,6 +81,7 @@ import { ElMessage } from 'element-plus'
|
|||||||
import Config from './config.vue'
|
import Config from './config.vue'
|
||||||
import { useAdminInfo } from '@/stores/adminInfo'
|
import { useAdminInfo } from '@/stores/adminInfo'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
import globalPopUp from './globalPopUp.vue'
|
||||||
import { routePush } from '@/utils/router'
|
import { routePush } from '@/utils/router'
|
||||||
import { fullUrl } from '@/utils/common'
|
import { fullUrl } from '@/utils/common'
|
||||||
import html2canvas from 'html2canvas'
|
import html2canvas from 'html2canvas'
|
||||||
@@ -80,7 +100,7 @@ const state = reactive({
|
|||||||
showLayoutDrawer: false,
|
showLayoutDrawer: false,
|
||||||
showAdminInfoPopover: false
|
showAdminInfoPopover: false
|
||||||
})
|
})
|
||||||
|
const globalPopUpRef = ref()
|
||||||
const savePng = () => {
|
const savePng = () => {
|
||||||
html2canvas(document.body, {
|
html2canvas(document.body, {
|
||||||
scale: 1,
|
scale: 1,
|
||||||
@@ -122,6 +142,9 @@ const handleCommand = (key: string) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const temporaryLandingEvent = () => {
|
||||||
|
globalPopUpRef.value.open()
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -139,6 +162,7 @@ const handleCommand = (key: string) => {
|
|||||||
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
background-color: v-bind('configStore.getColorVal("headerBarBackground")');
|
||||||
|
|
||||||
.nav-menu-item {
|
.nav-menu-item {
|
||||||
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -233,4 +257,15 @@ const handleCommand = (key: string) => {
|
|||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.nav-menu-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 13px;
|
||||||
|
right: 7px;
|
||||||
|
font-size: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #ff0000;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0 3px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__header .el-dialog__headerbtn:hover .el-icon {
|
.el-dialog__header .el-dialog__headerbtn:hover .el-icon {
|
||||||
color: #409eff;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-dialog__header .el-dialog__title {
|
.el-dialog__header .el-dialog__title {
|
||||||
@@ -244,3 +244,30 @@
|
|||||||
.el-select__input-wrapper {
|
.el-select__input-wrapper {
|
||||||
width: 11px;
|
width: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-drawer__header {
|
||||||
|
background: var(--el-color-primary);
|
||||||
|
padding: 18px;
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__header .el-drawer__close-btn {
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__header .el-drawer__close-btn .el-icon {
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__header .el-drawer__close-btn:hover .el-icon {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__header .el-drawer__title {
|
||||||
|
color: var(--el-color-white);
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|||||||
2
src/styles/element.min.css
vendored
2
src/styles/element.min.css
vendored
@@ -1 +1 @@
|
|||||||
.el-input .el-input__inner{height:30px;line-height:calc(var(--el-input-height, 40px) - 4px)}.datetime-picker{height:32px;padding-top:0;padding-bottom:0}.el-divider__text.is-center{transform:translateX(-50%) translateY(-62%)}.el-menu{user-select:none}.el-menu .el-menu-item:hover,.el-menu .el-sub-menu__title:hover{background-color:var(--el-menu-hover-color) !important;color:var(--el-menu-active-color) !important}.el-menu .el-menu-item:hover .icon,.el-menu .el-sub-menu__title:hover .icon{color:var(--el-menu-active-color) !important}.atooltip{margin-top:0px !important;padding:0 !important}.el-dialog{padding:0px !important}.el-dialog .el-dialog__footer{padding:15px;box-shadow:var(--el-box-shadow);width:100%;bottom:0}.el-dialog__body{max-height:60vh;overflow-y:auto;padding:10px}.el-dialog__header{background:var(--el-color-primary);padding:15px;margin-right:0px}.el-dialog__header .el-dialog__headerbtn{top:5px}.el-dialog__header .el-dialog__headerbtn .el-icon{color:var(--el-color-white)}.el-dialog__header .el-dialog__headerbtn:hover .el-icon{color:#409eff}.el-dialog__header .el-dialog__title{color:var(--el-color-white)}.el-table{--el-table-border-color:var(--ba-border-color)}.el-card{border:none}.el-card__header{border-bottom:1px solid var(--el-border-color-extra-light)}.el-textarea__inner{padding:5px 11px}.el-overlay-dialog,.el-tabs__content,.ba-scroll-style{scrollbar-width:none}.el-overlay-dialog::-webkit-scrollbar,.el-tabs__content::-webkit-scrollbar,.ba-scroll-style::-webkit-scrollbar{width:5px;height:5px}.el-overlay-dialog::-webkit-scrollbar-thumb,.el-tabs__content::-webkit-scrollbar-thumb,.ba-scroll-style::-webkit-scrollbar-thumb{background:#eaeaea;border-radius:var(--el-border-radius-base);box-shadow:none;-webkit-box-shadow:none}.el-overlay-dialog:hover::-webkit-scrollbar-thumb:hover,.el-tabs__content:hover::-webkit-scrollbar-thumb:hover,.ba-scroll-style:hover::-webkit-scrollbar-thumb:hover{background:#c8c9cc}.ba-input-item-radio{margin-bottom:10px}.ba-input-item-radio .el-radio-group .el-radio{margin-bottom:8px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{background:var(--el-color-primary);color:var(--el-color-white)}.el-tabs__header{margin-bottom:0}.el-form--inline .el-form-item{margin-bottom:10px}.el-tabs--border-card>.el-tabs__content{padding:10px}.el-page-header__header{line-height:32px}.el-page-header__header .el-page-header__content{font-size:14px;font-weight:700}.el-select{min-width:200px}.el-tabs__content{height:calc(100% - 40px)}.el-tabs__content .el-tab-pane{height:100%}.el-button--primary:focus{color:var(--el-color-white);outline:0}.el-button--primary:hover{color:var(--el-color-white);border-color:var(--el-color-primary-light-3);background-color:var(--el-color-primary-light-3);outline:0}.el-button.is-plain:focus{color:var(--el-button-text-color);border-color:var(--el-button-border-color)}.el-button.is-plain:hover{color:var(--el-color-primary);border-color:var(--el-color-primary)}.el-button.is-link:focus{color:var(--el-button-text-color)}.el-button.is-link:hover{color:var(--el-button-hover-link-text-color)}.el-button--primary.is-link:hover,.el-button--primary.is-plain:hover,.el-button--primary.is-text:hover{color:var(--el-color-primary-light-5);background-color:var(--el-color-primary-light-9) !important}.el-divider--horizontal{margin:15px 0}.el-step__title{cursor:pointer}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:var(--el-color-primary);opacity:0.6}.sgmap-ctrl-bottom-left{display:none !important}.el-drawer__header{margin-bottom:0 !important}.el-pagination__sizes .el-select{min-width:128px}.el-card__header{padding:10px}.el-card__header span{font-size:16px;font-weight:600}.el-select__input-wrapper{width:11px}
|
.el-input .el-input__inner{height:30px;line-height:calc(var(--el-input-height, 40px) - 4px)}.datetime-picker{height:32px;padding-top:0;padding-bottom:0}.el-divider__text.is-center{transform:translateX(-50%) translateY(-62%)}.el-menu{user-select:none}.el-menu .el-menu-item:hover,.el-menu .el-sub-menu__title:hover{background-color:var(--el-menu-hover-color) !important;color:var(--el-menu-active-color) !important}.el-menu .el-menu-item:hover .icon,.el-menu .el-sub-menu__title:hover .icon{color:var(--el-menu-active-color) !important}.atooltip{margin-top:0px !important;padding:0 !important}.el-dialog{padding:0px !important}.el-dialog .el-dialog__footer{padding:15px;box-shadow:var(--el-box-shadow);width:100%;bottom:0}.el-dialog__body{max-height:60vh;overflow-y:auto;padding:10px}.el-dialog__header{background:var(--el-color-primary);padding:15px;margin-right:0px}.el-dialog__header .el-dialog__headerbtn{top:5px}.el-dialog__header .el-dialog__headerbtn .el-icon{color:var(--el-color-white)}.el-dialog__header .el-dialog__headerbtn:hover .el-icon{color:#ccc}.el-dialog__header .el-dialog__title{color:var(--el-color-white)}.el-table{--el-table-border-color:var(--ba-border-color)}.el-card{border:none}.el-card__header{border-bottom:1px solid var(--el-border-color-extra-light)}.el-textarea__inner{padding:5px 11px}.el-overlay-dialog,.el-tabs__content,.ba-scroll-style{scrollbar-width:none}.el-overlay-dialog::-webkit-scrollbar,.el-tabs__content::-webkit-scrollbar,.ba-scroll-style::-webkit-scrollbar{width:5px;height:5px}.el-overlay-dialog::-webkit-scrollbar-thumb,.el-tabs__content::-webkit-scrollbar-thumb,.ba-scroll-style::-webkit-scrollbar-thumb{background:#eaeaea;border-radius:var(--el-border-radius-base);box-shadow:none;-webkit-box-shadow:none}.el-overlay-dialog:hover::-webkit-scrollbar-thumb:hover,.el-tabs__content:hover::-webkit-scrollbar-thumb:hover,.ba-scroll-style:hover::-webkit-scrollbar-thumb:hover{background:#c8c9cc}.ba-input-item-radio{margin-bottom:10px}.ba-input-item-radio .el-radio-group .el-radio{margin-bottom:8px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{background:var(--el-color-primary);color:var(--el-color-white)}.el-tabs__header{margin-bottom:0}.el-form--inline .el-form-item{margin-bottom:10px}.el-tabs--border-card>.el-tabs__content{padding:10px}.el-page-header__header{line-height:32px}.el-page-header__header .el-page-header__content{font-size:14px;font-weight:700}.el-select{min-width:200px}.el-tabs__content{height:calc(100% - 40px)}.el-tabs__content .el-tab-pane{height:100%}.el-button--primary:focus{color:var(--el-color-white);outline:0}.el-button--primary:hover{color:var(--el-color-white);border-color:var(--el-color-primary-light-3);background-color:var(--el-color-primary-light-3);outline:0}.el-button.is-plain:focus{color:var(--el-button-text-color);border-color:var(--el-button-border-color)}.el-button.is-plain:hover{color:var(--el-color-primary);border-color:var(--el-color-primary)}.el-button.is-link:focus{color:var(--el-button-text-color)}.el-button.is-link:hover{color:var(--el-button-hover-link-text-color)}.el-button--primary.is-link:hover,.el-button--primary.is-plain:hover,.el-button--primary.is-text:hover{color:var(--el-color-primary-light-5);background-color:var(--el-color-primary-light-9) !important}.el-divider--horizontal{margin:15px 0}.el-step__title{cursor:pointer}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:var(--el-color-primary);opacity:0.6}.sgmap-ctrl-bottom-left{display:none !important}.el-drawer__header{margin-bottom:0 !important}.el-pagination__sizes .el-select{min-width:128px}.el-card__header{padding:10px}.el-card__header span{font-size:16px;font-weight:600}.el-select__input-wrapper{width:11px}.el-drawer__header{background:var(--el-color-primary);padding:18px;margin-right:0px}.el-drawer__header .el-drawer__close-btn{top:5px}.el-drawer__header .el-drawer__close-btn .el-icon{color:var(--el-color-white)}.el-drawer__header .el-drawer__close-btn:hover .el-icon{color:#ccc}.el-drawer__header .el-drawer__title{color:var(--el-color-white);font-size:18px}.el-drawer__body{padding:10px}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
}
|
}
|
||||||
.el-dialog__headerbtn:hover {
|
.el-dialog__headerbtn:hover {
|
||||||
.el-icon {
|
.el-icon {
|
||||||
color: #409eff;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,4 +232,28 @@
|
|||||||
.el-select__input-wrapper {
|
.el-select__input-wrapper {
|
||||||
width: 11px;
|
width: 11px;
|
||||||
}
|
}
|
||||||
|
.el-drawer__header {
|
||||||
|
background: var(--el-color-primary);
|
||||||
|
padding: 18px;
|
||||||
|
margin-right: 0px;
|
||||||
|
|
||||||
|
.el-drawer__close-btn {
|
||||||
|
top: 5px;
|
||||||
|
.el-icon {
|
||||||
|
color: var(--el-color-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-drawer__close-btn:hover {
|
||||||
|
.el-icon {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-drawer__title {
|
||||||
|
color: var(--el-color-white);
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-drawer__body {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|||||||
251
src/utils/mqtt.ts
Normal file
251
src/utils/mqtt.ts
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
import type { MqttClient, OnMessageCallback, IClientOptions, IClientSubscribeOptions } from 'mqtt';
|
||||||
|
import mqtt from 'mqtt';
|
||||||
|
|
||||||
|
interface MQTTOptions {
|
||||||
|
protocolId?: string;
|
||||||
|
qos?: 0 | 1 | 2;
|
||||||
|
clean?: boolean;
|
||||||
|
connectTimeout?: number;
|
||||||
|
clientId?: string;
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
reconnectPeriod?: number; // 重连间隔(ms)
|
||||||
|
maxReconnectTimes?: number; // 最大重连次数
|
||||||
|
}
|
||||||
|
|
||||||
|
class MQTT {
|
||||||
|
private topic: string;
|
||||||
|
private client: MqttClient | null = null;
|
||||||
|
private isConnected: boolean = false;
|
||||||
|
private reconnectCount: number = 0;
|
||||||
|
private maxReconnectTimes: number;
|
||||||
|
private reconnectPeriod: number;
|
||||||
|
private isManuallyDisconnected: boolean = false;
|
||||||
|
private defaultOptions: MQTTOptions = {
|
||||||
|
protocolId: 'MQTT',
|
||||||
|
qos: 2,
|
||||||
|
clean: true,
|
||||||
|
connectTimeout: 30 * 1000,
|
||||||
|
clientId: `mqttjs_${Math.random().toString(16).substr(2, 8)}`,
|
||||||
|
username: 't_user',
|
||||||
|
password: 'njcnpqs',
|
||||||
|
reconnectPeriod: 1000, // 默认1秒重试一次
|
||||||
|
maxReconnectTimes: 3, // 默认最大重连5次
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(topic: string, options: MQTTOptions = {}) {
|
||||||
|
this.topic = topic;
|
||||||
|
this.maxReconnectTimes = options.maxReconnectTimes || this.defaultOptions.maxReconnectTimes!;
|
||||||
|
this.reconnectPeriod = options.reconnectPeriod || this.defaultOptions.reconnectPeriod!;
|
||||||
|
|
||||||
|
// 合并选项
|
||||||
|
this.defaultOptions = { ...this.defaultOptions, ...options };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 MQTT 客户端
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
async init(): Promise<void> {
|
||||||
|
if (this.client) {
|
||||||
|
throw new Error('MQTT 客户端已初始化');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/');
|
||||||
|
const mqttUrl = response.headers.get('X-Mqtt-Url') || 'ws://192.168.1.68:8083/mqtt';
|
||||||
|
|
||||||
|
this.client = mqtt.connect(mqttUrl, this.defaultOptions as IClientOptions);
|
||||||
|
this.setupEventListeners();
|
||||||
|
|
||||||
|
// 等待连接成功或超时
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
if (!this.isConnected) {
|
||||||
|
reject(new Error('MQTT 连接超时'));
|
||||||
|
}
|
||||||
|
}, this.defaultOptions.connectTimeout);
|
||||||
|
|
||||||
|
this.client?.on('connect', () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
this.isConnected = true;
|
||||||
|
this.reconnectCount = 0; // 连接成功重置重连计数
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client?.on('error', (error) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
console.error('MQTT 连接错误:', error);
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化 MQTT 失败:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置事件监听器
|
||||||
|
*/
|
||||||
|
private setupEventListeners(): void {
|
||||||
|
if (!this.client) return;
|
||||||
|
|
||||||
|
this.client.on('close', () => {
|
||||||
|
console.log('MQTT 连接已关闭');
|
||||||
|
this.isConnected = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.on('offline', () => {
|
||||||
|
console.log('MQTT 客户端离线');
|
||||||
|
this.isConnected = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.on('reconnect', () => {
|
||||||
|
console.log(`MQTT 正在尝试重连 (${this.reconnectCount + 1}/${this.maxReconnectTimes})...`);
|
||||||
|
|
||||||
|
// 检查是否超过最大重连次数
|
||||||
|
if (this.reconnectCount >= this.maxReconnectTimes) {
|
||||||
|
console.log('已达到最大重连次数,停止重连');
|
||||||
|
this.client?.end(true);
|
||||||
|
this.client = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reconnectCount++;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅主题
|
||||||
|
* @param subscribeOptions 可选的订阅选项
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
async subscribe(subscribeOptions: IClientSubscribeOptions = {}): Promise<void> {
|
||||||
|
if (!this.client || !this.isConnected) {
|
||||||
|
throw new Error('MQTT 客户端未连接');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client?.subscribe(
|
||||||
|
this.topic,
|
||||||
|
{ qos: this.defaultOptions.qos, ...subscribeOptions },
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error('订阅失败:', error);
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
console.log('订阅成功');
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消订阅
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
async unsubscribe(): Promise<void> {
|
||||||
|
if (!this.client || !this.isConnected) {
|
||||||
|
throw new Error('MQTT 客户端未连接');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client?.unsubscribe(this.topic, (error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error('取消订阅失败:', error);
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
console.log('取消订阅成功');
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置消息回调
|
||||||
|
* @param callback 消息回调函数
|
||||||
|
*/
|
||||||
|
onMessage(callback: OnMessageCallback): void {
|
||||||
|
if (!this.client) {
|
||||||
|
throw new Error('MQTT 客户端未初始化');
|
||||||
|
}
|
||||||
|
this.client.on('message', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布消息
|
||||||
|
* @param message 要发布的消息
|
||||||
|
* @param options 发布选项
|
||||||
|
* @returns Promise<void>
|
||||||
|
*/
|
||||||
|
async publish(
|
||||||
|
message: string | Buffer,
|
||||||
|
options: { qos?: 0 | 1 | 2; retain?: boolean } = {}
|
||||||
|
): Promise<void> {
|
||||||
|
if (!this.client || !this.isConnected) {
|
||||||
|
throw new Error('MQTT 客户端未连接');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.client?.publish(
|
||||||
|
this.topic,
|
||||||
|
message,
|
||||||
|
{ qos: this.defaultOptions.qos, ...options },
|
||||||
|
(error) => {
|
||||||
|
if (error) {
|
||||||
|
console.error('消息发布失败:', error);
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
console.log('消息发布成功');
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断开连接
|
||||||
|
* @param force 是否强制断开
|
||||||
|
*/
|
||||||
|
disconnect(force: boolean = false): void {
|
||||||
|
this.isManuallyDisconnected = true;
|
||||||
|
|
||||||
|
if (this.client) {
|
||||||
|
this.client.end(force, () => {
|
||||||
|
console.log('MQTT 连接已断开');
|
||||||
|
this.isConnected = false;
|
||||||
|
this.client = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查连接状态
|
||||||
|
* @returns boolean
|
||||||
|
*/
|
||||||
|
isConnectedToBroker(): boolean {
|
||||||
|
return this.isConnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前重连次数
|
||||||
|
* @returns number
|
||||||
|
*/
|
||||||
|
getReconnectCount(): number {
|
||||||
|
return this.reconnectCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重置重连计数器
|
||||||
|
*/
|
||||||
|
resetReconnectCount(): void {
|
||||||
|
this.reconnectCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MQTT;
|
||||||
@@ -45,10 +45,10 @@ export default class SocketService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch('/')
|
const response = await fetch('/')
|
||||||
const mqttUrl = response.headers.get('X-Mqtt-Url')
|
const WebSocketUrl = response.headers.get('X-WebSocket-Url')
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// ws://192.168.1.69:10407/mgtt/api/pushMessage/
|
// ws://192.168.1.69:10407/mgtt/api/pushMessage/
|
||||||
const url = (mqttUrl || 'ws://192.168.1.68:10407/api/pushMessage/') + id
|
const url = (WebSocketUrl || 'ws://192.168.1.68:10407/api/pushMessage/') + id
|
||||||
this.ws = new WebSocket(url)
|
this.ws = new WebSocket(url)
|
||||||
|
|
||||||
this.ws.onopen = () => this.handleOpen()
|
this.ws.onopen = () => this.handleOpen()
|
||||||
|
|||||||
@@ -89,39 +89,18 @@
|
|||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="version" title="版本信息"></vxe-column>
|
<vxe-column field="version" title="版本信息"></vxe-column>
|
||||||
<vxe-column field="ip" title="网络参数"></vxe-column>
|
<vxe-column field="ip" title="网络参数"></vxe-column>
|
||||||
<!-- <vxe-column field="baseFlowMeal" title="基础套餐(MB)"></vxe-column>
|
|
||||||
<vxe-column field="reamFlowMeal" title="扩展套餐(MB)"></vxe-column>
|
|
||||||
<vxe-column title="剩余流量(MB)">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-tag v-if="row.level === 4" type="primary">
|
|
||||||
{{
|
|
||||||
row.level === 4
|
|
||||||
? (row.baseFlowMeal + row.reamFlowMeal - row.statisValue).toFixed(2)
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</el-tag>
|
|
||||||
</template>
|
|
||||||
</vxe-column>
|
|
||||||
<vxe-column title="流量使用占比(%)">
|
|
||||||
<template #default="{ row }">
|
|
||||||
{{
|
|
||||||
row.level === 4
|
|
||||||
? ((row.statisValue / (row.baseFlowMeal + row.reamFlowMeal)) * 100).toFixed(2)
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</template>
|
|
||||||
</vxe-column> -->
|
|
||||||
<vxe-column field="runFlag" title="终端状态">
|
<vxe-column field="runFlag" title="终端状态">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag v-if="row.runFlag === 0" type="success" size="small">投运</el-tag>
|
<el-tag v-if="row.runFlag === 0" type="success" :disable-transitions="true" size="small">投运</el-tag>
|
||||||
<el-tag v-if="row.runFlag === 1" type="warning" size="small">检修</el-tag>
|
<el-tag v-if="row.runFlag === 1" type="warning" :disable-transitions="true" size="small">检修</el-tag>
|
||||||
<el-tag v-if="row.runFlag === 2" type="danger" size="small">停运</el-tag>
|
<el-tag v-if="row.runFlag === 2" type="danger" :disable-transitions="true" size="small">停运</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column field="comFlag" title="通讯状态">
|
<vxe-column field="comFlag" title="通讯状态">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-tag v-if="row.comFlag === 0" type="danger" size="small">中断</el-tag>
|
<el-tag v-if="row.comFlag === 0" type="danger" :disable-transitions="true" size="small">中断</el-tag>
|
||||||
<el-tag v-if="row.comFlag === 1" type="success" size="small">正常</el-tag>
|
<el-tag v-if="row.comFlag === 1" type="success" :disable-transitions="true" size="small">正常</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</vxe-column>
|
</vxe-column>
|
||||||
<vxe-column title="操作" width="160">
|
<vxe-column title="操作" width="160">
|
||||||
|
|||||||
@@ -53,23 +53,15 @@
|
|||||||
修改提交
|
修改提交
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item style="right: 500px; position: absolute; overflow: hidden">
|
||||||
|
<LocationInformation style="width: 16px; margin-right: 8px; color: #396" />
|
||||||
|
<span style="font-size: 16px; font-weight: bold; color: #396">当前操作节点:</span>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item style="right: 0; position: absolute; overflow: hidden">
|
<el-form-item style="right: 0; position: absolute; overflow: hidden">
|
||||||
|
<div class="title" :class="titleList.length > 5 ? 'titleScroll' : ''">
|
||||||
<div class="title">
|
|
||||||
<LocationInformation style="width: 16px; margin-right: 8px; color: #396" />
|
|
||||||
<span style="font-size: 16px; font-weight: bold; color: #396">当前操作节点:</span>
|
|
||||||
|
|
||||||
<span v-for="(item, index) in titleList">{{ index == 0 ? '' : ' > ' }}{{ item }}</span>
|
<span v-for="(item, index) in titleList">{{ index == 0 ? '' : ' > ' }}{{ item }}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <i style="font-size: 20px; color: #396" icon="el-icon-LocationInformation"></i> -->
|
|
||||||
|
|
||||||
<!-- <div style="float: right">
|
|
||||||
<el-breadcrumb separator-icon="el-icon-ArrowRightBold" style="font-weight: bold">
|
|
||||||
<el-breadcrumb-item v-for="item in titleList" :key="item">
|
|
||||||
{{ item }}
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div> -->
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div id="scrollBox" :style="{ height: Height.height }" style="overflow-y: auto">
|
<div id="scrollBox" :style="{ height: Height.height }" style="overflow-y: auto">
|
||||||
@@ -1609,13 +1601,12 @@
|
|||||||
placeholder="请输入电网侧变电站"
|
placeholder="请输入电网侧变电站"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item class="form-item" label="实际安裝粒置:">
|
<el-form-item class="form-item" label="实际安装位置:">
|
||||||
|
|
||||||
<el-select
|
<el-select
|
||||||
filterable
|
filterable
|
||||||
v-model="lineItem.actualArea"
|
v-model="lineItem.actualArea"
|
||||||
placeholder="请选择实际安裝粒置"
|
placeholder="请选择实际安装位置"
|
||||||
:disabled="pageStatus == 1"
|
:disabled="pageStatus == 1"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@@ -2033,7 +2024,11 @@ const latff: any = ref((rule: any, value: any, callback: any) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const plevel = ref(0)
|
const plevel = ref(0)
|
||||||
|
const nodeDataList=ref()
|
||||||
|
const nodeEventList=ref()
|
||||||
const nodeClick = (e: anyObj, data: any) => {
|
const nodeClick = (e: anyObj, data: any) => {
|
||||||
|
nodeDataList.value = data
|
||||||
|
nodeEventList.value = e
|
||||||
plevel.value = data.data.plevel
|
plevel.value = data.data.plevel
|
||||||
treeClickCount.value++
|
treeClickCount.value++
|
||||||
if (treeClickCount.value > 2) return
|
if (treeClickCount.value > 2) return
|
||||||
@@ -2355,8 +2350,10 @@ const next = async () => {
|
|||||||
const black = () => {
|
const black = () => {
|
||||||
pageStatus.value = 1
|
pageStatus.value = 1
|
||||||
busBarIndex.value = '0'
|
busBarIndex.value = '0'
|
||||||
deviceIndex.value = '0';
|
deviceIndex.value = '0'
|
||||||
lineIndex.value = '0';
|
lineIndex.value = '0'
|
||||||
|
nodeClick(nodeEventList.value,nodeDataList.value)
|
||||||
|
|
||||||
}
|
}
|
||||||
// 确认提交
|
// 确认提交
|
||||||
const onsubmit = () => {
|
const onsubmit = () => {
|
||||||
@@ -2880,58 +2877,107 @@ const evaluate = (node: any) => {
|
|||||||
evaluate(node.parent)
|
evaluate(node.parent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const selectChanged = (value: any) => {
|
const selectChanged = async (value: any) => {
|
||||||
if (value === '3d68ceef26a579efe2fe0cdc654911b7') {
|
let num: any = voltageLevelArr.filter(item => item.id == value)[0].value
|
||||||
setTheDefaultValue(10, 0.38 * 1000, 0.38 * 100)
|
let capacity = 10
|
||||||
|
switch (num) {
|
||||||
//750kv
|
case '500':
|
||||||
} else if (value === '4cf2d844c47a15a1c16a65b4bbfd1b0e') {
|
capacity = 4500
|
||||||
setTheDefaultValue(7000, 750 * 1000, 750 * 100)
|
break
|
||||||
|
case '330':
|
||||||
//6kv
|
capacity = 3000
|
||||||
} else if (value === '37b81bf8aa0fd54098716da3fc0ee433') {
|
break
|
||||||
setTheDefaultValue(100, 6 * 1000, 6 * 100)
|
case '220':
|
||||||
|
capacity = 2000
|
||||||
//10kv
|
break
|
||||||
} else if (value === 'e3da890104e3c4ae1f005021411a1fd7') {
|
case '110':
|
||||||
setTheDefaultValue(100, 10 * 1000, 10 * 100)
|
capacity = 750
|
||||||
|
break
|
||||||
//20kv
|
case '35':
|
||||||
} else if (value === '87065e15765e5899114a6d6b9e4fb3cb') {
|
capacity = 259
|
||||||
setTheDefaultValue(200, 20 * 1000, 20 * 100)
|
break
|
||||||
|
case '10':
|
||||||
//35kv
|
capacity = 100
|
||||||
} else if (value === '8529cfa11356a0666afd3f9fa4da09a4') {
|
break
|
||||||
setTheDefaultValue(250, 35 * 1000, 35 * 100)
|
case '6':
|
||||||
|
capacity = 100
|
||||||
//66kv
|
break
|
||||||
} else if (value === '9ce75596a3368da4adf3374b4fc3b619') {
|
case '0.38':
|
||||||
setTheDefaultValue(500, 66 * 1000, 66 * 100)
|
capacity = 10
|
||||||
|
break
|
||||||
//110kv
|
case '20':
|
||||||
} else if (value === 'e96d74b79bd50ad0bc00a405246f1e1f') {
|
capacity = 200
|
||||||
setTheDefaultValue(750, 110 * 1000, 110 * 100)
|
break
|
||||||
|
case '66':
|
||||||
//220kv
|
capacity = 500
|
||||||
} else if (value === '1b7b58ed8fcc2992b95334eaa9010c41') {
|
break
|
||||||
setTheDefaultValue(2000, 220 * 1000, 220 * 100)
|
case '750':
|
||||||
|
capacity = 7000
|
||||||
//330kv
|
break
|
||||||
} else if (value === 'c1b37350a67f5e229a1f96ace0ad04dc') {
|
case '800':
|
||||||
setTheDefaultValue(3000, 330 * 1000, 330 * 100)
|
capacity = 7000
|
||||||
|
break
|
||||||
//500kv
|
case '1000':
|
||||||
} else if (value === '1fa650685c77db1656c70f9db4a2edc6') {
|
capacity = 9000
|
||||||
setTheDefaultValue(4500, 500 * 1000, 500 * 100)
|
break
|
||||||
|
|
||||||
//1000kv
|
|
||||||
} else if (value === '674cf02fb3fcfd9f99fd786cfca090df') {
|
|
||||||
setTheDefaultValue(9000, 1000 * 1000, 1000 * 100)
|
|
||||||
} else {
|
|
||||||
setTheDefaultValue(10, 10, 10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setvoltageDev(voltageLevelArr.filter(item => item.id == value)[0].value)
|
setTimeout(() => {
|
||||||
|
setTheDefaultValue(capacity, num * 1000, num < 1 ? num * 1000 : 100)
|
||||||
|
setvoltageDev(num)
|
||||||
|
}, 0)
|
||||||
|
|
||||||
|
// // 0.38
|
||||||
|
// if (value === '3d68ceef26a579efe2fe0cdc654911b7') {
|
||||||
|
// setTheDefaultValue(10, 0.38 * 1000, 0.38 * 1000)
|
||||||
|
|
||||||
|
// //750kv
|
||||||
|
// } else if (value === '4cf2d844c47a15a1c16a65b4bbfd1b0e') {
|
||||||
|
// setTheDefaultValue(7000, 750 * 1000, 100)
|
||||||
|
|
||||||
|
// //6kv
|
||||||
|
// } else if (value === '37b81bf8aa0fd54098716da3fc0ee433') {
|
||||||
|
// setTheDefaultValue(100, 6 * 1000, 100)
|
||||||
|
|
||||||
|
// //10kv
|
||||||
|
// } else if (value === 'e3da890104e3c4ae1f005021411a1fd7') {
|
||||||
|
// setTheDefaultValue(100, 10 * 1000, 100)
|
||||||
|
|
||||||
|
// //20kv
|
||||||
|
// } else if (value === '87065e15765e5899114a6d6b9e4fb3cb') {
|
||||||
|
// setTheDefaultValue(200, 20 * 1000, 100)
|
||||||
|
|
||||||
|
// //35kv
|
||||||
|
// } else if (value === '8529cfa11356a0666afd3f9fa4da09a4') {
|
||||||
|
// setTheDefaultValue(250, 35 * 1000, 100)
|
||||||
|
|
||||||
|
// //66kv
|
||||||
|
// } else if (value === '9ce75596a3368da4adf3374b4fc3b619') {
|
||||||
|
// setTheDefaultValue(500, 66 * 1000, 100)
|
||||||
|
|
||||||
|
// //110kv
|
||||||
|
// } else if (value === 'e96d74b79bd50ad0bc00a405246f1e1f') {
|
||||||
|
// setTheDefaultValue(750, 110 * 1000, 100)
|
||||||
|
|
||||||
|
// //220kv
|
||||||
|
// } else if (value === '1b7b58ed8fcc2992b95334eaa9010c41') {
|
||||||
|
// setTheDefaultValue(2000, 220 * 1000, 100)
|
||||||
|
|
||||||
|
// //330kv
|
||||||
|
// } else if (value === 'c1b37350a67f5e229a1f96ace0ad04dc') {
|
||||||
|
// setTheDefaultValue(3000, 330 * 1000, 100)
|
||||||
|
|
||||||
|
// //500kv
|
||||||
|
// } else if (value === '1fa650685c77db1656c70f9db4a2edc6') {
|
||||||
|
// setTheDefaultValue(4500, 500 * 1000, 100)
|
||||||
|
|
||||||
|
// //1000kv
|
||||||
|
// } else if (value === '674cf02fb3fcfd9f99fd786cfca090df') {
|
||||||
|
// setTheDefaultValue(9000, 1000 * 1000, 100)
|
||||||
|
// } else {
|
||||||
|
// setTheDefaultValue(10, 1, 1)
|
||||||
|
// }
|
||||||
|
// setvoltageDev(voltageLevelArr.filter(item => item.id == value)[0].value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const setTheDefaultValue = (capacity: number, pt1: number, pt2: number) => {
|
const setTheDefaultValue = (capacity: number, pt1: number, pt2: number) => {
|
||||||
@@ -3005,10 +3051,10 @@ const area = () => {
|
|||||||
month = '0' + (month + 1)
|
month = '0' + (month + 1)
|
||||||
}
|
}
|
||||||
let day: any = data.getDate()
|
let day: any = data.getDate()
|
||||||
if (day >= 10) {
|
if (day >= 10) {
|
||||||
day = day
|
day = day
|
||||||
} else {
|
} else {
|
||||||
day = '0' + (day )
|
day = '0' + day
|
||||||
}
|
}
|
||||||
deviceBODetail.value.thisTimeCheck = year + '-' + month + '-' + day
|
deviceBODetail.value.thisTimeCheck = year + '-' + month + '-' + day
|
||||||
deviceBODetail.value.loginTime = year + '-' + month + '-' + day
|
deviceBODetail.value.loginTime = year + '-' + month + '-' + day
|
||||||
@@ -3087,9 +3133,12 @@ area()
|
|||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
|
overflow: hidden;
|
||||||
// display: flex;
|
// display: flex;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.titleScroll {
|
||||||
animation: scroll 10s linear infinite; /* 滚动动画 */
|
animation: scroll 10s linear infinite; /* 滚动动画 */
|
||||||
}
|
}
|
||||||
@keyframes scroll {
|
@keyframes scroll {
|
||||||
|
|||||||
@@ -114,7 +114,7 @@
|
|||||||
label="装机容量(MW)"
|
label="装机容量(MW)"
|
||||||
|
|
||||||
>
|
>
|
||||||
{{ proviteData.ratePower }}
|
{{ proviteData?.ratePower }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item
|
<el-descriptions-item
|
||||||
label="PCC供电设备容量(MVA)"
|
label="PCC供电设备容量(MVA)"
|
||||||
|
|||||||
@@ -26,10 +26,10 @@
|
|||||||
<template #operation>
|
<template #operation>
|
||||||
<el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增</el-button>
|
<el-button icon="el-icon-Plus" type="primary" @click="addFormModel">新增</el-button>
|
||||||
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button>
|
<el-button icon="el-icon-Delete" type="primary" @click="deleteEven">删除</el-button>
|
||||||
<el-button icon="el-icon-Download" type="primary" @click="exportExcelTemplate" :loading="loading">
|
<!-- <el-button icon="el-icon-Download" type="primary" @click="exportExcelTemplate" :loading="loading">
|
||||||
模板下载
|
模板下载
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button>
|
<el-button icon="el-icon-Upload" type="primary" @click="importUserData">批量导入</el-button> -->
|
||||||
</template>
|
</template>
|
||||||
</TableHeader>
|
</TableHeader>
|
||||||
<Table ref="tableRef" />
|
<Table ref="tableRef" />
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
<TableHeader datePicker area showExport>
|
<TableHeader datePicker area showExport>
|
||||||
<template #select>
|
<template #select>
|
||||||
<el-form-item label="统计类型:">
|
<!-- <el-form-item label="统计类型:">
|
||||||
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id">
|
<el-select v-model="tableStore.table.params.statisticalType" placeholder="请选择统计类型" value-key="id">
|
||||||
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" :value="item">
|
<el-option v-for="item in classificationData" :key="item.id" :label="item.name" :value="item">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item> -->
|
||||||
<el-form-item label="电压等级:">
|
<el-form-item label="电压等级:">
|
||||||
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
|
<el-select v-model="tableStore.table.params.scale" filterable multiple collapse-tags clearable
|
||||||
placeholder="请选择电压等级" value-key="id">
|
placeholder="请选择电压等级" value-key="id">
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ onMounted(() => {
|
|||||||
})
|
})
|
||||||
const handleNodeClick = (data: any, node: any) => {
|
const handleNodeClick = (data: any, node: any) => {
|
||||||
if (data.level === 6) {
|
if (data.level === 6) {
|
||||||
console.log('🚀 ~ handleNodeClick ~ data:', data)
|
|
||||||
monitoringPoint.setValue('lineId', data.id)
|
monitoringPoint.setValue('lineId', data.id)
|
||||||
monitoringPoint.setValue('pid', data.pids)
|
monitoringPoint.setValue('pid', data.pids)
|
||||||
monitoringPoint.setValue('lineName', data.alias)
|
monitoringPoint.setValue('lineName', data.alias)
|
||||||
|
|||||||
@@ -167,14 +167,14 @@ const init = () => {
|
|||||||
if (formData.condition.length == 0) {
|
if (formData.condition.length == 0) {
|
||||||
return ElMessage.warning('请选择指标类型')
|
return ElMessage.warning('请选择指标类型')
|
||||||
}
|
}
|
||||||
loading.value = true
|
|
||||||
formData.lineId = checked.value ? monitoringPoint.state.lineIds : [monitoringPoint.state.lineId]
|
formData.lineId = checked.value ? monitoringPoint.state.lineIds : [monitoringPoint.state.lineId]
|
||||||
formData.searchBeginTime = datePickerRef.value.timeValue[0]
|
formData.searchBeginTime = datePickerRef.value.timeValue[0]
|
||||||
formData.searchEndTime = datePickerRef.value.timeValue[1]
|
formData.searchEndTime = datePickerRef.value.timeValue[1]
|
||||||
|
|
||||||
if (formData.lineId.length > 3) {
|
if (formData.lineId.length > 3) {
|
||||||
return ElMessage.warning('最多只能选择3个监测点')
|
return ElMessage.warning('最多只能选择3个监测点')
|
||||||
}
|
}
|
||||||
|
loading.value = true
|
||||||
let directionValue = formData.condition.findIndex(item => {
|
let directionValue = formData.condition.findIndex(item => {
|
||||||
if (item === '39') {
|
if (item === '39') {
|
||||||
item = '50'
|
item = '50'
|
||||||
@@ -1695,6 +1695,8 @@ const getEcharts = () => {
|
|||||||
echarts.connect('group')
|
echarts.connect('group')
|
||||||
}
|
}
|
||||||
const conditionChange = () => {
|
const conditionChange = () => {
|
||||||
|
console.log(123)
|
||||||
|
|
||||||
//判断一个指标时
|
//判断一个指标时
|
||||||
if (formData.condition.length == 1) {
|
if (formData.condition.length == 1) {
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -15,12 +15,7 @@
|
|||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<my-echart class="tall pt10" :options="echartList" />
|
<my-echart class="tall pt10" :options="echartList" />
|
||||||
<div class="tall">
|
<div class="tall">
|
||||||
<vxe-table
|
<vxe-table height="auto" auto-resize :data="list" v-bind="defaultAttribute">
|
||||||
height="auto"
|
|
||||||
auto-resize
|
|
||||||
:data="list"
|
|
||||||
v-bind="defaultAttribute"
|
|
||||||
>
|
|
||||||
<vxe-column field="gdName" title="供电公司"></vxe-column>
|
<vxe-column field="gdName" title="供电公司"></vxe-column>
|
||||||
<vxe-column field="subName" title="变电站"></vxe-column>
|
<vxe-column field="subName" title="变电站"></vxe-column>
|
||||||
<vxe-column field="lineName" title="监测点"></vxe-column>
|
<vxe-column field="lineName" title="监测点"></vxe-column>
|
||||||
@@ -125,11 +120,11 @@ const map = (res: any) => {
|
|||||||
visualMap: {
|
visualMap: {
|
||||||
left: 26,
|
left: 26,
|
||||||
bottom: 40,
|
bottom: 40,
|
||||||
|
|
||||||
show: true,
|
show: true,
|
||||||
color: ['#ff0000', '#37b70c'],
|
color: ['#A52a2a', '#DAA520'],
|
||||||
min: minNum,
|
min: 0,
|
||||||
max: maxNum,
|
max: maxNum,
|
||||||
calculable: true,
|
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: '#000',
|
color: '#000',
|
||||||
fontSize: 12
|
fontSize: 12
|
||||||
@@ -140,13 +135,14 @@ const map = (res: any) => {
|
|||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
mapType: 'nanshan',
|
mapType: 'nanshan',
|
||||||
|
type: 'heatmap',
|
||||||
top: 'center',
|
top: 'center',
|
||||||
left: 'center',
|
left: 'center',
|
||||||
width: '65%',
|
width: '65%',
|
||||||
height: '95%',
|
height: '95%',
|
||||||
|
|
||||||
// name: 'AQI',
|
// name: 'AQI',
|
||||||
type: 'heatmap',
|
|
||||||
coordinateSystem: 'geo',
|
coordinateSystem: 'geo',
|
||||||
blurSize: 40,
|
blurSize: 40,
|
||||||
data: areaData
|
data: areaData
|
||||||
@@ -159,6 +155,7 @@ const map = (res: any) => {
|
|||||||
|
|
||||||
// 柱状图数据处理
|
// 柱状图数据处理
|
||||||
const histogram = (res: any) => {
|
const histogram = (res: any) => {
|
||||||
|
echartMapList.value.visualMap.max = Math.max(...res.map((item: any) => item.count)) || 1
|
||||||
echartList.value = {
|
echartList.value = {
|
||||||
title: {
|
title: {
|
||||||
text: '区域暂降次数'
|
text: '区域暂降次数'
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import router from '@/router'
|
|||||||
import { useMonitoringPoint } from '@/stores/monitoringPoint'
|
import { useMonitoringPoint } from '@/stores/monitoringPoint'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
// name: 'Descentsystem/monitoringpoint'
|
name: 'Descentsystem/monitoringpoint'
|
||||||
})
|
})
|
||||||
const isReload = ref(false)
|
const isReload = ref(false)
|
||||||
const navigationRef = ref()
|
const navigationRef = ref()
|
||||||
|
|||||||
@@ -37,9 +37,10 @@
|
|||||||
<span>无暂降</span>
|
<span>无暂降</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- v-if="hackReset" -->
|
||||||
<baidu-map
|
<baidu-map
|
||||||
class="bm-view"
|
class="bm-view"
|
||||||
v-if="hackReset"
|
|
||||||
:zoom="zoom"
|
:zoom="zoom"
|
||||||
:map-click="false"
|
:map-click="false"
|
||||||
:scroll-wheel-zoom="true"
|
:scroll-wheel-zoom="true"
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="selectBox">
|
<div class="selectBox">
|
||||||
<el-select @change="pointChange" filterable clearable v-model="lineId" placeholder="输入监测点名称查询">
|
<el-select @change="pointChange" filterable clearable v-model="lineId" placeholder="输入监测点名称查询">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in areaLineInfo"
|
v-for="item in areaLineInfo"
|
||||||
:key="item.lineId"
|
:key="item.lineId"
|
||||||
@@ -51,9 +51,10 @@
|
|||||||
></el-option>
|
></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- v-if="hackReset" -->
|
||||||
<baidu-map
|
<baidu-map
|
||||||
class="bm-view"
|
class="bm-view"
|
||||||
v-if="hackReset"
|
|
||||||
:zoom="zoom"
|
:zoom="zoom"
|
||||||
:map-click="false"
|
:map-click="false"
|
||||||
:scroll-wheel-zoom="true"
|
:scroll-wheel-zoom="true"
|
||||||
@@ -158,7 +159,7 @@ import PopupEvent from './popupEvent.vue'
|
|||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
// name: 'Descentsystem/overview'
|
name: 'Descentsystem/overview'
|
||||||
}) // 添加响应式变量
|
}) // 添加响应式变量
|
||||||
|
|
||||||
const height = mainHeight(20)
|
const height = mainHeight(20)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-dialog draggable v-model="dialogVisible" :title="title" :before-close="Cancel">
|
<el-dialog draggable v-model="dialogVisible" :title="title" :before-close="Cancel">
|
||||||
<el-form :inline="false" :model="configStore" label-width="auto">
|
<el-form :inline="false" :model="configStore" label-width="auto" ref="formRef" :rules="rules">
|
||||||
<el-divider border-style="dashed">全局</el-divider>
|
<el-divider border-style="dashed">全局</el-divider>
|
||||||
<div class="layout-config-global form-two">
|
<div class="layout-config-global form-two">
|
||||||
<el-form-item label="组件主名称">
|
<el-form-item label="组件主名称" prop="name">
|
||||||
<el-input v-model="configStore.name" placeholder="请输入主题名称" />
|
<el-input v-model.trim="configStore.name" placeholder="请输入主题名称" maxlength="32" show-word-limit />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="后台页面切换动画">
|
<el-form-item label="后台页面切换动画" prop="mainAnimation">
|
||||||
<el-select v-model="configStore.mainAnimation">
|
<el-select v-model="configStore.mainAnimation">
|
||||||
<el-option label="slide-right" value="slide-right"></el-option>
|
<el-option label="slide-right" value="slide-right"></el-option>
|
||||||
<el-option label="slide-left" value="slide-left"></el-option>
|
<el-option label="slide-left" value="slide-left"></el-option>
|
||||||
@@ -17,22 +17,23 @@
|
|||||||
<el-option label="el-zoom-in-bottom" value="el-zoom-in-bottom"></el-option>
|
<el-option label="el-zoom-in-bottom" value="el-zoom-in-bottom"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="组件主题色">
|
<el-form-item label="组件主题色" prop="elementUiPrimary">
|
||||||
<el-color-picker v-model="configStore.elementUiPrimary[0]" />
|
<el-color-picker v-model="configStore.elementUiPrimary[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="表格标题栏背景颜色">
|
<el-form-item label="表格标题栏背景颜色" prop="tableHeaderBackground">
|
||||||
<el-color-picker v-model="configStore.tableHeaderBackground[0]" />
|
<el-color-picker v-model="configStore.tableHeaderBackground[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="表格标题栏文字颜色">
|
<el-form-item label="表格标题栏文字颜色" prop="tableHeaderColor">
|
||||||
<el-color-picker v-model="configStore.tableHeaderColor[0]" />
|
<el-color-picker v-model="configStore.tableHeaderColor[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="表格激活栏颜色">
|
<el-form-item label="表格激活栏颜色" prop="tableCurrent">
|
||||||
<el-color-picker v-model="configStore.tableCurrent[0]" />
|
<el-color-picker v-model="configStore.tableCurrent[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="组件主描述">
|
<el-form-item label="组件主描述" prop="remark">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="configStore.remark"
|
v-model.trim="configStore.remark"
|
||||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||||
|
maxlength="300" show-word-limit
|
||||||
type="textarea"
|
type="textarea"
|
||||||
placeholder="请输入描述"
|
placeholder="请输入描述"
|
||||||
/>
|
/>
|
||||||
@@ -40,32 +41,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<el-divider border-style="dashed">侧边栏</el-divider>
|
<el-divider border-style="dashed">侧边栏</el-divider>
|
||||||
<div class="layout-config-aside form-two">
|
<div class="layout-config-aside form-two">
|
||||||
<el-form-item label="侧边菜单栏背景色">
|
<el-form-item label="侧边菜单栏背景色" prop="menuBackground">
|
||||||
<el-color-picker v-model="configStore.menuBackground[0]" />
|
<el-color-picker v-model="configStore.menuBackground[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="侧边菜单文字颜色">
|
<el-form-item label="侧边菜单文字颜色" prop="menuColor">
|
||||||
<el-color-picker v-model="configStore.menuColor[0]" />
|
<el-color-picker v-model="configStore.menuColor[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="侧边菜单激活项背景色">
|
<el-form-item label="侧边菜单激活项背景色" prop="menuActiveBackground">
|
||||||
<el-color-picker v-model="configStore.menuActiveBackground[0]" />
|
<el-color-picker v-model="configStore.menuActiveBackground[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="侧边菜单激活项文字色">
|
<el-form-item label="侧边菜单激活项文字色" prop="menuActiveColor">
|
||||||
<el-color-picker v-model="configStore.menuActiveColor[0]" />
|
<el-color-picker v-model="configStore.menuActiveColor[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="侧边菜单顶栏背景色">
|
<el-form-item label="侧边菜单顶栏背景色" prop="menuTopBarBackground">
|
||||||
<el-color-picker v-model="configStore.menuTopBarBackground[0]" />
|
<el-color-picker v-model="configStore.menuTopBarBackground[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-divider border-style="dashed">顶栏</el-divider>
|
<el-divider border-style="dashed">顶栏</el-divider>
|
||||||
<div class="layout-config-aside form-two">
|
<div class="layout-config-aside form-two">
|
||||||
<el-form-item label="顶栏背景色">
|
<el-form-item label="顶栏背景色" prop="headerBarBackground">
|
||||||
<el-color-picker v-model="configStore.headerBarBackground[0]" />
|
<el-color-picker v-model="configStore.headerBarBackground[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="顶栏文字色">
|
<el-form-item label="顶栏文字色" prop="headerBarTabColor">
|
||||||
<el-color-picker v-model="configStore.headerBarTabColor[0]" />
|
<el-color-picker v-model="configStore.headerBarTabColor[0]" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="顶栏logo">
|
<el-form-item label="顶栏logo" prop="logoFile">
|
||||||
<el-image
|
<el-image
|
||||||
style="height: 50px"
|
style="height: 50px"
|
||||||
:src="logoFile.url"
|
:src="logoFile.url"
|
||||||
@@ -133,11 +134,176 @@ const configStore = ref({
|
|||||||
faviconFile: '',
|
faviconFile: '',
|
||||||
remark: ''
|
remark: ''
|
||||||
})
|
})
|
||||||
|
// 完善校验规则
|
||||||
|
const rules = reactive({
|
||||||
|
name: [{ required: true, message: '请输入组件主名称', trigger: 'blur' }],
|
||||||
|
remark: [{ required: true, message: '请输入组件备注', trigger: 'blur' }],
|
||||||
|
mainAnimation: [{ required: true, message: '请选择页面切换动画', trigger: 'change' }],
|
||||||
|
elementUiPrimary: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择组件主题色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableHeaderBackground: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择表格标题栏背景颜色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableHeaderColor: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择表格标题栏文字颜色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableCurrent: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择表格激活栏颜色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
menuBackground: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择侧边菜单栏背景色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
menuColor: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择侧边菜单文字颜色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
menuActiveBackground: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择侧边菜单激活项背景色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
menuActiveColor: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择侧边菜单激活项文字色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
menuTopBarBackground: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择侧边菜单顶栏背景色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
headerBarBackground: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择顶栏背景色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
headerBarTabColor: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value || !value[0]) {
|
||||||
|
callback(new Error('请选择顶栏文字色'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
logoFile: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
validator: (rule: any, value: any, callback: any) => {
|
||||||
|
// 编辑时如果已有图片则不校验
|
||||||
|
if (title.value === '修改主题' && logoFile.url) {
|
||||||
|
callback()
|
||||||
|
} else if (!value && !logoFile.url) {
|
||||||
|
callback(new Error('请上传顶栏logo'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trigger: 'change'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
const logoFile = reactive({
|
const logoFile = reactive({
|
||||||
url: '',
|
url: '',
|
||||||
raw: ''
|
raw: ''
|
||||||
})
|
})
|
||||||
|
const formRef = ref()
|
||||||
|
|
||||||
const open = (e: any) => {
|
const open = (e: any) => {
|
||||||
title.value = e.text
|
title.value = e.text
|
||||||
@@ -167,50 +333,54 @@ const open = (e: any) => {
|
|||||||
}
|
}
|
||||||
// 确定主题
|
// 确定主题
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
configStore.value.faviconFile = configStore.value.logoFile
|
formRef.value.validate((valid: boolean) => {
|
||||||
configStore.value.color = configStore.value.elementUiPrimary[0]
|
if (valid) {
|
||||||
let form = new FormData()
|
configStore.value.faviconFile = configStore.value.logoFile
|
||||||
for (let k in configStore.value) {
|
configStore.value.color = configStore.value.elementUiPrimary[0]
|
||||||
if (
|
let form = new FormData()
|
||||||
k == 'logoFile' ||
|
for (let k in configStore.value) {
|
||||||
k == 'faviconFile' ||
|
if (
|
||||||
k == 'name' ||
|
k == 'logoFile' ||
|
||||||
k == 'color' ||
|
k == 'faviconFile' ||
|
||||||
k == 'remark' ||
|
k == 'name' ||
|
||||||
k == 'mainAnimation' ||
|
k == 'color' ||
|
||||||
k == 'id'
|
k == 'remark' ||
|
||||||
) {
|
k == 'mainAnimation' ||
|
||||||
form.append(k, configStore.value[k])
|
k == 'id'
|
||||||
} else if (k == 'logoUrl' || k == 'faviconUrl') {
|
) {
|
||||||
if (configStore.value.logoFile == null) {
|
form.append(k, configStore.value[k])
|
||||||
let str = configStore.value[k].match(/base64,([^"]+)/)[1]
|
} else if (k == 'logoUrl' || k == 'faviconUrl') {
|
||||||
let bin = atob(str)
|
if (configStore.value.logoFile == null) {
|
||||||
let arr = new Array(bin.length)
|
let str = configStore.value[k].match(/base64,([^"]+)/)[1]
|
||||||
for (let i = 0; i < bin.length; i++) {
|
let bin = atob(str)
|
||||||
arr[i] = bin.charCodeAt(i)
|
let arr = new Array(bin.length)
|
||||||
|
for (let i = 0; i < bin.length; i++) {
|
||||||
|
arr[i] = bin.charCodeAt(i)
|
||||||
|
}
|
||||||
|
let b = new Uint8Array(arr)
|
||||||
|
const blob = new Blob([b], { type: 'image/jpeg' })
|
||||||
|
form.append('faviconFile', blob)
|
||||||
|
form.append('logoFile', blob)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
form.append(k, JSON.stringify(configStore.value[k]))
|
||||||
}
|
}
|
||||||
let b = new Uint8Array(arr)
|
|
||||||
const blob = new Blob([b], { type: 'image/jpeg' })
|
|
||||||
form.append('faviconFile', blob)
|
|
||||||
form.append('logoFile', blob)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
form.append(k, JSON.stringify(configStore.value[k]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (title.value == '新增主题') {
|
if (title.value == '新增主题') {
|
||||||
addTheme(form).then(res => {
|
addTheme(form).then(res => {
|
||||||
ElMessage.success('新增成功')
|
ElMessage.success('新增成功')
|
||||||
Cancel()
|
Cancel()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (title.value == '修改主题') {
|
if (title.value == '修改主题') {
|
||||||
updateTheme(form).then(res => {
|
updateTheme(form).then(res => {
|
||||||
ElMessage.success('修改成功')
|
ElMessage.success('修改成功')
|
||||||
Cancel()
|
Cancel()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
// 取消
|
// 取消
|
||||||
const Cancel = () => {
|
const Cancel = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user