develop-cloud #2
@ -330,6 +330,23 @@ export function configStrategy(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取策略运行参数配置(按站点)
|
||||||
|
export function getStrategyRuntimeConfig(siteId) {
|
||||||
|
return request({
|
||||||
|
url: `/system/strategyRuntimeConfig/getBySiteId?siteId=${siteId}`,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存策略运行参数配置(按站点)
|
||||||
|
export function saveStrategyRuntimeConfig(data) {
|
||||||
|
return request({
|
||||||
|
url: `/system/strategyRuntimeConfig/save`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//http://localhost:8089/strategy/temp/getTempNameList?strategyId=1&siteId=021_FXX_01
|
//http://localhost:8089/strategy/temp/getTempNameList?strategyId=1&siteId=021_FXX_01
|
||||||
//获取策略下的所有模板列表
|
//获取策略下的所有模板列表
|
||||||
export function getTempNameList({siteId, strategyId}) {
|
export function getTempNameList({siteId, strategyId}) {
|
||||||
|
|||||||
@ -4,7 +4,10 @@
|
|||||||
<el-row type="flex" >
|
<el-row type="flex" >
|
||||||
<el-card shadow="hover" class="card common-card-container-body-no-padding" v-for="(item,index) in data" :key="index+'zdInfo'" :style="{borderBottomColor:item.color}">
|
<el-card shadow="hover" class="card common-card-container-body-no-padding" v-for="(item,index) in data" :key="index+'zdInfo'" :style="{borderBottomColor:item.color}">
|
||||||
<div class="info">{{ item.title }}</div>
|
<div class="info">{{ item.title }}</div>
|
||||||
<div class="num">{{item.num | formatNumber}}</div>
|
<div class="num">
|
||||||
|
<i v-if="item.loading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{item.num | formatNumber}}</span>
|
||||||
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -18,30 +21,35 @@ export default {
|
|||||||
title:'站点总数(座)',
|
title:'站点总数(座)',
|
||||||
num:'',
|
num:'',
|
||||||
color:'#FFBD00',
|
color:'#FFBD00',
|
||||||
attr:'siteNum'
|
attr:'siteNum',
|
||||||
|
loading: true
|
||||||
},{
|
},{
|
||||||
title:'装机功率(MW)',
|
title:'装机功率(MW)',
|
||||||
num:'',
|
num:'',
|
||||||
color:'#3C81FF',
|
color:'#3C81FF',
|
||||||
attr:'installPower'
|
attr:'installPower',
|
||||||
|
loading: true
|
||||||
|
|
||||||
},{
|
},{
|
||||||
title:'装机容量(MW)',
|
title:'装机容量(MW)',
|
||||||
num:'',
|
num:'',
|
||||||
color:'#5AC7C0',
|
color:'#5AC7C0',
|
||||||
attr:'installCapacity'
|
attr:'installCapacity',
|
||||||
|
loading: true
|
||||||
|
|
||||||
},{
|
},{
|
||||||
title:'总充电量(KWh)',
|
title:'总充电量(KWh)',
|
||||||
num:'',
|
num:'',
|
||||||
color:'#A696FF',
|
color:'#A696FF',
|
||||||
attr:'totalChargedCap'
|
attr:'totalChargedCap',
|
||||||
|
loading: true
|
||||||
|
|
||||||
},{
|
},{
|
||||||
title:'总放电量(KWh)',
|
title:'总放电量(KWh)',
|
||||||
num:'',
|
num:'',
|
||||||
color:'#A696FF',
|
color:'#A696FF',
|
||||||
attr:'totalDischargedCap'
|
attr:'totalDischargedCap',
|
||||||
|
loading: true
|
||||||
|
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@ -50,6 +58,7 @@ export default {
|
|||||||
setData(res = {}){
|
setData(res = {}){
|
||||||
this.data.forEach((item)=>{
|
this.data.forEach((item)=>{
|
||||||
item.num =res[item.attr]
|
item.num =res[item.attr]
|
||||||
|
item.loading = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,8 +2,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="zd-select-container">
|
<div class="zd-select-container">
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<el-form-item label="站点选择">
|
<el-form-item :label="showLabel ? '站点选择' : ''" :class="{'no-label': !showLabel}">
|
||||||
<el-select v-model="id" placeholder="请选择换电站名称" :loading="loading" loading-text="正在加载数据" @change="onSubmit">
|
<el-select
|
||||||
|
v-model="id"
|
||||||
|
:size="size"
|
||||||
|
:placeholder="placeholder"
|
||||||
|
:loading="loading"
|
||||||
|
loading-text="正在加载数据"
|
||||||
|
:style="{width: selectWidth}"
|
||||||
|
@change="onSubmit"
|
||||||
|
>
|
||||||
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'zdxeSelect'"></el-option>
|
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'zdxeSelect'"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -15,7 +23,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.zd-select-container {
|
||||||
|
.el-form {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.no-label ::v-deep .el-form-item__label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.no-label ::v-deep .el-form-item__content {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import {getAllSites} from '@/api/ems/zddt'
|
import {getAllSites} from '@/api/ems/zddt'
|
||||||
@ -31,6 +53,26 @@ import {mapGetters} from "vuex"
|
|||||||
type:String,
|
type:String,
|
||||||
default:'',
|
default:'',
|
||||||
required:false
|
required:false
|
||||||
|
},
|
||||||
|
showLabel: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: 'medium',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: String,
|
||||||
|
default: '请选择换电站名称',
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
selectWidth: {
|
||||||
|
type: String,
|
||||||
|
default: '220px',
|
||||||
|
required: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -44,6 +86,16 @@ import {mapGetters} from "vuex"
|
|||||||
computed:{
|
computed:{
|
||||||
...mapGetters(["zdList"]),
|
...mapGetters(["zdList"]),
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
defaultSiteId(newVal) {
|
||||||
|
if (!newVal || !this.siteList || this.siteList.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.siteList.find(item => item.siteId === newVal) && this.id !== newVal) {
|
||||||
|
this.id = newVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods:{
|
methods:{
|
||||||
onSubmit(){
|
onSubmit(){
|
||||||
this.$emit('submitSite',this.id)
|
this.$emit('submitSite',this.id)
|
||||||
@ -60,7 +112,6 @@ import {mapGetters} from "vuex"
|
|||||||
getList(){
|
getList(){
|
||||||
return getAllSites().then(response => {
|
return getAllSites().then(response => {
|
||||||
this.siteList = response.data || []
|
this.siteList = response.data || []
|
||||||
console.log("获取站点列表返回数据",response,this.siteList)
|
|
||||||
this.setDefaultSite()
|
this.setDefaultSite()
|
||||||
}).finally(() => {this.loading=false;this.searchLoading=false})
|
}).finally(() => {this.loading=false;this.searchLoading=false})
|
||||||
}
|
}
|
||||||
@ -71,15 +122,13 @@ import {mapGetters} from "vuex"
|
|||||||
this.$nextTick(()=>{
|
this.$nextTick(()=>{
|
||||||
if(this.getListByStore){
|
if(this.getListByStore){
|
||||||
if(this.zdList.length === 0){
|
if(this.zdList.length === 0){
|
||||||
this.getList().then(()=>{
|
this.getList().then(()=>{
|
||||||
this.$store.commit('SET_ZD_LIST', this.siteList)
|
this.$store.commit('SET_ZD_LIST', this.siteList)
|
||||||
console.log("从store中获取站点列表数据,但是store中的zdList=[],所以从接口获取数据",this.zdList,this.siteList)
|
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
this.siteList = this.zdList
|
this.siteList = this.zdList
|
||||||
this.loading=false
|
this.loading=false
|
||||||
this.searchLoading=false
|
this.searchLoading=false
|
||||||
console.log("从store中获取站点列表数据",this.zdList,this.siteList)
|
|
||||||
this.setDefaultSite()
|
this.setDefaultSite()
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@ -22,6 +22,16 @@
|
|||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
<div v-if="device!=='mobile'" class="site-select-wrap">
|
||||||
|
<zd-select
|
||||||
|
:get-list-by-store="true"
|
||||||
|
:show-label="false"
|
||||||
|
size="mini"
|
||||||
|
select-width="220px"
|
||||||
|
:default-site-id="$route.query.siteId"
|
||||||
|
@submitSite="onSiteChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="hover">
|
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="hover">
|
||||||
<div class="avatar-wrapper">
|
<div class="avatar-wrapper">
|
||||||
@ -54,6 +64,7 @@ import Screenfull from '@/components/Screenfull'
|
|||||||
import SizeSelect from '@/components/SizeSelect'
|
import SizeSelect from '@/components/SizeSelect'
|
||||||
import Search from '@/components/HeaderSearch'
|
import Search from '@/components/HeaderSearch'
|
||||||
import BigDataPopup from '@/components/BigDataPopup'
|
import BigDataPopup from '@/components/BigDataPopup'
|
||||||
|
import ZdSelect from '@/components/Ems/ZdSelect/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: ['setLayout'],
|
emits: ['setLayout'],
|
||||||
@ -64,7 +75,8 @@ export default {
|
|||||||
Screenfull,
|
Screenfull,
|
||||||
SizeSelect,
|
SizeSelect,
|
||||||
Search,
|
Search,
|
||||||
BigDataPopup
|
BigDataPopup,
|
||||||
|
ZdSelect
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
@ -85,6 +97,22 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
onSiteChange(id) {
|
||||||
|
if (!id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
localStorage.setItem('global_site_id', id)
|
||||||
|
if (id !== this.$route.query.siteId) {
|
||||||
|
this.$router.push({
|
||||||
|
path: this.$route.path,
|
||||||
|
query: {
|
||||||
|
...this.$route.query,
|
||||||
|
siteId: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.$store.dispatch('getSiteAlarmNum', id)
|
||||||
|
},
|
||||||
showBigDataImg() {
|
showBigDataImg() {
|
||||||
this.$refs.bigDataPopup.show = true
|
this.$refs.bigDataPopup.show = true
|
||||||
},
|
},
|
||||||
@ -150,6 +178,22 @@ export default {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
|
||||||
|
.site-select-wrap {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 10px 0 14px;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
::v-deep .el-form-item__content {
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input__inner {
|
||||||
|
border-radius: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.big-data-container {
|
.big-data-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
@ -215,6 +259,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -10,11 +10,16 @@ import { isRelogin } from '@/utils/request'
|
|||||||
NProgress.configure({ showSpinner: false })
|
NProgress.configure({ showSpinner: false })
|
||||||
|
|
||||||
const whiteList = ['/login', '/register']
|
const whiteList = ['/login', '/register']
|
||||||
|
const GLOBAL_SITE_STORAGE_KEY = 'global_site_id'
|
||||||
|
|
||||||
const isWhiteList = (path) => {
|
const isWhiteList = (path) => {
|
||||||
return whiteList.some(pattern => isPathMatch(pattern, path))
|
return whiteList.some(pattern => isPathMatch(pattern, path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shouldAppendSiteId = (path) => {
|
||||||
|
return !['/login', '/register', '/404', '/401'].includes(path) && !path.startsWith('/redirect')
|
||||||
|
}
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
NProgress.start()
|
NProgress.start()
|
||||||
if (getToken()) {
|
if (getToken()) {
|
||||||
@ -26,6 +31,24 @@ router.beforeEach((to, from, next) => {
|
|||||||
} else if (isWhiteList(to.path)) {
|
} else if (isWhiteList(to.path)) {
|
||||||
next()
|
next()
|
||||||
} else {
|
} else {
|
||||||
|
const routeSiteId = to.query?.siteId
|
||||||
|
if (routeSiteId) {
|
||||||
|
localStorage.setItem(GLOBAL_SITE_STORAGE_KEY, routeSiteId)
|
||||||
|
} else {
|
||||||
|
const globalSiteId = localStorage.getItem(GLOBAL_SITE_STORAGE_KEY)
|
||||||
|
if (globalSiteId && shouldAppendSiteId(to.path)) {
|
||||||
|
next({
|
||||||
|
path: to.path,
|
||||||
|
query: {
|
||||||
|
...to.query,
|
||||||
|
siteId: globalSiteId
|
||||||
|
},
|
||||||
|
hash: to.hash,
|
||||||
|
replace: true
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
if (store.getters.roles.length === 0) {
|
if (store.getters.roles.length === 0) {
|
||||||
isRelogin.show = true
|
isRelogin.show = true
|
||||||
// 判断当前用户是否已拉取完user_info信息
|
// 判断当前用户是否已拉取完user_info信息
|
||||||
|
|||||||
@ -285,6 +285,28 @@ export const dzjk = [
|
|||||||
activeSecondMenuName: 'DzjkClpz'
|
activeSecondMenuName: 'DzjkClpz'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'runtimeParam',
|
||||||
|
component: () => import('@/views/ems/dzjk/clpz/runtimeParam/index.vue'),
|
||||||
|
name: 'DzjkClpzRuntimeParam',
|
||||||
|
meta: {
|
||||||
|
title: '运行参数',
|
||||||
|
breadcrumb: false,
|
||||||
|
activeMenu: '/dzjk',
|
||||||
|
activeSecondMenuName: 'DzjkClpz'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sbbh',
|
||||||
|
component: () => import('@/views/ems/site/sbbh/index.vue'),
|
||||||
|
name: 'DzjkClpzSbbh',
|
||||||
|
meta: {
|
||||||
|
title: '设备保护',
|
||||||
|
breadcrumb: false,
|
||||||
|
activeMenu: '/dzjk',
|
||||||
|
activeSecondMenuName: 'DzjkClpz'
|
||||||
|
},
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'xftg',
|
// path: 'xftg',
|
||||||
// component: () => import('@/views/ems/dzjk/clpz/xftg/index.vue'),
|
// component: () => import('@/views/ems/dzjk/clpz/xftg/index.vue'),
|
||||||
@ -300,4 +322,3 @@ export const dzjk = [
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@ -98,7 +98,7 @@ export const constantRoutes = [
|
|||||||
path: 'monitor-point-mapping',
|
path: 'monitor-point-mapping',
|
||||||
component: () => import('@/views/ems/site/zdlb/MonitorPointMapping.vue'),
|
component: () => import('@/views/ems/site/zdlb/MonitorPointMapping.vue'),
|
||||||
name: 'MonitorPointMapping',
|
name: 'MonitorPointMapping',
|
||||||
meta: { title: '单站监控项目点位配置', activeMenu: '/ems/site/zdlb' }
|
meta: { title: '单站监控项目点位配置', activeMenu: '/dzjk/clpz/sbbh' }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -50,4 +50,3 @@ export default {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
137
src/views/ems/dzjk/clpz/runtimeParam/index.vue
Normal file
137
src/views/ems/dzjk/clpz/runtimeParam/index.vue
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ems-dashboard-editor-container" v-loading="loading">
|
||||||
|
<el-card shadow="always" class="common-card-container">
|
||||||
|
<div slot="header" class="clearfix">
|
||||||
|
<span class="card-title">运行参数配置</span>
|
||||||
|
<span class="site-tag">站点:{{ siteId || '-' }}</span>
|
||||||
|
</div>
|
||||||
|
<el-form ref="form" :model="form" :rules="rules" label-width="180px" style="max-width: 760px;">
|
||||||
|
<el-form-item label="SOC下限(%)" prop="socDown">
|
||||||
|
<el-input-number v-model="form.socDown" :min="0" :max="100" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="SOC上限(%)" prop="socUp">
|
||||||
|
<el-input-number v-model="form.socUp" :min="0" :max="100" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防逆流阈值(kW)" prop="antiReverseThreshold">
|
||||||
|
<el-input-number v-model="form.antiReverseThreshold" :min="0" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防逆流阈值上浮比例(%)" prop="antiReverseRangePercent">
|
||||||
|
<el-input-number v-model="form.antiReverseRangePercent" :min="0" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防逆流恢复上限(kW)" prop="antiReverseUp">
|
||||||
|
<el-input-number v-model="form.antiReverseUp" :min="0" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防逆流降功率比例(%)" prop="antiReversePowerDownPercent">
|
||||||
|
<el-input-number v-model="form.antiReversePowerDownPercent" :min="0" :max="100" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="防逆流硬停阈值(kW)" prop="antiReverseHardStopThreshold">
|
||||||
|
<el-input-number v-model="form.antiReverseHardStopThreshold" :min="0" :step="1" :precision="2" controls-position="right" style="width: 220px;" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" :loading="saveLoading" @click="handleSave">保存</el-button>
|
||||||
|
<el-button @click="init">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import getQuerySiteId from '@/mixins/ems/getQuerySiteId'
|
||||||
|
import { getStrategyRuntimeConfig, saveStrategyRuntimeConfig } from '@/api/ems/dzjk'
|
||||||
|
|
||||||
|
const emptyForm = () => ({
|
||||||
|
siteId: '',
|
||||||
|
socDown: 0,
|
||||||
|
socUp: 100,
|
||||||
|
antiReverseThreshold: 30,
|
||||||
|
antiReverseRangePercent: 20,
|
||||||
|
antiReverseUp: 100,
|
||||||
|
antiReversePowerDownPercent: 10,
|
||||||
|
antiReverseHardStopThreshold: 20
|
||||||
|
})
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DzjkClpzRuntimeParam',
|
||||||
|
mixins: [getQuerySiteId],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
saveLoading: false,
|
||||||
|
form: emptyForm(),
|
||||||
|
rules: {
|
||||||
|
socDown: [
|
||||||
|
{ required: true, message: '请输入SOC下限', trigger: 'change' }
|
||||||
|
],
|
||||||
|
socUp: [
|
||||||
|
{ required: true, message: '请输入SOC上限', trigger: 'change' }
|
||||||
|
],
|
||||||
|
antiReverseThreshold: [
|
||||||
|
{ required: true, message: '请输入防逆流阈值', trigger: 'change' }
|
||||||
|
],
|
||||||
|
antiReverseRangePercent: [
|
||||||
|
{ required: true, message: '请输入防逆流阈值上浮比例', trigger: 'change' }
|
||||||
|
],
|
||||||
|
antiReverseUp: [
|
||||||
|
{ required: true, message: '请输入防逆流恢复上限', trigger: 'change' }
|
||||||
|
],
|
||||||
|
antiReversePowerDownPercent: [
|
||||||
|
{ required: true, message: '请输入防逆流降功率比例', trigger: 'change' }
|
||||||
|
],
|
||||||
|
antiReverseHardStopThreshold: [
|
||||||
|
{ required: true, message: '请输入防逆流硬停阈值', trigger: 'change' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
if (!this.siteId) {
|
||||||
|
this.form = emptyForm()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading = true
|
||||||
|
getStrategyRuntimeConfig(this.siteId).then(response => {
|
||||||
|
const data = response?.data || {}
|
||||||
|
this.form = {
|
||||||
|
...emptyForm(),
|
||||||
|
...data,
|
||||||
|
siteId: this.siteId
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSave() {
|
||||||
|
if (!this.siteId) {
|
||||||
|
this.$message.error('缺少站点ID')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$refs.form.validate(valid => {
|
||||||
|
if (!valid) return
|
||||||
|
if (Number(this.form.socDown) > Number(this.form.socUp)) {
|
||||||
|
this.$message.error('SOC下限不能大于SOC上限')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.saveLoading = true
|
||||||
|
saveStrategyRuntimeConfig({ ...this.form, siteId: this.siteId }).then(response => {
|
||||||
|
if (response?.code === 200) {
|
||||||
|
this.$message.success('保存成功')
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.saveLoading = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.site-tag {
|
||||||
|
float: right;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -9,14 +9,6 @@
|
|||||||
<el-form-item label="soc限制" prop="sdcLimit" required>
|
<el-form-item label="soc限制" prop="sdcLimit" required>
|
||||||
<el-switch :active-value="1" :inactive-value="0" v-model="formData.sdcLimit"></el-switch>
|
<el-switch :active-value="1" :inactive-value="0" v-model="formData.sdcLimit"></el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <template v-if="formData.sdcLimit === 1">-->
|
|
||||||
<el-form-item label="soc下限" prop="sdcDown">
|
|
||||||
<el-input v-model="formData.sdcDown" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="soc上限" prop="sdcUp">
|
|
||||||
<el-input v-model="formData.sdcUp" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- </template>-->
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button type="primary" size="mini" @click="addTime">新增</el-button>
|
<el-button type="primary" size="mini" @click="addTime">新增</el-button>
|
||||||
<!-- 新增时间段表单-->
|
<!-- 新增时间段表单-->
|
||||||
@ -64,6 +56,12 @@
|
|||||||
<el-input v-model="formInline.chargeDischargePower" placeholder="请输入"
|
<el-input v-model="formInline.chargeDischargePower" placeholder="请输入"
|
||||||
:style="{width: '100%'}"></el-input>
|
:style="{width: '100%'}"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="soc下限" prop="sdcDown">
|
||||||
|
<el-input v-model="formInline.sdcDown" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="soc上限" prop="sdcUp">
|
||||||
|
<el-input v-model="formInline.sdcUp" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="充电状态" prop="chargeStatus">
|
<el-form-item label="充电状态" prop="chargeStatus">
|
||||||
<el-select v-model="formInline.chargeStatus" placeholder="请选择" :style="{width: '100%'}">
|
<el-select v-model="formInline.chargeStatus" placeholder="请选择" :style="{width: '100%'}">
|
||||||
<el-option v-for="(value,key) in chargeStatusOptions" :key="key+'chargeStatusOptions'" :label="value"
|
<el-option v-for="(value,key) in chargeStatusOptions" :key="key+'chargeStatusOptions'" :label="value"
|
||||||
@ -84,20 +82,100 @@
|
|||||||
<el-table-column
|
<el-table-column
|
||||||
prop="startTime"
|
prop="startTime"
|
||||||
label="开始时间">
|
label="开始时间">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-time-select
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model="scope.row.startTime"
|
||||||
|
placeholder="开始时间"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:01',
|
||||||
|
end: '23:59'
|
||||||
|
}"
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ scope.row.startTime || '-' }}</span>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="endTime"
|
prop="endTime"
|
||||||
label="结束时间">
|
label="结束时间">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-time-select
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model="scope.row.endTime"
|
||||||
|
placeholder="结束时间"
|
||||||
|
:picker-options="{
|
||||||
|
start: '00:00',
|
||||||
|
step: '00:01',
|
||||||
|
end: '23:59',
|
||||||
|
minTime: scope.row.startTime
|
||||||
|
}"
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ scope.row.endTime || '-' }}</span>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="chargeDischargePower"
|
prop="chargeDischargePower"
|
||||||
label="充放功率(kW)">
|
label="充放功率(kW)">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model.trim="scope.row.chargeDischargePower"
|
||||||
|
placeholder="请输入"
|
||||||
|
clearable
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ scope.row.chargeDischargePower || '-' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="sdcDown"
|
||||||
|
label="SOC下限">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model.trim="scope.row.sdcDown"
|
||||||
|
placeholder="请输入"
|
||||||
|
clearable
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ scope.row.sdcDown === null || scope.row.sdcDown === undefined || scope.row.sdcDown === '' ? '-' : scope.row.sdcDown + '%' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
prop="sdcUp"
|
||||||
|
label="SOC上限">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model.trim="scope.row.sdcUp"
|
||||||
|
placeholder="请输入"
|
||||||
|
clearable
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ scope.row.sdcUp === null || scope.row.sdcUp === undefined || scope.row.sdcUp === '' ? '-' : scope.row.sdcUp + '%' }}</span>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="chargeStatus"
|
prop="chargeStatus"
|
||||||
label="充电状态">
|
label="充电状态">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ chargeStatusOptions[scope.row.chargeStatus] }}
|
<el-select
|
||||||
|
v-if="mode === 'edit'"
|
||||||
|
v-model="scope.row.chargeStatus"
|
||||||
|
placeholder="请选择"
|
||||||
|
:style="{width: '100%'}"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="(value,key) in chargeStatusOptions"
|
||||||
|
:key="key+'chargeStatusEditOptions'"
|
||||||
|
:label="value"
|
||||||
|
:value="key"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
<span v-else>{{ chargeStatusOptions[scope.row.chargeStatus] }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
@ -138,8 +216,6 @@ export default {
|
|||||||
formData: {
|
formData: {
|
||||||
templateName: '',
|
templateName: '',
|
||||||
sdcLimit: false,
|
sdcLimit: false,
|
||||||
sdcDown: '',
|
|
||||||
sdcUp: '',
|
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
templateName: [{
|
templateName: [{
|
||||||
@ -147,19 +223,13 @@ export default {
|
|||||||
message: '请输入',
|
message: '请输入',
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}],
|
}],
|
||||||
sdcDown: [
|
|
||||||
{required: true, message: '请输入', trigger: 'blur'},
|
|
||||||
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'}
|
|
||||||
],
|
|
||||||
sdcUp: [
|
|
||||||
{required: true, message: '请输入', trigger: 'blur'},
|
|
||||||
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'}
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
showAddTime: false,
|
showAddTime: false,
|
||||||
formInline: {
|
formInline: {
|
||||||
timeRange: range,
|
timeRange: range,
|
||||||
chargeDischargePower: '',
|
chargeDischargePower: '',
|
||||||
|
sdcDown: '',
|
||||||
|
sdcUp: '',
|
||||||
chargeStatus: ''
|
chargeStatus: ''
|
||||||
},
|
},
|
||||||
formInlineRule: {
|
formInlineRule: {
|
||||||
@ -175,6 +245,14 @@ export default {
|
|||||||
},
|
},
|
||||||
{pattern: /^-?\d*\.?\d*$/, message: '请输入合法数字或小数'}
|
{pattern: /^-?\d*\.?\d*$/, message: '请输入合法数字或小数'}
|
||||||
],
|
],
|
||||||
|
sdcDown: [
|
||||||
|
{required: true, message: '请输入', trigger: 'blur'},
|
||||||
|
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'}
|
||||||
|
],
|
||||||
|
sdcUp: [
|
||||||
|
{required: true, message: '请输入', trigger: 'blur'},
|
||||||
|
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'}
|
||||||
|
],
|
||||||
chargeStatus: [{
|
chargeStatus: [{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请选择充放状态',
|
message: '请选择充放状态',
|
||||||
@ -198,11 +276,9 @@ export default {
|
|||||||
this.formData = {
|
this.formData = {
|
||||||
templateName: '',
|
templateName: '',
|
||||||
sdcLimit: false,
|
sdcLimit: false,
|
||||||
sdcDown: '',
|
|
||||||
sdcUp: '',
|
|
||||||
}
|
}
|
||||||
this.formInline = {
|
this.formInline = {
|
||||||
timeRange: this.secondRange, chargeDischargePower: '', chargeStatus: ''
|
timeRange: this.secondRange, chargeDischargePower: '', sdcDown: '', sdcUp: '', chargeStatus: ''
|
||||||
}//startTime: '', endTime: '',
|
}//startTime: '', endTime: '',
|
||||||
this.showAddTime = false
|
this.showAddTime = false
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
@ -216,14 +292,12 @@ export default {
|
|||||||
getStrategyTempDetail(this.editTempId).then(response => {
|
getStrategyTempDetail(this.editTempId).then(response => {
|
||||||
const data = JSON.parse(JSON.stringify(response?.data || []));
|
const data = JSON.parse(JSON.stringify(response?.data || []));
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
const {templateName, sdcLimit, sdcDown, sdcUp} = JSON.parse(JSON.stringify(data[0]));
|
const {templateName, sdcLimit} = JSON.parse(JSON.stringify(data[0]));
|
||||||
this.formData.templateName = templateName
|
this.formData.templateName = templateName
|
||||||
this.formData.sdcLimit = sdcLimit
|
this.formData.sdcLimit = sdcLimit
|
||||||
this.formData.sdcDown = sdcDown
|
|
||||||
this.formData.sdcUp = sdcUp
|
|
||||||
}
|
}
|
||||||
if (data.length === 1) {
|
if (data.length === 1) {
|
||||||
const {startTime, endTime} = data;
|
const {startTime, endTime} = data[0];
|
||||||
if (!startTime || !endTime) {
|
if (!startTime || !endTime) {
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
} else {
|
} else {
|
||||||
@ -242,15 +316,15 @@ export default {
|
|||||||
cancelAddTime() {
|
cancelAddTime() {
|
||||||
this.$refs.addTimeForm.resetFields()
|
this.$refs.addTimeForm.resetFields()
|
||||||
this.showAddTime = false
|
this.showAddTime = false
|
||||||
this.formInline = {timeRange: this.secondRange, chargeDischargePower: '', chargeStatus: ''}//startTime: '', endTime: '',
|
this.formInline = {timeRange: this.secondRange, chargeDischargePower: '', sdcDown: '', sdcUp: '', chargeStatus: ''}//startTime: '', endTime: '',
|
||||||
},
|
},
|
||||||
saveTime() {
|
saveTime() {
|
||||||
//表单校验,校验成功,添加到tableData里
|
//表单校验,校验成功,添加到tableData里
|
||||||
this.$refs.addTimeForm.validate(valid => {
|
this.$refs.addTimeForm.validate(valid => {
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
const {timeRange: [startTime, endTime], chargeDischargePower, chargeStatus} = this.formInline
|
const {timeRange: [startTime, endTime], chargeDischargePower, sdcDown, sdcUp, chargeStatus} = this.formInline
|
||||||
|
|
||||||
this.tableData.push({startTime, endTime, chargeDischargePower, chargeStatus})
|
this.tableData.push({startTime, endTime, chargeDischargePower, sdcDown, sdcUp, chargeStatus})
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.cancelAddTime()
|
this.cancelAddTime()
|
||||||
})
|
})
|
||||||
@ -262,9 +336,14 @@ export default {
|
|||||||
saveDialog() {
|
saveDialog() {
|
||||||
this.$refs.addTempForm.validate(valid => {
|
this.$refs.addTempForm.validate(valid => {
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
const {templateName, sdcLimit, sdcDown, sdcUp} = this.formData
|
const {templateName, sdcLimit} = this.formData
|
||||||
const {siteId, updateStrategyId} = this.$home
|
const {siteId, updateStrategyId} = this.$home
|
||||||
const {tableData} = this
|
const tableData = this.tableData.map(item => ({
|
||||||
|
...item,
|
||||||
|
sdcDown: this.normalizeSocValue(item.sdcDown),
|
||||||
|
sdcUp: this.normalizeSocValue(item.sdcUp)
|
||||||
|
}))
|
||||||
|
if (!this.validateTableData(tableData)) return
|
||||||
if (this.mode === 'edit') {
|
if (this.mode === 'edit') {
|
||||||
editStrategyTemp({
|
editStrategyTemp({
|
||||||
siteId,
|
siteId,
|
||||||
@ -272,8 +351,6 @@ export default {
|
|||||||
templateId: this.editTempId,
|
templateId: this.editTempId,
|
||||||
templateName,
|
templateName,
|
||||||
sdcLimit,
|
sdcLimit,
|
||||||
sdcDown,
|
|
||||||
sdcUp,
|
|
||||||
timeConfigList: tableData
|
timeConfigList: tableData
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response?.code === 200) {
|
if (response?.code === 200) {
|
||||||
@ -288,8 +365,6 @@ export default {
|
|||||||
strategyId: updateStrategyId,
|
strategyId: updateStrategyId,
|
||||||
templateName,
|
templateName,
|
||||||
sdcLimit,
|
sdcLimit,
|
||||||
sdcDown,
|
|
||||||
sdcUp,
|
|
||||||
timeConfigList: tableData
|
timeConfigList: tableData
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response?.code === 200) {
|
if (response?.code === 200) {
|
||||||
@ -300,14 +375,64 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
normalizeSocValue(value) {
|
||||||
|
if (value === null || value === undefined) return null
|
||||||
|
const normalized = String(value).replace('%', '').trim()
|
||||||
|
return normalized === '' ? null : normalized
|
||||||
|
},
|
||||||
|
toMinutes(timeValue) {
|
||||||
|
if (!timeValue || String(timeValue).indexOf(':') < 0) return -1
|
||||||
|
const [h, m] = String(timeValue).split(':')
|
||||||
|
const hour = Number(h), minute = Number(m)
|
||||||
|
if (!Number.isInteger(hour) || !Number.isInteger(minute)) return -1
|
||||||
|
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) return -1
|
||||||
|
return hour * 60 + minute
|
||||||
|
},
|
||||||
|
validateTableData(list = []) {
|
||||||
|
const numberPattern = /^-?\d+(\.\d+)?$/
|
||||||
|
const socPattern = /^(0|[1-9]\d*)(\.\d+)?$/
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
const row = list[i]
|
||||||
|
const rowNo = i + 1
|
||||||
|
if (!row.startTime || !row.endTime) {
|
||||||
|
this.$message.error(`第${rowNo}行:开始时间和结束时间不能为空`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
const startMinute = this.toMinutes(row.startTime)
|
||||||
|
const endMinute = this.toMinutes(row.endTime)
|
||||||
|
if (startMinute < 0 || endMinute < 0 || startMinute >= endMinute) {
|
||||||
|
this.$message.error(`第${rowNo}行:时间范围不合法`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!numberPattern.test(String(row.chargeDischargePower ?? '').trim())) {
|
||||||
|
this.$message.error(`第${rowNo}行:充放功率格式不正确`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!socPattern.test(String(row.sdcDown ?? '').trim())) {
|
||||||
|
this.$message.error(`第${rowNo}行:SOC下限格式不正确`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!socPattern.test(String(row.sdcUp ?? '').trim())) {
|
||||||
|
this.$message.error(`第${rowNo}行:SOC上限格式不正确`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (Number(row.sdcDown) > Number(row.sdcUp)) {
|
||||||
|
this.$message.error(`第${rowNo}行:SOC下限不能大于SOC上限`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (row.chargeStatus === undefined || row.chargeStatus === null || row.chargeStatus === '') {
|
||||||
|
this.$message.error(`第${rowNo}行:请选择充电状态`)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
},
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
// 清空所有数据
|
// 清空所有数据
|
||||||
this.$refs.addTempForm.resetFields()
|
this.$refs.addTempForm.resetFields()
|
||||||
this.formData = {
|
this.formData = {
|
||||||
templateName: '',
|
templateName: '',
|
||||||
sdcLimit: 0,
|
sdcLimit: 0,
|
||||||
sdcDown: '',
|
|
||||||
sdcUp: '',
|
|
||||||
}
|
}
|
||||||
this.tableData = []
|
this.tableData = []
|
||||||
this.cancelAddTime()
|
this.cancelAddTime()
|
||||||
@ -322,4 +447,4 @@ export default {
|
|||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -39,14 +39,14 @@
|
|||||||
prop="sdcDown"
|
prop="sdcDown"
|
||||||
label="SOC下限">
|
label="SOC下限">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{scope.row.sdcDown ? scope.row. sdcDown + '%' : '-'}}
|
{{scope.row.sdcDown === null || scope.row.sdcDown === undefined || scope.row.sdcDown === '' ? '-' : scope.row.sdcDown + '%'}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="sdcUp"
|
prop="sdcUp"
|
||||||
label="SOC上限">
|
label="SOC上限">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{scope.row.sdcUp ? scope.row.sdcUp + '%' : '-'}}
|
{{scope.row.sdcUp === null || scope.row.sdcUp === undefined || scope.row.sdcUp === '' ? '-' : scope.row.sdcUp + '%'}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
@ -92,7 +92,7 @@ export default {
|
|||||||
activeBtn:'',
|
activeBtn:'',
|
||||||
tempList:[],
|
tempList:[],
|
||||||
tableData:[],
|
tableData:[],
|
||||||
mixinPrototype:['templateName','sdcLimit','sdcDown','sdcUp']
|
mixinPrototype:['templateName','sdcLimit']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed:{
|
computed:{
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import resize from '@/mixins/ems/resize'
|
import resize from '@/mixins/ems/resize'
|
||||||
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
||||||
import {getPointData} from '@/api/ems/dzjk'
|
import {getProjectDisplayData} from '@/api/ems/dzjk'
|
||||||
|
import {getPointConfigCurve} from '@/api/ems/site'
|
||||||
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -48,8 +49,34 @@ export default {
|
|||||||
getGVQXData() {
|
getGVQXData() {
|
||||||
this.showLoading()
|
this.showLoading()
|
||||||
const {siteId, timeRange} = this
|
const {siteId, timeRange} = this
|
||||||
getPointData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => {
|
getProjectDisplayData(siteId).then(response => {
|
||||||
this.setOption(response?.data || [])
|
const displayData = response?.data || []
|
||||||
|
const sectionRows = displayData.filter(item =>
|
||||||
|
item && item.sectionName === '当日功率曲线' && item.useFixedDisplay !== 1 && item.dataPoint
|
||||||
|
)
|
||||||
|
const tasks = sectionRows.map(row => {
|
||||||
|
const pointId = String(row.dataPoint || '').trim()
|
||||||
|
if (!pointId) return Promise.resolve(null)
|
||||||
|
return getPointConfigCurve({
|
||||||
|
siteId,
|
||||||
|
pointId,
|
||||||
|
pointType: 'data',
|
||||||
|
rangeType: 'custom',
|
||||||
|
startTime: this.normalizeDateTime(timeRange[0], false),
|
||||||
|
endTime: this.normalizeDateTime(timeRange[1], true)
|
||||||
|
}).then(curveResponse => {
|
||||||
|
const list = curveResponse?.data || []
|
||||||
|
return {
|
||||||
|
name: row.fieldName || row.fieldCode || pointId,
|
||||||
|
data: list
|
||||||
|
.map(item => [this.parseToTimestamp(item.dataTime), Number(item.pointValue)])
|
||||||
|
.filter(item => item[0] && !Number.isNaN(item[1]))
|
||||||
|
}
|
||||||
|
}).catch(() => null)
|
||||||
|
})
|
||||||
|
return Promise.all(tasks)
|
||||||
|
}).then(series => {
|
||||||
|
this.setOption((series || []).filter(Boolean))
|
||||||
}).finally(() => this.hideLoading())
|
}).finally(() => this.hideLoading())
|
||||||
},
|
},
|
||||||
init(siteId) {
|
init(siteId) {
|
||||||
@ -70,12 +97,18 @@ export default {
|
|||||||
hideLoading() {
|
hideLoading() {
|
||||||
this.chart && this.chart.hideLoading()
|
this.chart && this.chart.hideLoading()
|
||||||
},
|
},
|
||||||
setOption(data) {
|
normalizeDateTime(value, endOfDay) {
|
||||||
const source = [['日期', '电网功率', '负载功率', '储能功率', '光伏功率', 'soc平均值', 'soh平均值', '电池平均温度平均值']]
|
const raw = String(value || '').trim()
|
||||||
console.log('source.slice(1)', source[0].slice(1))
|
if (!raw) return ''
|
||||||
this.chart && data.forEach((item) => {
|
if (raw.includes(' ')) return raw
|
||||||
source.push([item.statisDate, item.gridPower, item.loadPower, item.storagePower, item.pvPower, item.avgSoc, item.avgSoh, item.avgTemp])
|
return `${raw} ${endOfDay ? '23:59:59' : '00:00:00'}`
|
||||||
})
|
},
|
||||||
|
parseToTimestamp(value) {
|
||||||
|
if (!value) return null
|
||||||
|
const t = new Date(value).getTime()
|
||||||
|
return Number.isNaN(t) ? null : t
|
||||||
|
},
|
||||||
|
setOption(seriesData = []) {
|
||||||
this.chart.setOption({
|
this.chart.setOption({
|
||||||
grid: {
|
grid: {
|
||||||
containLabel: true
|
containLabel: true
|
||||||
@ -86,35 +119,28 @@ export default {
|
|||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
axisPointer: { type: 'cross' }
|
||||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: "#333333",
|
color: "#333333",
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'time',
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: [{
|
||||||
{
|
type: 'value',
|
||||||
type: 'value',
|
}],
|
||||||
},
|
series: seriesData.map((item) => {
|
||||||
{
|
|
||||||
type: 'value',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
dataset: {source},
|
|
||||||
series: source[0].slice(1).map((item, index) => {
|
|
||||||
return {
|
return {
|
||||||
type: 'line',//index === 5 ? 'bar' : 'line',
|
name: item.name,
|
||||||
|
type: 'line',
|
||||||
showSymbol: false,
|
showSymbol: false,
|
||||||
symbolSize: 2,
|
symbolSize: 2,
|
||||||
smooth: true,
|
smooth: true,
|
||||||
areaStyle: {
|
areaStyle: {
|
||||||
opacity: 0.5,
|
opacity: 0.5,
|
||||||
},
|
},
|
||||||
yAxisIndex: index <= 4 ? 0 : 1
|
data: item.data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -124,4 +150,3 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,8 @@
|
|||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import resize from '@/mixins/ems/resize'
|
import resize from '@/mixins/ems/resize'
|
||||||
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
import DateRangeSelect from '@/components/Ems/DateRangeSelect/index.vue'
|
||||||
import {getSevenChargeData} from '@/api/ems/dzjk'
|
import {getProjectDisplayData} from '@/api/ems/dzjk'
|
||||||
|
import {getPointConfigCurve} from '@/api/ems/site'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [resize],
|
mixins: [resize],
|
||||||
@ -45,8 +46,34 @@ export default {
|
|||||||
getWeekKData() {
|
getWeekKData() {
|
||||||
this.showLoading()
|
this.showLoading()
|
||||||
const {siteId, timeRange} = this
|
const {siteId, timeRange} = this
|
||||||
getSevenChargeData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => {
|
getProjectDisplayData(siteId).then(response => {
|
||||||
this.setOption(response?.data || [])
|
const displayData = response?.data || []
|
||||||
|
const sectionRows = displayData.filter(item =>
|
||||||
|
item && item.sectionName === '一周充放曲线' && item.useFixedDisplay !== 1 && item.dataPoint
|
||||||
|
)
|
||||||
|
const tasks = sectionRows.map(row => {
|
||||||
|
const pointId = String(row.dataPoint || '').trim()
|
||||||
|
if (!pointId) return Promise.resolve(null)
|
||||||
|
return getPointConfigCurve({
|
||||||
|
siteId,
|
||||||
|
pointId,
|
||||||
|
pointType: 'data',
|
||||||
|
rangeType: 'custom',
|
||||||
|
startTime: this.normalizeDateTime(timeRange[0], false),
|
||||||
|
endTime: this.normalizeDateTime(timeRange[1], true)
|
||||||
|
}).then(curveResponse => {
|
||||||
|
const list = curveResponse?.data || []
|
||||||
|
return {
|
||||||
|
name: row.fieldName || row.fieldCode || pointId,
|
||||||
|
data: list
|
||||||
|
.map(item => [this.parseToTimestamp(item.dataTime), Number(item.pointValue)])
|
||||||
|
.filter(item => item[0] && !Number.isNaN(item[1]))
|
||||||
|
}
|
||||||
|
}).catch(() => null)
|
||||||
|
})
|
||||||
|
return Promise.all(tasks)
|
||||||
|
}).then(series => {
|
||||||
|
this.setOption((series || []).filter(Boolean))
|
||||||
}).finally(() => this.hideLoading())
|
}).finally(() => this.hideLoading())
|
||||||
},
|
},
|
||||||
init(siteId) {
|
init(siteId) {
|
||||||
@ -65,18 +92,23 @@ export default {
|
|||||||
hideLoading() {
|
hideLoading() {
|
||||||
this.chart && this.chart.hideLoading()
|
this.chart && this.chart.hideLoading()
|
||||||
},
|
},
|
||||||
setOption(data, unit) {
|
normalizeDateTime(value, endOfDay) {
|
||||||
const source = [['日期', '充电量', '放电量']]
|
const raw = String(value || '').trim()
|
||||||
data.forEach(item => {
|
if (!raw) return ''
|
||||||
source.push([item.ammeterDate, item.chargedCap, item.disChargedCap])
|
if (raw.includes(' ')) return raw
|
||||||
})
|
return `${raw} ${endOfDay ? '23:59:59' : '00:00:00'}`
|
||||||
|
},
|
||||||
|
parseToTimestamp(value) {
|
||||||
|
if (!value) return null
|
||||||
|
const t = new Date(value).getTime()
|
||||||
|
return Number.isNaN(t) ? null : t
|
||||||
|
},
|
||||||
|
setOption(seriesData = []) {
|
||||||
this.chart && this.chart.setOption({
|
this.chart && this.chart.setOption({
|
||||||
color: ['#4472c4', '#70ad47'],//所有充放电颜色保持统一
|
color: ['#4472c4', '#70ad47'],//所有充放电颜色保持统一
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer: { // 坐标轴指示器,坐标轴触发有效
|
axisPointer: { type: 'cross' }
|
||||||
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
containLabel: true
|
containLabel: true
|
||||||
@ -86,9 +118,7 @@ export default {
|
|||||||
bottom: '15',
|
bottom: '15',
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'time'
|
||||||
name: unit,
|
|
||||||
nameLocation: 'center'
|
|
||||||
},
|
},
|
||||||
yAxis: [{
|
yAxis: [{
|
||||||
type: 'value',
|
type: 'value',
|
||||||
@ -100,19 +130,12 @@ export default {
|
|||||||
onZero: false
|
onZero: false
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
dataset: {
|
series: seriesData.map(item => ({
|
||||||
source
|
name: item.name,
|
||||||
},
|
yAxisIndex: 0,
|
||||||
series: [
|
type: 'bar',
|
||||||
{
|
data: item.data
|
||||||
yAxisIndex: 0,
|
}))
|
||||||
type: 'bar',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
yAxisIndex: 0,
|
|
||||||
type: 'bar',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div>
|
||||||
<el-row style="background: #fff" class="row-container" :gutter="15">
|
<el-row style="background: #fff" class="row-container" :gutter="15">
|
||||||
<el-col :xs="24" :sm="24" :lg="5">
|
<el-col :xs="24" :sm="24" :lg="5">
|
||||||
<!-- 站点信息-->
|
<!-- 站点信息-->
|
||||||
@ -21,13 +21,19 @@
|
|||||||
<div class="title">
|
<div class="title">
|
||||||
<i class="el-icon-location"></i>
|
<i class="el-icon-location"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="value">{{ info.siteAddress }}</div>
|
<div class="value">
|
||||||
|
<i v-if="isBaseInfoLoading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ info.siteAddress || '-' }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="site-info">
|
<div class="site-info">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<i class="el-icon-date"></i>
|
<i class="el-icon-date"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="value">{{ info.runningTime || '-' }}</div>
|
<div class="value">
|
||||||
|
<i v-if="isBaseInfoLoading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ info.runningTime || '-' }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 装机功率、容量 -->
|
<!-- 装机功率、容量 -->
|
||||||
<el-row :gutter="10" style="margin-top:20px;">
|
<el-row :gutter="10" style="margin-top:20px;">
|
||||||
@ -38,7 +44,8 @@
|
|||||||
<div class="sjgl-wrapper">
|
<div class="sjgl-wrapper">
|
||||||
<div class="sjgl-title">装机功率(MW)</div>
|
<div class="sjgl-title">装机功率(MW)</div>
|
||||||
<div class="sjgl-value">
|
<div class="sjgl-value">
|
||||||
{{ info.installPower | formatNumber }}
|
<i v-if="isBaseInfoLoading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ info.installPower | formatNumber }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -49,7 +56,8 @@
|
|||||||
<div class="sjgl-wrapper">
|
<div class="sjgl-wrapper">
|
||||||
<div class="sjgl-title">装机容量(MW)</div>
|
<div class="sjgl-title">装机容量(MW)</div>
|
||||||
<div class="sjgl-value">
|
<div class="sjgl-value">
|
||||||
{{ info.installCapacity | formatNumber }}
|
<i v-if="isBaseInfoLoading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ info.installCapacity | formatNumber }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -67,7 +75,10 @@
|
|||||||
<span class="card-title">总累计运行数据</span>
|
<span class="card-title">总累计运行数据</span>
|
||||||
<div class="total-count">
|
<div class="total-count">
|
||||||
<span class="title">总收入</span>
|
<span class="title">总收入</span>
|
||||||
<span class="value">{{ runningInfo.totalRevenue | formatNumber }}</span>
|
<span class="value">
|
||||||
|
<i v-if="isRunningInfoLoading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ totalRevenueDisplayValue | formatNumber }}</span>
|
||||||
|
</span>
|
||||||
<span class="unit">元</span>
|
<span class="unit">元</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -77,14 +88,15 @@
|
|||||||
<el-row :gutter="10">
|
<el-row :gutter="10">
|
||||||
<el-col
|
<el-col
|
||||||
:span="6"
|
:span="6"
|
||||||
v-for="(item, index) in sjglData"
|
v-for="(item, index) in runningDataCards"
|
||||||
:key="index + 'sjglData'"
|
:key="index + 'sjglData'"
|
||||||
class="sjgl-col"
|
class="sjgl-col"
|
||||||
>
|
>
|
||||||
<div class="sjgl-wrapper">
|
<div class="sjgl-wrapper">
|
||||||
<div class="sjgl-title">{{ item.title }}</div>
|
<div class="sjgl-title">{{ item.title }}</div>
|
||||||
<div class="sjgl-value" :style="{color:item.color}">
|
<div class="sjgl-value" :style="{color:item.color}">
|
||||||
{{ runningInfo[item.attr] | formatNumber }}
|
<i v-if="item.loading" class="el-icon-loading"></i>
|
||||||
|
<span v-else>{{ item.value | formatNumber }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@ -104,7 +116,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {getSingleSiteBaseInfo} from "@/api/ems/zddt";
|
import {getSingleSiteBaseInfo} from "@/api/ems/zddt";
|
||||||
import {getDzjkHomeView} from "@/api/ems/dzjk";
|
import {getDzjkHomeView, getProjectDisplayData} from "@/api/ems/dzjk";
|
||||||
import WeekChart from "./WeekChart.vue";
|
import WeekChart from "./WeekChart.vue";
|
||||||
import ActiveChart from "./ActiveChart.vue";
|
import ActiveChart from "./ActiveChart.vue";
|
||||||
import AlarmTable from "./AlarmTable.vue";
|
import AlarmTable from "./AlarmTable.vue";
|
||||||
@ -119,7 +131,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
sjglData: [
|
baseInfoLoading: false,
|
||||||
|
runningInfoLoading: false,
|
||||||
|
fallbackSjglData: [
|
||||||
{
|
{
|
||||||
title: "今日充电量(kWh)",
|
title: "今日充电量(kWh)",
|
||||||
attr: "dayChargedCap",
|
attr: "dayChargedCap",
|
||||||
@ -163,38 +177,106 @@ export default {
|
|||||||
],
|
],
|
||||||
info: {}, //基本信息
|
info: {}, //基本信息
|
||||||
runningInfo: {}, //总累计运行数据+报警表格
|
runningInfo: {}, //总累计运行数据+报警表格
|
||||||
|
runningDisplayData: [], //单站监控项目配置展示数据
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
isBaseInfoLoading() {
|
||||||
|
const state = this.$data || {};
|
||||||
|
return !!(state.baseInfoLoading || state.loading);
|
||||||
|
},
|
||||||
|
isRunningInfoLoading() {
|
||||||
|
const state = this.$data || {};
|
||||||
|
return !!(state.runningInfoLoading || state.loading);
|
||||||
|
},
|
||||||
tableData() {
|
tableData() {
|
||||||
return this.runningInfo?.siteMonitorHomeAlarmVo || [];
|
return this.runningInfo?.siteMonitorHomeAlarmVo || [];
|
||||||
},
|
},
|
||||||
|
totalRunningSectionData() {
|
||||||
|
return (this.runningDisplayData || []).filter(item => item.sectionName === "总累计运行数据");
|
||||||
|
},
|
||||||
|
totalRevenueDisplayItem() {
|
||||||
|
const sectionData = this.totalRunningSectionData || [];
|
||||||
|
const byFieldCode = sectionData.find(item => item.fieldCode === "totalRevenue");
|
||||||
|
if (byFieldCode) {
|
||||||
|
return byFieldCode;
|
||||||
|
}
|
||||||
|
return sectionData.find(item => item.fieldName === "总收入");
|
||||||
|
},
|
||||||
|
totalRevenueDisplayValue() {
|
||||||
|
return this.totalRevenueDisplayItem ? this.totalRevenueDisplayItem.fieldValue : this.runningInfo.totalRevenue;
|
||||||
|
},
|
||||||
|
runningDataCards() {
|
||||||
|
const sectionData = this.totalRunningSectionData || [];
|
||||||
|
if (sectionData.length > 0) {
|
||||||
|
const revenueFieldCode = this.totalRevenueDisplayItem ? this.totalRevenueDisplayItem.fieldCode : "";
|
||||||
|
return sectionData
|
||||||
|
.filter(item => item.fieldCode !== revenueFieldCode)
|
||||||
|
.map((item, index) => ({
|
||||||
|
title: item.fieldName,
|
||||||
|
value: item.fieldValue,
|
||||||
|
color: this.getCardColor(index),
|
||||||
|
loading: this.isRunningInfoLoading,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
return this.fallbackSjglData.map(item => ({
|
||||||
|
title: item.title,
|
||||||
|
value: this.runningInfo[item.attr],
|
||||||
|
color: item.color,
|
||||||
|
loading: this.isRunningInfoLoading,
|
||||||
|
}));
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setBaseInfoLoading(loading) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(this.$data, "baseInfoLoading")) {
|
||||||
|
this.baseInfoLoading = loading;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$set(this.$data, "baseInfoLoading", loading);
|
||||||
|
},
|
||||||
|
setRunningInfoLoading(loading) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(this.$data, "runningInfoLoading")) {
|
||||||
|
this.runningInfoLoading = loading;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$set(this.$data, "runningInfoLoading", loading);
|
||||||
|
},
|
||||||
|
getCardColor(index) {
|
||||||
|
const colors = ['#4472c4', '#70ad47', '#4472c4', '#f67438', '#4472c4', '#70ad47', '#70ad47', '#f67438'];
|
||||||
|
return colors[index % colors.length];
|
||||||
|
},
|
||||||
toAlarm() {
|
toAlarm() {
|
||||||
this.$router.push({path: "/dzjk/gzgj", query: this.$route.query});
|
this.$router.push({path: "/dzjk/gzgj", query: this.$route.query});
|
||||||
},
|
},
|
||||||
getBaseInfo() {
|
getBaseInfo() {
|
||||||
|
this.setBaseInfoLoading(true);
|
||||||
return getSingleSiteBaseInfo(this.siteId).then((response) => {
|
return getSingleSiteBaseInfo(this.siteId).then((response) => {
|
||||||
this.info = response?.data || {};
|
this.info = response?.data || {};
|
||||||
|
}).finally(() => {
|
||||||
|
this.setBaseInfoLoading(false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
getRunningInfo() {
|
getRunningInfo() {
|
||||||
return getDzjkHomeView(this.siteId).then((response) => {
|
this.setRunningInfoLoading(true);
|
||||||
this.runningInfo = response?.data || {};
|
return Promise.all([
|
||||||
|
getDzjkHomeView(this.siteId),
|
||||||
|
getProjectDisplayData(this.siteId),
|
||||||
|
]).then(([homeResponse, displayResponse]) => {
|
||||||
|
this.runningInfo = homeResponse?.data || {};
|
||||||
|
this.runningDisplayData = displayResponse?.data || [];
|
||||||
|
}).finally(() => {
|
||||||
|
this.setRunningInfoLoading(false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
init() {
|
init() {
|
||||||
this.loading = true;
|
|
||||||
// 功率曲线
|
// 功率曲线
|
||||||
this.$refs.activeChart.init(this.siteId);
|
this.$refs.activeChart.init(this.siteId);
|
||||||
// 一周冲放曲线
|
// 一周冲放曲线
|
||||||
this.$refs.weekChart.init(this.siteId);
|
this.$refs.weekChart.init(this.siteId);
|
||||||
// 静态信息 this.getBaseInfo()
|
// 静态信息 this.getBaseInfo()
|
||||||
// 总累计运行数据+故障告警 this.getRunningInfo()
|
// 总累计运行数据+故障告警 this.getRunningInfo()
|
||||||
Promise.all([this.getBaseInfo(), this.getRunningInfo()]).finally(() => {
|
Promise.all([this.getBaseInfo(), this.getRunningInfo()]);
|
||||||
this.loading = false;
|
|
||||||
});
|
|
||||||
// 一分钟循环一次总累计运行数据
|
// 一分钟循环一次总累计运行数据
|
||||||
this.updateInterval(this.getRunningInfo);
|
this.updateInterval(this.getRunningInfo);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="ems-dashboard-editor-container">
|
<div class="ems-dashboard-editor-container">
|
||||||
<zd-select :get-list-by-store="true" :default-site-id="$route.query.siteId" @submitSite="submitSite"/>
|
|
||||||
<el-menu
|
<el-menu
|
||||||
class="ems-second-menu"
|
class="ems-second-menu"
|
||||||
:default-active="$route.meta.activeSecondMenuName"
|
:default-active="$route.meta.activeSecondMenuName"
|
||||||
@ -28,11 +27,8 @@
|
|||||||
<script>
|
<script>
|
||||||
import { dzjk } from '@/router/ems'
|
import { dzjk } from '@/router/ems'
|
||||||
const childrenRoute = dzjk[0].children[0].children//获取到单站监控下面的字路由
|
const childrenRoute = dzjk[0].children[0].children//获取到单站监控下面的字路由
|
||||||
console.log('childrenRoute',childrenRoute)
|
|
||||||
import ZdSelect from '@/components/Ems/ZdSelect/index.vue'
|
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
export default {
|
export default {
|
||||||
components:{ZdSelect},
|
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
childrenRoute,
|
childrenRoute,
|
||||||
@ -44,18 +40,6 @@ export default {
|
|||||||
dzjkAlarmLighting:state=>state.ems.dzjkAlarmLighting
|
dzjkAlarmLighting:state=>state.ems.dzjkAlarmLighting
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods:{
|
|
||||||
submitSite(id){
|
|
||||||
if(id !== this.$route.query.siteId){
|
|
||||||
// console.log('单站监控选择了其他的站点id=',id,'并更新页面地址参数')
|
|
||||||
this.$router.push({query:{...this.$route.query,siteId:id}})
|
|
||||||
}else{
|
|
||||||
// console.log('单站监控选择了相同的其他的站点id=',id,'页面地址不发生改变')
|
|
||||||
}
|
|
||||||
//获取告警列表数据
|
|
||||||
this.$store.dispatch('getSiteAlarmNum',id)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
beforeRouteLeave(to,from, next){
|
beforeRouteLeave(to,from, next){
|
||||||
//从单站监控下面的所有子页面跳出时会触发
|
//从单站监控下面的所有子页面跳出时会触发
|
||||||
// 清空store中的zdList 保障下次进入到单站监控会重新调用接口获取数据
|
// 清空store中的zdList 保障下次进入到单站监控会重新调用接口获取数据
|
||||||
@ -66,6 +50,9 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.ems-dashboard-editor-container{
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
.dzjk-ems-content-container{
|
.dzjk-ems-content-container{
|
||||||
margin-top:0;
|
margin-top:0;
|
||||||
min-height: 60vh;
|
min-height: 60vh;
|
||||||
|
|||||||
@ -1,25 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ems-dashboard-editor-container" v-loading="loading">
|
<div class="ems-dashboard-editor-container">
|
||||||
<zd-info></zd-info>
|
<zd-info></zd-info>
|
||||||
<div class="ems-content-container ems-content-container-padding">
|
<div class="ems-content-container ems-content-container-padding">
|
||||||
<div class="content-title">数据概览</div>
|
<div class="content-title">数据概览</div>
|
||||||
<el-row :gutter="15" style="background:#fff;margin:30px 0;">
|
<el-row :gutter="15" style="background:#fff;margin:30px 0;">
|
||||||
<el-col :xs="24" :sm="12" :lg="12">
|
<el-col :xs="24" :sm="12" :lg="12" v-loading="chartLoading.dlzbchart">
|
||||||
<dlzb-chart ref="dlzbchart"/>
|
<dlzb-chart ref="dlzbchart"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" :lg="12">
|
<el-col :xs="24" :sm="12" :lg="12" v-loading="chartLoading.xtxlchart">
|
||||||
<xtxl-chart ref="xtxlchart"/>
|
<xtxl-chart ref="xtxlchart"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-row :gutter="15" style="background:#fff;margin:0;">
|
<el-row :gutter="15" style="background:#fff;margin:0;">
|
||||||
<el-col :xs="24" :sm="8" :lg="8">
|
<el-col :xs="24" :sm="8" :lg="8" v-loading="chartLoading.gjqsChart">
|
||||||
<gjqs-chart ref="gjqsChart"/>
|
<gjqs-chart ref="gjqsChart"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="8" :lg="8">
|
<el-col :xs="24" :sm="8" :lg="8" v-loading="chartLoading.sbgjzbChart">
|
||||||
<sbgjzb-chart ref="sbgjzbChart"/>
|
<sbgjzb-chart ref="sbgjzbChart"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="8" :lg="8">
|
<el-col :xs="24" :sm="8" :lg="8" v-loading="chartLoading.gjdjfbChart">
|
||||||
<gjdjfb-chart ref="gjdjfbChart"/>
|
<gjdjfb-chart ref="gjdjfbChart"/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
@ -47,24 +47,45 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading:false,
|
chartLoading: {
|
||||||
|
dlzbchart: false,
|
||||||
|
xtxlchart: false,
|
||||||
|
gjqsChart: false,
|
||||||
|
sbgjzbChart: false,
|
||||||
|
gjdjfbChart: false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
setChartLoading(loading) {
|
||||||
|
this.chartLoading = {
|
||||||
|
dlzbchart: loading,
|
||||||
|
xtxlchart: loading,
|
||||||
|
gjqsChart: loading,
|
||||||
|
sbgjzbChart: loading,
|
||||||
|
gjdjfbChart: loading
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hideChartLoading(key) {
|
||||||
|
this.$set(this.chartLoading, key, false)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loading = true
|
this.setChartLoading(true)
|
||||||
dataList().then(response => {
|
dataList().then(response => {
|
||||||
const data = JSON.parse(JSON.stringify(response?.data || {}))
|
const data = JSON.parse(JSON.stringify(response?.data || {}))
|
||||||
this.$refs.dlzbchart.initChart(data?.elecDataList || [])
|
this.$refs.dlzbchart.initChart(data?.elecDataList || [])
|
||||||
|
this.hideChartLoading('dlzbchart')
|
||||||
this.$refs.xtxlchart.initChart(data?.sysEfficList || [])
|
this.$refs.xtxlchart.initChart(data?.sysEfficList || [])
|
||||||
|
this.hideChartLoading('xtxlchart')
|
||||||
this.$refs.gjqsChart.initChart(data?.alarmDataList || [])
|
this.$refs.gjqsChart.initChart(data?.alarmDataList || [])
|
||||||
|
this.hideChartLoading('gjqsChart')
|
||||||
this.$refs.sbgjzbChart.initChart(data?.deviceAlarmList || [])
|
this.$refs.sbgjzbChart.initChart(data?.deviceAlarmList || [])
|
||||||
|
this.hideChartLoading('sbgjzbChart')
|
||||||
this.$refs.gjdjfbChart.initChart(data?.alarmLevelList || [])
|
this.$refs.gjdjfbChart.initChart(data?.alarmLevelList || [])
|
||||||
|
this.hideChartLoading('gjdjfbChart')
|
||||||
}).finally(() => {
|
}).catch(() => {
|
||||||
this.loading = false
|
this.setChartLoading(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
||||||
<el-form :inline="true" class="select-container">
|
<el-form :inline="true" class="select-container">
|
||||||
<el-form-item label="站点选择">
|
|
||||||
<el-select v-model="form.siteId" placeholder="请选择换电站名称" :loading="searchLoading" loading-text="正在加载数据" clearable>
|
|
||||||
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'zdxeSelect'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="订阅topic">
|
<el-form-item label="订阅topic">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.mqttTopic"
|
v-model="form.mqttTopic"
|
||||||
@ -90,12 +85,21 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {deleteMqtt,getMqttList} from '@/api/ems/site'
|
import {deleteMqtt,getMqttList} from '@/api/ems/site'
|
||||||
import {getAllSites} from '@/api/ems/zddt'
|
|
||||||
import AddMqtt from './AddMqtt.vue'
|
import AddMqtt from './AddMqtt.vue'
|
||||||
export default {
|
export default {
|
||||||
name: "Mqtt",
|
name: "Mqtt",
|
||||||
components: {AddMqtt},
|
components: {AddMqtt},
|
||||||
computed: { },
|
computed: { },
|
||||||
|
watch: {
|
||||||
|
'$route.query.siteId'(newSiteId) {
|
||||||
|
const normalizedSiteId = this.hasValidSiteId(newSiteId) ? String(newSiteId).trim() : ''
|
||||||
|
if (normalizedSiteId === this.form.siteId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.form.siteId = normalizedSiteId
|
||||||
|
this.onSearch()
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form:{
|
form:{
|
||||||
@ -103,8 +107,6 @@ export default {
|
|||||||
topicName:'',
|
topicName:'',
|
||||||
mqttTopic:''
|
mqttTopic:''
|
||||||
},
|
},
|
||||||
siteList:[],
|
|
||||||
searchLoading:false,
|
|
||||||
loading:false,
|
loading:false,
|
||||||
tableData:[],
|
tableData:[],
|
||||||
pageSize:10,//分页栏当前每个数据总数
|
pageSize:10,//分页栏当前每个数据总数
|
||||||
@ -113,6 +115,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
hasValidSiteId(siteId) {
|
||||||
|
return !!(siteId !== undefined && siteId !== null && String(siteId).trim())
|
||||||
|
},
|
||||||
// 分页
|
// 分页
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.pageSize = val;
|
this.pageSize = val;
|
||||||
@ -133,22 +138,19 @@ export default {
|
|||||||
},
|
},
|
||||||
onReset(){
|
onReset(){
|
||||||
this.form={
|
this.form={
|
||||||
siteId:'',
|
siteId:this.form.siteId,
|
||||||
topicName:'',
|
topicName:'',
|
||||||
mqttTopic:''
|
mqttTopic:''
|
||||||
}
|
}
|
||||||
this.pageNum =1//每次搜索从1开始搜索
|
this.pageNum =1//每次搜索从1开始搜索
|
||||||
this.getData()
|
this.getData()
|
||||||
},
|
},
|
||||||
//获取站点列表
|
|
||||||
getZdList(){
|
|
||||||
this.searchLoading=true
|
|
||||||
return getAllSites().then(response => {
|
|
||||||
this.siteList = response?.data || []
|
|
||||||
// if( this.siteList.length>0 ) this.siteId = this.siteList[0].siteId
|
|
||||||
}).finally(() => {this.searchLoading=false})
|
|
||||||
},
|
|
||||||
getData(){
|
getData(){
|
||||||
|
if (!this.form.siteId) {
|
||||||
|
this.tableData = []
|
||||||
|
this.totalSize = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
this.loading=true;
|
this.loading=true;
|
||||||
const {mqttTopic,topicName,siteId} = this.form;
|
const {mqttTopic,topicName,siteId} = this.form;
|
||||||
const {pageNum,pageSize} = this;
|
const {pageNum,pageSize} = this;
|
||||||
@ -193,8 +195,7 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loading=true
|
this.form.siteId = this.hasValidSiteId(this.$route.query.siteId) ? String(this.$route.query.siteId).trim() : ''
|
||||||
this.getZdList()
|
|
||||||
this.getData()
|
this.getData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,23 +19,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
<el-form :inline="true" class="select-container">
|
<el-form :inline="true" class="select-container">
|
||||||
<el-form-item label="站点">
|
|
||||||
<el-select
|
|
||||||
v-model="queryParams.siteId"
|
|
||||||
placeholder="请选择站点"
|
|
||||||
:loading="searchLoading"
|
|
||||||
loading-text="正在加载数据"
|
|
||||||
clearable
|
|
||||||
@change="handleSiteChange"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="(item, index) in siteList"
|
|
||||||
:key="index + 'siteSelect'"
|
|
||||||
:label="item.siteName"
|
|
||||||
:value="item.siteId"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备类型">
|
<el-form-item label="设备类型">
|
||||||
<el-select v-model="queryParams.deviceCategory" placeholder="请选择设备类型" clearable @change="onSearch">
|
<el-select v-model="queryParams.deviceCategory" placeholder="请选择设备类型" clearable @change="onSearch">
|
||||||
<el-option
|
<el-option
|
||||||
@ -75,16 +58,17 @@
|
|||||||
|
|
||||||
<el-table class="common-table" :data="tableData" stripe max-height="560px">
|
<el-table class="common-table" :data="tableData" stripe max-height="560px">
|
||||||
<el-table-column prop="siteId" label="站点ID" min-width="120" />
|
<el-table-column prop="siteId" label="站点ID" min-width="120" />
|
||||||
<el-table-column label="设备类型/设备ID" min-width="180">
|
<el-table-column prop="pointId" label="点位ID" min-width="280" />
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ (scope.row.deviceCategory || '-') + ' / ' + (scope.row.deviceId || '-') }}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="点位名" min-width="140">
|
<el-table-column label="点位名" min-width="140">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.pointName || '-' }}
|
{{ scope.row.pointName || '-' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="设备类型/设备ID" min-width="180">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ formatDeviceInfo(scope.row) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="dataKey" label="数据键" min-width="180" />
|
<el-table-column prop="dataKey" label="数据键" min-width="180" />
|
||||||
<el-table-column label="类型" width="88">
|
<el-table-column label="类型" width="88">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@ -100,7 +84,7 @@
|
|||||||
<el-table-column prop="dataUnit" label="单位" min-width="80" />
|
<el-table-column prop="dataUnit" label="单位" min-width="80" />
|
||||||
<el-table-column label="操作" width="220" fixed="right">
|
<el-table-column label="操作" width="220" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" :disabled="scope.row.pointType === 'calc'" @click="openCurveDialog(scope.row)">曲线</el-button>
|
<el-button type="text" @click="openCurveDialog(scope.row)">曲线</el-button>
|
||||||
<el-button type="text" @click="openEditDialog(scope.row.id)">编辑</el-button>
|
<el-button type="text" @click="openEditDialog(scope.row.id)">编辑</el-button>
|
||||||
<el-button type="text" style="color: #f56c6c;" @click="handleDelete(scope.row.id)">删除</el-button>
|
<el-button type="text" style="color: #f56c6c;" @click="handleDelete(scope.row.id)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
@ -132,14 +116,7 @@
|
|||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="站点" prop="siteId">
|
<el-form-item label="站点" prop="siteId">
|
||||||
<el-select v-model="form.siteId" placeholder="请选择站点" @change="handleFormSiteChange">
|
<el-input v-model="form.siteId" disabled />
|
||||||
<el-option
|
|
||||||
v-for="(item, index) in siteList"
|
|
||||||
:key="index + 'formSite'"
|
|
||||||
:label="item.siteName"
|
|
||||||
:value="item.siteId"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@ -150,7 +127,21 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12" v-if="form.pointType === 'data'">
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="点位ID" prop="pointId">
|
||||||
|
<el-input v-model.trim="form.pointId" placeholder="请输入点位ID(系统唯一)" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="点位名称" prop="pointName">
|
||||||
|
<el-input v-model.trim="form.pointName" placeholder="请输入点位名称" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12" v-if="form.pointType === 'data' || form.pointType === 'calc'">
|
||||||
<el-form-item label="设备类型" prop="deviceCategory">
|
<el-form-item label="设备类型" prop="deviceCategory">
|
||||||
<el-select v-model="form.deviceCategory" placeholder="请选择设备类型" @change="handleFormCategoryChange">
|
<el-select v-model="form.deviceCategory" placeholder="请选择设备类型" @change="handleFormCategoryChange">
|
||||||
<el-option
|
<el-option
|
||||||
@ -162,11 +153,9 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="16">
|
|
||||||
<el-col :span="12" v-if="form.pointType === 'data'">
|
<el-col :span="12" v-if="form.pointType === 'data'">
|
||||||
<el-form-item label="设备ID" prop="deviceId">
|
<el-form-item label="设备ID" prop="deviceId">
|
||||||
<el-select v-model="form.deviceId" placeholder="请选择设备" clearable>
|
<el-select v-model="form.deviceId" placeholder="请选择设备">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="(item,index) in formDeviceList"
|
v-for="(item,index) in formDeviceList"
|
||||||
:key="item.__key || (index + 'formDevice')"
|
:key="item.__key || (index + 'formDevice')"
|
||||||
@ -176,18 +165,13 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="16">
|
||||||
<el-col :span="12" v-if="form.pointType === 'data'">
|
<el-col :span="12" v-if="form.pointType === 'data'">
|
||||||
<el-form-item label="寄存器地址" prop="registerAddress">
|
<el-form-item label="寄存器地址" prop="registerAddress">
|
||||||
<el-input v-model.trim="form.registerAddress" placeholder="请输入寄存器地址" />
|
<el-input v-model.trim="form.registerAddress" placeholder="请输入寄存器地址" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="16">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="点位名称" prop="pointName">
|
|
||||||
<el-input v-model.trim="form.pointName" placeholder="请输入点位名称" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="数据键" prop="dataKey">
|
<el-form-item label="数据键" prop="dataKey">
|
||||||
<el-input v-model.trim="form.dataKey" placeholder="请输入数据键" />
|
<el-input v-model.trim="form.dataKey" placeholder="请输入数据键" />
|
||||||
@ -229,8 +213,8 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="item in calcDataPointOptions"
|
v-for="item in calcDataPointOptions"
|
||||||
:key="`${item.siteId || ''}_${item.deviceId || ''}_${item.dataKey}`"
|
:key="`${item.siteId || ''}_${item.deviceId || ''}_${item.dataKey}`"
|
||||||
:label="`${item.dataKey}${item.pointDesc ? ' - ' + item.pointDesc : ''}`"
|
:label="`${item.pointId}${item.pointDesc ? ' - ' + item.pointDesc : ''}`"
|
||||||
:value="item.dataKey"
|
:value="item.pointId"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -343,7 +327,6 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getAllSites } from '@/api/ems/zddt'
|
|
||||||
import { getAllDeviceCategory } from '@/api/ems/search'
|
import { getAllDeviceCategory } from '@/api/ems/search'
|
||||||
import {
|
import {
|
||||||
importPointConfigCsv,
|
importPointConfigCsv,
|
||||||
@ -354,12 +337,7 @@ import {
|
|||||||
deletePointMatch,
|
deletePointMatch,
|
||||||
getDeviceListBySiteAndCategory,
|
getDeviceListBySiteAndCategory,
|
||||||
getPointConfigLatestValues,
|
getPointConfigLatestValues,
|
||||||
getPointConfigCurve,
|
getPointConfigCurve
|
||||||
getPointCalcConfigList,
|
|
||||||
getPointCalcConfigDetail,
|
|
||||||
addPointCalcConfig,
|
|
||||||
updatePointCalcConfig,
|
|
||||||
deletePointCalcConfig
|
|
||||||
} from '@/api/ems/site'
|
} from '@/api/ems/site'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -367,8 +345,6 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
searchLoading: false,
|
|
||||||
siteList: [],
|
|
||||||
deviceCategoryList: [],
|
deviceCategoryList: [],
|
||||||
tableData: [],
|
tableData: [],
|
||||||
total: 0,
|
total: 0,
|
||||||
@ -379,6 +355,7 @@ export default {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
siteId: '',
|
siteId: '',
|
||||||
deviceCategory: '',
|
deviceCategory: '',
|
||||||
|
deviceId: '',
|
||||||
dataKey: '',
|
dataKey: '',
|
||||||
pointDesc: '',
|
pointDesc: '',
|
||||||
pointType: 'data'
|
pointType: 'data'
|
||||||
@ -392,7 +369,8 @@ export default {
|
|||||||
curveQuery: {
|
curveQuery: {
|
||||||
siteId: '',
|
siteId: '',
|
||||||
deviceId: '',
|
deviceId: '',
|
||||||
dataKey: '',
|
pointId: '',
|
||||||
|
pointType: 'data',
|
||||||
rangeType: 'custom',
|
rangeType: 'custom',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: ''
|
endTime: ''
|
||||||
@ -412,6 +390,7 @@ export default {
|
|||||||
deviceCategory: '',
|
deviceCategory: '',
|
||||||
deviceId: '',
|
deviceId: '',
|
||||||
registerAddress: '',
|
registerAddress: '',
|
||||||
|
pointId: '',
|
||||||
pointName: '',
|
pointName: '',
|
||||||
dataKey: '',
|
dataKey: '',
|
||||||
pointDesc: '',
|
pointDesc: '',
|
||||||
@ -426,51 +405,9 @@ export default {
|
|||||||
alarmUpper1: ''
|
alarmUpper1: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
siteId: [{ required: true, message: '请选择站点', trigger: 'change' }],
|
siteId: [{ required: true, message: '请先在顶部选择站点', trigger: 'change' }],
|
||||||
pointType: [{ required: true, message: '请选择点位类型', trigger: 'change' }],
|
pointType: [{ required: true, message: '请选择点位类型', trigger: 'change' }],
|
||||||
deviceCategory: [{
|
pointId: [{ required: true, message: '请输入点位ID', trigger: 'blur' }],
|
||||||
validator: (rule, value, callback) => {
|
|
||||||
if (this.form.pointType !== 'data') {
|
|
||||||
callback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!String(value || '').trim()) {
|
|
||||||
callback(new Error('请选择设备类型'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback()
|
|
||||||
},
|
|
||||||
trigger: 'change'
|
|
||||||
}],
|
|
||||||
deviceId: [{
|
|
||||||
validator: (rule, value, callback) => {
|
|
||||||
if (this.form.pointType !== 'data') {
|
|
||||||
callback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!String(value || '').trim()) {
|
|
||||||
callback(new Error('请选择设备ID'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback()
|
|
||||||
},
|
|
||||||
trigger: 'change'
|
|
||||||
}],
|
|
||||||
registerAddress: [{
|
|
||||||
validator: (rule, value, callback) => {
|
|
||||||
if (this.form.pointType !== 'data') {
|
|
||||||
callback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!String(value || '').trim()) {
|
|
||||||
callback(new Error('请输入寄存器地址'))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
callback()
|
|
||||||
},
|
|
||||||
trigger: 'blur'
|
|
||||||
}],
|
|
||||||
dataKey: [{ required: true, message: '请输入数据键', trigger: 'blur' }],
|
|
||||||
pointName: [{ required: true, message: '请输入点位名称', trigger: 'blur' }],
|
pointName: [{ required: true, message: '请输入点位名称', trigger: 'blur' }],
|
||||||
calcExpression: [{
|
calcExpression: [{
|
||||||
validator: (rule, value, callback) => {
|
validator: (rule, value, callback) => {
|
||||||
@ -489,18 +426,33 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
'$route.query.siteId'(newSiteId) {
|
||||||
|
const normalizedSiteId = this.hasValidSiteId(newSiteId) ? String(newSiteId).trim() : ''
|
||||||
|
if (normalizedSiteId === this.queryParams.siteId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.queryParams.siteId = normalizedSiteId
|
||||||
|
this.queryParams.deviceCategory = ''
|
||||||
|
this.queryParams.deviceId = ''
|
||||||
|
this.onSearch()
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatDeviceInfo(row) {
|
||||||
|
if (!row) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
const deviceCategory = row.deviceCategory || ''
|
||||||
|
const deviceId = row.deviceId || ''
|
||||||
|
if (!deviceCategory && !deviceId) {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
return `${deviceCategory}/${deviceId}`
|
||||||
|
},
|
||||||
hasValidSiteId(siteId) {
|
hasValidSiteId(siteId) {
|
||||||
return !!(siteId !== undefined && siteId !== null && String(siteId).trim())
|
return !!(siteId !== undefined && siteId !== null && String(siteId).trim())
|
||||||
},
|
},
|
||||||
getSiteList() {
|
|
||||||
this.searchLoading = true
|
|
||||||
return getAllSites().then(response => {
|
|
||||||
this.siteList = response?.data || []
|
|
||||||
}).finally(() => {
|
|
||||||
this.searchLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getCategoryList() {
|
getCategoryList() {
|
||||||
return getAllDeviceCategory().then(response => {
|
return getAllDeviceCategory().then(response => {
|
||||||
this.deviceCategoryList = response?.data || []
|
this.deviceCategoryList = response?.data || []
|
||||||
@ -535,40 +487,18 @@ export default {
|
|||||||
},
|
},
|
||||||
getData() {
|
getData() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
if (this.activePointTab === 'calc') {
|
getPointMatchList(this.queryParams).then(response => {
|
||||||
const calcParams = {
|
const rows = response?.rows || []
|
||||||
pageNum: this.queryParams.pageNum,
|
this.tableData = rows.map(item => ({
|
||||||
pageSize: this.queryParams.pageSize,
|
...item,
|
||||||
siteId: this.queryParams.siteId,
|
pointType: item.pointType || 'data',
|
||||||
dataKey: this.queryParams.dataKey,
|
latestValue: '-'
|
||||||
pointDesc: this.queryParams.pointDesc
|
}))
|
||||||
}
|
this.total = response?.total || 0
|
||||||
getPointCalcConfigList(calcParams).then(response => {
|
this.loadLatestValues()
|
||||||
const rows = response?.rows || []
|
}).finally(() => {
|
||||||
this.tableData = rows.map(item => ({
|
this.loading = false
|
||||||
...item,
|
})
|
||||||
pointType: 'calc',
|
|
||||||
latestValue: '-'
|
|
||||||
}))
|
|
||||||
this.total = response?.total || 0
|
|
||||||
this.loadLatestValues()
|
|
||||||
}).finally(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getPointMatchList(this.queryParams).then(response => {
|
|
||||||
const rows = response?.rows || []
|
|
||||||
this.tableData = rows.map(item => ({
|
|
||||||
...item,
|
|
||||||
pointType: item.pointType || 'data',
|
|
||||||
latestValue: '-'
|
|
||||||
}))
|
|
||||||
this.total = response?.total || 0
|
|
||||||
this.loadLatestValues()
|
|
||||||
}).finally(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
loadLatestValues() {
|
loadLatestValues() {
|
||||||
if (!this.tableData.length) {
|
if (!this.tableData.length) {
|
||||||
@ -582,7 +512,55 @@ export default {
|
|||||||
dataKey: item.dataKey
|
dataKey: item.dataKey
|
||||||
}))
|
}))
|
||||||
if (!points.length) {
|
if (!points.length) {
|
||||||
this.tableData = this.applyCalcLatestValues(this.tableData)
|
const calcRows = this.tableData.filter(item => item.pointType === 'calc')
|
||||||
|
if (!calcRows.length) {
|
||||||
|
this.tableData = this.applyCalcLatestValues(this.tableData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loadCalcDependencyRows(calcRows).then(depRows => {
|
||||||
|
if (!depRows.length) {
|
||||||
|
this.tableData = this.applyCalcLatestValues(this.tableData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const depPoints = depRows.map(item => ({
|
||||||
|
siteId: item.siteId,
|
||||||
|
deviceId: item.deviceId,
|
||||||
|
dataKey: item.dataKey
|
||||||
|
}))
|
||||||
|
return getPointConfigLatestValues({ points: depPoints }).then(response => {
|
||||||
|
const latestList = response?.data || []
|
||||||
|
const latestMap = latestList.reduce((acc, item) => {
|
||||||
|
const key = `${item.siteId || ''}__${item.deviceId || ''}__${item.dataKey || ''}`
|
||||||
|
acc[key] = item.pointValue
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
const depRowsWithLatest = depRows.map(row => {
|
||||||
|
const key = `${row.siteId || ''}__${row.deviceId || ''}__${row.dataKey || ''}`
|
||||||
|
const latestValue = latestMap[key]
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
latestValue: (latestValue === null || latestValue === undefined || latestValue === '') ? '-' : latestValue
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const mergedRows = this.applyCalcLatestValues([...depRowsWithLatest, ...this.tableData])
|
||||||
|
const calcLatestMap = mergedRows
|
||||||
|
.filter(item => item.pointType === 'calc')
|
||||||
|
.reduce((acc, item) => {
|
||||||
|
acc[this.getCalcRowKey(item)] = item.latestValue
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
this.tableData = this.tableData.map(row => {
|
||||||
|
if (row.pointType !== 'calc') return row
|
||||||
|
const nextLatest = calcLatestMap[this.getCalcRowKey(row)]
|
||||||
|
return {
|
||||||
|
...row,
|
||||||
|
latestValue: (nextLatest === null || nextLatest === undefined || nextLatest === '') ? '-' : nextLatest
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}).catch(() => {
|
||||||
|
this.tableData = this.applyCalcLatestValues(this.tableData)
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
getPointConfigLatestValues({ points }).then(response => {
|
getPointConfigLatestValues({ points }).then(response => {
|
||||||
@ -603,6 +581,78 @@ export default {
|
|||||||
this.tableData = this.applyCalcLatestValues(withDataLatestValue)
|
this.tableData = this.applyCalcLatestValues(withDataLatestValue)
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
|
getCalcRowKey(row) {
|
||||||
|
return `${row.id || ''}__${row.siteId || ''}__${row.pointId || ''}`
|
||||||
|
},
|
||||||
|
extractExpressionTokens(expression) {
|
||||||
|
const expr = String(expression || '').trim()
|
||||||
|
if (!expr) return []
|
||||||
|
if (!/^[0-9A-Za-z_+\-*/().\s]+$/.test(expr)) return []
|
||||||
|
const matched = expr.match(/\b[A-Za-z_][A-Za-z0-9_]*\b/g) || []
|
||||||
|
return Array.from(new Set(matched.map(item => String(item || '').trim()).filter(Boolean)))
|
||||||
|
},
|
||||||
|
loadCalcDependencyRows(calcRows = []) {
|
||||||
|
if (!calcRows.length) {
|
||||||
|
return Promise.resolve([])
|
||||||
|
}
|
||||||
|
const tokenBySite = {}
|
||||||
|
calcRows.forEach(row => {
|
||||||
|
const siteId = String(row.siteId || '').trim()
|
||||||
|
if (!siteId) return
|
||||||
|
const tokens = this.extractExpressionTokens(row.calcExpression)
|
||||||
|
if (!tokenBySite[siteId]) {
|
||||||
|
tokenBySite[siteId] = new Set()
|
||||||
|
}
|
||||||
|
tokens.forEach(token => tokenBySite[siteId].add(token))
|
||||||
|
})
|
||||||
|
const siteIds = Object.keys(tokenBySite)
|
||||||
|
if (!siteIds.length) {
|
||||||
|
return Promise.resolve([])
|
||||||
|
}
|
||||||
|
const tasks = siteIds.map(siteId => {
|
||||||
|
return getPointMatchList({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 5000,
|
||||||
|
siteId,
|
||||||
|
pointType: 'data'
|
||||||
|
}).then(response => {
|
||||||
|
const rows = response?.rows || []
|
||||||
|
const targetTokens = tokenBySite[siteId] || new Set()
|
||||||
|
if (!targetTokens.size) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
const normalizedTokenSet = new Set()
|
||||||
|
targetTokens.forEach(token => {
|
||||||
|
normalizedTokenSet.add(token)
|
||||||
|
normalizedTokenSet.add(token.toUpperCase())
|
||||||
|
normalizedTokenSet.add(token.toLowerCase())
|
||||||
|
})
|
||||||
|
return rows.filter(item => {
|
||||||
|
const pointId = String(item.pointId || '').trim()
|
||||||
|
if (!pointId) return false
|
||||||
|
if (!item.siteId || !item.deviceId || !item.dataKey) return false
|
||||||
|
return normalizedTokenSet.has(pointId) ||
|
||||||
|
normalizedTokenSet.has(pointId.toUpperCase()) ||
|
||||||
|
normalizedTokenSet.has(pointId.toLowerCase())
|
||||||
|
}).map(item => ({
|
||||||
|
...item,
|
||||||
|
pointType: 'data',
|
||||||
|
latestValue: '-'
|
||||||
|
}))
|
||||||
|
}).catch(() => [])
|
||||||
|
})
|
||||||
|
return Promise.all(tasks).then(resultList => {
|
||||||
|
const flatRows = resultList.reduce((acc, rows) => acc.concat(rows || []), [])
|
||||||
|
const uniqueMap = {}
|
||||||
|
flatRows.forEach(row => {
|
||||||
|
const key = `${row.siteId || ''}__${row.deviceId || ''}__${row.dataKey || ''}`
|
||||||
|
if (!uniqueMap[key]) {
|
||||||
|
uniqueMap[key] = row
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return Object.values(uniqueMap)
|
||||||
|
})
|
||||||
|
},
|
||||||
applyCalcLatestValues(rows = []) {
|
applyCalcLatestValues(rows = []) {
|
||||||
const dataPointMap = {}
|
const dataPointMap = {}
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
@ -610,12 +660,31 @@ export default {
|
|||||||
if (row.latestValue === '-' || row.latestValue === '' || row.latestValue === null || row.latestValue === undefined) {
|
if (row.latestValue === '-' || row.latestValue === '' || row.latestValue === null || row.latestValue === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const deviceKey = `${row.siteId || ''}__${row.deviceId || ''}__${row.dataKey || ''}`
|
const tokens = [row.pointId]
|
||||||
const siteKey = `${row.siteId || ''}__${row.dataKey || ''}`
|
.map(item => String(item || '').trim())
|
||||||
dataPointMap[deviceKey] = row.latestValue
|
.filter(Boolean)
|
||||||
if (dataPointMap[siteKey] === undefined) {
|
tokens.forEach(token => {
|
||||||
dataPointMap[siteKey] = row.latestValue
|
const deviceKey = `${row.siteId || ''}__${row.deviceId || ''}__${token}`
|
||||||
}
|
const siteKey = `${row.siteId || ''}__${token}`
|
||||||
|
dataPointMap[deviceKey] = row.latestValue
|
||||||
|
if (dataPointMap[siteKey] === undefined) {
|
||||||
|
dataPointMap[siteKey] = row.latestValue
|
||||||
|
}
|
||||||
|
const upperToken = token.toUpperCase()
|
||||||
|
const lowerToken = token.toLowerCase()
|
||||||
|
const upperDeviceKey = `${row.siteId || ''}__${row.deviceId || ''}__${upperToken}`
|
||||||
|
const upperSiteKey = `${row.siteId || ''}__${upperToken}`
|
||||||
|
const lowerDeviceKey = `${row.siteId || ''}__${row.deviceId || ''}__${lowerToken}`
|
||||||
|
const lowerSiteKey = `${row.siteId || ''}__${lowerToken}`
|
||||||
|
dataPointMap[upperDeviceKey] = row.latestValue
|
||||||
|
if (dataPointMap[upperSiteKey] === undefined) {
|
||||||
|
dataPointMap[upperSiteKey] = row.latestValue
|
||||||
|
}
|
||||||
|
dataPointMap[lowerDeviceKey] = row.latestValue
|
||||||
|
if (dataPointMap[lowerSiteKey] === undefined) {
|
||||||
|
dataPointMap[lowerSiteKey] = row.latestValue
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
return rows.map(row => {
|
return rows.map(row => {
|
||||||
if (row.pointType !== 'calc') return row
|
if (row.pointType !== 'calc') return row
|
||||||
@ -632,9 +701,17 @@ export default {
|
|||||||
const tokenPattern = /\b[A-Za-z_][A-Za-z0-9_]*\b/g
|
const tokenPattern = /\b[A-Za-z_][A-Za-z0-9_]*\b/g
|
||||||
const missingKeys = []
|
const missingKeys = []
|
||||||
const resolvedExpr = expr.replace(tokenPattern, token => {
|
const resolvedExpr = expr.replace(tokenPattern, token => {
|
||||||
const deviceKey = `${siteId || ''}__${deviceId || ''}__${token}`
|
const candidates = [token, token.toUpperCase(), token.toLowerCase()]
|
||||||
const siteKey = `${siteId || ''}__${token}`
|
let value
|
||||||
const value = dataPointMap[deviceKey] !== undefined ? dataPointMap[deviceKey] : dataPointMap[siteKey]
|
for (let i = 0; i < candidates.length; i++) {
|
||||||
|
const candidate = candidates[i]
|
||||||
|
const deviceKey = `${siteId || ''}__${deviceId || ''}__${candidate}`
|
||||||
|
const siteKey = `${siteId || ''}__${candidate}`
|
||||||
|
value = dataPointMap[deviceKey] !== undefined ? dataPointMap[deviceKey] : dataPointMap[siteKey]
|
||||||
|
if (value !== undefined && value !== null && value !== '' && value !== '-') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if (value === undefined || value === null || value === '' || value === '-') {
|
if (value === undefined || value === null || value === '' || value === '-') {
|
||||||
missingKeys.push(token)
|
missingKeys.push(token)
|
||||||
return 'NaN'
|
return 'NaN'
|
||||||
@ -664,11 +741,13 @@ export default {
|
|||||||
this.getData()
|
this.getData()
|
||||||
},
|
},
|
||||||
onReset() {
|
onReset() {
|
||||||
|
const currentSiteId = this.queryParams.siteId
|
||||||
this.queryParams = {
|
this.queryParams = {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
siteId: '',
|
siteId: currentSiteId,
|
||||||
deviceCategory: '',
|
deviceCategory: '',
|
||||||
|
deviceId: '',
|
||||||
dataKey: '',
|
dataKey: '',
|
||||||
pointDesc: '',
|
pointDesc: '',
|
||||||
pointType: this.activePointTab
|
pointType: this.activePointTab
|
||||||
@ -684,10 +763,6 @@ export default {
|
|||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1
|
||||||
this.getData()
|
this.getData()
|
||||||
},
|
},
|
||||||
handleSiteChange() {
|
|
||||||
this.queryParams.deviceCategory = ''
|
|
||||||
this.onSearch()
|
|
||||||
},
|
|
||||||
handleSizeChange(val) {
|
handleSizeChange(val) {
|
||||||
this.queryParams.pageSize = val
|
this.queryParams.pageSize = val
|
||||||
this.getData()
|
this.getData()
|
||||||
@ -748,6 +823,7 @@ export default {
|
|||||||
deviceCategory: this.queryParams.deviceCategory || '',
|
deviceCategory: this.queryParams.deviceCategory || '',
|
||||||
deviceId: '',
|
deviceId: '',
|
||||||
registerAddress: '',
|
registerAddress: '',
|
||||||
|
pointId: '',
|
||||||
pointName: '',
|
pointName: '',
|
||||||
dataKey: '',
|
dataKey: '',
|
||||||
pointDesc: '',
|
pointDesc: '',
|
||||||
@ -780,26 +856,18 @@ export default {
|
|||||||
openEditDialog(id) {
|
openEditDialog(id) {
|
||||||
this.resetForm()
|
this.resetForm()
|
||||||
this.loading = true
|
this.loading = true
|
||||||
if (this.activePointTab === 'calc') {
|
getPointMatchDetail(id).then(response => {
|
||||||
getPointCalcConfigDetail(id).then(response => {
|
this.form = Object.assign(this.form, response?.data || {})
|
||||||
this.form = Object.assign(this.form, response?.data || {})
|
this.form.pointType = this.form.pointType || 'data'
|
||||||
this.form.pointType = 'calc'
|
this.form.isAlarm = Number(this.form.isAlarm || 0)
|
||||||
this.dialogVisible = true
|
this.dialogVisible = true
|
||||||
this.loadCalcDataPointOptions()
|
if (this.form.pointType === 'calc') {
|
||||||
}).finally(() => {
|
return this.loadCalcDataPointOptions()
|
||||||
this.loading = false
|
}
|
||||||
})
|
return this.getFormDeviceList()
|
||||||
} else {
|
}).finally(() => {
|
||||||
getPointMatchDetail(id).then(response => {
|
this.loading = false
|
||||||
this.form = Object.assign(this.form, response?.data || {})
|
})
|
||||||
this.form.pointType = this.form.pointType || 'data'
|
|
||||||
this.form.isAlarm = Number(this.form.isAlarm || 0)
|
|
||||||
this.dialogVisible = true
|
|
||||||
return this.getFormDeviceList()
|
|
||||||
}).finally(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
handleDelete(id) {
|
handleDelete(id) {
|
||||||
this.$confirm('确认删除该点位配置吗?', '提示', {
|
this.$confirm('确认删除该点位配置吗?', '提示', {
|
||||||
@ -807,22 +875,12 @@ export default {
|
|||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
if (this.activePointTab === 'calc') {
|
return deletePointMatch(id)
|
||||||
return deletePointCalcConfig(id)
|
|
||||||
} else {
|
|
||||||
return deletePointMatch(id)
|
|
||||||
}
|
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.$message.success('删除成功')
|
this.$message.success('删除成功')
|
||||||
this.getData()
|
this.getData()
|
||||||
}).catch(() => {})
|
}).catch(() => {})
|
||||||
},
|
},
|
||||||
handleFormSiteChange() {
|
|
||||||
this.form.deviceCategory = ''
|
|
||||||
this.form.deviceId = ''
|
|
||||||
this.formDeviceList = []
|
|
||||||
this.loadCalcDataPointOptions()
|
|
||||||
},
|
|
||||||
handleFormCategoryChange() {
|
handleFormCategoryChange() {
|
||||||
this.form.deviceId = ''
|
this.form.deviceId = ''
|
||||||
this.getFormDeviceList()
|
this.getFormDeviceList()
|
||||||
@ -856,7 +914,7 @@ export default {
|
|||||||
params.deviceId = this.form.deviceId
|
params.deviceId = this.form.deviceId
|
||||||
}
|
}
|
||||||
return getPointMatchList(params).then(response => {
|
return getPointMatchList(params).then(response => {
|
||||||
this.calcDataPointOptions = response?.rows || []
|
this.calcDataPointOptions = (response?.rows || []).filter(item => String(item.pointId || '').trim())
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.calcDataPointOptions = []
|
this.calcDataPointOptions = []
|
||||||
})
|
})
|
||||||
@ -871,15 +929,12 @@ export default {
|
|||||||
this.selectedCalcDataKey = ''
|
this.selectedCalcDataKey = ''
|
||||||
},
|
},
|
||||||
openCurveDialog(row) {
|
openCurveDialog(row) {
|
||||||
if (row.pointType === 'calc') {
|
|
||||||
this.$message.warning('计算点暂不支持曲线查询')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.curveDialogTitle = `曲线 - ${row.pointDesc || row.dataKey || ''}`
|
this.curveDialogTitle = `曲线 - ${row.pointDesc || row.dataKey || ''}`
|
||||||
this.curveQuery = {
|
this.curveQuery = {
|
||||||
siteId: row.siteId || '',
|
siteId: row.siteId || '',
|
||||||
deviceId: row.deviceId || '',
|
deviceId: row.deviceId || '',
|
||||||
dataKey: row.dataKey || '',
|
pointId: row.pointId || '',
|
||||||
|
pointType: row.pointType || 'data',
|
||||||
rangeType: 'custom',
|
rangeType: 'custom',
|
||||||
startTime: '',
|
startTime: '',
|
||||||
endTime: ''
|
endTime: ''
|
||||||
@ -952,7 +1007,7 @@ export default {
|
|||||||
return normalized.slice(0, 16)
|
return normalized.slice(0, 16)
|
||||||
},
|
},
|
||||||
loadCurveData() {
|
loadCurveData() {
|
||||||
if (!this.curveQuery.siteId || !this.curveQuery.deviceId || !this.curveQuery.dataKey) {
|
if (!this.curveQuery.siteId || !this.curveQuery.pointId) {
|
||||||
this.$message.warning('点位信息不完整,无法查询曲线')
|
this.$message.warning('点位信息不完整,无法查询曲线')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -964,7 +1019,16 @@ export default {
|
|||||||
this.curveQuery.startTime = this.curveCustomRange[0]
|
this.curveQuery.startTime = this.curveCustomRange[0]
|
||||||
this.curveQuery.endTime = this.curveCustomRange[1]
|
this.curveQuery.endTime = this.curveCustomRange[1]
|
||||||
this.curveLoading = true
|
this.curveLoading = true
|
||||||
getPointConfigCurve(this.curveQuery).then(response => {
|
const query = {
|
||||||
|
siteId: this.curveQuery.siteId,
|
||||||
|
deviceId: this.curveQuery.deviceId,
|
||||||
|
pointId: this.curveQuery.pointId,
|
||||||
|
pointType: this.curveQuery.pointType,
|
||||||
|
rangeType: this.curveQuery.rangeType,
|
||||||
|
startTime: this.curveQuery.startTime,
|
||||||
|
endTime: this.curveQuery.endTime
|
||||||
|
}
|
||||||
|
getPointConfigCurve(query).then(response => {
|
||||||
const rows = response?.data || []
|
const rows = response?.data || []
|
||||||
this.renderCurveChart(rows)
|
this.renderCurveChart(rows)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
@ -1016,10 +1080,38 @@ export default {
|
|||||||
],
|
],
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: this.curveQuery.dataKey || '点位值',
|
name: this.curveQuery.pointId || '点位值',
|
||||||
type: 'line',
|
type: 'line',
|
||||||
data: yData,
|
data: yData,
|
||||||
connectNulls: true
|
connectNulls: true,
|
||||||
|
markPoint: {
|
||||||
|
symbolSize: 44,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
formatter(params) {
|
||||||
|
const name = params && params.name ? params.name : ''
|
||||||
|
const value = params && params.value !== undefined && params.value !== null ? params.value : '-'
|
||||||
|
return `${name}: ${value}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
type: 'max',
|
||||||
|
name: '最大值',
|
||||||
|
itemStyle: {
|
||||||
|
color: '#f56c6c'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'min',
|
||||||
|
name: '最小值',
|
||||||
|
itemStyle: {
|
||||||
|
color: '#409eff'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
@ -1039,27 +1131,18 @@ export default {
|
|||||||
? ''
|
? ''
|
||||||
: String(this.form.deviceId).trim()
|
: String(this.form.deviceId).trim()
|
||||||
const dataKey = (this.form.dataKey || '').trim()
|
const dataKey = (this.form.dataKey || '').trim()
|
||||||
if (!dataKey) {
|
const pointId = (this.form.pointId || '').trim()
|
||||||
this.$message.warning('请输入数据键')
|
if (!pointId) {
|
||||||
|
this.$message.warning('请输入点位ID')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const normalizedDeviceCategory = String(this.form.deviceCategory || '').trim()
|
||||||
if (pointType === 'data') {
|
if (pointType === 'data') {
|
||||||
if (!this.form.deviceCategory) {
|
if (deviceId && this.formDeviceList.length > 0 && !this.formDeviceList.some(item => item.__value === deviceId)) {
|
||||||
this.$message.warning('请选择设备类型')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!deviceId) {
|
|
||||||
this.$message.warning('请选择设备ID')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!this.form.registerAddress || !String(this.form.registerAddress).trim()) {
|
|
||||||
this.$message.warning('请输入寄存器地址')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.formDeviceList.length > 0 && !this.formDeviceList.some(item => item.__value === deviceId)) {
|
|
||||||
this.$message.warning('设备ID无效,请重新选择')
|
this.$message.warning('设备ID无效,请重新选择')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.form.registerAddress = this.form.registerAddress ? String(this.form.registerAddress).trim() : ''
|
||||||
} else {
|
} else {
|
||||||
const calcExpression = String(this.form.calcExpression || '').trim()
|
const calcExpression = String(this.form.calcExpression || '').trim()
|
||||||
if (!calcExpression) {
|
if (!calcExpression) {
|
||||||
@ -1070,19 +1153,24 @@ export default {
|
|||||||
this.$message.warning('计算表达式格式不正确')
|
this.$message.warning('计算表达式格式不正确')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.form.deviceCategory = this.form.deviceCategory || ''
|
|
||||||
this.form.deviceId = deviceId
|
|
||||||
this.form.registerAddress = this.form.registerAddress || ''
|
this.form.registerAddress = this.form.registerAddress || ''
|
||||||
}
|
}
|
||||||
|
this.form.deviceCategory = normalizedDeviceCategory
|
||||||
this.form.deviceId = deviceId
|
this.form.deviceId = deviceId
|
||||||
|
this.form.pointId = pointId
|
||||||
this.form.dataKey = dataKey
|
this.form.dataKey = dataKey
|
||||||
this.form.pointType = pointType
|
this.form.pointType = pointType
|
||||||
|
|
||||||
if (pointType === 'calc') {
|
if (pointType === 'calc') {
|
||||||
const request = this.form.id ? updatePointCalcConfig : addPointCalcConfig
|
const request = this.form.id ? updatePointMatch : addPointMatch
|
||||||
const calcData = {
|
const calcData = {
|
||||||
id: this.form.id,
|
id: this.form.id,
|
||||||
siteId: this.form.siteId,
|
siteId: this.form.siteId,
|
||||||
|
pointType: 'calc',
|
||||||
|
deviceCategory: this.form.deviceCategory,
|
||||||
|
deviceId: '',
|
||||||
|
registerAddress: '',
|
||||||
|
pointId: this.form.pointId,
|
||||||
pointName: this.form.pointName,
|
pointName: this.form.pointName,
|
||||||
dataKey: this.form.dataKey,
|
dataKey: this.form.dataKey,
|
||||||
pointDesc: this.form.pointDesc,
|
pointDesc: this.form.pointDesc,
|
||||||
@ -1111,7 +1199,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
Promise.all([this.getSiteList(), this.getCategoryList()]).then(() => {
|
this.queryParams.siteId = this.hasValidSiteId(this.$route.query.siteId) ? String(this.$route.query.siteId).trim() : ''
|
||||||
|
this.getCategoryList().then(() => {
|
||||||
this.getData()
|
this.getData()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,11 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
||||||
<el-form :inline="true" class="select-container">
|
<el-form :inline="true" class="select-container">
|
||||||
<el-form-item label="站点选择">
|
|
||||||
<el-select v-model="siteId" placeholder="请选择换电站名称" :loading="searchLoading" loading-text="正在加载数据" @change="onSearch" clearable>
|
|
||||||
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'zdxeSelect'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="年份选择">
|
<el-form-item label="年份选择">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="defaultYear"
|
v-model="defaultYear"
|
||||||
@ -33,7 +28,7 @@
|
|||||||
:key="item.id"
|
:key="item.id"
|
||||||
>
|
>
|
||||||
<div slot="header" class="time-range-header">
|
<div slot="header" class="time-range-header">
|
||||||
<span class="card-title">{{siteList.find(i=>i.siteId===item.siteId).siteName || item.siteId || ''}}-{{item.month}}月电价时段划分</span>
|
<span class="card-title">{{item.siteId || ''}}-{{item.month}}月电价时段划分</span>
|
||||||
<div>
|
<div>
|
||||||
<el-button type="primary" size="mini" @click="addPowerConfig(item.id)">编辑</el-button>
|
<el-button type="primary" size="mini" @click="addPowerConfig(item.id)">编辑</el-button>
|
||||||
<el-button type="warning" size="mini" @click="deletePowerConfig(item)">删除</el-button>
|
<el-button type="warning" size="mini" @click="deletePowerConfig(item)">删除</el-button>
|
||||||
@ -61,21 +56,28 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {energyPriceConfig,listPriceConfig} from '@/api/ems/powerTariff'
|
import {energyPriceConfig,listPriceConfig} from '@/api/ems/powerTariff'
|
||||||
import {getAllSites} from '@/api/ems/zddt'
|
|
||||||
import AddPowerTariff from './AddPowerTariff.vue'
|
import AddPowerTariff from './AddPowerTariff.vue'
|
||||||
import DateTimeSelect from "@/views/ems/search/DateTimeSelect.vue";
|
import DateTimeSelect from "@/views/ems/search/DateTimeSelect.vue";
|
||||||
export default {
|
export default {
|
||||||
name: "PowerTariff",
|
name: "PowerTariff",
|
||||||
components: {DateTimeSelect, AddPowerTariff},
|
components: {DateTimeSelect, AddPowerTariff},
|
||||||
computed: { },
|
computed: { },
|
||||||
|
watch: {
|
||||||
|
'$route.query.siteId'(newSiteId) {
|
||||||
|
const normalizedSiteId = this.hasValidSiteId(newSiteId) ? String(newSiteId).trim() : ''
|
||||||
|
if (normalizedSiteId === this.siteId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.siteId = normalizedSiteId
|
||||||
|
this.onSearch()
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading:false,
|
loading:false,
|
||||||
pageNum:1,
|
pageNum:1,
|
||||||
pageSize:40,
|
pageSize:40,
|
||||||
searchLoading:false,
|
|
||||||
siteId:'',
|
siteId:'',
|
||||||
siteList:[],
|
|
||||||
tableData:[],
|
tableData:[],
|
||||||
tableTotal:0,
|
tableTotal:0,
|
||||||
defaultYear:'',
|
defaultYear:'',
|
||||||
@ -93,6 +95,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods:{
|
methods:{
|
||||||
|
hasValidSiteId(siteId) {
|
||||||
|
return !!(siteId !== undefined && siteId !== null && String(siteId).trim())
|
||||||
|
},
|
||||||
resetTableData(){
|
resetTableData(){
|
||||||
this.tableData=[]
|
this.tableData=[]
|
||||||
this.tableTotal=0
|
this.tableTotal=0
|
||||||
@ -102,19 +107,16 @@ export default {
|
|||||||
onSearch(){
|
onSearch(){
|
||||||
this.getData(true)
|
this.getData(true)
|
||||||
},
|
},
|
||||||
//获取站点列表
|
|
||||||
getZdList(){
|
|
||||||
this.searchLoading=true
|
|
||||||
return getAllSites().then(response => {
|
|
||||||
this.siteList = response?.data || []
|
|
||||||
if( this.siteList.length>0 ) this.siteId = this.siteList[0].siteId
|
|
||||||
}).finally(() => {this.searchLoading=false})
|
|
||||||
},
|
|
||||||
changeDefaultYear(){
|
changeDefaultYear(){
|
||||||
this.getData(true)
|
this.getData(true)
|
||||||
},
|
},
|
||||||
getData(reset=false){
|
getData(reset=false){
|
||||||
reset && this.resetTableData()
|
reset && this.resetTableData()
|
||||||
|
if (!this.siteId) {
|
||||||
|
this.tableData = []
|
||||||
|
this.tableTotal = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
if(!reset && this.tableData.length>=this.tableTotal) return
|
if(!reset && this.tableData.length>=this.tableTotal) return
|
||||||
this.loading=true;
|
this.loading=true;
|
||||||
const date = new Date(this.defaultYear).getFullYear()
|
const date = new Date(this.defaultYear).getFullYear()
|
||||||
@ -163,10 +165,8 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.defaultYear = new Date()
|
this.defaultYear = new Date()
|
||||||
this.loading=true
|
this.siteId = this.hasValidSiteId(this.$route.query.siteId) ? String(this.$route.query.siteId).trim() : ''
|
||||||
this.getZdList().then(()=>{
|
this.getData(true)
|
||||||
this.getData(true)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -17,19 +17,11 @@
|
|||||||
label-width="140px"
|
label-width="140px"
|
||||||
>
|
>
|
||||||
<el-form-item label="站点" prop="siteId">
|
<el-form-item label="站点" prop="siteId">
|
||||||
<el-select
|
<el-input
|
||||||
v-model="formData.siteId"
|
v-model="formData.siteId"
|
||||||
placeholder="请选择"
|
|
||||||
:style="{ width: '50%' }"
|
:style="{ width: '50%' }"
|
||||||
@change="changeType"
|
disabled
|
||||||
>
|
></el-input>
|
||||||
<el-option
|
|
||||||
:label="item.siteName"
|
|
||||||
:value="item.siteId"
|
|
||||||
v-for="(item, index) in siteList"
|
|
||||||
:key="index + 'siteOptions'"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="设备保护名称" prop="faultName">
|
<el-form-item label="设备保护名称" prop="faultName">
|
||||||
<el-input
|
<el-input
|
||||||
@ -272,7 +264,6 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import {mapState} from "vuex";
|
import {mapState} from "vuex";
|
||||||
import {getAllSites} from "@/api/ems/zddt";
|
|
||||||
import {validText} from "@/utils/validate";
|
import {validText} from "@/utils/validate";
|
||||||
import {addProtectPlan, getDeviceListBySiteAndCategory, getProtectPlan, updateProtectPlan} from "@/api/ems/site";
|
import {addProtectPlan, getDeviceListBySiteAndCategory, getProtectPlan, updateProtectPlan} from "@/api/ems/site";
|
||||||
import {getAllDeviceCategory, pointFuzzyQuery} from "@/api/ems/search";
|
import {getAllDeviceCategory, pointFuzzyQuery} from "@/api/ems/search";
|
||||||
@ -301,7 +292,6 @@ export default {
|
|||||||
protectionSettings: [],
|
protectionSettings: [],
|
||||||
protectionPlan: [],
|
protectionPlan: [],
|
||||||
dialogTableVisible: false,
|
dialogTableVisible: false,
|
||||||
siteList: [], //站点列表 从接口获取数据
|
|
||||||
formData: {
|
formData: {
|
||||||
id: "", //设备唯一标识
|
id: "", //设备唯一标识
|
||||||
siteId: "", //站点ID
|
siteId: "", //站点ID
|
||||||
@ -313,13 +303,6 @@ export default {
|
|||||||
description: '',//方案描述
|
description: '',//方案描述
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
siteId: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: "请选择站点",
|
|
||||||
trigger: ["blur", "change"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
faultName: [
|
faultName: [
|
||||||
{required: true, message: "请输入设备保护名称", trigger: "blur"},
|
{required: true, message: "请输入设备保护名称", trigger: "blur"},
|
||||||
],
|
],
|
||||||
@ -353,8 +336,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
open(id, siteId) {
|
open(id, siteId) {
|
||||||
|
this.formData.siteId = siteId || ''
|
||||||
this.dialogTableVisible = true
|
this.dialogTableVisible = true
|
||||||
this.getZdList();
|
|
||||||
this.getDeviceCategoryList().then(() => {
|
this.getDeviceCategoryList().then(() => {
|
||||||
if (id && siteId) {
|
if (id && siteId) {
|
||||||
// this.getDeviceList('PCS', siteId)
|
// this.getDeviceList('PCS', siteId)
|
||||||
@ -560,56 +543,6 @@ export default {
|
|||||||
console.log('设置选中设备类型、设备配置完成', this[type][index])
|
console.log('设置选中设备类型、设备配置完成', this[type][index])
|
||||||
},
|
},
|
||||||
|
|
||||||
//获取站点列表
|
|
||||||
getZdList() {
|
|
||||||
this.loading += 1;
|
|
||||||
getAllSites()
|
|
||||||
.then((response) => {
|
|
||||||
this.siteList = response?.data || [];
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.loading -= 1;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// 切换站点
|
|
||||||
// 重新获取设备列表
|
|
||||||
// 清空选中的设备、点位信息
|
|
||||||
changeType() {
|
|
||||||
//获取当前站点下的pcs和bms
|
|
||||||
this.updateSiteDeviceList()
|
|
||||||
if (this.protectionSettings.length > 0) {
|
|
||||||
const list = this.protectionSettings
|
|
||||||
list.forEach((item) => {
|
|
||||||
item.point = ""
|
|
||||||
item.pointName = ""
|
|
||||||
item.deviceId = []
|
|
||||||
item.deviceName = []
|
|
||||||
item.categoryName = ''
|
|
||||||
item.deviceCategory = ''
|
|
||||||
});
|
|
||||||
// this.$set(this,'protectionSettings',list)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.protectionSettings.splice(0, this.protectionSettings.length, ...list)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (this.protectionPlan.length > 0) {
|
|
||||||
const list = this.protectionPlan
|
|
||||||
list.forEach((item) => {
|
|
||||||
item.point = ""
|
|
||||||
item.pointName = ""
|
|
||||||
item.deviceId = []
|
|
||||||
item.deviceName = []
|
|
||||||
item.categoryName = ''
|
|
||||||
item.deviceCategory = ''
|
|
||||||
});
|
|
||||||
// this.$set(this,'protectionPlan',list)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.protectionPlan.splice(0, this.protectionPlan.length, ...list)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
saveDialog() {
|
saveDialog() {
|
||||||
function getToastMsg(name, type, index) {
|
function getToastMsg(name, type, index) {
|
||||||
return {
|
return {
|
||||||
@ -5,22 +5,6 @@
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
>
|
>
|
||||||
<el-form :inline="true" class="select-container">
|
<el-form :inline="true" class="select-container">
|
||||||
<el-form-item label="站点选择">
|
|
||||||
<el-select
|
|
||||||
v-model="form.siteId"
|
|
||||||
placeholder="请选择换电站名称"
|
|
||||||
:loading="searchLoading"
|
|
||||||
loading-text="正在加载数据"
|
|
||||||
clearable
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
:label="item.siteName"
|
|
||||||
:value="item.siteId"
|
|
||||||
v-for="(item, index) in siteList"
|
|
||||||
:key="index + 'zdxeSelect'"
|
|
||||||
></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="故障名称">
|
<el-form-item label="故障名称">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.faultName"
|
v-model="form.faultName"
|
||||||
@ -34,8 +18,8 @@
|
|||||||
<el-button @click="onReset" native-type="button">重置</el-button>
|
<el-button @click="onReset" native-type="button">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button type="primary" @click="addDevice" native-type="button"
|
<el-button type="primary" @click="addPlan" native-type="button"
|
||||||
>新增设备</el-button
|
>新增方案</el-button
|
||||||
>
|
>
|
||||||
<el-table
|
<el-table
|
||||||
class="common-table"
|
class="common-table"
|
||||||
@ -92,8 +76,8 @@
|
|||||||
style="margin-top: 15px; text-align: center"
|
style="margin-top: 15px; text-align: center"
|
||||||
>
|
>
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
<add-device
|
<add-plan
|
||||||
ref="addDevice"
|
ref="addPlan"
|
||||||
@update="getData"
|
@update="getData"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -104,20 +88,18 @@ import {
|
|||||||
protectPlanList,
|
protectPlanList,
|
||||||
deleteProtectPlan,
|
deleteProtectPlan,
|
||||||
} from "@/api/ems/site";
|
} from "@/api/ems/site";
|
||||||
import { getAllSites } from "@/api/ems/zddt";
|
import getQuerySiteId from '@/mixins/ems/getQuerySiteId'
|
||||||
import AddDevice from "./AddDevice.vue";
|
import AddPlan from "./AddPlan.vue";
|
||||||
export default {
|
export default {
|
||||||
name: "SBBH",
|
name: "SBBH",
|
||||||
components: { AddDevice },
|
components: { AddPlan },
|
||||||
|
mixins: [getQuerySiteId],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form:{
|
form:{
|
||||||
siteId:'',
|
|
||||||
faultName:''
|
faultName:''
|
||||||
},
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
searchLoading: false,
|
|
||||||
siteList: [],
|
|
||||||
tableData: [],
|
tableData: [],
|
||||||
pageSize: 10, //分页栏当前每个数据总数
|
pageSize: 10, //分页栏当前每个数据总数
|
||||||
pageNum: 1, //分页栏当前页数
|
pageNum: 1, //分页栏当前页数
|
||||||
@ -126,6 +108,10 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.pageNum = 1;
|
||||||
|
this.getData();
|
||||||
|
},
|
||||||
handleProtectionSettings(data){
|
handleProtectionSettings(data){
|
||||||
if(!data || !JSON.parse(data)) return
|
if(!data || !JSON.parse(data)) return
|
||||||
const arr = JSON.parse(data),
|
const arr = JSON.parse(data),
|
||||||
@ -144,13 +130,17 @@ export default {
|
|||||||
})
|
})
|
||||||
return str.join('')
|
return str.join('')
|
||||||
},
|
},
|
||||||
// 新增设备 展示弹窗
|
// 新增方案 展示弹窗
|
||||||
addDevice() {
|
addPlan() {
|
||||||
this.$refs.addDevice.open()
|
if (!this.siteId) {
|
||||||
|
this.$message.warning('请先在顶部选择站点')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$refs.addPlan.open('', this.siteId)
|
||||||
},
|
},
|
||||||
// 编辑设备
|
// 编辑设备
|
||||||
editDevice(row) {
|
editDevice(row) {
|
||||||
this.$refs.addDevice.open(row.id,row.siteId)
|
this.$refs.addPlan.open(row.id, this.siteId || row.siteId)
|
||||||
},
|
},
|
||||||
//删除设备
|
//删除设备
|
||||||
deleteDevice(row) {
|
deleteDevice(row) {
|
||||||
@ -210,7 +200,6 @@ export default {
|
|||||||
// 重置
|
// 重置
|
||||||
onReset() {
|
onReset() {
|
||||||
this.form={
|
this.form={
|
||||||
siteId: "",
|
|
||||||
faultName: "",
|
faultName: "",
|
||||||
}
|
}
|
||||||
this.pageNum = 1; //每次搜索从1开始搜索
|
this.pageNum = 1; //每次搜索从1开始搜索
|
||||||
@ -218,9 +207,14 @@ export default {
|
|||||||
},
|
},
|
||||||
// 获取数据
|
// 获取数据
|
||||||
getData() {
|
getData() {
|
||||||
|
if (!this.siteId) {
|
||||||
|
this.tableData = []
|
||||||
|
this.totalSize = 0
|
||||||
|
return
|
||||||
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
const { pageNum, pageSize } = this,{siteId,faultName=''}=this.form;
|
const { pageNum, pageSize } = this,{faultName=''}=this.form;
|
||||||
protectPlanList({ siteId, faultName,pageNum, pageSize })
|
protectPlanList({ siteId: this.siteId, faultName,pageNum, pageSize })
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.tableData = response?.rows || [];
|
this.tableData = response?.rows || [];
|
||||||
this.totalSize = response?.total || 0;
|
this.totalSize = response?.total || 0;
|
||||||
@ -229,29 +223,6 @@ export default {
|
|||||||
this.loading = false;
|
this.loading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//获取站点列表
|
|
||||||
getZdList() {
|
|
||||||
this.searchLoading = true;
|
|
||||||
return getAllSites()
|
|
||||||
.then((response) => {
|
|
||||||
this.siteList = response?.data || [];
|
|
||||||
if (this.siteList.length > 0) this.form.siteId = this.siteList[0].siteId;
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.searchLoading = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.loading = true;
|
|
||||||
this.form = {
|
|
||||||
siteId: "",
|
|
||||||
faultName: "",
|
|
||||||
};
|
|
||||||
this.pageNum = 1; //每次搜索从1开始搜索
|
|
||||||
this.getZdList().then(() => {
|
|
||||||
this.getData();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,133 +3,135 @@
|
|||||||
:show-close="false" destroy-on-close lock-scroll append-to-body width="800px" class="ems-dialog"
|
:show-close="false" destroy-on-close lock-scroll append-to-body width="800px" class="ems-dialog"
|
||||||
:title="mode === 'add'?'新增设备':`编辑设备` ">
|
:title="mode === 'add'?'新增设备':`编辑设备` ">
|
||||||
<div v-loading="loading>0">
|
<div v-loading="loading>0">
|
||||||
<el-form v-loading="loading>0" ref="addTempForm" inline :model="formData" :rules="rules" size="medium"
|
<div class="form-layout" :class="{ 'has-pcs': isPcs }">
|
||||||
label-width="120px" class="device-form">
|
<el-form v-loading="loading>0" ref="addTempForm" inline :model="formData" :rules="rules" size="medium"
|
||||||
<el-form-item label="站点" prop="siteId">
|
label-width="120px" class="device-form base-form">
|
||||||
<el-select v-model="formData.siteId" placeholder="请选择" :style="{width: '100%'}" @change="changeType">
|
<el-form-item label="站点" prop="siteId">
|
||||||
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList"
|
<el-select v-model="formData.siteId" placeholder="请选择" :style="{width: '100%'}" @change="changeType">
|
||||||
:key="index+'siteOptions'"></el-option>
|
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList"
|
||||||
</el-select>
|
:key="index+'siteOptions'"></el-option>
|
||||||
</el-form-item>
|
</el-select>
|
||||||
<el-form-item label="设备id" prop="deviceId">
|
</el-form-item>
|
||||||
<el-input v-model="formData.deviceId" placeholder="请输入" maxlength="60" clearable :style="{width: '100%'}">
|
<el-form-item label="设备id" prop="deviceId">
|
||||||
</el-input>
|
<el-input v-model="formData.deviceId" placeholder="请输入" maxlength="60" clearable :style="{width: '100%'}">
|
||||||
</el-form-item>
|
</el-input>
|
||||||
<el-form-item label="设备名称" prop="deviceName">
|
</el-form-item>
|
||||||
<el-input v-model="formData.deviceName" placeholder="请输入" clearable :style="{width: '100%'}">
|
<el-form-item label="设备名称" prop="deviceName">
|
||||||
</el-input>
|
<el-input v-model="formData.deviceName" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
</el-form-item>
|
</el-input>
|
||||||
<el-form-item label="设备描述" prop="description">
|
</el-form-item>
|
||||||
<el-input v-model="formData.description" type="textarea" placeholder="请输入" clearable
|
<el-form-item label="设备描述" prop="description">
|
||||||
:style="{width: '100%'}">
|
<el-input v-model="formData.description" type="textarea" placeholder="请输入" clearable
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="工作状态" prop="communicationStatus">
|
|
||||||
<el-select v-model="formData.communicationStatus" placeholder="请选择" :style="{width: '100%'}">
|
|
||||||
<el-option :label="value" :value="key" v-for="(value,key) in communicationStatusOptions"
|
|
||||||
:key="key+'communicationStatusOptions'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备类型" prop="deviceType">
|
|
||||||
<el-select v-model="formData.deviceType" placeholder="请选择" :style="{width: '100%'}">
|
|
||||||
<el-option :label="value" :value="key" v-for="(value,key) in deviceTypeOptions"
|
|
||||||
:key="key+'deviceTypeOptions'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备类别" prop="deviceCategory">
|
|
||||||
<el-select v-model="formData.deviceCategory" placeholder="请选择" :style="{width: '100%'}"
|
|
||||||
@change="changeType">
|
|
||||||
<el-option :label="item.name" :value="item.code" v-for="(item,index) in deviceCategoryList"
|
|
||||||
:key="index+'deviceCategoryList'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="上级设备" prop="parentId" v-if="dccDeviceCategoryList.includes(formData.deviceCategory)">
|
|
||||||
<el-select v-model="formData.parentId"
|
|
||||||
:placeholder="parentDeviceList.length === 0 && !formData.siteId ? '请先选择站点' : '请选择'"
|
|
||||||
:style="{width: '100%'}">
|
|
||||||
<el-option :label="item.deviceName" :value="item.id" v-for="(item,index) in parentDeviceList"
|
|
||||||
:key="index+'parentDeviceList'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="TCP设备的ip地址" prop="ipAddress" v-if="formData.deviceType === 'TCP'">
|
|
||||||
<el-input v-model="formData.ipAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="TCP设备的端口号" prop="ipPort" v-if="formData.deviceType === 'TCP'">
|
|
||||||
<el-input v-model="formData.ipPort" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="从站地址" prop="slaveId" v-if="formData.deviceType === 'TCP'">
|
|
||||||
<el-input v-model="formData.slaveId" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="串口路径" prop="serialPort">
|
|
||||||
<el-input v-model="formData.serialPort" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="波特率" prop="baudRate">
|
|
||||||
<el-input v-model="formData.baudRate" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="数据位" prop="dataBits">
|
|
||||||
<el-input v-model="formData.dataBits" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="停止位" prop="stopBits">
|
|
||||||
<el-input v-model="formData.stopBits" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="校验位" prop="parity">
|
|
||||||
<el-input v-model="formData.parity" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="图片" prop="pictureUrl">
|
|
||||||
<image-upload :limit="1" :drag="false" @input="uploadImage" :value="formData.pictureUrl"/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
<!-- pcs配置-->
|
|
||||||
<el-form v-if="isPcs" ref="pcsSettingForm" inline :model="pcsSetting" size="medium"
|
|
||||||
label-width="120px" class="device-form" :rules="pcsSettingRules">
|
|
||||||
<div style="font-size: 14px;padding: 10px 0 20px;font-weight: 600;">PCS配置</div>
|
|
||||||
<el-form-item label="开关机地址" prop="pointAddress">
|
|
||||||
<el-input v-model="pcsSetting.pointAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="功率地址" prop="powerAddress">
|
|
||||||
<el-input v-model="pcsSetting.powerAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开机指令" prop="startCommand">
|
|
||||||
<el-input v-model="pcsSetting.startCommand" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="开机目标功率" prop="startPower">
|
|
||||||
<el-input v-model="pcsSetting.startPower" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关机指令" prop="stopCommand">
|
|
||||||
<el-input v-model="pcsSetting.stopCommand" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关机目标功率" prop="stopPower">
|
|
||||||
<el-input v-model="pcsSetting.stopPower" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="电池簇数" prop="clusterNum">
|
|
||||||
<el-input v-model="pcsSetting.clusterNum" placeholder="请输入" clearable :style="{width: '100%'}">
|
|
||||||
</el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<br>
|
|
||||||
<template v-for="index in parseInt(pcsSetting.clusterNum) || 0">
|
|
||||||
<el-form-item :label="'电池簇'+(index)+'地址'"
|
|
||||||
prop="clusterPointAddress">
|
|
||||||
<el-input v-model="pcsSetting.clusterPointAddress[index-1]" placeholder="请输入" clearable
|
|
||||||
:style="{width: '100%'}">
|
:style="{width: '100%'}">
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</template>
|
<el-form-item label="工作状态" prop="communicationStatus">
|
||||||
</el-form>
|
<el-select v-model="formData.communicationStatus" placeholder="请选择" :style="{width: '100%'}">
|
||||||
|
<el-option :label="value" :value="key" v-for="(value,key) in communicationStatusOptions"
|
||||||
|
:key="key+'communicationStatusOptions'"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备类型" prop="deviceType">
|
||||||
|
<el-select v-model="formData.deviceType" placeholder="请选择" :style="{width: '100%'}">
|
||||||
|
<el-option :label="value" :value="key" v-for="(value,key) in deviceTypeOptions"
|
||||||
|
:key="key+'deviceTypeOptions'"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="设备类别" prop="deviceCategory">
|
||||||
|
<el-select v-model="formData.deviceCategory" placeholder="请选择" :style="{width: '100%'}"
|
||||||
|
@change="changeType">
|
||||||
|
<el-option :label="item.name" :value="item.code" v-for="(item,index) in deviceCategoryList"
|
||||||
|
:key="index+'deviceCategoryList'"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="上级设备" prop="parentId" v-if="dccDeviceCategoryList.includes(formData.deviceCategory)">
|
||||||
|
<el-select v-model="formData.parentId"
|
||||||
|
:placeholder="parentDeviceList.length === 0 && !formData.siteId ? '请先选择站点' : '请选择'"
|
||||||
|
:style="{width: '100%'}">
|
||||||
|
<el-option :label="item.deviceName" :value="item.id" v-for="(item,index) in parentDeviceList"
|
||||||
|
:key="index+'parentDeviceList'"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="TCP设备的ip地址" prop="ipAddress" v-if="formData.deviceType === 'TCP'">
|
||||||
|
<el-input v-model="formData.ipAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="TCP设备的端口号" prop="ipPort" v-if="formData.deviceType === 'TCP'">
|
||||||
|
<el-input v-model="formData.ipPort" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="从站地址" prop="slaveId" v-if="formData.deviceType === 'TCP'">
|
||||||
|
<el-input v-model="formData.slaveId" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="串口路径" prop="serialPort">
|
||||||
|
<el-input v-model="formData.serialPort" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="波特率" prop="baudRate">
|
||||||
|
<el-input v-model="formData.baudRate" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="数据位" prop="dataBits">
|
||||||
|
<el-input v-model="formData.dataBits" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="停止位" prop="stopBits">
|
||||||
|
<el-input v-model="formData.stopBits" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="校验位" prop="parity">
|
||||||
|
<el-input v-model="formData.parity" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<!-- pcs配置-->
|
||||||
|
<el-form v-if="isPcs" ref="pcsSettingForm" inline :model="pcsSetting" size="medium"
|
||||||
|
label-width="120px" class="device-form pcs-form" :rules="pcsSettingRules">
|
||||||
|
<div style="font-size: 14px;padding: 10px 0 20px;font-weight: 600;">PCS配置</div>
|
||||||
|
<el-form-item label="开关机地址" prop="pointAddress">
|
||||||
|
<el-input v-model="pcsSetting.pointAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="功率地址" prop="powerAddress">
|
||||||
|
<el-input v-model="pcsSetting.powerAddress" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开机指令" prop="startCommand">
|
||||||
|
<el-input v-model="pcsSetting.startCommand" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="开机目标功率" prop="startPower">
|
||||||
|
<el-input v-model="pcsSetting.startPower" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="关机指令" prop="stopCommand">
|
||||||
|
<el-input v-model="pcsSetting.stopCommand" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="关机目标功率" prop="stopPower">
|
||||||
|
<el-input v-model="pcsSetting.stopPower" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="倍率" prop="powerMultiplier">
|
||||||
|
<el-input v-model="pcsSetting.powerMultiplier" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="电池簇数" prop="clusterNum">
|
||||||
|
<el-input v-model="pcsSetting.clusterNum" placeholder="请输入" clearable :style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<br>
|
||||||
|
<template v-for="index in parseInt(pcsSetting.clusterNum) || 0">
|
||||||
|
<el-form-item :label="'电池簇'+(index)+'地址'"
|
||||||
|
prop="clusterPointAddress">
|
||||||
|
<el-input v-model="pcsSetting.clusterPointAddress[index-1]" placeholder="请输入" clearable
|
||||||
|
:style="{width: '100%'}">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div slot="footer">
|
<div slot="footer">
|
||||||
<el-button @click="closeDialog">取消</el-button>
|
<el-button @click="closeDialog">取消</el-button>
|
||||||
@ -177,6 +179,13 @@ export default {
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const validateDecimal = (rule, value, callback) => {
|
||||||
|
if (value !== '' && !/^(0|[1-9]\d*)(\.\d+)?$/.test(value)) {
|
||||||
|
callback(new Error('只能输入非负数字!'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
loading: 0,
|
loading: 0,
|
||||||
dccDeviceCategoryList: ['CLUSTER', 'BATTERY'],//需要展示上级设备的设备类型
|
dccDeviceCategoryList: ['CLUSTER', 'BATTERY'],//需要展示上级设备的设备类型
|
||||||
@ -201,7 +210,6 @@ export default {
|
|||||||
dataBits: '',//数据位
|
dataBits: '',//数据位
|
||||||
stopBits: '',//停止位
|
stopBits: '',//停止位
|
||||||
parity: '',//校验位
|
parity: '',//校验位
|
||||||
pictureUrl: '',//设备图片
|
|
||||||
slaveId: '',//从站地址
|
slaveId: '',//从站地址
|
||||||
},
|
},
|
||||||
pcsSetting: {
|
pcsSetting: {
|
||||||
@ -212,6 +220,7 @@ export default {
|
|||||||
stopCommand: "",//关机指令
|
stopCommand: "",//关机指令
|
||||||
startPower: '',//开机目标功率
|
startPower: '',//开机目标功率
|
||||||
stopPower: '',//关机目标功率
|
stopPower: '',//关机目标功率
|
||||||
|
powerMultiplier: '',//目标功率倍率
|
||||||
clusterNum: '',//电池簇数
|
clusterNum: '',//电池簇数
|
||||||
clusterPointAddress: []//电池簇地址
|
clusterPointAddress: []//电池簇地址
|
||||||
},
|
},
|
||||||
@ -264,9 +273,6 @@ export default {
|
|||||||
parity: [
|
parity: [
|
||||||
{validator: validateText, trigger: 'blur'}
|
{validator: validateText, trigger: 'blur'}
|
||||||
],
|
],
|
||||||
// pictureUrl:[
|
|
||||||
// { required: true, message: '请上传图片', trigger: ['blur', 'change']}
|
|
||||||
// ],
|
|
||||||
},
|
},
|
||||||
pcsSettingRules: {
|
pcsSettingRules: {
|
||||||
pointAddress: [
|
pointAddress: [
|
||||||
@ -290,6 +296,9 @@ export default {
|
|||||||
stopPower: [
|
stopPower: [
|
||||||
{validator: validateText, trigger: 'blur'}
|
{validator: validateText, trigger: 'blur'}
|
||||||
],
|
],
|
||||||
|
powerMultiplier: [
|
||||||
|
{validator: validateDecimal, trigger: 'blur'}
|
||||||
|
],
|
||||||
clusterNum: [
|
clusterNum: [
|
||||||
{required: true, message: '请输入电池簇数', trigger: 'blur'},
|
{required: true, message: '请输入电池簇数', trigger: 'blur'},
|
||||||
{validator: validateNumber, trigger: 'blur'}
|
{validator: validateNumber, trigger: 'blur'}
|
||||||
@ -351,9 +360,6 @@ export default {
|
|||||||
this.getParentDeviceList()
|
this.getParentDeviceList()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
uploadImage(data) {
|
|
||||||
this.formData.pictureUrl = data
|
|
||||||
},
|
|
||||||
//获取站点列表
|
//获取站点列表
|
||||||
getZdList() {
|
getZdList() {
|
||||||
this.loading += 1
|
this.loading += 1
|
||||||
@ -404,7 +410,6 @@ export default {
|
|||||||
dataBits = '',//数据位
|
dataBits = '',//数据位
|
||||||
stopBits = '',//停止位
|
stopBits = '',//停止位
|
||||||
parity = '',//校验位
|
parity = '',//校验位
|
||||||
pictureUrl = '',//设备图片
|
|
||||||
slaveId = '',//从站地址
|
slaveId = '',//从站地址
|
||||||
} = this.formData;
|
} = this.formData;
|
||||||
const {
|
const {
|
||||||
@ -415,6 +420,7 @@ export default {
|
|||||||
stopCommand,
|
stopCommand,
|
||||||
startPower,
|
startPower,
|
||||||
stopPower,
|
stopPower,
|
||||||
|
powerMultiplier,
|
||||||
clusterNum,
|
clusterNum,
|
||||||
clusterPointAddress
|
clusterPointAddress
|
||||||
} = this.pcsSetting
|
} = this.pcsSetting
|
||||||
@ -434,7 +440,6 @@ export default {
|
|||||||
dataBits,
|
dataBits,
|
||||||
stopBits,
|
stopBits,
|
||||||
parity,
|
parity,
|
||||||
pictureUrl,
|
|
||||||
slaveId,
|
slaveId,
|
||||||
}
|
}
|
||||||
if (this.isPcs) {
|
if (this.isPcs) {
|
||||||
@ -445,6 +450,7 @@ export default {
|
|||||||
stopCommand,
|
stopCommand,
|
||||||
startPower,
|
startPower,
|
||||||
stopPower,
|
stopPower,
|
||||||
|
powerMultiplier,
|
||||||
clusterNum,
|
clusterNum,
|
||||||
clusterPointAddress: JSON.stringify(!clusterNum ? [] : (clusterPointAddress || []).slice(0, clusterNum))
|
clusterPointAddress: JSON.stringify(!clusterNum ? [] : (clusterPointAddress || []).slice(0, clusterNum))
|
||||||
}
|
}
|
||||||
@ -508,7 +514,6 @@ export default {
|
|||||||
dataBits: '',//数据位
|
dataBits: '',//数据位
|
||||||
stopBits: '',//停止位
|
stopBits: '',//停止位
|
||||||
parity: '',//校验位
|
parity: '',//校验位
|
||||||
pictureUrl: '',//设备图片
|
|
||||||
slaveId: '',//从站地址
|
slaveId: '',//从站地址
|
||||||
}
|
}
|
||||||
this.pcsSetting = {
|
this.pcsSetting = {
|
||||||
@ -519,6 +524,7 @@ export default {
|
|||||||
stopCommand: "",//关机指令
|
stopCommand: "",//关机指令
|
||||||
startPower: '',//开机目标功率
|
startPower: '',//开机目标功率
|
||||||
stopPower: '',//关机目标功率
|
stopPower: '',//关机目标功率
|
||||||
|
powerMultiplier: '',//目标功率倍率
|
||||||
clusterNum: '',//电池簇数
|
clusterNum: '',//电池簇数
|
||||||
clusterPointAddress: []//电池簇地址
|
clusterPointAddress: []//电池簇地址
|
||||||
}
|
}
|
||||||
@ -531,6 +537,25 @@ export default {
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
.form-layout {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-layout.has-pcs {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.base-form {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-layout.has-pcs .base-form,
|
||||||
|
.form-layout.has-pcs .pcs-form {
|
||||||
|
width: calc(50% - 8px);
|
||||||
|
}
|
||||||
|
|
||||||
.device-form {
|
.device-form {
|
||||||
::v-deep .el-form-item--medium .el-form-item__content {
|
::v-deep .el-form-item--medium .el-form-item__content {
|
||||||
width: 260px;
|
width: 260px;
|
||||||
@ -541,4 +566,8 @@ export default {
|
|||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-layout.has-pcs .device-form .el-form-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,13 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
<div class="ems-dashboard-editor-container" style="background-color: #ffffff" v-loading="loading">
|
||||||
<el-form :inline="true" class="select-container">
|
<el-form :inline="true" class="select-container">
|
||||||
<el-form-item label="站点选择">
|
|
||||||
<el-select v-model="siteId" placeholder="请选择换电站名称" :loading="searchLoading" loading-text="正在加载数据"
|
|
||||||
@change="onSearch" clearable>
|
|
||||||
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList"
|
|
||||||
:key="index+'zdxeSelect'"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="设备类型">
|
<el-form-item label="设备类型">
|
||||||
<el-select v-model="deviceCategory" placeholder="请选择设备类型" @change="onSearch" clearable>
|
<el-select v-model="deviceCategory" placeholder="请选择设备类型" @change="onSearch" clearable>
|
||||||
<el-option
|
<el-option
|
||||||
@ -24,34 +17,6 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-button type="primary" @click="addDevice" native-type="button">新增设备</el-button>
|
<el-button type="primary" @click="addDevice" native-type="button">新增设备</el-button>
|
||||||
<el-dropdown @command="(val)=>downloadPointDetail(val,false)">
|
|
||||||
<el-button
|
|
||||||
style="margin-left:10px;"
|
|
||||||
type="primary"
|
|
||||||
plain>
|
|
||||||
下载点位清单
|
|
||||||
</el-button>
|
|
||||||
<el-dropdown-menu slot="dropdown">
|
|
||||||
<el-dropdown-item v-for="(item,index) in deviceCategoryList" :key="index+'deviceCategoryList'"
|
|
||||||
:command="item">
|
|
||||||
{{ item.name }}
|
|
||||||
</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</el-dropdown>
|
|
||||||
<!-- <el-dropdown @command="(val)=>uploadPointDetail(val,false)">-->
|
|
||||||
<!-- <el-button-->
|
|
||||||
<!-- style="margin-left:10px;"-->
|
|
||||||
<!-- type="success"-->
|
|
||||||
<!-- plain>-->
|
|
||||||
<!-- 上传点位清单-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<!-- <el-dropdown-menu slot="dropdown">-->
|
|
||||||
<!-- <el-dropdown-item v-for="(item,index) in deviceCategoryList" :key="index+'deviceCategoryList'"-->
|
|
||||||
<!-- :command="item">-->
|
|
||||||
<!-- {{ item.name }}-->
|
|
||||||
<!-- </el-dropdown-item>-->
|
|
||||||
<!-- </el-dropdown-menu>-->
|
|
||||||
<!-- </el-dropdown>-->
|
|
||||||
<el-table
|
<el-table
|
||||||
class="common-table"
|
class="common-table"
|
||||||
:data="tableData"
|
:data="tableData"
|
||||||
@ -79,39 +44,11 @@
|
|||||||
prop="categoryName"
|
prop="categoryName"
|
||||||
label="设备类别">
|
label="设备类别">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
|
||||||
prop="deviceStatus"
|
|
||||||
label="在线状态">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ $store.state.ems.deviceStatusOptions[scope.row.deviceStatus] }}</span>
|
|
||||||
<!-- <pcs-switch v-if="scope.row.deviceCategory === 'PCS' && ![null,'',undefined].includes(scope.row.deviceStatus)"-->
|
|
||||||
<!-- style="margin-left:5px;"-->
|
|
||||||
<!-- :data="{siteId:scope.row.siteId,deviceStatus:scope.row.deviceStatus,deviceId:scope.row.deviceId,deviceName:scope.row.deviceName}"-->
|
|
||||||
<!-- @updateSuccess="getData"/>-->
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
fixed="right"
|
fixed="right"
|
||||||
label="操作"
|
label="操作"
|
||||||
width="250">
|
width="180">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
|
||||||
@click="downloadPointDetail(scope.row,true)"
|
|
||||||
style="margin-top:10px;"
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
size="mini">
|
|
||||||
下载点位清单
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
@click="uploadPointDetail(scope.row,true)"
|
|
||||||
style="margin-top:10px;"
|
|
||||||
type="success"
|
|
||||||
plain
|
|
||||||
size="mini">
|
|
||||||
上传点位清单
|
|
||||||
</el-button>
|
|
||||||
<br>
|
|
||||||
<el-button
|
<el-button
|
||||||
@click="editDevice(scope.row)"
|
@click="editDevice(scope.row)"
|
||||||
style="margin-top:10px;"
|
style="margin-top:10px;"
|
||||||
@ -154,30 +91,34 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<add-device ref="addDevice" :mode="mode" :id="editDeviceId" @update="getData" @clear="clearEditDeviceData"/>
|
<add-device ref="addDevice" :mode="mode" :id="editDeviceId" @update="getData" @clear="clearEditDeviceData"/>
|
||||||
<point-upload ref="pointUpload" @update="getData"/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {deleteService, getDeviceDetailInfo, getDeviceInfoList} from '@/api/ems/site'
|
import {deleteService, getDeviceDetailInfo, getDeviceInfoList} from '@/api/ems/site'
|
||||||
import {getAllSites} from '@/api/ems/zddt'
|
|
||||||
import {formatNumber} from "@/filters/ems";
|
import {formatNumber} from "@/filters/ems";
|
||||||
import {getAllDeviceCategory} from '@/api/ems/search'
|
import {getAllDeviceCategory} from '@/api/ems/search'
|
||||||
import AddDevice from "./AddDevice.vue";
|
import AddDevice from "./AddDevice.vue";
|
||||||
import PointUpload from "./PointUpload.vue";
|
|
||||||
// import PcsSwitch from "./PcsSwitch.vue";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Sblb",
|
name: "Sblb",
|
||||||
components: {AddDevice, PointUpload},
|
components: {AddDevice},
|
||||||
|
watch: {
|
||||||
|
'$route.query.siteId'(newSiteId) {
|
||||||
|
const normalizedSiteId = this.hasValidSiteId(newSiteId) ? String(newSiteId).trim() : ''
|
||||||
|
if (normalizedSiteId === this.siteId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.siteId = normalizedSiteId
|
||||||
|
this.onSearch()
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
searchLoading: false,
|
|
||||||
mode: '',//新增、编辑设备
|
mode: '',//新增、编辑设备
|
||||||
editDeviceId: '',//编辑设备id
|
editDeviceId: '',//编辑设备id
|
||||||
siteId: '',
|
siteId: '',
|
||||||
siteList: [],
|
|
||||||
deviceCategory: '',//搜索栏设备类型
|
deviceCategory: '',//搜索栏设备类型
|
||||||
deviceCategoryList: [],//设备类别
|
deviceCategoryList: [],//设备类别
|
||||||
tableData: [],
|
tableData: [],
|
||||||
@ -209,34 +150,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
hasValidSiteId(siteId) {
|
||||||
|
return !!(siteId !== undefined && siteId !== null && String(siteId).trim())
|
||||||
|
},
|
||||||
// 获取设备类别
|
// 获取设备类别
|
||||||
getDeviceCategoryList() {
|
getDeviceCategoryList() {
|
||||||
getAllDeviceCategory().then(response => {
|
getAllDeviceCategory().then(response => {
|
||||||
this.deviceCategoryList = response?.data || []
|
this.deviceCategoryList = response?.data || []
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// 下载点位清单
|
|
||||||
downloadPointDetail(command, isDetail = false) {
|
|
||||||
const siteId = isDetail ? command.siteId : this.siteId
|
|
||||||
const deviceCategory = isDetail ? command.deviceCategory : command.code
|
|
||||||
const categoryName = isDetail ? command.categoryName : command.name
|
|
||||||
const deviceId = isDetail ? command.deviceId : null
|
|
||||||
console.log('下载', command, isDetail)
|
|
||||||
this.download('ems/pointMatch/export', {
|
|
||||||
siteId,
|
|
||||||
deviceCategory,
|
|
||||||
deviceId,
|
|
||||||
}, `点位清单_${categoryName}_${new Date().getTime()}.xlsx`)
|
|
||||||
},
|
|
||||||
// 上传点位清单
|
|
||||||
uploadPointDetail(command, isDetail = false) {
|
|
||||||
const siteId = isDetail ? command.siteId : this.siteId
|
|
||||||
const deviceCategory = isDetail ? command.deviceCategory : command.code
|
|
||||||
const categoryName = isDetail ? command.categoryName : command.name
|
|
||||||
const deviceId = isDetail ? command.deviceId : ''
|
|
||||||
console.log('上传', command, isDetail)
|
|
||||||
this.$refs.pointUpload.showDialog({siteId, deviceCategory, categoryName, deviceId})
|
|
||||||
},
|
|
||||||
clearEditDeviceData() {
|
clearEditDeviceData() {
|
||||||
this.mode = '';
|
this.mode = '';
|
||||||
this.editDeviceId = ''
|
this.editDeviceId = ''
|
||||||
@ -342,26 +264,13 @@ export default {
|
|||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
|
||||||
//获取站点列表
|
|
||||||
getZdList() {
|
|
||||||
this.searchLoading = true
|
|
||||||
return getAllSites().then(response => {
|
|
||||||
this.siteList = response?.data || []
|
|
||||||
if (this.siteList.length > 0) this.siteId = this.siteList[0].siteId
|
|
||||||
}).finally(() => {
|
|
||||||
this.searchLoading = false
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.loading = true
|
this.siteId = this.hasValidSiteId(this.$route.query.siteId) ? String(this.$route.query.siteId).trim() : ''
|
||||||
this.siteId = ''
|
|
||||||
this.pageNum = 1//每次搜索从1开始搜索
|
this.pageNum = 1//每次搜索从1开始搜索
|
||||||
this.getDeviceCategoryList()
|
this.getDeviceCategoryList()
|
||||||
this.getZdList().then(() => {
|
this.getData()
|
||||||
this.getData()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,7 +3,10 @@
|
|||||||
<div class="header-row">
|
<div class="header-row">
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<div class="page-title">单站监控项目点位配置</div>
|
<div class="page-title">单站监控项目点位配置</div>
|
||||||
<div class="page-desc">站点:{{ siteName || siteId || '-' }}</div>
|
<div class="page-desc">
|
||||||
|
<span class="site-label">站点:</span>
|
||||||
|
<span>{{ siteName || siteId || '-' }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="goBack">返回</el-button>
|
<el-button @click="goBack">返回</el-button>
|
||||||
@ -34,15 +37,42 @@
|
|||||||
<el-table-column prop="section" label="分组" min-width="180" />
|
<el-table-column prop="section" label="分组" min-width="180" />
|
||||||
<el-table-column prop="name" label="页面展示名称" min-width="280" />
|
<el-table-column prop="name" label="页面展示名称" min-width="280" />
|
||||||
<el-table-column prop="field" label="字段名" min-width="260" />
|
<el-table-column prop="field" label="字段名" min-width="260" />
|
||||||
<el-table-column label="点位" min-width="420">
|
<el-table-column label="点位" min-width="300">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-input
|
<el-input
|
||||||
v-model.trim="scope.row.point"
|
v-model.trim="scope.row.point"
|
||||||
placeholder="请输入点位"
|
placeholder="请输入点位"
|
||||||
clearable
|
clearable
|
||||||
|
class="short-input"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="固定展示值" min-width="300">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="scope.row.fixedValue"
|
||||||
|
placeholder="请输入固定展示值"
|
||||||
|
clearable
|
||||||
|
class="short-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="固定展示" width="120" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-checkbox v-model="scope.row.useFixedDisplay" :true-label="1" :false-label="0" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="handleDeleteItem(scope.$index, topMenu.items)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<el-tabs
|
<el-tabs
|
||||||
@ -61,15 +91,42 @@
|
|||||||
<el-table-column prop="section" label="分组" min-width="180" />
|
<el-table-column prop="section" label="分组" min-width="180" />
|
||||||
<el-table-column prop="name" label="页面展示名称" min-width="280" />
|
<el-table-column prop="name" label="页面展示名称" min-width="280" />
|
||||||
<el-table-column prop="field" label="字段名" min-width="260" />
|
<el-table-column prop="field" label="字段名" min-width="260" />
|
||||||
<el-table-column label="点位" min-width="420">
|
<el-table-column label="点位" min-width="300">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-input
|
<el-input
|
||||||
v-model.trim="scope.row.point"
|
v-model.trim="scope.row.point"
|
||||||
placeholder="请输入点位"
|
placeholder="请输入点位"
|
||||||
clearable
|
clearable
|
||||||
|
class="short-input"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="固定展示值" min-width="300">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-input
|
||||||
|
v-model.trim="scope.row.fixedValue"
|
||||||
|
placeholder="请输入固定展示值"
|
||||||
|
clearable
|
||||||
|
class="short-input"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="固定展示" width="120" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-checkbox v-model="scope.row.useFixedDisplay" :true-label="1" :false-label="0" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button
|
||||||
|
type="text"
|
||||||
|
size="small"
|
||||||
|
@click="handleDeleteItem(scope.$index, child.items)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
@ -85,17 +142,25 @@ export default {
|
|||||||
name: 'MonitorPointMapping',
|
name: 'MonitorPointMapping',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
siteId: '',
|
||||||
|
siteName: '',
|
||||||
activeTopMenu: 'HOME',
|
activeTopMenu: 'HOME',
|
||||||
activeChildMap: {},
|
activeChildMap: {},
|
||||||
topMenuList: []
|
topMenuList: [],
|
||||||
|
deletedFieldCodes: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
watch: {
|
||||||
siteId() {
|
'$route.query.siteId': {
|
||||||
return this.$route.query.siteId || ''
|
immediate: false,
|
||||||
},
|
async handler(newSiteId) {
|
||||||
siteName() {
|
if (newSiteId === this.siteId) {
|
||||||
return this.$route.query.siteName || ''
|
return
|
||||||
|
}
|
||||||
|
this.siteId = newSiteId || ''
|
||||||
|
this.siteName = this.$route.query.siteName || this.siteId
|
||||||
|
await this.initMenuStructure()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -105,6 +170,7 @@ export default {
|
|||||||
async initMenuStructure() {
|
async initMenuStructure() {
|
||||||
if (!this.siteId) {
|
if (!this.siteId) {
|
||||||
this.topMenuList = []
|
this.topMenuList = []
|
||||||
|
this.deletedFieldCodes = []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const response = await getSingleMonitorProjectPointMapping(this.siteId)
|
const response = await getSingleMonitorProjectPointMapping(this.siteId)
|
||||||
@ -131,7 +197,9 @@ export default {
|
|||||||
section: row.sectionName || '-',
|
section: row.sectionName || '-',
|
||||||
name: row.fieldName || '-',
|
name: row.fieldName || '-',
|
||||||
field: row.fieldCode || '',
|
field: row.fieldCode || '',
|
||||||
point: row.dataPoint || ''
|
point: row.dataPoint || '',
|
||||||
|
fixedValue: row.fixedDataPoint || '',
|
||||||
|
useFixedDisplay: row.useFixedDisplay === 1 ? 1 : 0
|
||||||
}
|
}
|
||||||
const topItem = topMap.get(topKey)
|
const topItem = topMap.get(topKey)
|
||||||
const isTopDirect = moduleCode === menuCode || moduleCode === 'HOME'
|
const isTopDirect = moduleCode === menuCode || moduleCode === 'HOME'
|
||||||
@ -152,6 +220,7 @@ export default {
|
|||||||
const firstTop = this.topMenuList[0]
|
const firstTop = this.topMenuList[0]
|
||||||
this.activeTopMenu = firstTop ? firstTop.code : 'HOME'
|
this.activeTopMenu = firstTop ? firstTop.code : 'HOME'
|
||||||
this.activeChildMap = {}
|
this.activeChildMap = {}
|
||||||
|
this.deletedFieldCodes = []
|
||||||
this.topMenuList.forEach(top => {
|
this.topMenuList.forEach(top => {
|
||||||
if (top.children && top.children.length > 0) {
|
if (top.children && top.children.length > 0) {
|
||||||
this.$set(this.activeChildMap, top.code, top.children[0].code)
|
this.$set(this.activeChildMap, top.code, top.children[0].code)
|
||||||
@ -168,6 +237,23 @@ export default {
|
|||||||
})
|
})
|
||||||
return rows
|
return rows
|
||||||
},
|
},
|
||||||
|
handleDeleteItem(index, list) {
|
||||||
|
if (!Array.isArray(list) || index < 0 || index >= list.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$confirm('是否确认删除该条明细记录?删除后需点击“保存”才会生效。', '提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
const fieldCode = list[index] && list[index].field
|
||||||
|
if (fieldCode && !this.deletedFieldCodes.includes(fieldCode)) {
|
||||||
|
this.deletedFieldCodes.push(fieldCode)
|
||||||
|
}
|
||||||
|
list.splice(index, 1)
|
||||||
|
this.$message.success('已删除该条明细记录')
|
||||||
|
}).catch(() => {})
|
||||||
|
},
|
||||||
async saveData() {
|
async saveData() {
|
||||||
if (!this.siteId) {
|
if (!this.siteId) {
|
||||||
this.$message.warning('缺少站点ID')
|
this.$message.warning('缺少站点ID')
|
||||||
@ -175,13 +261,29 @@ export default {
|
|||||||
}
|
}
|
||||||
const mappings = this.getAllMappingRows()
|
const mappings = this.getAllMappingRows()
|
||||||
.filter(item => item.field)
|
.filter(item => item.field)
|
||||||
.map(item => ({ fieldCode: item.field, dataPoint: item.point || '' }))
|
.map(item => ({
|
||||||
await saveSingleMonitorProjectPointMapping({ siteId: this.siteId, mappings })
|
fieldCode: item.field,
|
||||||
this.$message.success('保存成功')
|
dataPoint: item.point || '',
|
||||||
|
fixedDataPoint: item.fixedValue || '',
|
||||||
|
useFixedDisplay: item.useFixedDisplay === 1 ? 1 : 0
|
||||||
|
}))
|
||||||
|
const response = await saveSingleMonitorProjectPointMapping({
|
||||||
|
siteId: this.siteId,
|
||||||
|
mappings,
|
||||||
|
deletedFieldCodes: this.deletedFieldCodes
|
||||||
|
})
|
||||||
|
const affectedRows = Number(response?.data || 0)
|
||||||
|
if (affectedRows > 0) {
|
||||||
|
this.$message.success(`保存成功,已写入 ${affectedRows} 条`)
|
||||||
|
} else {
|
||||||
|
this.$message.warning('保存完成,但写入 0 条,请检查字段编码和点位值是否有效')
|
||||||
|
}
|
||||||
await this.initMenuStructure()
|
await this.initMenuStructure()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
this.siteId = this.$route.query.siteId || ''
|
||||||
|
this.siteName = this.$route.query.siteName || this.siteId
|
||||||
await this.initMenuStructure()
|
await this.initMenuStructure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,6 +311,16 @@ export default {
|
|||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.site-label {
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.short-input {
|
||||||
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.child-menu-tabs {
|
.child-menu-tabs {
|
||||||
|
|||||||
@ -59,11 +59,10 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="操作"
|
label="操作"
|
||||||
width="220"
|
width="120"
|
||||||
fixed="right">
|
fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" size="small" @click="openEditDialog(scope.row)">编辑</el-button>
|
<el-button type="text" size="small" @click="openEditDialog(scope.row)">编辑</el-button>
|
||||||
<el-button type="text" size="small" @click="openPointMappingPage(scope.row)">配置</el-button>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -266,15 +265,6 @@ export default {
|
|||||||
this.$refs.siteForm && this.$refs.siteForm.clearValidate()
|
this.$refs.siteForm && this.$refs.siteForm.clearValidate()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
openPointMappingPage(row) {
|
|
||||||
this.$router.push({
|
|
||||||
path: '/ems/site/zdlb/monitor-point-mapping',
|
|
||||||
query: {
|
|
||||||
siteId: row.siteId,
|
|
||||||
siteName: row.siteName || ''
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
submitSite() {
|
submitSite() {
|
||||||
this.$refs.siteForm.validate(valid => {
|
this.$refs.siteForm.validate(valid => {
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
|||||||
Reference in New Issue
Block a user