21 Commits

Author SHA1 Message Date
d9eeee106f Merge branch 'develop' into single-develop 2025-12-16 13:48:09 +08:00
c90f4f5766 Merge branch 'develop' into single-develop 2025-12-16 11:14:50 +08:00
4a4d26f018 生产、云下环境变量配置 2025-12-15 17:41:29 +08:00
1a11c67aad test 环境变量配置 2025-12-15 14:42:27 +08:00
71fd48918d Merge branch 'develop' into single-develop
# Conflicts:
#	src/assets/styles/common.scss
2025-12-12 17:47:57 +08:00
34d9e038e6 合并代码 2025-12-10 15:09:33 +08:00
b4c49c3e58 Merge branch 'develop' into single-develop 2025-12-05 09:49:54 +08:00
9cfce671a6 Merge branch 'develop' into single-develop 2025-12-05 09:16:54 +08:00
87e3db9f0f 云下使用深色主题区分云上 2025-11-28 15:21:42 +08:00
4132d8e539 合并develop最新代码 2025-11-28 15:18:27 +08:00
28176ce052 Merge branch 'develop' into single-develop 2025-11-13 16:53:19 +08:00
fdcf82e343 Merge branch 'develop' into single-develop 2025-11-12 16:38:00 +08:00
e4c6f1f798 Merge branch 'develop' into single-develop 2025-11-12 10:59:13 +08:00
f4a42c168f Merge branch 'develop' into single-develop 2025-11-07 14:59:56 +08:00
371a2d8be0 菜单更新,单站监控展示 2025-11-05 14:50:11 +08:00
c403922639 Merge branch 'develop' into single-develop 2025-11-05 14:10:00 +08:00
2a3d2fcf63 Merge branch 'develop' into single-develop 2025-09-22 17:59:25 +08:00
25bb28f77a Merge branch 'develop' into single-develop 2025-09-17 14:57:30 +08:00
3d5d8918d7 合并develop最新代码 2025-08-20 17:53:26 +08:00
fe14089562 在路由权限校验中获取设备列表 2025-07-23 21:35:40 +08:00
b68f2608f3 本地 2025-07-21 23:00:41 +08:00
52 changed files with 3295 additions and 2882 deletions

View File

@ -5,8 +5,9 @@ VUE_APP_TITLE = 上动新能源-EMS管理系统
NODE_ENV = 'production' NODE_ENV = 'production'
# EMS管理系统/生产环境 # EMS管理系统/生产环境
VUE_APP_BASE_API= 'http://1.15.120.242:8089' VUE_APP_BASE_API= 'http://127.0.0.1:8089'
# EMS管理系统/生产环境 图片拼接地址 # EMS管理系统/生产环境 图片拼接地址
VUE_APP_IMG_URL = 'http://1.15.120.242:8089' VUE_APP_IMG_URL = 'http://127.0.0.1:8089'

View File

@ -10,7 +10,7 @@ import ThemePicker from "@/components/ThemePicker"
export default { export default {
name: "App", name: "App",
components: { ThemePicker } components: { ThemePicker },
} }
</script> </script>
<style scoped> <style scoped>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 MiB

View File

@ -4,8 +4,8 @@
//右侧内容区域 //右侧内容区域
//父元素 //父元素
.ems-dashboard-editor-container { .ems-dashboard-editor-container{
background-color: #F1F5FC; background-color: #FFFFFF;//#F1F5FC
padding: 24px; padding: 24px;
font-size: 12px; font-size: 12px;
} }
@ -104,10 +104,6 @@
.el-card__header { .el-card__header {
background-color: #b64040; //#fc6b69; background-color: #b64040; //#fc6b69;
} }
.work-status {
color: #b64040 !important;;
}
} }
//绿色背景颜色标题 //绿色背景颜色标题
@ -115,10 +111,6 @@
.el-card__header { .el-card__header {
background-color: #40b6a5; //#05aea3; background-color: #40b6a5; //#05aea3;
} }
.work-status {
color: #40b6a5 !important;
}
} }
//灰色背景颜色标题 //灰色背景颜色标题
@ -126,10 +118,6 @@
.el-card__header { .el-card__header {
background-color: #666666; background-color: #666666;
} }
.work-status {
color: #666666 !important;;
}
} }
} }
@ -280,7 +268,7 @@
.ems-third-menu-container { .ems-third-menu-container {
position: relative; position: relative;
padding-left: 140px; padding-left: 160px;
background-color: #ffffff; background-color: #ffffff;
.ems-third-menu { .ems-third-menu {
@ -288,10 +276,9 @@
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
height: fit-content; height: fit-content;
position: absolute; position: absolute;
top: 0; top:20px;
left: 0; left:20px;
.el-menu-item{
.el-menu-item {
line-height: 45px; line-height: 45px;
height: 45px; height: 45px;
padding: 0 !important; padding: 0 !important;

View File

@ -1,137 +0,0 @@
<template>
<el-dialog
:fullscreen="true"
:append-to-body="true"
:visible.sync="show"
:show-close="false"
top="0"
custom-class="big-data-dialog"
>
<div class="swiper-container">
<div class="swiper-icon left-icon" v-show="imgIndex > 0">
<i class="el-icon-d-arrow-left icon" @click="toLeft"></i>
</div>
<div v-show="showRightIcon" class="swiper-icon right-icon">
<i class="el-icon-d-arrow-right icon" @click="toRight"></i>
</div>
<div
class="img-container"
:style="{ transform: 'translateX(' + imgIndex * -100 + 'vw)' }"
>
<img
v-for="index in maxImgNumber"
:key="'swiperImg' + index"
:src="require(`@/assets/images/ems/bigData-${index}.png`)"
alt=""
/>
</div>
</div>
<div class="close-btn" @click="show = false">
<i class="el-icon-close"></i>
</div>
</el-dialog>
</template>
<style lang="scss" scoped>
.close-btn {
position: absolute;
right: 10px;
top: 10px;
font-size: 23px;
line-height: 20px;
color: rgba(217, 242, 255, 1);
cursor: pointer;
}
.swiper-container {
height: 100%;
width: 100%;
overflow: hidden;
position: relative;
.swiper-icon {
color: rgba(217, 242, 255, 1);
position: absolute;
top: 50%;
transform: translateY(-50%);
z-index: 20;
cursor: pointer;
font-size: 30px;
padding: 20px;
background: transparent;
&.left-icon {
left: 20px;
}
&.right-icon {
right: 20px;
}
&:hover {
.icon {
opacity: 1;
}
}
.icon {
transition: all 0.6s;
opacity: 0;
}
}
.img-container {
height: 100%;
transition: all 1s;
display: flex;
flex-direction: row;
z-index: 0;
img {
width: 100vw;
height: 100vh;
display: block;
margin: 0;
flex-shrink: 0;
}
}
}
</style>
<style lang="scss">
.big-data-dialog {
.el-dialog__header {
display: none;
}
.el-dialog__body {
padding: 0;
margin: 0;
position: relative;
}
}
</style>
<script>
export default {
data() {
return {
show: false,
imgIndex: 0,
maxImgNumber: 3,
};
},
computed: {
showRightIcon() {
return this.imgIndex < this.maxImgNumber - 1;
},
},
watch: {
show: {
handler(newValue) {
if (!newValue) this.imgIndex = 0;
},
immediate: true,
},
},
methods: {
toLeft() {
if (this.imgIndex === 0) return;
this.imgIndex -= 1;
},
toRight() {
if (this.imgIndex >= this.maxImgNumber - 1) return;
this.imgIndex += 1;
},
},
};
</script>

View File

@ -1,68 +1,36 @@
<template> <template>
<div class="time-range"> <div class="time-range">
<el-date-picker <el-date-picker
v-model="dateRange" v-model="dateRange"
:class="miniTimePicker ? 'mini-date-picker' : ''" type="daterange"
type="daterange" range-separator=""
range-separator="" start-placeholder="开始时间"
start-placeholder="开始时间" value-format="yyyy-MM-dd"
value-format="yyyy-MM-dd" :clearable="false"
:clearable="false" :picker-options="pickerOptions"
:picker-options="pickerOptions" end-placeholder="结束时间">
end-placeholder="结束时间"> </el-date-picker>
</el-date-picker> <el-button size="mini" style="margin-left: 10px;" :loading="loading" @click="reset">重置</el-button>
<template v-if="!showIcon"> <el-button type="primary" size="mini" :loading="loading" @click="search">搜索</el-button>
<el-button size="mini" style="margin-left: 10px;" :loading="loading" @click="reset">重置</el-button> <el-button type="primary" size="mini" :loading="loading" @click="timeLine('before')">上一时段</el-button>
<el-button type="primary" size="mini" :loading="loading" @click="search">搜索</el-button> <el-button type="primary" size="mini" :loading="loading" @click="timeLine('next')" :disabled="disabledNextBtn">下一时段</el-button>
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('before')">上一时段</el-button> </div>
<el-button type="primary" size="mini" :loading="loading" @click="timeLine('next')" :disabled="disabledNextBtn">
下一时段
</el-button>
</template>
<template v-else>
<el-button class="btn-icon" icon="el-icon-refresh-right" circle size="mini" style="margin-left: 8px;"
:loading="loading"
@click="reset"></el-button>
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-search" circle :loading="loading"
@click="search"></el-button>
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-d-arrow-left" circle :loading="loading"
@click="timeLine('before')"></el-button>
<el-button class="btn-icon" type="primary" size="mini" icon="el-icon-d-arrow-right" circle :loading="loading"
@click="timeLine('next')"
:disabled="disabledNextBtn"></el-button>
</template>
</div>
</template> </template>
<script> <script>
import {formatDate} from '@/filters/ems' import {formatDate} from '@/filters/ems'
export default { export default {
props: { computed:{
showIcon: { disabledNextBtn(){
type: Boolean,
required: false,
default: false
},
miniTimePicker: {
type: Boolean,
required: false,
default: false
}
},
computed: {
disabledNextBtn() {
return new Date(this.dateRange[1]) >= new Date(this.defaultDateRange[1]) return new Date(this.dateRange[1]) >= new Date(this.defaultDateRange[1])
} }
}, },
data() { data() {
return { return {
loading: false, loading:false,
dateRange: [], dateRange:[],
defaultDateRange: [], defaultDateRange:[],
pickerOptions: { pickerOptions:{
disabledDate(time) { disabledDate(time) {
return time.getTime() > Date.now(); return time.getTime() > Date.now();
}, },
@ -70,81 +38,64 @@ export default {
} }
}, },
methods: { methods: {
init(today = false) { init(today=false){
const now = new Date(), formatNow = formatDate(now); const now = new Date(),formatNow = formatDate(now);
const weekAgo = formatDate(today ? new Date(now.getTime()) : new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000)) const weekAgo = formatDate(today ? new Date(now.getTime()) : new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000))
this.dateRange = [weekAgo, formatNow]; this.dateRange = [weekAgo, formatNow];
this.defaultDateRange = [weekAgo, formatNow]; this.defaultDateRange=[weekAgo, formatNow];
this.$emit('updateDate', this.dateRange) this.$emit('updateDate',this.dateRange)
}, },
showBtnLoading(status) { showBtnLoading(status){
this.loading = status this.loading = status
}, },
resetDate() { resetDate(){
this.dateRange = this.defaultDateRange this.dateRange = this.defaultDateRange
}, },
//重置 设置时间范围为初始化时间段 //重置 设置时间范围为初始化时间段
reset() { reset(){
this.resetDate() this.resetDate()
this.$emit('reset') this.$emit('reset')
this.$emit('updateDate', this.dateRange) this.$emit('updateDate',this.dateRange)
}, },
// 搜索 // 搜索
search() { search(){
this.$emit('updateDate', this.dateRange) this.$emit('updateDate',this.dateRange)
}, },
timeLine(type) { timeLine(type){
if (!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) return if(!this.dateRange || !this.dateRange[0] || !this.dateRange[1]) return
const nowStartTimes = new Date(this.dateRange[0]).getTime(), nowEndTimes = new Date(this.dateRange[1]).getTime(), const nowStartTimes = new Date(this.dateRange[0]).getTime(),nowEndTimes = new Date(this.dateRange[1]).getTime(),maxTime = new Date(this.defaultDateRange[1]).getTime()
maxTime = new Date(this.defaultDateRange[1]).getTime()
const nowDis = nowEndTimes - nowStartTimes//用户当前选择时间差 可能=0 const nowDis = nowEndTimes - nowStartTimes//用户当前选择时间差 可能=0
//baseTime,maxTime 毫秒数 //baseTime,maxTime 毫秒数
const baseDis = 24 * 60 * 60 * 1000 const baseDis = 24 * 60 * 60 * 1000
const calcDis = nowDis === 0 ? baseDis : nowDis const calcDis = nowDis === 0 ? baseDis : nowDis
let start = type === 'before' ? nowStartTimes - calcDis : nowStartTimes + calcDis let start = type === 'before' ? nowStartTimes - calcDis : nowStartTimes + calcDis
if (start > maxTime) start = maxTime if(start>maxTime) start=maxTime
let end = type === 'before' ? nowEndTimes - calcDis : nowEndTimes + calcDis let end = type === 'before' ? nowEndTimes - calcDis : nowEndTimes + calcDis
if (end > maxTime) end = maxTime if(end>maxTime) end=maxTime
this.dateRange = [formatDate(start), formatDate(end)] this.dateRange = [formatDate(start),formatDate(end)]
this.$emit('updateDate', this.dateRange) this.$emit('updateDate',this.dateRange)
}, },
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.time-range { .time-range{
display: flex; display: flex;
::v-deep {
::v-deep { .el-range-editor--medium .el-range__icon, .el-range-editor--medium .el-range__close-icon{
line-height: 22px;
.el-range-editor--medium .el-range__icon, .el-range-editor--medium .el-range__close-icon { }
line-height: 22px; .el-range-editor--medium.el-input__inner{
height: 30px;
}
.el-range-editor--medium .el-range-separator{
line-height: 24px;
}
.el-button--mini{
padding:3px 10px;
}
} }
.el-range-editor--medium.el-input__inner {
height: 30px;
}
.el-range-editor--medium .el-range-separator {
line-height: 22px;
}
.el-button--mini {
padding: 3px 10px;
}
// 展示icon的小组件
.btn-icon.el-button--mini {
padding: 3px 8px;
margin-left: 6px;
}
//小宽度时间选择框
.mini-date-picker {
width: 250px !important;
}
}
} }
</style> </style>

View File

@ -32,13 +32,13 @@ export default {
attr:'installCapacity' attr:'installCapacity'
},{ },{
title:'总充电量(KWh', title:'总充电量(MWh',
num:'', num:'',
color:'#A696FF', color:'#A696FF',
attr:'totalChargedCap' attr:'totalChargedCap'
},{ },{
title:'总放电量(KWh', title:'总放电量(MWh',
num:'', num:'',
color:'#A696FF', color:'#A696FF',
attr:'totalDischargedCap' attr:'totalDischargedCap'

View File

@ -1,24 +1,19 @@
<template> <template>
<div class="navbar"> <div class="navbar">
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
@toggleClick="toggleSideBar"/>
<breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container"/> <breadcrumb v-if="!topNav" id="breadcrumb-container" class="breadcrumb-container" />
<top-nav v-if="topNav" id="topmenu-container" class="topmenu-container"/> <top-nav v-if="topNav" id="topmenu-container" class="topmenu-container" />
<div class="right-menu"> <div class="right-menu">
<template v-if="device!=='mobile'"> <template v-if="device!=='mobile'">
<div class="big-data-container"> <search id="header-search" class="right-menu-item" />
<i class="el-icon-s-marketing big-data-icon" @click.stop="showBigDataImg"></i>
</div>
<search id="header-search" class="right-menu-item"/>
<screenfull id="screenfull" class="right-menu-item hover-effect"/> <screenfull id="screenfull" class="right-menu-item hover-effect" />
<el-tooltip content="布局大小" effect="dark" placement="bottom"> <el-tooltip content="布局大小" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect"/> <size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
</template> </template>
@ -37,23 +32,22 @@
</el-dropdown-item> </el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
<div class="right-menu-item hover-effect setting" @click="setLayout" v-if="setting"> <div class="right-menu-item hover-effect setting" @click="setLayout" v-if="setting">
<svg-icon icon-class="more-up"/> <svg-icon icon-class="more-up" />
</div> </div>
</div> </div>
<BigDataPopup ref="bigDataPopup"/>
</div> </div>
</template> </template>
<script> <script>
import {mapGetters} from 'vuex' import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb' import Breadcrumb from '@/components/Breadcrumb'
import TopNav from '@/components/TopNav' import TopNav from '@/components/TopNav'
import Hamburger from '@/components/Hamburger' import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull' 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'
export default { export default {
emits: ['setLayout'], emits: ['setLayout'],
@ -63,8 +57,7 @@ export default {
Hamburger, Hamburger,
Screenfull, Screenfull,
SizeSelect, SizeSelect,
Search, Search
BigDataPopup
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
@ -85,9 +78,6 @@ export default {
} }
}, },
methods: { methods: {
showBigDataImg() {
this.$refs.bigDataPopup.show = true
},
toggleSideBar() { toggleSideBar() {
this.$store.dispatch('app/toggleSideBar') this.$store.dispatch('app/toggleSideBar')
}, },
@ -103,8 +93,7 @@ export default {
this.$store.dispatch('LogOut').then(() => { this.$store.dispatch('LogOut').then(() => {
location.href = '/index' location.href = '/index'
}) })
}).catch(() => { }).catch(() => {})
})
} }
} }
} }
@ -116,7 +105,7 @@ export default {
overflow: hidden; overflow: hidden;
position: relative; position: relative;
background: #fff; background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, .08); box-shadow: 0 1px 4px rgba(0,21,41,.08);
.hamburger-container { .hamburger-container {
line-height: 46px; line-height: 46px;
@ -124,7 +113,7 @@ export default {
float: left; float: left;
cursor: pointer; cursor: pointer;
transition: background .3s; transition: background .3s;
-webkit-tap-highlight-color: transparent; -webkit-tap-highlight-color:transparent;
&:hover { &:hover {
background: rgba(0, 0, 0, .025) background: rgba(0, 0, 0, .025)
@ -150,17 +139,6 @@ export default {
height: 100%; height: 100%;
line-height: 50px; line-height: 50px;
.big-data-container {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 24px;
color: #5a5e66;
vertical-align: text-bottom;
cursor: pointer;
}
&:focus { &:focus {
outline: none; outline: none;
} }
@ -199,7 +177,7 @@ export default {
border-radius: 50%; border-radius: 50%;
} }
.user-nickname { .user-nickname{
position: relative; position: relative;
bottom: 10px; bottom: 10px;
font-size: 14px; font-size: 14px;

View File

@ -6,16 +6,16 @@ const getQuerySiteId= {
} }
}, },
watch: { watch: {
'$route.query':{ '$store.state.ems.zdList':{
handler (newQuery,oldQuery) { handler (newQuery,oldQuery) {
if(!newQuery || newQuery.length === 0){return}
// 参数变化处理 // 参数变化处理
this.$nextTick(() => { this.$nextTick(() => {
const {siteId} =newQuery const {siteId} =newQuery[0]
if(siteId){ this.siteId = siteId
this.siteId = siteId siteId && this.init(newQuery.siteId)
siteId && this.init(newQuery.siteId) console.log('watch站点列表返回数据newQuery=',newQuery)
console.log('mixin=>getQuerySiteId=>页面参数siteId发生了变化,this.siteId=',this.siteId) console.log('设置页面siteIdthis.siteId=',this.siteId)
}
}) })
}, },
immediate: true, immediate: true,

View File

@ -31,6 +31,7 @@ router.beforeEach((to, from, next) => {
// 判断当前用户是否已拉取完user_info信息 // 判断当前用户是否已拉取完user_info信息
store.dispatch('GetInfo').then(() => { store.dispatch('GetInfo').then(() => {
isRelogin.show = false isRelogin.show = false
store.dispatch('getZdList')
store.dispatch('GenerateRoutes').then(accessRoutes => { store.dispatch('GenerateRoutes').then(accessRoutes => {
// 根据roles权限生成可访问的路由表 // 根据roles权限生成可访问的路由表
router.addRoutes(accessRoutes) // 动态添加可访问路由表 router.addRoutes(accessRoutes) // 动态添加可访问路由表

View File

@ -7,295 +7,257 @@ export const dzjk = [
path: '/dzjk', path: '/dzjk',
component: Layout, component: Layout,
redirect: '/dzjk/home', redirect: '/dzjk/home',
meta: {title: '单站监控', icon: 'dashboard',}, meta: {title: '单站监控', icon: 'server',},
alwaysShow: false, alwaysShow: false,
name: 'Dzjk', name: 'Dzjk',
hidden: true,
children: [ children: [
{ {
path: '', path: '/dzjk/home',
component: () => import('@/views/ems/dzjk/index'), component: () => import('@/views/ems/dzjk/home/index.vue'),
name: 'Dzjk', name: 'DzjkHome',
redirect: '/dzjk/home', meta: {title: '站点首页', breadcrumb: false, activeMenu: '/dzjk/home', activeSecondMenuName: 'DzjkHome'}
hidden: true, },
{
path: '/dzjk/zxlt',
component: () => import('@/views/ems/dzjk/zxlt/index.vue'),
name: 'DzjkZxlt',
meta: {title: '主线路图', breadcrumb: false, activeMenu: '/dzjk/zxlt', activeSecondMenuName: 'DzjkZxlt'}
},
{
path: '/dzjk/sbjk',
component: () => import('@/views/ems/dzjk/sbjk/index.vue'),
name: 'DzjkSbjk',
alwaysShow: false,
meta: {title: '设备监控', breadcrumb: false, activeMenu: '/dzjk/sbjk'},
hidden: false,
redirect: '/dzjk/sbjk/ssyx',
children: [ children: [
{ {
path: '/dzjk/home', path: 'ssyx',
component: () => import('@/views/ems/dzjk/home/index.vue'), component: () => import('@/views/ems/dzjk/sbjk/ssyx/index.vue'),
name: 'DzjkHome', name: 'DzjkSbjkSsyx',
hidden: true,
meta: { meta: {
title: '站点首页', title: '实时运行',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'SSYX'
},
},
{
path: 'ems',
component: () => import('@/views/ems/dzjk/sbjk/ems/index.vue'),
name: 'DzjkSbjkEms',
hidden: true,
meta: {
title: 'EMS',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'EMS'
},
},
{
path: 'pcs',
component: () => import('@/views/ems/dzjk/sbjk/pcs/index.vue'),
name: 'DzjkSbjkPcs',
hidden: true,
meta: {
title: 'PCS',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'PCS'
},
},
{
path: 'bmszl',
component: () => import('@/views/ems/dzjk/sbjk/bmszl/index.vue'),
name: 'DzjkSbjkBmszl',
hidden: true,
meta: {
title: 'BMS总览',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'STACK'
},
},
{
path: 'bmsdcc',
component: () => import('@/views/ems/dzjk/sbjk/bmsdcc/index.vue'),
name: 'DzjkSbjkBmsdcc',
hidden: true,
meta: {
title: 'BMS电池簇',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'CLUSTER'
},
},
{
path: 'dtdc',
component: () => import('@/views/ems/dzjk/sbjk/dtdc/index.vue'),
name: 'DzjkSbjkDtdc',
hidden: true,
meta: {
title: '单体电池',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'BATTERY'
},
},
{
path: 'db',
component: () => import('@/views/ems/dzjk/sbjk/db/index.vue'),
name: 'DzjkSbjkDb',
hidden: true,
meta: {
title: '电表',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'AMMETER'
},
},
{
path: 'yl',
component: () => import('@/views/ems/dzjk/sbjk/yl/index.vue'),
name: 'DzjkSbjkYl',
hidden: true,
meta: {
title: '液冷',
breadcrumb: false,
activeMenu: '/dzjk/sbjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'COOLING'
},
},
{
path: 'dh',
component: () => import('@/views/ems/dzjk/sbjk/dh/index.vue'),
name: 'DzjkSbjkDh',
hidden: true,
meta: {
title: '动环',
breadcrumb: false, breadcrumb: false,
activeMenu: '/dzjk', activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkHome' activeSecondMenuName: 'DzjkSbjk',
} deviceCategory: 'DH'
},
}, },
{ {
path: '/dzjk/zxlt', path: 'xf',
component: () => import('@/views/ems/dzjk/zxlt/index.vue'), component: () => import('@/views/ems/dzjk/sbjk/xf/index.vue'),
name: 'DzjkZxlt', name: 'DzjkSbjkXf',
hidden: true,
meta: { meta: {
title: '主线路图', title: '消防',
breadcrumb: false, breadcrumb: false,
activeMenu: '/dzjk', activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkZxlt' activeSecondMenuName: 'DzjkSbjk',
} deviceCategory: 'XF'
}, },
{
path: '/dzjk/sbjk',
component: () => import('@/views/ems/dzjk/sbjk/index.vue'),
name: 'DzjkSbjk',
meta: {title: '设备监控', breadcrumb: false, activeMenu: '/dzjk'},
redirect: '/dzjk/sbjk/ssyx',
children: [
{
path: 'ssyx',
component: () => import('@/views/ems/dzjk/sbjk/ssyx/index.vue'),
name: 'DzjkSbjkSsyx',
meta: {
title: '实时运行',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'SSYX'
},
},
{
path: 'ems',
component: () => import('@/views/ems/dzjk/sbjk/ems/index.vue'),
name: 'DzjkSbjkEms',
meta: {
title: 'EMS',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'EMS'
},
},
{
path: 'pcs',
component: () => import('@/views/ems/dzjk/sbjk/pcs/index.vue'),
name: 'DzjkSbjkPcs',
meta: {
title: 'PCS',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'PCS'
},
},
{
path: 'bmszl',
component: () => import('@/views/ems/dzjk/sbjk/bmszl/index.vue'),
name: 'DzjkSbjkBmszl',
meta: {
title: 'BMS总览',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'STACK'
},
},
{
path: 'bmsdcc',
component: () => import('@/views/ems/dzjk/sbjk/bmsdcc/index.vue'),
name: 'DzjkSbjkBmsdcc',
meta: {
title: 'BMS电池簇',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'CLUSTER'
},
},
{
path: 'dtdc',
component: () => import('@/views/ems/dzjk/sbjk/dtdc/index.vue'),
name: 'DzjkSbjkDtdc',
meta: {
title: 'BMS单体电池',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'BATTERY'
},
},
{
path: 'db',
component: () => import('@/views/ems/dzjk/sbjk/db/index.vue'),
name: 'DzjkSbjkDb',
meta: {
title: '电表',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'AMMETER'
},
},
{
path: 'yl',
component: () => import('@/views/ems/dzjk/sbjk/yl/index.vue'),
name: 'DzjkSbjkYl',
meta: {
title: '冷却',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'COOLING'
},
},
{
path: 'dh',
component: () => import('@/views/ems/dzjk/sbjk/dh/index.vue'),
name: 'DzjkSbjkDh',
meta: {
title: '动环',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'DH'
},
},
{
path: 'xf',
component: () => import('@/views/ems/dzjk/sbjk/xf/index.vue'),
name: 'DzjkSbjkXf',
meta: {
title: '消防',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkSbjk',
deviceCategory: 'XF'
},
}
]
},
{
path: '/dzjk/gzgj',
component: () => import('@/views/ems/dzjk/gzgj/index.vue'),
name: 'DzjkGzgj',
meta: {
title: '故障告警',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkGzgj'
}
},
{
path: '/dzjk/tjbb',
component: () => import('@/views/ems/dzjk/tjbb/index.vue'),
name: 'DzjkTjbb',
meta: {title: '统计报表', breadcrumb: false, activeMenu: '/dzjk'},
redirect: '/dzjk/tjbb/gltj',
children: [
{
path: 'gltj',
component: () => import('@/views/ems/dzjk/tjbb/gltj/index.vue'),
name: 'DzjkTjbbGltj',
meta: {
title: '运行统计',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'glqx',
component: () => import('@/views/ems/dzjk/tjbb/glqx/index.vue'),
name: 'DzjkTjbbGlqx',
meta: {
title: '功率曲线',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'pcsqx',
component: () => import('@/views/ems/dzjk/tjbb/pcsqx/index.vue'),
name: 'DzjkTjbbPcsqx',
meta: {
title: 'PCS曲线',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dcdqx',
component: () => import('@/views/ems/dzjk/tjbb/dcdqx/index.vue'),
name: 'DzjkTjbbDcdqx',
meta: {
title: '电池堆曲线',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dcwd',
component: () => import('@/views/ems/dzjk/tjbb/dcwd/index.vue'),
name: 'DzjkTjbbDcwd',
meta: {
title: '电池温度',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dbbb',
component: () => import('@/views/ems/dzjk/tjbb/dbbb/index.vue'),
name: 'DzjkTjbbDbbb',
meta: {
title: '电表报表',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'sybb',
component: () => import('@/views/ems/dzjk/tjbb/sybb/index.vue'),
name: 'DzjkTjbbSybb',
meta: {
title: '收益报表',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkTjbb'
},
}
]
},
{
path: '/dzjk/clpz',
component: () => import('@/views/ems/dzjk/clpz/index.vue'),
name: 'DzjkClpz',
meta: {title: '策略配置', breadcrumb: false, activeMenu: '/dzjk'},
redirect: '/dzjk/clpz/clyx',
children: [
{
path: 'clyx',
component: () => import('@/views/ems/dzjk/clpz/clyx/index.vue'),
name: 'DzjkClpzClyx',
meta: {
title: '策略运行',
breadcrumb: false,
activeMenu: '/dzjk',
activeSecondMenuName: 'DzjkClpz'
},
},
// {
// path: 'xftg',
// component: () => import('@/views/ems/dzjk/clpz/xftg/index.vue'),
// hidden:true,
// breadcrumb: false,
// name: 'DzjkClpzXftg',
// meta: { title: '削峰填谷',breadcrumb: false,activeMenu: '/dzjk',activeSecondMenuName:'DzjkClpz'},
// }
]
} }
] ]
},
{
path: '/dzjk/gzgj',
component: () => import('@/views/ems/dzjk/gzgj/index.vue'),
name: 'DzjkGzgj',
meta: {title: '故障告警', breadcrumb: false, activeMenu: '/dzjk/gzgj', activeSecondMenuName: 'DzjkGzgj'}
},
{
path: '/dzjk/tjbb',
component: () => import('@/views/ems/dzjk/tjbb/index.vue'),
name: 'DzjkTjbb',
alwaysShow: false,
meta: {title: '统计报表', breadcrumb: false, activeMenu: '/dzjk/tjbb'},
hidden: false,
redirect: '/dzjk/tjbb/gltj',
children: [
{
path: 'gltj',
component: () => import('@/views/ems/dzjk/tjbb/gltj/index.vue'),
name: 'DzjkTjbbGltj',
hidden: true,
meta: {
title: '概率统计',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'glqx',
component: () => import('@/views/ems/dzjk/tjbb/glqx/index.vue'),
name: 'DzjkTjbbGlqx',
hidden: true,
meta: {
title: '功率曲线',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'pcsqx',
component: () => import('@/views/ems/dzjk/tjbb/pcsqx/index.vue'),
name: 'DzjkTjbbPcsqx',
hidden: true,
meta: {
title: 'PCS曲线',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dcdqx',
component: () => import('@/views/ems/dzjk/tjbb/dcdqx/index.vue'),
name: 'DzjkTjbbDcdqx',
hidden: true,
meta: {
title: '电池堆曲线',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dcwd',
component: () => import('@/views/ems/dzjk/tjbb/dcwd/index.vue'),
name: 'DzjkTjbbDcwd',
hidden: true,
meta: {
title: '电池温度',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
},
{
path: 'dbbb',
component: () => import('@/views/ems/dzjk/tjbb/dbbb/index.vue'),
name: 'DzjkTjbbDbbb',
hidden: true,
meta: {
title: '电表报表',
breadcrumb: false,
activeMenu: '/dzjk/tjbb',
activeSecondMenuName: 'DzjkTjbb'
},
}
]
},
{
path: '/dzjk/clpz',
component: () => import('@/views/ems/dzjk/clpz/clyx/index.vue'),
name: 'DzjkClpz',
meta: {title: '策略配置', breadcrumb: false, activeMenu: '/dzjk/clpz'},
} }
] ]
} }

View File

@ -7,7 +7,7 @@ module.exports = {
/** /**
* 侧边栏主题 深色主题theme-dark浅色主题theme-light * 侧边栏主题 深色主题theme-dark浅色主题theme-light
*/ */
sideTheme: 'theme-light', sideTheme: 'theme-dark',
/** /**
* 系统布局配置 * 系统布局配置

View File

@ -1,3 +1,4 @@
import {getAllSites} from '@/api/ems/zddt'
import {getAlarmDetailList, getSiteAllDeviceCategory} from '@/api/ems/dzjk' import {getAlarmDetailList, getSiteAllDeviceCategory} from '@/api/ems/dzjk'
const ems = { const ems = {
@ -5,18 +6,8 @@ const ems = {
dzjkAlarmLighting: false,//单站监控 告警统计红点标志 dzjkAlarmLighting: false,//单站监控 告警统计红点标志
zdList: [], zdList: [],
zdDeviceCategoryOptions: {},//站点各个站点包含的设备种类 {021_DDS_01:["BATTERY","CLUSTER","STACK", "DH", "AMMETER", "PCS", "XF"],021_DDS_02:[]...} zdDeviceCategoryOptions: {},//站点各个站点包含的设备种类 {021_DDS_01:["BATTERY","CLUSTER","STACK", "DH", "AMMETER", "PCS", "XF"],021_DDS_02:[]...}
CLUSTERWorkStatusOptions: {'0': '静置', '1': '充电', '2': '放电', '3': '待机', '5': '运行', '9': "故障"},//电池簇工作状态 workStatusOptions: {'0': '正常', '1': '异常', '2': '停止'},//工作状态
PCSWorkStatusOptions: {'0': '运行', '1': '机', '2': '故障', '3': '待机', '4': '充电', '5': '放电'},//PCS工作状态 deviceStatusOptions: {'0': '离线', '1': '机', '2': '运行', '3': '故障', '4': '停机'},//设备状态
STACKWorkStatusOptions: {
"0": "静置",
"1": "充电",
"2": "放电",
"3": "浮充",
'4': '待机',
'5': '运行',
'9': "故障"
},//STACKBMS总览工作状态
deviceStatusOptions: {'0': '离线', '1': '在线'},//设备状态
gridStatusOptions: {'0': '并网', '1': '未并网'},//并网状态 gridStatusOptions: {'0': '并网', '1': '未并网'},//并网状态
controlModeOptions: {'0': '远程', '1': '本地'},//控制模式 controlModeOptions: {'0': '远程', '1': '本地'},//控制模式
warnOptions: {0: '正常', 1: '中断', 2: '不在线', 3: '异常'},//告警状态 warnOptions: {0: '正常', 1: '中断', 2: '不在线', 3: '异常'},//告警状态
@ -27,7 +18,7 @@ const ems = {
deviceTypeOptions: {'TCP': 'TCP', 'RTU': 'RTU'},//设备类型 deviceTypeOptions: {'TCP': 'TCP', 'RTU': 'RTU'},//设备类型
ticketStatusOptions: {1: '待处理', 2: '处理中', 3: '已处理'},//工单处理状态 ticketStatusOptions: {1: '待处理', 2: '处理中', 3: '已处理'},//工单处理状态
strategyStatusOptions: {'0': '未启用', '1': '已运行', '2': '已暂停', '3': '禁用', '4': '删除'},//策略状态 strategyStatusOptions: {'0': '未启用', '1': '已运行', '2': '已暂停', '3': '禁用', '4': '删除'},//策略状态
chargeStatusOptions: {'1': '充电', '2': '待机', '3': '放电'},//冲放状态 chargeStatusOptions: {'1': '充电', '2': '待机'},//冲放状态
comparisonOperatorOptions: {'>': '>', '<': '<', '=': '=', '>=': '>=', '<=': '<='}, comparisonOperatorOptions: {'>': '>', '<': '<', '=': '=', '>=': '>=', '<=': '<='},
relationWithPoint: {'||': '||', '&&': '&&'} relationWithPoint: {'||': '||', '&&': '&&'}
}, },
@ -43,6 +34,14 @@ const ems = {
} }
}, },
actions: { actions: {
getZdList({commit, state}) {
if (state.zdList.length === 0) {
getAllSites().then(response => {
commit('SET_ZD_LIST', response?.data || [])
console.log('store action getZdList 获取站点数据', state.zdList)
})
}
},
//查询站点的所有待处理0的告警 存在展示红点标志 //查询站点的所有待处理0的告警 存在展示红点标志
getSiteAlarmNum({state, commit}, siteId) { getSiteAlarmNum({state, commit}, siteId) {
getAlarmDetailList({ getAlarmDetailList({

View File

@ -33,12 +33,13 @@ const permission = {
GenerateRoutes({ commit }) { GenerateRoutes({ commit }) {
return new Promise(resolve => { return new Promise(resolve => {
// 向后端请求路由数据 // 向后端请求路由数据
getRouters().then(res => { getRouters().then(res => {
let hasDzjk = false let sysDzjk = -1
if(res?.data){ if(res?.data){
res.data.forEach(i=>{ sysDzjk = res.data.findIndex(i=>{
i.children && i.children.find(j=>j.path.indexOf('dzjk')>-1) && (hasDzjk=true) return i.children && i.children.find(j=>j.path.indexOf('dzjk')>-1)
}) })
if(sysDzjk>-1) res.data.splice(sysDzjk,1)
} }
const sdata = JSON.parse(JSON.stringify(res.data)) const sdata = JSON.parse(JSON.stringify(res.data))
const rdata = JSON.parse(JSON.stringify(res.data)) const rdata = JSON.parse(JSON.stringify(res.data))
@ -47,7 +48,7 @@ const permission = {
const asyncRoutes = filterDynamicRoutes(dynamicRoutes) const asyncRoutes = filterDynamicRoutes(dynamicRoutes)
rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true })
router.addRoutes(asyncRoutes) router.addRoutes(asyncRoutes)
if(!hasDzjk){ if(sysDzjk === -1){
const index = constantRoutes.findIndex(i=>i.path.indexOf('dzjk')>-1) const index = constantRoutes.findIndex(i=>i.path.indexOf('dzjk')>-1)
constantRoutes.splice(index,1) constantRoutes.splice(index,1)
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading" class="ems-dashboard-editor-container ems-content-container-padding">
<template v-if="!showTemp"> <template v-if="!showTemp">
<el-button v-if="!showTemp" type="primary" plain @click="settingStrategy" style="margin-bottom: 20px;">新增策略</el-button> <el-button v-if="!showTemp" type="primary" plain @click="settingStrategy" style="margin-bottom: 20px;">新增策略</el-button>
<cl-container v-for="(item,index) in list" :key="index+'clContainer'" :info="item" :hide-setting-btn="showTemp" class="contain" @update="init" @showSetting="settingStrategy(item)"> <cl-container v-for="(item,index) in list" :key="index+'clContainer'" :info="item" :hide-setting-btn="showTemp" class="contain" @update="init" @showSetting="settingStrategy(item)">

View File

@ -1,53 +0,0 @@
<template>
<div class="ems-dashboard-editor-container ems-third-menu-container">
<el-menu
class="ems-third-menu"
:default-active="$route.name"
background-color="#ffffff"
text-color="#666666"
active-text-color="#ffffff"
>
<el-menu-item :index="item.name" v-for="(item,index) in childrenRoute" :key="index+'clpzChildrenRoute'">
<router-link style="height: 100%;width: 100%;display: block;" :to="{path:item.path,query:$route.query}">
{{item.meta.title}}
</router-link>
</el-menu-item>
</el-menu>
<div class="ems-content-container ems-content-container-padding clpz-ems-content-container">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</div>
</template>
<script>
import { dzjk } from '@/router/ems'
const childrenRoute = dzjk[0].children[0].children.find(item=> item.name==='DzjkClpz').children.filter(item=>!item?.hidden)//获取到统计报表下面的字路由
console.log('设备监控子路由',childrenRoute)
export default {
name:'DzjkClpz',
data(){
return {
childrenRoute,
activeMenu:''
}
},
mounted() {
console.log('当前统计报表页面路由',this.$route)
}
}
</script>
<style scoped lang="scss">
.clpz-ems-content-container{
margin-top:0;
padding-top:0;
padding-right: 0;
flex: 1;
}
</style>

View File

@ -1,140 +1,119 @@
<template> <template>
<el-dialog :visible.sync="dialogTableVisible" class="ems-dialog add-template-dialog" <el-dialog :visible.sync="dialogTableVisible" class="ems-dialog" :title="mode === 'add'?'新增模板':`编辑模板` ">
:title="mode === 'add'?'新增模板':`编辑模板` "> <el-form ref="addTempForm" :model="formData" :rules="rules" size="medium" label-width="100px">
<el-form ref="addTempForm" :model="formData" :rules="rules" size="medium" label-width="100px"> <el-form-item label="模板名称" prop="templateName">
<el-form-item label="模板名称" prop="templateName"> <el-input v-model="formData.templateName" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="formData.templateName" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <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">-->
<!-- <template v-if="formData.sdcLimit === 1">--> <el-form-item label="soc下限" prop="sdcDown">
<el-form-item label="soc下限" prop="sdcDown"> <el-input v-model="formData.sdcDown" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
<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-button type="primary" size="mini" @click="addTime">新增</el-button>
<!-- 新增时间段表单-->
<el-collapse-transition>
<el-card v-show="showAddTime" shadow="always" class="common-card-container" style="margin-top:25px;">
<el-form class="add-time-form transition-box" ref="addTimeForm" :model="formInline" :rules="formInlineRule"
label-width="100px" style="margin-top:25px">
<!-- <el-form-item label="开始时间" prop="startTime">-->
<!-- <el-time-select-->
<!-- placeholder="开始时间"-->
<!-- v-model="formInline.startTime"-->
<!-- :picker-options="{-->
<!-- start: '00:00',-->
<!-- step: '00:01',-->
<!-- end: '23:00',-->
<!-- }">-->
<!-- </el-time-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="结束时间" prop="endTime">-->
<!-- <el-time-select-->
<!-- placeholder="结束时间"-->
<!-- v-model="formInline.endTime"-->
<!-- :picker-options="{-->
<!-- start: '00:00',-->
<!-- step: '00:01',-->
<!-- end: '23:00',-->
<!-- minTime: formInline.startTime-->
<!-- }">-->
<!-- </el-time-select>-->
<!-- </el-form-item>-->
<el-form-item label="时间范围" prop="timeRange">
<el-time-picker
is-range
v-model="formInline.timeRange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围"
format="HH:mm"
value-format="HH:mm"
:style="{width: '100%'}">
</el-time-picker>
</el-form-item> </el-form-item>
<el-form-item label="冲放功率" prop="chargeDischargePower"> <el-form-item label="soc上限" prop="sdcUp">
<el-input v-model="formInline.chargeDischargePower" placeholder="请输入" <el-input v-model="formData.sdcUp" placeholder="请输入" clearable :style="{width: '100%'}"></el-input>
:style="{width: '100%'}"></el-input>
</el-form-item> </el-form-item>
<el-form-item label="充电状态" prop="chargeStatus"> <!-- </template>-->
<el-select v-model="formInline.chargeStatus" placeholder="请选择" :style="{width: '100%'}"> </el-form>
<el-option v-for="(value,key) in chargeStatusOptions" :key="key+'chargeStatusOptions'" :label="value" <el-button type="primary" size="mini" @click="addTime">新增</el-button>
:value="key"></el-option> <!-- 新增时间段表单-->
</el-select> <el-collapse-transition>
</el-form-item> <el-card v-show="showAddTime" shadow="always" class="common-card-container" style="margin-top:25px;">
<el-form-item> <el-form class="add-time-form transition-box" ref="addTimeForm" :model="formInline" :rules="formInlineRule" label-width="100px" style="margin-top:25px">
<el-button type="primary" size="mini" @click="saveTime">保存</el-button> <el-form-item label="开始时间" prop="startTime">
<el-button size="mini" @click="cancelAddTime">取消</el-button> <el-time-select
</el-form-item> placeholder="开始时间"
</el-form> v-model="formInline.startTime"
</el-card> :picker-options="{
</el-collapse-transition> start: '00:00',
<el-table step: '01:00',
end: '23:00',
}">
</el-time-select>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-time-select
placeholder="结束时间"
v-model="formInline.endTime"
:picker-options="{
start: '00:00',
step: '01:00',
end: '23:00',
minTime: formInline.startTime
}">
</el-time-select>
</el-form-item>
<el-form-item label="冲放功率" prop="chargeDischargePower">
<el-input v-model="formInline.chargeDischargePower" placeholder="请输入"></el-input>
</el-form-item>
<el-form-item label="充电状态" prop="chargeStatus">
<el-select v-model="formInline.chargeStatus" placeholder="请选择">
<el-option v-for="(value,key) in chargeStatusOptions" :key="key+'chargeStatusOptions'" :label="value" :value="key"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" size="mini" @click="saveTime">保存</el-button>
<el-button size="mini" @click="cancelAddTime">取消</el-button>
</el-form-item>
</el-form>
</el-card>
</el-collapse-transition>
<el-table
:data="tableData" :data="tableData"
border border
style="width: 100%;margin-top:25px"> style="width: 100%;margin-top:25px">
<el-table-column <!-- todo 如果要在span-method中使用column.property 在表格中必须定义prop="xxx"属性-->
<el-table-column
prop="startTime" prop="startTime"
label="开始时间"> label="开始时间">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="endTime" prop="endTime"
label="结束时间"> label="结束时间">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="chargeDischargePower" prop="chargeDischargePower"
label="充放功率kW"> label="充放功率kW">
</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] }} {{chargeStatusOptions[scope.row.chargeStatus]}}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
fixed="right" fixed="right"
label="操作" label="操作"
width="120"> width="120">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
@click.native.prevent="deleteRow(scope.$index, tableData)" @click.native.prevent="deleteRow(scope.$index, tableData)"
type="warning" type="warning"
size="mini"> size="mini">
删除 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div slot="footer"> <div slot="footer">
<el-button @click="closeDialog">取消</el-button> <el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="saveDialog">确定</el-button> <el-button type="primary" @click="saveDialog">确定</el-button>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
<script> <script>
import {mapState} from 'vuex' import {mapState} from 'vuex'
import {addStrategyTemp, editStrategyTemp, getStrategyTempDetail} from '@/api/ems/dzjk' import {addStrategyTemp,editStrategyTemp,getStrategyTempDetail} from '@/api/ems/dzjk'
export default { export default {
inject: ['$home'], inject:['$home'],
data() { data() {
const now = new Date()
const year = now.getFullYear(), month = now.getMonth(), day = now.getDate()
const range = [new Date(year, month, day, 0), new Date(year, month, day, 23)]
return { return {
mode: '', mode:'',
editTempId: '', editTempId:'',
dialogTableVisible: false, dialogTableVisible:false,
secondRange: range,
formData: { formData: {
templateName: '', templateName: '',
sdcLimit: false, sdcLimit: false,
@ -148,41 +127,44 @@ export default {
trigger: 'blur' trigger: 'blur'
}], }],
sdcDown: [ sdcDown: [
{required: true, message: '请输入', trigger: 'blur'}, {required: true,message: '请输入', trigger: 'blur'},
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'} { pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数' }
], ],
sdcUp: [ sdcUp: [
{required: true, message: '请输入', trigger: 'blur'}, {required: true,message: '请输入', trigger: 'blur'},
{pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数'} { pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数' }
], ],
}, },
showAddTime: false, showAddTime: false,
formInline: { formInline:{
timeRange: range, startTime:'',endTime:'',chargeDischargePower:'',chargeStatus:''
chargeDischargePower: '',
chargeStatus: ''
}, },
formInlineRule: { formInlineRule:{
timeRange: [{ startTime: [{
required: true, required: true,
message: '请选择时间范围', message: '请选择开始时间',
trigger: 'change'
}],
endTime: [{
required: true,
message: '请选择结束时间',
trigger: 'change' trigger: 'change'
}], }],
chargeDischargePower: [{ chargeDischargePower: [{
required: true, required: true,
message: '请输入冲放功率', message: '请输入冲放功率',
trigger: 'blur' trigger: 'blur'
}, },
{pattern: /^-?\d*\.?\d*$/, message: '请输入合法数字或小数'} { pattern: /^(0|[1-9]\d*)(\.\d+)?$/, message: '请输入合法数字或小数' }
], ],
chargeStatus: [{ chargeStatus:[{
required: true, required: true,
message: '请选择充放状态', message: '请选择充放状态',
trigger: ['blur', 'change'] trigger: ['blur','change']
} }
] ]
}, },
tableData: [], tableData:[],
} }
}, },
computed: { computed: {
@ -190,136 +172,145 @@ export default {
chargeStatusOptions: state => state?.ems?.chargeStatusOptions || {}, chargeStatusOptions: state => state?.ems?.chargeStatusOptions || {},
}) })
}, },
watch: {
"formInline.startTime":{
handler(newVal){
if(newVal && this.formInline.endTime){
const endTime = parseInt((this.formInline.endTime).split(':')[0] || 0)
const startTime =parseInt(newVal.split(':')[0])
if(endTime<=startTime){
this.formInline.endTime = `${startTime+1 <=9 ? '0'+(startTime+1) : startTime+1}:00`
}
}
},
deep:true
},
},
methods: { methods: {
changeSiteId() { changeSiteId(){
this.dialogTableVisible = false this.dialogTableVisible=false
this.mode = '' this.mode=''
this.editTempId = '' this.editTempId=''
this.formData = { this.formData={
templateName: '', templateName: '',
sdcLimit: false, sdcLimit: false,
sdcDown: '', sdcDown: '',
sdcUp: '', sdcUp: '',
} }
this.formInline = { this.formInline={
timeRange: this.secondRange, chargeDischargePower: '', chargeStatus: '' startTime:'',endTime:'',chargeDischargePower:'',chargeStatus:''
}//startTime: '', endTime: '', }
this.showAddTime = false this.showAddTime = false
this.tableData = [] this.tableData=[]
}, },
show({mode = 'add', editTempId = ''}) { show({mode = 'add', editTempId = ''}){
this.$nextTick(() => { this.$nextTick(() => {
this.dialogTableVisible = true this.dialogTableVisible = true
this.mode = mode this.mode = mode
this.editTempId = editTempId this.editTempId=editTempId
if (mode === 'edit' && editTempId) { if(mode === 'edit' && editTempId){
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,sdcDown,sdcUp} =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.sdcDown=sdcDown
this.formData.sdcUp = sdcUp this.formData.sdcUp=sdcUp
} }
if (data.length === 1) { if(data.length === 1){
const {startTime, endTime} = data; const {startTime,endTime}=data;
if (!startTime || !endTime) { if(!startTime || !endTime){
this.tableData = [] this.tableData = []
} else { }else{
this.tableData = data this.tableData= data
} }
} else { }else{
this.tableData = data this.tableData= data
} }
}) })
} }
}) })
}, },
addTime() { addTime(){
this.showAddTime = true this.showAddTime=true
}, },
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 = {startTime:'',endTime:'',chargeDischargePower:'',chargeStatus:''}
}, },
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 this.tableData.push(JSON.parse(JSON.stringify(this.formInline)));
this.$nextTick(() => {this.cancelAddTime()})
this.tableData.push({startTime, endTime, chargeDischargePower, chargeStatus})
this.$nextTick(() => {
this.cancelAddTime()
})
}) })
}, },
deleteRow(index) { deleteRow(index){
this.tableData.splice(index, 1) this.tableData.splice(index,1)
}, },
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 {siteId, updateStrategyId} = this.$home let status = true
const {tableData} = this this.tableData.forEach((outer,outerIndex)=>{
if (this.mode === 'edit') { const {startTime, endTime}=outer
editStrategyTemp({ const outerStart = parseInt(startTime),outerEnd = parseInt(endTime)
siteId, if(outerStart>outerEnd){
strategyId: updateStrategyId, status = false
templateId: this.editTempId, }else{
templateName, this.tableData.forEach((inner,innerIndex)=>{
sdcLimit, if(innerIndex !== outerIndex){
sdcDown, const {startTime:innerStartTime, endTime:innerEndTime}=inner
sdcUp, const innerStart = parseInt(innerStartTime),innerEnd = parseInt(innerEndTime)
timeConfigList: tableData if((innerStart<outerStart && innerEnd>outerEnd) || !((innerStart<outerStart && innerEnd<=outerStart) || (innerStart>=outerEnd && innerEnd>outerEnd))){
}).then(response => { status=false
if (response?.code === 200) { }
this.closeDialog() }
this.$emit('update') })
this.$emit('updateTimeSetting')
} }
}) })
} else { if(!status){
addStrategyTemp({ return this.$message.error('时间选择范围冲突');
siteId, }
strategyId: updateStrategyId, const {templateName,sdcLimit,sdcDown,sdcUp} = this.formData
templateName, const {siteId,updateStrategyId} =this.$home
sdcLimit, const {tableData} = this
sdcDown, if(this.mode==='edit'){
sdcUp, editStrategyTemp({siteId,strategyId:updateStrategyId,templateId:this.editTempId,templateName,sdcLimit,sdcDown,sdcUp,timeConfigList:tableData}).then(response=>{
timeConfigList: tableData if(response?.code === 200){
}).then(response => { this.closeDialog()
if (response?.code === 200) { this.$emit('update')
this.closeDialog() this.$emit('updateTimeSetting')
this.$emit('update') }
} })
}) }else{
} addStrategyTemp({siteId,strategyId:updateStrategyId,templateName,sdcLimit,sdcDown,sdcUp,timeConfigList:tableData}).then(response=>{
if(response?.code === 200){
this.closeDialog()
this.$emit('update')
}
})
}
}) })
}, },
closeDialog() { closeDialog(){
// 清空所有数据 // 清空所有数据
this.$refs.addTempForm.resetFields() this.$refs.addTempForm.resetFields()
this.formData = { this.formData={
templateName: '', templateName: '',
sdcLimit: 0, sdcLimit:0,
sdcDown: '', sdcDown: '',
sdcUp: '', sdcUp: '',
} }
this.tableData = [] this.tableData=[]
this.cancelAddTime() this.cancelAddTime()
this.dialogTableVisible = false this.dialogTableVisible=false
} }
} }
} }
</script> </script>
<style lang="scss" scoped>
.add-template-dialog {
max-height: 90vh;
overflow-y: auto;
}
</style>

View File

@ -2,7 +2,7 @@
<template> <template>
<!-- <cl-container :hideSettingBtn="true">--> <!-- <cl-container :hideSettingBtn="true">-->
<!-- <template v-slot:default>--> <!-- <template v-slot:default>-->
<div> <div class="ems-dashboard-editor-container ems-content-container-padding">
<temp-table ref="tempTable" @updateTimeSetting="updateTimeSetting"/> <temp-table ref="tempTable" @updateTimeSetting="updateTimeSetting"/>
<time-setting ref="timeSetting"/> <time-setting ref="timeSetting"/>
<temp-power-chart ref="tomePowerChart"/> <temp-power-chart ref="tomePowerChart"/>

View File

@ -1,30 +1,27 @@
<template> <template>
<el-card v-loading="loading" gshadow="always" class="common-card-container common-card-container-no-title-bg"> <div v-loading="loading" class="ems-dashboard-editor-container ems-content-container-padding">
<!-- 搜索栏--> <!-- 搜索栏-->
<el-form :inline="true" class="select-container"> <el-form :inline="true" class="select-container">
<el-form-item label="设备清单"> <el-form-item label="设备清单">
<el-select v-model="search.deviceId" clearable placeholder="请选择" :loading="loading" <el-select v-model="search.deviceId" clearable placeholder="请选择" :loading="loading" loading-text="正在加载数据">
loading-text="正在加载数据"> <el-option :label="item.deviceName" :value="item.deviceId" v-for="(item,key) in deviceOptions" :key="key+'deviceIdOptions'"></el-option>
<el-option :label="item.deviceName" :value="item.deviceId" v-for="(item,key) in deviceOptions"
:key="key+'deviceIdOptions'"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="告警等级"> <el-form-item label="告警等级">
<el-select v-model="search.alarmLevel" clearable placeholder="请选择" :loading="loading" <el-select v-model="search.alarmLevel" clearable placeholder="请选择" :loading="loading" loading-text="正在加载数据">
loading-text="正在加载数据" style="width: 130px"> <el-option :label="value" :value="key" v-for="(value,key) in $store.state.ems.alarmLevelOptions" :key="key+'alarmLevelOptions'"></el-option>
<el-option :label="value" :value="key" v-for="(value,key) in $store.state.ems.alarmLevelOptions"
:key="key+'alarmLevelOptions'"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="时间选择"> <el-form-item label="时间选择">
<el-date-picker <el-date-picker
v-model="dateRange" v-model="dateRange"
type="daterange" type="daterange"
range-separator="" range-separator=""
start-placeholder="开始时间" start-placeholder="开始时间"
:picker-options="pickerOptions" :picker-options="pickerOptions"
:default-value="defaultDateRange" :default-value="defaultDateRange"
end-placeholder="结束时间"> end-placeholder="结束时间">
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -39,9 +36,7 @@
<el-row style=""> <el-row style="">
<el-col :xs="24" :sm="24" :lg="24"> <el-col :xs="24" :sm="24" :lg="24">
<el-button-group class="ems-btns-group"> <el-button-group class="ems-btns-group">
<el-button v-for="(item,index) in btnList" :key="index+'dtdcBtns'" <el-button v-for="(item,index) in btnList" :key="index+'dtdcBtns'" :class="{'activeBtn' : activeBtn === item.id}" @click="changeDataType(item.id)">{{item.name}}</el-button>
:class="{'activeBtn' : activeBtn === item.id}" @click="changeDataType(item.id)">{{ item.name }}
</el-button>
</el-button-group> </el-button-group>
</el-col> </el-col>
</el-row> </el-row>
@ -52,198 +47,179 @@
stripe stripe
max-height="500" max-height="500"
style="width: 100%;margin-top:25px;"> style="width: 100%;margin-top:25px;">
<el-table-column <el-table-column
prop="deviceName" prop="deviceName"
label="设备名称"> label="设备名称">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="告警等级" label="告警等级"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ $store.state.ems.alarmLevelOptions[scope.row.alarmLevel] }}</span> <span>{{$store.state.ems.alarmLevelOptions[scope.row.alarmLevel]}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="alarmContent" prop="alarmContent"
show-overflow-tooltip show-overflow-tooltip
label="告警内容"> label="告警内容">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="alarmStartTime" prop="alarmStartTime"
label="告警发生时间"> label="告警发生时间">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ formatDate(scope.row.alarmStartTime, true) }}</span> <span>{{formatDate(scope.row.alarmStartTime,true)}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
prop="alarmEndTime" prop="alarmEndTime"
label="告警结束时间"> label="告警结束时间">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ formatDate(scope.row.alarmEndTime, true) }}</span> <span>{{formatDate(scope.row.alarmEndTime,true)}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
label="状态"> label="状态">
<template slot-scope="scope"> <template slot-scope="scope">
<span <span :class="['0','2'].includes(scope.row.status) ? 'warning-status' : ''">{{$store.state.ems.alarmStatusOptions[scope.row.status]}}</span>
:class="['0','2'].includes(scope.row.status) ? 'warning-status' : ''">{{ </template>
$store.state.ems.alarmStatusOptions[scope.row.status] </el-table-column>
}}</span> <el-table-column
</template>
</el-table-column>
<el-table-column
label="工单" label="工单"
fixed="right" fixed="right"
width="250" width="250"
> >
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" size="mini" v-if="scope.row.ticketNo" @click="toTicket"> <el-button type="text" size="mini" v-if="scope.row.ticketNo" @click="toTicket">已生成工单(工单号:{{scope.row.ticketNo}})</el-button>
已生成工单(工单号:{{ scope.row.ticketNo }}) <el-button type="primary" size="mini" v-else @click="createTicket(scope.row.id)">生成工单</el-button>
</el-button> </template>
<el-button type="primary" size="mini" v-else @click="createTicket(scope.row.id)">生成工单</el-button> </el-table-column>
</template> </el-table>
</el-table-column>
</el-table>
<el-pagination <el-pagination
v-show="tableData.length>0" v-show="tableData.length>0"
background background
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
:current-page="pageNum" :current-page="pageNum"
:page-size="pageSize" :page-size="pageSize"
:page-sizes="[10, 20, 30, 40]" :page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="totalSize" :total="totalSize"
style="margin-top:15px;text-align: center" style="margin-top:15px;text-align: center"
> >
</el-pagination> </el-pagination>
</div> </div>
</el-card> </div>
</template> </template>
<script> <script>
import {createTicketNo, getAlarmDetailList} from '@/api/ems/dzjk' import {getAlarmDetailList,createTicketNo} from'@/api/ems/dzjk'
import {getDeviceList} from '@/api/ems/site' import {getDeviceList} from'@/api/ems/site'
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {formatDate} from '@/filters/ems' import { formatDate } from '@/filters/ems'
export default { export default {
name: 'DzjkGzgj', name:'DzjkGzgj',
mixins: [getQuerySiteId], mixins:[getQuerySiteId],
data() { data() {
return { return {
loading: false, loading:false,
btnList: [ btnList:[
{name: '未处理告警', id: 'today'}, {name:'未处理告警',id:'today'},
{name: '历史告警', id: 'history'}, {name:'历史告警',id:'history'},
], ],
deviceOptions: [],//设备列表 deviceOptions:[],//设备列表
pickerOptions: { pickerOptions:{
disabledDate(time) { disabledDate(time) {
return time.getTime() > Date.now(); return time.getTime() > Date.now();
}, },
}, },
defaultDateRange: [],//默认展示的时间 defaultDateRange:[],//默认展示的时间
dateRange: [],//alarmStartTime,alarmEndTime dateRange:[],//alarmStartTime,alarmEndTime
activeBtn: 'today', activeBtn:'today',
search: {deviceId: '', alarmLevel: ''}, search:{deviceId:'',alarmLevel:''},
// 表格、分页 // 表格、分页
tableData: [], tableData:[],
pageSize: 10,//分页栏当前每个数据总数 pageSize:10,//分页栏当前每个数据总数
pageNum: 1,//分页栏当前页数 pageNum:1,//分页栏当前页数
totalSize: 0,//table表格数据总数 totalSize:0,//table表格数据总数
} }
}, },
methods: { methods:{
formatDate, formatDate,
toTicket() { toTicket(){
this.$router.push({path: '/ticket'}) this.$router.push({path:'/ticket'})
}, },
//生成工单 //生成工单
createTicket(id) { createTicket(id){
this.loading = true this.loading = true
createTicketNo({id}).then(response => { createTicketNo({id}).then(response=>{
response?.data && this.toTicket() response?.data && this.toTicket()
}).finally(() => { }).finally(()=>{this.loading = false})
this.loading = false
})
}, },
// 判断是否是同一天 // 判断是否是同一天
isSameDay(day1, day2) { isSameDay(day1, day2) {
const date1 = new Date(day1), date2 = new Date(day2) const date1 = new Date(day1),date2 = new Date(day2)
return date1.getFullYear() === date2.getFullYear() && return date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() && date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate(); date1.getDate() === date2.getDate();
}, },
// 分页 // 分页
handleSizeChange(val) { handleSizeChange(val) {
this.pageSize = val; this.pageSize = val;
this.$nextTick(() => { this.$nextTick(()=>{
this.getData() this.getData()
}) })
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageNum = val this.pageNum = val
this.$nextTick(() => { this.$nextTick(()=>{
this.getData() this.getData()
}) })
}, },
// 搜索 // 搜索
onSearch() { onSearch(){
this.pageNum = 1//每次搜索从1开始搜索 this.pageNum =1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 重置 // 重置
onReset() { onReset(){
this.search = {deviceId: '', alarmLevel: ''} this.search={deviceId:'',alarmLevel:''}
this.dateRange = [] this.dateRange=[]
this.pageNum = 1//每次搜索从1开始搜索 this.pageNum =1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 切换今日、历史告警 // 切换今日、历史告警
changeDataType(id) { changeDataType(id){
if (id !== this.activeBtn) { if(id !== this.activeBtn){
console.log('点击了不同的菜单,更新数据') console.log('点击了不同的菜单,更新数据')
this.activeBtn = id; this.activeBtn=id;
this.getData() this.getData()
} }
}, },
// 获取数据 // 获取数据
getData() { getData(){
this.$store.dispatch('getSiteAlarmNum', this.siteId) this.$store.dispatch('getSiteAlarmNum',this.siteId)
this.loading = true this.loading=true
const {deviceId, alarmLevel} = this.search const {deviceId,alarmLevel} = this.search
const {siteId, pageNum, pageSize, activeBtn} = this const {siteId,pageNum,pageSize,activeBtn} =this
const [alarmStartTime = '', alarmEndTime = ''] = (this.dateRange || []) const [alarmStartTime='',alarmEndTime='']=(this.dateRange || [])
let status = activeBtn === 'today' ? '0' : '1,2' let status = activeBtn === 'today' ? '0' : '1,2'
getAlarmDetailList({ getAlarmDetailList({status,deviceId,alarmLevel,siteId,pageSize,pageNum,alarmStartTime:formatDate(alarmStartTime),alarmEndTime:formatDate(alarmEndTime)}).then(response => {
status, this.tableData=response?.rows || [];
deviceId,
alarmLevel,
siteId,
pageSize,
pageNum,
alarmStartTime: formatDate(alarmStartTime),
alarmEndTime: formatDate(alarmEndTime)
}).then(response => {
this.tableData = response?.rows || [];
this.totalSize = response?.total || 0 this.totalSize = response?.total || 0
}).finally(() => { }).finally(() => {this.loading=false})
this.loading = false
})
}, },
getDeviceOptions() { getDeviceOptions(){
getDeviceList(this.siteId).then(response => { getDeviceList(this.siteId).then(response => {
this.deviceOptions = JSON.parse(JSON.stringify(response?.data || [])) this.deviceOptions = JSON.parse(JSON.stringify(response?.data || []))
}) })
}, },
init() { init(){
this.getDeviceOptions() this.getDeviceOptions()
this.onReset() this.onReset()
}, },
}, },
mounted() { mounted(){
const now = new Date(); const now = new Date();
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1); const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
this.defaultDateRange = [lastMonth, now]; this.defaultDateRange = [lastMonth, now];

View File

@ -1,29 +1,30 @@
<template> <template>
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card"> <el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
<div slot="header" class="time-range-header"> <div slot="header" class="time-range-header">
<span class="card-title">当日功率曲线</span> <span class="card-title">当日功率曲线</span>
<date-range-select ref="dateRangeSelect" :showIcon="true" :mini-time-picker="true" @updateDate="updateDate"/> <date-range-select ref="dateRangeSelect" @updateDate="updateDate"/>
</div> </div>
<div style="height: 310px" id="activeChart"></div> <div style="height: 310px" id="activeChart"></div>
</el-card> </el-card>
</template> </template>
<script> <script>
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 { getPointData } from '@/api/ems/dzjk'
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
export default { export default {
mixins: [resize, intervalUpdate], mixins: [resize,intervalUpdate],
components: {DateRangeSelect}, components: {DateRangeSelect},
data() { data() {
return { return {
chart: null, chart: null,
timeRange: [], timeRange:[],
siteId: '', siteId:'',
isInit: true isInit:true
} }
}, },
mounted() { mounted() {
@ -40,23 +41,23 @@ export default {
}, },
methods: { methods: {
// 更新时间范围 重置图表 // 更新时间范围 重置图表
updateDate(data) { updateDate(data){
this.timeRange = data this.timeRange=data
!this.isInit && this.getGVQXData() !this.isInit && this.getGVQXData()
this.isInit = false this.isInit = false
}, },
getGVQXData() { getGVQXData(){
this.showLoading() this.showLoading()
const {siteId, timeRange} = this const {siteId,timeRange}=this
getPointData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => { getPointData({siteId,startDate:timeRange[0],endDate:timeRange[1]}).then(response => {
this.setOption(response?.data || []) this.setOption(response?.data || [])
}).finally(() => this.hideLoading()) }).finally(()=>this.hideLoading())
}, },
init(siteId) { init(siteId){
//初始化 清空数据 //初始化 清空数据
this.siteId = siteId this.siteId = siteId
this.isInit = true this.isInit = true
this.timeRange = [] this.timeRange=[]
this.$refs.dateRangeSelect.init(true) this.$refs.dateRangeSelect.init(true)
this.getGVQXData() this.getGVQXData()
this.updateInterval(this.getGVQXData) this.updateInterval(this.getGVQXData)
@ -64,17 +65,17 @@ export default {
initChart() { initChart() {
this.chart = echarts.init(document.querySelector('#activeChart')) this.chart = echarts.init(document.querySelector('#activeChart'))
}, },
showLoading() { showLoading(){
this.chart && this.chart.showLoading() this.chart && this.chart.showLoading()
}, },
hideLoading() { hideLoading(){
this.chart && this.chart.hideLoading() this.chart && this.chart.hideLoading()
}, },
setOption(data) { setOption(data) {
const source = [['日期', '电网功率', '负载功率', '储能功率', '光伏功率', 'soc平均值', 'soh平均值', '电池平均温度平均值']] const source = [['日期','电网功率','负载功率','储能功率','光伏功率','soc平均值','soh平均值','电池平均温度平均值']]
console.log('source.slice(1)', source[0].slice(1)) console.log('source.slice(1)',source[0].slice(1))
this.chart && data.forEach((item) => { this.chart && data.forEach((item)=>{
source.push([item.statisDate, item.gridPower, item.loadPower, item.storagePower, item.pvPower, item.avgSoc, item.avgSoh, item.avgTemp]) source.push([item.statisDate,item.gridPower,item.loadPower,item.storagePower,item.pvPower,item.avgSoc,item.avgSoh,item.avgTemp])
}) })
this.chart.setOption({ this.chart.setOption({
grid: { grid: {
@ -90,8 +91,8 @@ export default {
type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
} }
}, },
textStyle: { textStyle:{
color: "#333333", color:"#333333",
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
@ -104,17 +105,11 @@ export default {
type: 'value', type: 'value',
}, },
], ],
dataset: {source}, dataset:{source},
series: source[0].slice(1).map((item, index) => { series: source[0].slice(1).map((item,index)=>{
return { return {
type: 'line',//index === 5 ? 'bar' : 'line', type: 'line',
showSymbol: false, yAxisIndex:index<=4 ? 0 : 1
symbolSize: 2,
smooth: true,
areaStyle: {
opacity: 0.5,
},
yAxisIndex: index <= 4 ? 0 : 1
} }
}) })
}) })

View File

@ -1,11 +1,12 @@
<template> <template>
<el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card"> <el-card shadow="always" class="common-card-container common-card-container-body-no-padding time-range-card">
<div slot="header" class="time-range-header"> <div slot="header" class="time-range-header">
<span class="card-title">一周充放曲线</span> <span class="card-title">一周充放曲线</span>
<date-range-select ref="dateRangeSelect" :showIcon="true" :mini-time-picker="true" @updateDate="updateDate"/> <date-range-select ref="dateRangeSelect" @updateDate="updateDate"/>
</div> </div>
<div style="height: 310px" id="weekChart"></div> <div style="height: 310px" id="weekChart"></div>
</el-card> </el-card>
</template> </template>
<script> <script>
@ -13,15 +14,14 @@ 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 {getSevenChargeData} from '@/api/ems/dzjk'
export default { export default {
mixins: [resize], mixins: [resize],
components: {DateRangeSelect}, components: {DateRangeSelect},
data() { data() {
return { return {
chart: null, chart: null,
timeRange: [], timeRange:[],
siteId: '', siteId:'',
} }
}, },
mounted() { mounted() {
@ -38,40 +38,41 @@ export default {
}, },
methods: { methods: {
// 更新时间范围 重置图表 // 更新时间范围 重置图表
updateDate(data) { updateDate(data){
this.timeRange = data this.timeRange=data
this.getWeekKData() this.getWeekKData()
}, },
getWeekKData() { getWeekKData(){
this.showLoading() this.showLoading()
const {siteId, timeRange} = this const {siteId,timeRange}=this
getSevenChargeData({siteId, startDate: timeRange[0], endDate: timeRange[1]}).then(response => { this.hideLoading()
getSevenChargeData({siteId,startDate:timeRange[0],endDate:timeRange[1]}).then(response => {
this.setOption(response?.data || []) this.setOption(response?.data || [])
}).finally(() => this.hideLoading()) }).finally(()=>this.hideLoading())
}, },
init(siteId) { init(siteId){
//初始化 清空数据 //初始化 清空数据
this.siteId = siteId this.siteId = siteId
this.timeRange = [] this.timeRange=[]
this.deviceId = '' this.deviceId=''
this.$refs.dateRangeSelect.init() this.$refs.dateRangeSelect.init()
}, },
initChart() { initChart() {
this.chart = echarts.init(document.querySelector('#weekChart')) this.chart = echarts.init(document.querySelector('#weekChart'))
}, },
showLoading() { showLoading(){
this.chart && this.chart.showLoading() this.chart && this.chart.showLoading()
}, },
hideLoading() { hideLoading(){
this.chart && this.chart.hideLoading() this.chart && this.chart.hideLoading()
}, },
setOption(data, unit) { setOption(data,unit) {
const source = [['日期', '充电量', '放电量']] const source = [['日期','充电量','放电量']]
data.forEach(item => { data.forEach(item=>{
source.push([item.ammeterDate, item.chargedCap, item.disChargedCap]) source.push([item.ammeterDate, item.chargedCap,item.disChargedCap])
}) })
this.chart && this.chart.setOption({ this.chart && this.chart.setOption({
color: ['#4472c4', '#70ad47'],//所有充放电颜色保持统一 color:['#4472c4','#70ad47'],//所有充放电颜色保持统一
tooltip: { tooltip: {
trigger: 'axis', trigger: 'axis',
axisPointer: { // 坐标轴指示器,坐标轴触发有效 axisPointer: { // 坐标轴指示器,坐标轴触发有效
@ -87,29 +88,29 @@ export default {
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
name: unit, name:unit,
nameLocation: 'center' nameLocation:'center'
}, },
yAxis: [{ yAxis: [{
type: 'value', type: 'value',
name: '充电量/放电量kWh', name:'充电量/放电量kWh',
axisLine: { axisLine: {
lineStyle: { lineStyle:{
color: '#333333', color: '#333333',
}, },
onZero: false onZero:false
} }
}], }],
dataset: { dataset:{
source source
}, },
series: [ series: [
{ {
yAxisIndex: 0, yAxisIndex:0,
type: 'bar', type: 'bar',
}, },
{ {
yAxisIndex: 0, yAxisIndex:0,
type: 'bar', type: 'bar',
}, },
] ]

View File

@ -1,164 +1,133 @@
<template> <template>
<div v-loading="loading"> <div
class="ems-dashboard-editor-container ems-content-container-padding"
v-loading="loading"
>
<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 v-if="tableData.length > 0" :xs="24" :sm="24" :lg="24">
<!-- 站点信息--> <alarm-table :tableData="tableData" />
</el-col>
<el-col :xs="24" :sm="24" :lg="6">
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container common-card-container-body-no-padding" class="common-card-container common-card-container-body-no-padding"
> >
<div slot="header"> <div slot="header">
<span class="card-title">站点信息</span> <span class="card-title">站点信息</span>
<div class="alarm-msg" v-if="tableData.length > 0" @click="toAlarm">
<i class="el-icon-message-solid"></i> 设备告警
</div>
</div> </div>
<div <div
style="box-sizing: border-box; height: 218px; padding: 20px 15px" style="box-sizing: border-box; height: 250px; padding: 20px 15px"
> >
<!-- 地址运行时间--> <el-descriptions class="home-normal-info" :column="1">
<div class="site-info site-info-address"> <el-descriptions-item
<div class="title"> size="mini"
<i class="el-icon-location"></i> v-for="(item, index) in singleZdInfo"
</div> :key="index + 'singleZdInfo'"
<div class="value">{{ info.siteAddress }}</div> :label="item.title"
</div> >{{ info[item.attr] | formatNumber }}</el-descriptions-item
<div class="site-info">
<div class="title">
<i class="el-icon-date"></i>
</div>
<div class="value">{{ info.runningTime || '-' }}</div>
</div>
<!-- 装机功率容量 -->
<el-row :gutter="10" style="margin-top:20px;">
<el-col
:span="12"
class="sjgl-col power-col"
> >
<div class="sjgl-wrapper"> </el-descriptions>
<div class="sjgl-title">装机功率(MW)</div>
<div class="sjgl-value">
{{ info.installPower | formatNumber }}
</div>
</div>
</el-col>
<el-col
:span="12"
class="sjgl-col power-col"
>
<div class="sjgl-wrapper">
<div class="sjgl-title">装机容量(MW)</div>
<div class="sjgl-value">
{{ info.installCapacity | formatNumber }}
</div>
</div>
</el-col>
</el-row>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<!-- 总累计运行数据--> <el-col :xs="24" :sm="24" :lg="8">
<el-col :xs="24" :sm="24" :lg="19">
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container common-card-container-body-no-padding" class="common-card-container common-card-container-body-no-padding"
> >
<div slot="header"> <div slot="header">
<span class="card-title">总累计运行数据</span> <span class="card-title">总累计运行数据</span>
<div class="total-count">
<span class="title">总收入</span>
<span class="value">{{ runningInfo.totalRevenue | formatNumber }}</span>
<span class="unit"></span>
</div>
</div> </div>
<div <div
style="box-sizing: border-box; height: 218px; padding: 20px 15px" style="box-sizing: border-box; height: 250px; padding: 20px 15px"
> >
<el-row :gutter="10"> <el-row :gutter="20">
<el-col <el-col
:span="6" :span="12"
v-for="(item, index) in sjglData" v-for="(item, index) in sjglData"
:key="index + 'sjglData'" :key="index + 'sjglData'"
class="sjgl-col" class="sjgl-data"
> >
<div class="sjgl-wrapper"> <div class="sjgl-title">{{ item.title }}</div>
<div class="sjgl-title">{{ item.title }}</div> <div class="sjgl-value">
<div class="sjgl-value" :style="{color:item.color}"> {{ runningInfo[item.attr] | formatNumber }}
{{ runningInfo[item.attr] | formatNumber }}
</div>
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :xs="24" :sm="24" :lg="12"> <el-col :xs="24" :sm="24" :lg="10">
<week-chart ref="weekChart"/> <cl-info :info="runningInfo.strategyTempInfo" />
</el-col> </el-col>
<el-col :xs="24" :sm="24" :lg="12"> <el-col :xs="24" :sm="24" :lg="24">
<active-chart ref="activeChart"/> <week-chart ref="weekChart" />
</el-col>
<el-col :xs="24" :sm="24" :lg="24">
<active-chart ref="activeChart" />
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</template> </template>
<script> <script>
import {getSingleSiteBaseInfo} from "@/api/ems/zddt"; import { getSingleSiteBaseInfo } from "@/api/ems/zddt";
import {getDzjkHomeView} from "@/api/ems/dzjk"; import { getDzjkHomeView } 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";
import ClInfo from "./ClInfo.vue"; import ClInfo from "./ClInfo.vue";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
export default { export default {
name: "DzjkSbjkHome", name: "DzjkSbjkHome",
components: {WeekChart, ActiveChart, AlarmTable, ClInfo}, components: { WeekChart, ActiveChart, AlarmTable, ClInfo },
mixins: [getQuerySiteId, intervalUpdate], mixins: [getQuerySiteId, intervalUpdate],
data() { data() {
return { return {
loading: false, loading: false,
singleZdInfo: [
{
title: "电站位置",
attr: "siteAddress",
},
{
title: "投运时间",
attr: "runningTime",
},
{
title: "装机功率(MW)",
attr: "installPower",
},
{
title: "装机容量(MW)",
attr: "installCapacity",
},
],
sjglData: [ sjglData: [
{ {
title: "今日充电量kWh", title: "今日充电量kWh",
attr: "dayChargedCap", attr: "dayChargedCap",
color: '#4472c4'
}, },
{ {
title: "今日放电量kWh", title: "今日放电量kWh",
attr: "dayDisChargedCap", attr: "dayDisChargedCap",
color: '#70ad47'
}, },
{ {
title: "总充电量kWh", title: "总充电量kWh",
attr: "totalChargedCap", attr: "totalChargedCap",
color: '#4472c4'
},
{
title: "今日实时收入(元)",
attr: "dayRevenue",
color: '#f67438'
},
{
title: "昨日充电量kWh",
attr: "yesterdayChargedCap",
color: '#4472c4'
},
{
title: "昨日放电量kWh",
attr: "yesterdayDisChargedCap",
color: '#70ad47'
}, },
{ {
title: "总放电量kWh", title: "总放电量kWh",
attr: "totalDischargedCap", attr: "totalDischargedCap",
color: '#70ad47'
}, },
{ {
title: "昨日实时收入(元)", title: "收入(元)",
attr: "yesterdayRevenue", attr: "totalRevenue",
color: '#f67438' },
{
title: "当日实时收入(元)",
attr: "dayRevenue",
}, },
], ],
info: {}, //基本信息 info: {}, //基本信息
@ -167,13 +136,14 @@ export default {
}, },
computed: { computed: {
tableData() { tableData() {
console.log(
"this.runningInfo?.siteMonitorHomeAlarmVo ",
this.runningInfo?.siteMonitorHomeAlarmVo
);
return this.runningInfo?.siteMonitorHomeAlarmVo || []; return this.runningInfo?.siteMonitorHomeAlarmVo || [];
}, },
}, },
methods: { methods: {
toAlarm() {
this.$router.push({path: "/dzjk/gzgj", query: this.$route.query});
},
getBaseInfo() { getBaseInfo() {
return getSingleSiteBaseInfo(this.siteId).then((response) => { return getSingleSiteBaseInfo(this.siteId).then((response) => {
this.info = response?.data || {}; this.info = response?.data || {};
@ -203,73 +173,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
//设备告警
.alarm-msg {
background: #ff4949;
padding: 2px 5px;
font-size: 10px;
font-weight: bolder;
border-radius: 3px;
line-height: 20px;
cursor: pointer;
color: #fff;
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
//基本信息-地址 运行️时间
.site-info {
display: flex;
font-size: 12px;
line-height: 20px;
margin-bottom: 10px;
align-items: center;
&.site-info-address {
height: 40px;
}
.title {
color: #1791ff;
font-size: 18px;
line-height: 20px;
margin-right: 7px;
}
.value {
color: #000;
font-size: 12px;
max-height: 40px;
overflow: hidden;
}
}
//总收入
.total-count {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
font-size: 12px;
font-weight: bolder;
color: #333;
line-height: 14px;
.unit {
font-style: italic;
}
.value {
font-size: 22px;
font-weight: bolder;
color: #ed2f1d;
font-style: italic;
padding: 0 5px;
}
}
.row-container { .row-container {
& > .el-col { & > .el-col {
margin-bottom: 20px; margin-bottom: 20px;
@ -277,47 +180,25 @@ export default {
} }
//数据概览 //数据概览
.sjgl-col { .sjgl-data {
.sjgl-wrapper { text-align: center;
text-align: left; &:nth-child(1),
padding: 15px 20px;
background-color: #f2f7fb;
}
&.power-col {
.sjgl-wrapper {
padding: 10px;
.sjgl-value {
color: #c44444;
}
}
}
&:nth-child(4),
&:nth-child(2), &:nth-child(2),
&:nth-child(3), &:nth-child(3),
&:nth-child(4) { &:nth-child(4) {
margin-bottom: 10px; margin-bottom: 25px;
} }
.sjgl-title { .sjgl-title {
color: #717171; color: #666666;
line-height: 14px; line-height: 14px;
font-weight: bold;
} }
.sjgl-value { .sjgl-value {
color: rgba(51, 51, 51, 1); color: rgba(51, 51, 51, 1);
font-size: 22px; font-size: 26px;
line-height: 26px; line-height: 26px;
font-weight: bolder; font-weight: 500;
font-style: italic;
margin-top: 14px; margin-top: 14px;
width: 100%; word-wrap: break-word;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
} }
} }
</style> </style>
@ -325,12 +206,10 @@ export default {
<style lang="scss"> <style lang="scss">
.home-normal-info { .home-normal-info {
font-size: 12px; font-size: 12px;
.el-descriptions-item__container { .el-descriptions-item__container {
.el-descriptions-item__label { .el-descriptions-item__label {
color: #666666; color: #666666;
} }
.el-descriptions-item__content { .el-descriptions-item__content {
color: #333333; color: #333333;
} }

View File

@ -3,12 +3,13 @@
<div v-for="(baseInfo,index) in baseInfoList" :key="index+'bmsdccContainer'" style="margin-bottom:25px;"> <div v-for="(baseInfo,index) in baseInfoList" :key="index+'bmsdccContainer'" style="margin-bottom:25px;">
<el-card shadow="always" <el-card shadow="always"
class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg" class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
:class="handleCardClass(baseInfo)"> :class="{
'warning-card-container':baseInfo.workStatus && baseInfo.workStatus !== '0',
'running-card-container':baseInfo.workStatus === '0'
}">
<div slot="header"> <div slot="header">
<span <span
class="large-title">{{ class="large-title">{{ baseInfo.parentDeviceName ? `${baseInfo.parentDeviceName} -> ` : '' }}{{ baseInfo.deviceName }}</span>
baseInfo.parentDeviceName ? `${baseInfo.parentDeviceName} -> ` : ''
}}{{ baseInfo.deviceName }}</span>
<div class="info"> <div class="info">
<div>数据更新时间{{ baseInfo.dataUpdateTime || '-' }}</div> <div>数据更新时间{{ baseInfo.dataUpdateTime || '-' }}</div>
</div> </div>
@ -16,7 +17,7 @@
<el-button type="primary" round size="small" style="margin-right:20px;" <el-button type="primary" round size="small" style="margin-right:20px;"
@click="pointDetail(baseInfo,'point')">详细 @click="pointDetail(baseInfo,'point')">详细
</el-button> </el-button>
<el-badge :hidden="!baseInfo.alarmNum" :value="baseInfo.alarmNum || 0" class="item"> <el-badge :value="baseInfo.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(baseInfo,'alarmPoint')" @click="pointDetail(baseInfo,'alarmPoint')"
@ -26,16 +27,16 @@
</div> </div>
<div class="descriptions-main"> <div class="descriptions-main">
<el-descriptions direction="vertical" :column="3" :colon="false"> <el-descriptions direction="vertical" :column="3" :colon="false">
<el-descriptions-item <el-descriptions-item labelClassName="descriptions-label"
contentClassName="descriptions-direction work-status" :contentClassName="`descriptions-direction ${baseInfo.workStatus === '0' ? 'save' :'danger'}`"
:span="1" label="工作状态"> :span="1" label="工作状态">
{{ CLUSTERWorkStatusOptions[baseInfo.workStatus] }} {{ $store.state.ems.workStatusOptions[baseInfo.workStatus] }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item contentClassName="descriptions-direction" <el-descriptions-item labelClassName="descriptions-label" contentClassName="descriptions-direction"
:span="1" label="与PCS通信"> :span="1" label="与PCS通信">
{{ $store.state.ems.communicationStatusOptions[baseInfo.pcsCommunicationStatus] }} {{ $store.state.ems.communicationStatusOptions[baseInfo.pcsCommunicationStatus] }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item contentClassName="descriptions-direction" <el-descriptions-item labelClassName="descriptions-label" contentClassName="descriptions-direction"
:span="1" label="与EMS通信"> :span="1" label="与EMS通信">
{{ $store.state.ems.communicationStatusOptions[baseInfo.emsCommunicationStatus] }} {{ $store.state.ems.communicationStatusOptions[baseInfo.emsCommunicationStatus] }}
</el-descriptions-item> </el-descriptions-item>
@ -79,9 +80,7 @@
> >
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ @click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ scope.row.avgData }}</span>
scope.row.avgData
}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -89,9 +88,7 @@
label="单体最小值"> label="单体最小值">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ @click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ scope.row.minData }}</span>
scope.row.minData
}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -103,9 +100,7 @@
label="单体最大值"> label="单体最大值">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer " <span class="pointer "
@click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ @click="showChart( tablePointNameMap[scope.row.dataName+scope.column.label],baseInfo.deviceId)">{{ scope.row.maxData }}</span>
scope.row.maxData
}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -128,17 +123,11 @@ import PointTable from "@/views/ems/site/sblb/PointTable.vue";
import {getBMSBatteryCluster} from '@/api/ems/dzjk' import {getBMSBatteryCluster} from '@/api/ems/dzjk'
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
import {mapState} from "vuex";
export default { export default {
name: 'DzjkSbjkBmsdcc', name: 'DzjkSbjkBmsdcc',
mixins: [getQuerySiteId, intervalUpdate], mixins: [getQuerySiteId, intervalUpdate],
components: {PointTable, pointChart}, components: {PointTable, pointChart},
computed: {
...mapState({
CLUSTERWorkStatusOptions: state => state?.ems?.CLUSTERWorkStatusOptions || {},
})
},
data() { data() {
return { return {
loading: false, loading: false,
@ -173,10 +162,6 @@ export default {
} }
}, },
methods: { methods: {
handleCardClass(item) {
const {workStatus = ''} = item
return !(Object.keys(this.CLUSTERWorkStatusOptions).includes(item.workStatus)) ? "timing-card-container" : workStatus === '9' ? 'warning-card-container' : 'running-card-container'
},
// 查看设备电位表格 // 查看设备电位表格
pointDetail(row, dataType) { pointDetail(row, dataType) {
const {siteId, deviceId} = row const {siteId, deviceId} = row

View File

@ -1,10 +1,11 @@
<template> <template>
<div v-loading="loading"> <div v-loading="loading">
<div v-for="(baseInfo,index) in baseInfoList" :key="index+'bmszlContainer'" style="margin-bottom:25px;"> <div v-for="(baseInfo,index) in baseInfoList" :key="index+'bmszlContainer'" style="margin-bottom:25px;">
<el-card <el-card :class="{
:class="handleCardClass(baseInfo)" 'warning-card-container':baseInfo.workStatus && baseInfo.workStatus !== '0',
class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg" 'running-card-container':baseInfo.workStatus === '0'
shadow="always"> }" class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
shadow="always">
<div slot="header"> <div slot="header">
<span class="large-title">{{ baseInfo.deviceName }}</span> <span class="large-title">{{ baseInfo.deviceName }}</span>
<div class="info"> <div class="info">
@ -14,7 +15,7 @@
<el-button type="primary" round size="small" style="margin-right:20px;" <el-button type="primary" round size="small" style="margin-right:20px;"
@click="pointDetail(baseInfo,'point')">详细 @click="pointDetail(baseInfo,'point')">详细
</el-button> </el-button>
<el-badge :hidden="!baseInfo.alarmNum" :value="baseInfo.alarmNum || 0" class="item"> <el-badge :value="baseInfo.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(baseInfo,'alarmPoint')" @click="pointDetail(baseInfo,'alarmPoint')"
@ -25,9 +26,9 @@
<div class="descriptions-main"> <div class="descriptions-main">
<el-descriptions :colon="false" :column="3" direction="vertical"> <el-descriptions :colon="false" :column="3" direction="vertical">
<el-descriptions-item <el-descriptions-item
contentClassName="descriptions-direction work-status" :contentClassName="`descriptions-direction ${baseInfo.workStatus === '0' ? 'save' :'danger'}`" :span="1"
label="工作状态" labelClassName="descriptions-label"> label="工作状态" labelClassName="descriptions-label">
{{ STACKWorkStatusOptions[baseInfo.workStatus] }} {{ $store.state.ems.workStatusOptions[baseInfo.workStatus] }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item :span="1" contentClassName="descriptions-direction" label="与PCS通信" <el-descriptions-item :span="1" contentClassName="descriptions-direction" label="与PCS通信"
labelClassName="descriptions-label"> labelClassName="descriptions-label">
@ -96,9 +97,7 @@
prop="maxVoltage"> prop="maxVoltage">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart('最高单体电压',scope.row.clusterId,'CLUSTER')">{{ @click="showChart('最高单体电压',scope.row.clusterId,'CLUSTER')">{{ scope.row.maxCellVoltage }} V</span>
scope.row.maxCellVoltage
}} V</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -110,9 +109,7 @@
prop="minVoltage"> prop="minVoltage">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart('最低单体电压',scope.row.clusterId,'CLUSTER')">{{ @click="showChart('最低单体电压',scope.row.clusterId,'CLUSTER')">{{ scope.row.minCellVoltage }} V</span>
scope.row.minCellVoltage
}} V</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -123,9 +120,7 @@
label="单体最高温度"> label="单体最高温度">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart('最高单体温度',scope.row.clusterId,'CLUSTER')">{{ @click="showChart('最高单体温度',scope.row.clusterId,'CLUSTER')">{{ scope.row.maxCellTemp }} &#8451;</span>
scope.row.maxCellTemp
}} &#8451;</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -137,9 +132,7 @@
prop="minTemperature"> prop="minTemperature">
<template slot-scope="scope"> <template slot-scope="scope">
<span class="pointer" <span class="pointer"
@click="showChart('最低单体温度',scope.row.clusterId,'CLUSTER')">{{ @click="showChart('最低单体温度',scope.row.clusterId,'CLUSTER')">{{ scope.row.minCellTemp }} &#8451;</span>
scope.row.minCellTemp
}} &#8451;</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -162,17 +155,11 @@ import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
import pointChart from "./../PointChart.vue"; import pointChart from "./../PointChart.vue";
import PointTable from "@/views/ems/site/sblb/PointTable.vue"; import PointTable from "@/views/ems/site/sblb/PointTable.vue";
import {mapState} from "vuex";
export default { export default {
name: 'DzjkSbjkBmszl', name: 'DzjkSbjkBmszl',
components: {pointChart, PointTable}, components: {pointChart, PointTable},
mixins: [getQuerySiteId, intervalUpdate], mixins: [getQuerySiteId, intervalUpdate],
computed: {
...mapState({
STACKWorkStatusOptions: state => state?.ems?.STACKWorkStatusOptions || {},
})
},
data() { data() {
return { return {
loading: false, loading: false,
@ -191,11 +178,6 @@ export default {
} }
}, },
methods: { methods: {
handleCardClass(item) {
const {workStatus = ''} = item
return !Object.keys(this.STACKWorkStatusOptions).find(i => i === workStatus) ? "timing-card-container" : workStatus === '9' ? 'warning-card-container' : 'running-card-container'
},
// 查看设备电位表格 // 查看设备电位表格
pointDetail(row, dataType) { pointDetail(row, dataType) {
const {siteId, deviceId} = row const {siteId, deviceId} = row

View File

@ -6,8 +6,7 @@
shadow="always" shadow="always"
class="sbjk-card-container list" class="sbjk-card-container list"
:class="{ :class="{
'timing-card-container':!['0','2'].includes(item.emsCommunicationStatus), 'warning-card-container':item.emsCommunicationStatus && item.emsCommunicationStatus !== '0',
'warning-card-container':item.emsCommunicationStatus === '2',
'running-card-container':item.emsCommunicationStatus === '0' 'running-card-container':item.emsCommunicationStatus === '0'
}" }"
> >
@ -16,16 +15,18 @@
<div class="info"> <div class="info">
<div> <div>
{{ {{
communicationStatusOptions[item.emsCommunicationStatus] || '-' $store.state.ems.communicationStatusOptions[
item.emsCommunicationStatus
]
}} }}
</div> </div>
<div>数据更新时间{{ item.dataUpdateTime || '-' }}</div> <div>数据更新时间{{ item.dataUpdateTime }}</div>
</div> </div>
<div class="alarm"> <div class="alarm">
<el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')"> <el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">
详细 详细
</el-button> </el-button>
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item"> <el-badge :value="item.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(item,'alarmPoint')" @click="pointDetail(item,'alarmPoint')"
@ -34,11 +35,10 @@
</div> </div>
</div> </div>
<el-row class="device-info-row"> <el-row class="device-info-row">
<el-col v-for="(tempDataItem,tempDataIndex) in (deviceIdTypeMsg[item.deviceId] || otherTypeMsg)" <el-col v-for="(tempDataItem,tempDataIndex) in deviceIdTypeMsg[item.deviceId]" :key="tempDataIndex+'dbTempData'"
:key="tempDataIndex+'dbTempData'"
:span="8" class="device-info-col"> :span="8" class="device-info-col">
<span class="pointer" @click="showChart(tempDataItem.pointName,item.deviceId)"> <span class="pointer" @click="showChart(tempDataItem.pointName,item.deviceId)">
<span class="left">{{ tempDataItem.name }}</span> <span class="right">{{ item[tempDataItem.attr] || '-' }}<span <span class="left">{{ tempDataItem.name }}</span> <span class="right">{{ item[tempDataItem.attr] }}<span
v-html="tempDataItem.unit"></span></span> v-html="tempDataItem.unit"></span></span>
</span> </span>
</el-col> </el-col>
@ -56,18 +56,11 @@ import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getAmmeterDataList} from "@/api/ems/dzjk"; import {getAmmeterDataList} from "@/api/ems/dzjk";
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
import PointTable from "@/views/ems/site/sblb/PointTable.vue"; import PointTable from "@/views/ems/site/sblb/PointTable.vue";
import {mapState} from "vuex";
export default { export default {
name: "DzjkSbjkDb", name: "DzjkSbjkDb",
mixins: [getQuerySiteId, intervalUpdate], mixins: [getQuerySiteId, intervalUpdate],
components: {PointTable, pointChart}, components: {PointTable, pointChart},
computed: {
...mapState({
communicationStatusOptions: state => state?.ems?.communicationStatusOptions || {},
})
},
data() { data() {
return { return {
loading: false, loading: false,
@ -77,125 +70,89 @@ export default {
{ {
name: '正向有功电能', name: '正向有功电能',
attr: 'forwardActive', attr: 'forwardActive',
pointName: '正向有功电能', pointName: '正向有功电能'
unit: 'kWh'
}, },
{ {
name: '反向有功电能', name: '反向有功电能',
attr: 'reverseActive', attr: 'reverseActive',
pointName: '反向有功电能', pointName: '反向有功电能'
unit: 'kWh'
}, },
{ {
name: '正向无功电能', name: '正向无功电能',
attr: 'forwardReactive', attr: 'forwardReactive',
pointName: '正向无功电能', pointName: '正向无功电能'
unit: 'kvarh'
}, },
{ {
name: '反向无功电能', name: '反向无功电能',
attr: 'reverseReactive', attr: 'reverseReactive',
pointName: '反向无功电能', pointName: '反向无功电能'
unit: 'kvarh'
}, },
{ {
name: '有功功率', name: '有功功率',
attr: 'activePower', attr: 'activePower',
pointName: '总有功功率', pointName: '总有功功率'
unit: 'kW'
}, },
{ {
name: '无功功率', name: '无功功率',
attr: 'reactivePower', attr: 'reactivePower',
pointName: '总无功功率', pointName: '总无功功率'
unit: 'kvar'
} }
], ],
'METE': [ 'METE': [
{ {
name: '正向有功电能', name: '正向有功电能',
attr: 'forwardActive', attr: 'forwardActive',
pointName: '正向有功电能', pointName: '正向有功电能'
unit: 'kWh'
}, },
{ {
name: '反向有功电能', name: '反向有功电能',
attr: 'reverseActive', attr: 'reverseActive',
pointName: '反向有功电能', pointName: '反向有功电能'
unit: 'kWh'
}, },
{ {
name: '正向无功电能', name: '正向无功电能',
attr: 'forwardReactive', attr: 'forwardReactive',
pointName: '正向无功电能', pointName: '正向无功电能'
unit: 'kvarh'
}, },
{ {
name: '反向无功电能', name: '反向无功电能',
attr: 'reverseReactive', attr: 'reverseReactive',
pointName: '反向无功电能', pointName: '反向无功电能'
unit: 'kvarh'
}, },
{ {
name: '有功功率', name: '有功功率',
attr: 'activePower', attr: 'activePower',
pointName: '总有功功率', pointName: '总有功功率'
unit: 'kW'
}, },
{ {
name: '无功功率', name: '无功功率',
attr: 'reactivePower', attr: 'reactivePower',
pointName: '总无功功率', pointName: '总无功功率'
unit: 'kvar'
} }
], ],
'METEGF': [ 'METEGF': [
{ {
name: '有功电能', name: '有功电能',
attr: 'activeEnergy', attr: 'activeEnergy',
pointName: '有功电能', pointName: '有功电能'
unit: 'kWh'
}, },
{ {
name: '无功电能', name: '无功电能',
attr: 'reactiveEnergy', attr: 'reactiveEnergy',
pointName: '无功电能', pointName: '无功电能'
unit: 'kvarh'
}, },
{ {
name: '有功功率', name: '有功功率',
attr: 'activePower', attr: 'activePower',
pointName: '总有功功率', pointName: '总有功功率'
unit: 'kW'
}, },
{ {
name: '无功功率', name: '无功功率',
attr: 'reactivePower', attr: 'reactivePower',
pointName: '总无功功率', pointName: '总无功功率'
unit: 'kvar'
} }
] ]
}, }
otherTypeMsg: [
{
name: '正向有功电能',
attr: 'forwardActive',
pointName: '正向有功电能',
unit: 'kWh'
},
{
name: '反向有功电能',
attr: 'reverseActive',
pointName: '反向有功电能',
unit: 'kWh'
},
{
name: '有功功率',
attr: 'activePower',
pointName: '总有功功率',
unit: 'kW'
},
]
}; };
}, },
methods: { methods: {

View File

@ -14,7 +14,7 @@
<el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')"> <el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">
详细 详细
</el-button> </el-button>
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item"> <el-badge :value="item.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(item,'alarmPoint')" @click="pointDetail(item,'alarmPoint')"
@ -26,8 +26,7 @@
<el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'hdTempData'" :span="12" <el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'hdTempData'" :span="12"
class="device-info-col"> class="device-info-col">
<span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)"> <span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)">
<span class="left">{{ tempDataItem.title }}</span> <span <span class="left">{{ tempDataItem.title }}</span> <span class="right">{{ item[tempDataItem.attr] }}<span
class="right">{{ item[tempDataItem.attr] || '-' }}<span
v-html="tempDataItem.unit"></span></span> v-html="tempDataItem.unit"></span></span>
</span> </span>
</el-col> </el-col>

View File

@ -1,5 +1,206 @@
<template> <template>
<div v-loading="loading" class="ems"> <div v-loading="loading" class="ems">
<!-- <div-->
<!-- v-for="(item, index) in list"-->
<!-- :key="index + 'PcsHome'"-->
<!-- style="margin-bottom: 25px"-->
<!-- >-->
<!-- <el-card-->
<!-- :class="{-->
<!-- 'warning-card-container': item.workStatus === '1',-->
<!-- 'timing-card-container': item.workStatus === '2',-->
<!-- 'running-card-container': !['1', '2'].includes(item.workStatus),-->
<!-- }"-->
<!-- class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"-->
<!-- shadow="always"-->
<!-- >-->
<!-- &lt;!&ndash; 标题&ndash;&gt;-->
<!-- <div slot="header">-->
<!-- <span class="large-title"-->
<!-- >{{ item.deviceName }}</span-->
<!-- >-->
<!-- <div class="info">-->
<!-- <div>-->
<!-- {{-->
<!-- $store.state.ems.workStatusOptions[item.workStatus]-->
<!-- }}-->
<!-- </div>-->
<!-- <div>数据更新时间{{ item.dataUpdateTime }}</div>-->
<!-- </div>-->
<!-- <div class="alarm">-->
<!-- <el-button type="primary" size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">-->
<!-- 详细-->
<!-- </el-button>-->
<!-- <el-badge :value="item.alarmNum || 0" class="item">-->
<!-- <i-->
<!-- class="el-icon-message-solid alarm-icon"-->
<!-- @click="pointDetail(item,'alarmPoint')"-->
<!-- ></i>-->
<!-- </el-badge>-->
<!-- </div>-->
<!-- </div>-->
<!-- &lt;!&ndash; 工作状态&ndash;&gt;-->
<!-- <div class="descriptions-main">-->
<!-- <el-descriptions :colon="false" :column="5" direction="vertical">-->
<!-- <el-descriptions-item-->
<!-- :contentClassName="`descriptions-direction ${-->
<!-- item.workStatus === '0' ? 'save' : 'danger'-->
<!-- }`"-->
<!-- :span="1"-->
<!-- label="工作状态"-->
<!-- labelClassName="descriptions-label"-->
<!-- >{{-->
<!-- $store.state.ems.workStatusOptions[item.workStatus]-->
<!-- }}-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="工作模式"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- todo 手动/自动-->
<!-- {{-->
<!-- $store.state.ems.gridStatusOptions[item.gridStatus]-->
<!-- }}-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="并网状态"-->
<!-- labelClassName="descriptions-label"-->
<!-- >{{-->
<!-- $store.state.ems.gridStatusOptions[item.gridStatus]-->
<!-- }}-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="告警状态"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- todo-->
<!-- &lt;!&ndash;-->
<!-- {{-->
<!-- $store.state.ems.warnOptions[item.warnMode]-->
<!-- }}&ndash;&gt;-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :contentClassName="`descriptions-direction ${-->
<!-- item.deviceStatus === '2' ? 'save' : 'danger'-->
<!-- }`"-->
<!-- :span="1"-->
<!-- label="设备状态"-->
<!-- labelClassName="descriptions-label"-->
<!-- >{{-->
<!-- $store.state.ems.deviceStatusOptions[item.deviceStatus]-->
<!-- }}-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- </el-descriptions>-->
<!-- </div>-->
<!-- &lt;!&ndash; 用电量&ndash;&gt;-->
<!-- <div class="descriptions-main descriptions-main-bg-color">-->
<!-- <el-descriptions :colon="false" :column="5" direction="vertical">-->
<!-- <el-descriptions-item-->
<!-- :span="5"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="当日用电量:"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="电网用电量"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="储能放电量"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="储能充电量"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="负荷用电量"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- <el-descriptions-item-->
<!-- :span="1"-->
<!-- contentClassName="descriptions-direction"-->
<!-- label="光伏发电量"-->
<!-- labelClassName="descriptions-label"-->
<!-- >-->
<!-- </el-descriptions-item-->
<!-- >-->
<!-- </el-descriptions>-->
<!-- </div>-->
<!-- &lt;!&ndash; 表格&ndash;&gt;-->
<!-- <el-table-->
<!-- class="common-table"-->
<!-- stripe-->
<!-- style="width: 100%;margin-top:25px;">-->
<!-- <el-table-column-->
<!-- label="功率"-->
<!-- prop="type">-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="电网"-->
<!-- >-->
<!-- <template slot-scope="scope">-->
<!-- <span class="pointer"-->
<!-- @click="showChart('簇电压',scope.row.clusterId)">{{ scope.row.clusterVoltage }} V</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="储能">-->
<!-- <template slot-scope="scope">-->
<!-- <span class="pointer"-->
<!-- @click="showChart('簇电流',scope.row.clusterId)">{{ scope.row.clusterCurrent }} A</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="负荷">-->
<!-- <template slot-scope="scope">-->
<!-- <span class="pointer"-->
<!-- @click="showChart('簇电流',scope.row.clusterId)">{{ scope.row.clusterCurrent }} A</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column-->
<!-- label="光伏">-->
<!-- <template slot-scope="scope">-->
<!-- <span class="pointer"-->
<!-- @click="showChart('当前SOC',scope.row.clusterId)">{{ scope.row.currentSoc }} %</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- </el-table>-->
<!-- &lt;!&ndash; 图表&ndash;&gt;-->
<!-- <div id="emsChart" style="height: 350px"></div>-->
<!-- </el-card>-->
<!-- </div>-->
<el-card <el-card
v-for="(item,index) in list" v-for="(item,index) in list"
:key="index+'emsList'" :key="index+'emsList'"
@ -19,7 +220,7 @@
<div class="alarm"> <div class="alarm">
<el-button size="small" round style="margin-right:20px;" type="primary" @click="pointDetail(item,'point')">详细 <el-button size="small" round style="margin-right:20px;" type="primary" @click="pointDetail(item,'point')">详细
</el-button> </el-button>
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item"> <el-badge :value="item.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(item,'alarmPoint')" @click="pointDetail(item,'alarmPoint')"

View File

@ -19,14 +19,13 @@
</keep-alive> </keep-alive>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import { dzjk } from '@/router/ems' import { dzjk } from '@/router/ems'
import {mapState} from "vuex"; import {mapState} from "vuex";
const childrenRoute = dzjk[0].children[0].children.find(item=> item.name==='DzjkSbjk').children//获取到单站监控-设备监控下面的字路由 const childrenRoute = ((dzjk[0]?.children || []).find(item=> item.name==='DzjkSbjk').children) || []//获取到单站监控-设备监控下面的字路由
export default { export default {
name:'DzjkSbjk', name:'DzjkSbjk',
mixins:[getQuerySiteId], mixins:[getQuerySiteId],
@ -65,11 +64,14 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.sbjk-ems-content-container{ .sbjk-ems-dashboard-editor-container {
margin-top:0; display: flex;
padding-top:0; background: #ffffff;
}
.sbjk-ems-content-container {
margin-top: 0;
padding-top: 0;
padding-right: 0; padding-right: 0;
flex: 1; flex: 1;
} }
</style> </style>

View File

@ -8,7 +8,11 @@
style="margin-bottom: 25px" style="margin-bottom: 25px"
> >
<el-card <el-card
:class="handleCardClass(pcsItem)" :class="{
'warning-card-container': pcsItem.workStatus === '1',
'timing-card-container': pcsItem.workStatus === '2',
'running-card-container': !['1', '2'].includes(pcsItem.workStatus),
}"
class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg" class="sbjk-card-container common-card-container-body-no-padding common-card-container-no-title-bg"
shadow="always" shadow="always"
> >
@ -27,11 +31,17 @@
<div>数据更新时间{{ pcsItem.dataUpdateTime }}</div> <div>数据更新时间{{ pcsItem.dataUpdateTime }}</div>
</div> </div>
<div class="alarm"> <div class="alarm">
<pcs-switch style="margin-right:10px;"
:round="true"
size="small"
type="danger"
:data="pcsItem"
@updateSuccess="init"/>
<el-button type="primary" round size="small" style="margin-right:20px;" <el-button type="primary" round size="small" style="margin-right:20px;"
@click="pointDetail(pcsItem,'point')"> @click="pointDetail(pcsItem,'point')">
详细 详细
</el-button> </el-button>
<el-badge :hidden="!pcsItem.alarmNum" :value="pcsItem.alarmNum || 0" class="item"> <el-badge :value="pcsItem.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(pcsItem,'alarmPoint')" @click="pointDetail(pcsItem,'alarmPoint')"
@ -42,12 +52,14 @@
<div class="descriptions-main"> <div class="descriptions-main">
<el-descriptions :colon="false" :column="4" direction="vertical"> <el-descriptions :colon="false" :column="4" direction="vertical">
<el-descriptions-item <el-descriptions-item
contentClassName="descriptions-direction work-status" :contentClassName="`descriptions-direction ${
pcsItem.workStatus === '0' ? 'save' : 'danger'
}`"
:span="1" :span="1"
label="工作状态" label="工作状态"
labelClassName="descriptions-label" labelClassName="descriptions-label"
>{{ >{{
PCSWorkStatusOptions[pcsItem.workStatus] $store.state.ems.workStatusOptions[pcsItem.workStatus]
}} }}
</el-descriptions-item </el-descriptions-item
> >
@ -63,7 +75,7 @@
> >
<el-descriptions-item <el-descriptions-item
:contentClassName="`descriptions-direction ${ :contentClassName="`descriptions-direction ${
pcsItem.deviceStatus === '1' ? 'save' : 'danger' pcsItem.deviceStatus === '2' ? 'save' : 'danger'
}`" }`"
:span="1" :span="1"
label="设备状态" label="设备状态"
@ -184,17 +196,12 @@ import RealTimeBaseInfo from "./../RealTimeBaseInfo.vue";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getPcsDetailInfo, getRunningHeadInfo} from "@/api/ems/dzjk"; import {getPcsDetailInfo, getRunningHeadInfo} from "@/api/ems/dzjk";
import intervalUpdate from "@/mixins/ems/intervalUpdate"; import intervalUpdate from "@/mixins/ems/intervalUpdate";
import {mapState} from "vuex"; import PcsSwitch from "@/views/ems/site/sblb/PcsSwitch.vue";
export default { export default {
name: "DzjkSbjkPcs", name: "DzjkSbjkPcs",
components: {RealTimeBaseInfo, pointChart, PointTable}, components: {RealTimeBaseInfo, pointChart, PointTable, PcsSwitch},
mixins: [getQuerySiteId, intervalUpdate], mixins: [getQuerySiteId, intervalUpdate],
computed: {
...mapState({
PCSWorkStatusOptions: state => state?.ems?.PCSWorkStatusOptions || {},
})
},
data() { data() {
return { return {
loading: false, loading: false,
@ -202,10 +209,10 @@ export default {
pcsList: [], pcsList: [],
infoData: [ infoData: [
{ {
label: "总交流有功率", label: "总交流有功率",
attr: "totalActivePower", attr: "totalActivePower",
unit: "kW", unit: "kW",
pointName: "总交流有功率", pointName: "总交流有功率",
}, },
{ {
label: "当天交流充电量", label: "当天交流充电量",
@ -221,10 +228,10 @@ export default {
pointName: "A相电流", pointName: "A相电流",
}, },
{ {
label: "总交流无功率", label: "总交流无功率",
attr: "totalReactivePower", attr: "totalReactivePower",
unit: "kVar", unit: "kVar",
pointName: "总交流无功率", pointName: "总交流无功率",
}, },
{ {
label: "当天交流放电量", label: "当天交流放电量",
@ -281,10 +288,6 @@ export default {
}; };
}, },
methods: { methods: {
handleCardClass(item) {
const {workStatus = ''} = item
return workStatus === '1' || !Object.keys(this.PCSWorkStatusOptions).find(i => i === workStatus) ? "timing-card-container" : workStatus === '2' ? 'warning-card-container' : 'running-card-container'
},
// 查看设备电位表格 // 查看设备电位表格
pointDetail(row, dataType) { pointDetail(row, dataType) {
const {deviceId} = row const {deviceId} = row

View File

@ -1,12 +1,12 @@
<template> <template>
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container common-card-container-body-no-padding" class="common-card-container common-card-container-body-no-padding"
> >
<div slot="header"> <div slot="header">
<span class="card-title">PCS有功功率/PCS无功功率</span> <span class="card-title">PCS有功功率/PCS无功功率</span>
</div> </div>
<div style="height: 360px" id="cnglqxChart"/> <div style="height: 360px" id="cnglqxChart" />
</el-card> </el-card>
</template> </template>
@ -14,7 +14,7 @@
<script> <script>
import * as echarts from "echarts"; import * as echarts from "echarts";
import resize from "@/mixins/ems/resize"; import resize from "@/mixins/ems/resize";
import {storagePower} from "@/api/ems/dzjk"; import { storagePower } from "@/api/ems/dzjk";
export default { export default {
mixins: [resize], mixins: [resize],
@ -36,56 +36,56 @@ export default {
methods: { methods: {
init(siteId, timeRange) { init(siteId, timeRange) {
this.chart.showLoading(); this.chart.showLoading();
const [startTime = '', endTime = ''] = timeRange; const [startTime='', endTime=''] = timeRange;
storagePower(siteId, startTime, endTime) storagePower(siteId,startTime,endTime)
.then((response) => { .then((response) => {
this.setOption(response?.data?.pcsPowerList || []); this.setOption(response?.data?.pcsPowerList || []);
}) })
.finally(() => { .finally(() => {
this.chart.hideLoading(); this.chart.hideLoading();
}); });
}, },
setOption(data) { setOption(data) {
let xdata = [], let xdata = [],
series = []; series = [];
data.forEach((element, index) => { data.forEach((element, index) => {
if (index === 0) { if (index === 0) {
xdata = (element.energyStoragePowList || []).map((i) => i.createDate); xdata = (element.energyStoragePowList || []).map((i) => i.createDate);
} }
series.push( series.push(
{ {
type: "line", type: "line",
name: `${element.deviceId}有功功率`, name: `${element.deviceId}有功功率`,
areaStyle: { areaStyle: {
// color:'#FFBD00' // color:'#FFBD00'
},
data: (element.energyStoragePowList || []).map(
(i) => {
return {
value: i.pcsTotalActPower,
year: i.dateDay || ''
}
}
)
}, },
{ data: (element.energyStoragePowList || []).map(
type: "line", (i) => {
name: `${element.deviceId}无功功率`, return {
areaStyle: { value:i.pcsTotalActPower,
// color:'#FFBD00' year:i.dateDay || ''
}, }
data: (element.energyStoragePowList || []).map( }
(i) => { )
return { },
value: i.pcsTotalReactivePower, {
year: i.dateDay || '' type: "line",
} name: `${element.deviceId}无功功率`,
} areaStyle: {
), // color:'#FFBD00'
} },
data: (element.energyStoragePowList || []).map(
(i) => {
return {
value: i.pcsTotalReactivePower,
year:i.dateDay || ''
}
}
),
}
); );
}); });
this.chart && this.chart.setOption({ this.chart.setOption({
legend: { legend: {
left: "center", left: "center",
top: "5", top: "5",
@ -99,29 +99,29 @@ export default {
containLabel: true, containLabel: true,
}, },
tooltip: { tooltip: {
show: true, show:true,
trigger: "axis", trigger: "axis",
axisPointer: { axisPointer: {
// 坐标轴指示器,坐标轴触发有效 // 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow' type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
}, },
formatter: (params) => { formatter :(params)=>{
if (params.length <= 0) return if(params.length <= 0) return
let result = (params[0].data.year || '') + ' ' + params[0].name + '<div>' let result = (params[0].data.year || '')+' '+ params[0].name + '<div>'
params.forEach(item => { params.forEach(item=>{
const {color, seriesName, value} = item const {color,seriesName,value} = item
result += `<div style="position: relative;padding-left:20px;line-height: 20px;"> result += `<div style="position: relative;padding-left:20px;line-height: 20px;">
<div style="position: absolute;top:50%;left:0;width:12px;height:12px;border-radius:100%;background: ${color};transform: translateY(-50%)"></div> <div style="position: absolute;top:50%;left:0;width:12px;height:12px;border-radius:100%;background: ${color};transform: translateY(-50%)"></div>
<span>${seriesName}</span><span style="margin-left:20px;font-weight: 700">${value}</span></div>` <span>${seriesName}</span><span style="margin-left:20px;font-weight: 700">${value}</span></div>`
}) })
result += '</div>' result+='</div>'
return result return result
} }
}, },
textStyle: { textStyle: {
color: "#333333", color: "#333333",
}, },
xAxis: {type: "category", data: xdata}, xAxis: { type: "category", data: xdata },
yAxis: { yAxis: {
type: "value", type: "value",
}, },
@ -137,7 +137,7 @@ export default {
}, },
], ],
series, series,
}, true); });
}, },
}, },
}; };

View File

@ -54,7 +54,7 @@ export default {
year:element.dateDay, year:element.dateDay,
}); });
}); });
this.chart && this.chart.setOption({ xdata = this.chart.setOption({
legend: { legend: {
left: "center", left: "center",
top: "5", top: "5",
@ -115,7 +115,7 @@ export default {
data: ydata, data: ydata,
}, },
], ],
},true); });
}, },
}, },
}; };

View File

@ -57,7 +57,7 @@ export default {
} }
); );
}); });
this.chart && this.chart.setOption({ xdata = this.chart.setOption({
legend: { legend: {
left: "center", left: "center",
top: "5", top: "5",
@ -118,7 +118,7 @@ export default {
data: ydata, data: ydata,
}, },
], ],
},true); });
}, },
}, },
}; };

View File

@ -66,7 +66,7 @@ export default {
}), }),
}); });
}); });
this.chart && this.chart.setOption({ this.chart.setOption({
legend: { legend: {
left: "center", left: "center",
top: "5", top: "5",
@ -118,7 +118,7 @@ export default {
}, },
], ],
series, series,
},true); });
}, },
}, },
}; };

View File

@ -25,7 +25,7 @@
<el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')"> <el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">
详细 详细
</el-button> </el-button>
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item"> <el-badge :value="item.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(item,'alarmPoint')" @click="pointDetail(item,'alarmPoint')"
@ -37,10 +37,8 @@
<el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'hdTempData'" :span="12" <el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'hdTempData'" :span="12"
class="device-info-col"> class="device-info-col">
<span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)"> <span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)">
<span class="left">{{ tempDataItem.title }}</span> <span class="right">{{ <span class="left">{{ tempDataItem.title }}</span> <span class="right">{{ item[tempDataItem.attr] || '' }}<span
item[tempDataItem.attr] || '-' v-html="tempDataItem.unit"></span></span>
}}<span
v-html="tempDataItem.unit"></span></span>
</span> </span>
</el-col> </el-col>
</el-row> </el-row>

View File

@ -14,7 +14,7 @@
<el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')"> <el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">
详细 详细
</el-button> </el-button>
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item"> <el-badge :value="item.alarmNum || 0" class="item">
<i <i
class="el-icon-message-solid alarm-icon" class="el-icon-message-solid alarm-icon"
@click="pointDetail(item,'alarmPoint')" @click="pointDetail(item,'alarmPoint')"
@ -26,8 +26,7 @@
<el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'ylTempData'" :span="8" <el-col v-for="(tempDataItem,tempDataIndex) in tempData" :key="tempDataIndex+'ylTempData'" :span="8"
class="device-info-col"> class="device-info-col">
<span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)"> <span class="pointer" @click="showChart(tempDataItem.title,item.deviceId)">
<span class="left">{{ tempDataItem.title }}</span> <span <span class="left">{{ tempDataItem.title }}</span> <span class="right">{{ item[tempDataItem.attr] }}<span
class="right">{{ item[tempDataItem.attr] || '-' }}<span
v-html="tempDataItem.unit"></span></span> v-html="tempDataItem.unit"></span></span>
</span> </span>
</el-col> </el-col>

View File

@ -1,3 +1,4 @@
<template> <template>
<div style="width:100%" v-loading="loading"> <div style="width:100%" v-loading="loading">
<!-- 搜索栏--> <!-- 搜索栏-->
@ -21,185 +22,172 @@
<el-form-item> <el-form-item>
<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-item>
<el-button type="primary" @click="exportTable" native-type="button">导出</el-button>
</el-form-item>
</el-form> </el-form>
<!--表格--> <!--表格-->
<el-table <el-table
class="common-table" class="common-table"
:data="tableData" :data="tableData"
stripe stripe
style="width: 100%;margin-top:25px;"> style="width: 100%;margin-top:25px;">
<!-- 汇总列--> <!-- 汇总列-->
<el-table-column label="汇总"> <el-table-column label="汇总">
<el-table-column <el-table-column
prop="dataTime" prop="dataTime"
label="日期" label="日期"
width="120"> width="120">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!--充电量列--> <!--充电量列-->
<el-table-column label="充电量" align="center"> <el-table-column label="充电量" align="center">
<el-table-column <el-table-column
align="center" align="center"
prop="activePeakKwh" prop="activePeakKwh"
label="尖"> label="尖">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="activeHighKwh" prop="activeHighKwh"
label="峰"> label="峰">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="activeFlatKwh" prop="activeFlatKwh"
label="平"> label="平">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="activeValleyKwh" prop="activeValleyKwh"
label="谷"> label="谷">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="activeTotalKwh" prop="activeTotalKwh"
label="总"> label="总">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!--充电量列--> <!--充电量列-->
<el-table-column label="放电量" align="center"> <el-table-column label="放电量" align="center">
<el-table-column <el-table-column
align="center" align="center"
prop="reActivePeakKwh" prop="reActivePeakKwh"
label="尖"> label="尖">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="reActiveHighKwh" prop="reActiveHighKwh"
label="峰"> label="峰">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="reActiveFlatKwh" prop="reActiveFlatKwh"
label="平"> label="平">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="reActiveValleyKwh" prop="reActiveValleyKwh"
label="谷"> label="谷">
</el-table-column> </el-table-column>
<el-table-column <el-table-column
align="center" align="center"
prop="reActiveTotalKwh" prop="reActiveTotalKwh"
label="总"> label="总">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 效率--> <!-- 效率-->
<el-table-column label="效率(%)" align="center"> <el-table-column label="效率(%)" align="center">
<el-table-column <el-table-column
align="center" align="center"
prop="effect"> prop="effect">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-pagination <el-pagination
v-show="tableData.length>0" v-show="tableData.length>0"
background background
@size-change="handleSizeChange" @size-change="handleSizeChange"
@current-change="handleCurrentChange" @current-change="handleCurrentChange"
:current-page="pageNum" :current-page="pageNum"
:page-size="pageSize" :page-size="pageSize"
:page-sizes="[10, 20, 30, 40]" :page-sizes="[10, 20, 30, 40]"
layout="total, sizes, prev, pager, next, jumper" layout="total, sizes, prev, pager, next, jumper"
:total="totalSize" :total="totalSize"
style="margin-top:15px;text-align: center" style="margin-top:15px;text-align: center"
> >
</el-pagination> </el-pagination>
</div> </div>
</template> </template>
<script> <script>
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getAmmeterData} from '@/api/ems/dzjk' import { getAmmeterData} from '@/api/ems/dzjk'
import {formatDate} from "@/filters/ems"; import {formatDate} from "@/filters/ems";
export default { export default {
name: 'DzjkTjbbDbbb', name:'DzjkTjbbDbbb',
mixins: [getQuerySiteId], mixins: [getQuerySiteId],
data() { data() {
return { return {
loading: false, loading:false,
pickerOptions: { pickerOptions:{
disabledDate(time) { disabledDate(time) {
return time.getTime() > Date.now(); return time.getTime() > Date.now();
}, },
}, },
defaultDateRange: [],//默认展示的时间 defaultDateRange:[],//默认展示的时间
dateRange: [], dateRange:[],
tableData: [], tableData:[],
pageSize: 10,//分页栏当前每个数据总数 pageSize:10,//分页栏当前每个数据总数
pageNum: 1,//分页栏当前页数 pageNum:1,//分页栏当前页数
totalSize: 0,//table表格数据总数 totalSize:0,//table表格数据总数
} }
}, },
methods: { methods:{
// 导出表格
exportTable() {
if (!this.dateRange?.length) return
const [startTime, endTime] = this.dateRange
this.download('ems/statsReport/exportAmmeterData', {
siteId: this.siteId,
startTime,
endTime,
}, `电表报表_${startTime}-${endTime}.xlsx`)
},
// 搜索 // 搜索
onSearch() { onSearch(){
this.pageNum = 1//每次搜索从1开始搜索 this.pageNum =1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 重置 // 重置
onReset() { onReset(){
this.dateRange = this.defaultDateRange this.dateRange=this.defaultDateRange
this.pageNum = 1//每次搜索从1开始搜索 this.pageNum =1//每次搜索从1开始搜索
this.getData() this.getData()
}, },
// 分页 // 分页
handleSizeChange(val) { handleSizeChange(val) {
this.pageSize = val; this.pageSize = val;
this.$nextTick(() => { this.$nextTick(()=>{
this.getData() this.getData()
}) })
}, },
handleCurrentChange(val) { handleCurrentChange(val) {
this.pageNum = val this.pageNum = val
this.$nextTick(() => { this.$nextTick(()=>{
this.getData() this.getData()
}) })
}, },
// 获取数据 // 获取数据
getData() { getData(){
this.loading = true this.loading=true
const {siteId, pageNum, pageSize} = this const {siteId,pageNum,pageSize} =this
const [startTime = '', endTime = ''] = (this.dateRange || []) const [startTime='',endTime='']=(this.dateRange || [])
getAmmeterData({siteId: siteId, startTime, endTime, pageSize, pageNum}).then(response => { getAmmeterData({siteId:siteId,startTime,endTime,pageSize,pageNum}).then(response=>{
this.tableData = response?.rows || []; this.tableData=response?.rows || [];
this.totalSize = response?.total || 0 this.totalSize = response?.total || 0
}).finally(() => { }).finally(()=> {
this.loading = false this.loading = false
}) })
}, },
init() { init(){
this.dateRange = [] this.dateRange=[]
this.tableData = [] this.tableData=[]
this.totalSize = 0 this.totalSize=0
this.pageSize = 10 this.pageSize=10
this.pageNum = 1 this.pageNum = 1
let now = new Date(), lastDay = now.getTime(), firstDay = new Date(now.setDate(1)).getTime(); const now = new Date().getTime();
this.defaultDateRange = [formatDate(firstDay), formatDate(lastDay)]; const lastMonth = new Date(now-30 * 24 * 60 * 60 * 1000).getTime();
this.dateRange = [formatDate(firstDay), formatDate(lastDay)]; this.defaultDateRange = [formatDate(lastMonth), formatDate(now)];
this.dateRange=[formatDate(lastMonth), formatDate(now)];
this.getData() this.getData()
}, },
}, },
@ -207,8 +195,8 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep { ::v-deep{
.common-table.el-table .el-table__header-wrapper th, .common-table.el-table .el-table__fixed-header-wrapper th { .common-table.el-table .el-table__header-wrapper th, .common-table.el-table .el-table__fixed-header-wrapper th{
border-bottom: 1px solid #dfe6ec; border-bottom: 1px solid #dfe6ec;
} }
} }

View File

@ -1,23 +1,22 @@
<template> <template>
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container time-range-card" class="common-card-container time-range-card"
style="margin-top: 20px" style="margin-top: 20px"
> >
<div slot="header" class="time-range-header"> <div slot="header" class="time-range-header">
<span class="card-title"> </span> <span class="card-title"> </span>
<date-range-select ref="dateRangeSelect" @updateDate="updateDate"/> <date-range-select ref="dateRangeSelect" @updateDate="updateDate" />
</div> </div>
<div class="card-main" v-loading="loading"> <div class="card-main" v-loading="loading">
<el-button-group class="ems-btns-group"> <el-button-group class="ems-btns-group">
<el-button <el-button
v-for="(item, index) in btnList" v-for="(item, index) in btnList"
:key="index + 'dcdqxBtns'" :key="index + 'dcdqxBtns'"
size="mini" size="mini"
:class="{ activeBtn: activeBtn === item.id }" :class="{ activeBtn: activeBtn === item.id }"
@click="changeDataType(item.id)" @click="changeDataType(item.id)"
>{{ item.name }} >{{ item.name }}</el-button
</el-button
> >
</el-button-group> </el-button-group>
<div id="dcdEchart" style="height: 310px"></div> <div id="dcdEchart" style="height: 310px"></div>
@ -29,13 +28,12 @@
import * as echarts from "echarts"; import * as echarts from "echarts";
import resize from "@/mixins/ems/resize"; import resize from "@/mixins/ems/resize";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getStackData} from "@/api/ems/dzjk"; import { getStackData, getStackNameList } from "@/api/ems/dzjk";
import {formatDate} from "@/filters/ems"; import { formatDate } from "@/filters/ems";
import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue"; import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue";
export default { export default {
name: "DzjkTjbbDcdqx", name: "DzjkTjbbDcdqx",
components: {DateRangeSelect}, components: { DateRangeSelect },
mixins: [resize, getQuerySiteId], mixins: [resize, getQuerySiteId],
data() { data() {
return { return {
@ -48,10 +46,10 @@ export default {
loading: false, loading: false,
activeBtn: "1", activeBtn: "1",
btnList: [ btnList: [
{name: "堆平均维度", id: "1", attr: ["temp"], source: ["有功功率"]}, { name: "堆平均维度", id: "1", attr: ["temp"], source: ["有功功率"] },
{name: "堆电压", id: "2", attr: ["voltage"], source: ["堆电压"]}, { name: "堆电压", id: "2", attr: ["voltage"], source: ["堆电压"] },
{name: "堆电流", id: "3", attr: ["current"], source: ["堆电流"]}, { name: "堆电流", id: "3", attr: ["current"], source: ["堆电流"] },
{name: "堆soc", id: "4", attr: ["soc"], source: ["堆soc"]}, { name: "堆soc", id: "4", attr: ["soc"], source: ["堆soc"] },
], ],
}; };
}, },
@ -68,7 +66,7 @@ export default {
this.getData(); this.getData();
}, },
getData() { getData() {
const {siteId, activeBtn} = this; const { siteId, activeBtn } = this;
const [start = "", end = ""] = this.dateRange || []; const [start = "", end = ""] = this.dateRange || [];
//接口调用完成之后 设置图表、结束loading //接口调用完成之后 设置图表、结束loading
this.loading = true; this.loading = true;
@ -78,12 +76,12 @@ export default {
endTime: formatDate(end), endTime: formatDate(end),
dataType: activeBtn, dataType: activeBtn,
}) })
.then((response) => { .then((response) => {
this.setOption(response?.data || []); this.setOption(response?.data || []);
}) })
.finally(() => { .finally(() => {
this.loading = false; this.loading = false;
}); });
}, },
compareDate(date1, date2) { compareDate(date1, date2) {
console.log("比较时间", date1, date2); console.log("比较时间", date1, date2);
@ -94,9 +92,9 @@ export default {
const [date1_Y = "", date1_M = "", date1_D = ""] = date1.split("-"); //根据空格区分[年月日,小时] const [date1_Y = "", date1_M = "", date1_D = ""] = date1.split("-"); //根据空格区分[年月日,小时]
const [date2_Y = "", date2_M = "", date2_D = ""] = date2.split("-"); //根据空格区分[年月日,小时] const [date2_Y = "", date2_M = "", date2_D = ""] = date2.split("-"); //根据空格区分[年月日,小时]
return ( return (
(date1_Y === date2_Y && date1_M === date2_M && date1_D - date2_D) || (date1_Y === date2_Y && date1_M === date2_M && date1_D - date2_D) ||
(date1_Y === date2_Y && date1_M - date2_M) || (date1_Y === date2_Y && date1_M - date2_M) ||
date1_Y - date2_Y date1_Y - date2_Y
); );
}, },
setOption(data) { setOption(data) {
@ -108,7 +106,7 @@ export default {
const source = []; const source = [];
const sourceTop = ["日期"]; const sourceTop = ["日期"];
let map = {}, let map = {},
mapArr = []; mapArr = [];
// 生成所有{日期:[],日期:[]}格式的对象和所有包含所有日期的[日期1,日期2...] // 生成所有{日期:[],日期:[]}格式的对象和所有包含所有日期的[日期1,日期2...]
data.forEach((item) => { data.forEach((item) => {
item.dataList.forEach((inner) => { item.dataList.forEach((inner) => {
@ -138,53 +136,38 @@ export default {
}); });
source.unshift(sourceTop); source.unshift(sourceTop);
this.chart.setOption( this.chart.setOption(
{ {
grid: { grid: {
containLabel: true, containLabel: true,
},
legend: {
left: "center",
top: "10",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataZoom: [
{
type: "inside",
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
dataset: {source},
series: source[0].slice(1).map((item) => {
return {
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
};
}),
}, },
true legend: {
left: "center",
bottom: "15",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataset: { source },
series: source[0].slice(1).map((item) => {
return {
type: "line",
};
}),
},
true
); );
}, },
initChart() { initChart() {
@ -193,7 +176,7 @@ export default {
init() { init() {
this.$nextTick(() => { this.$nextTick(() => {
this.initChart(); this.initChart();
this.$refs.dateRangeSelect.init(true); this.$refs.dateRangeSelect.init();
}); });
}, },
}, },

View File

@ -1,14 +1,15 @@
<template> <template>
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container time-range-card" class="common-card-container time-range-card"
style="margin-top: 20px" style="margin-top: 20px"
> >
<div slot="header" class="time-range-header"> <div slot="header" class="time-range-header">
<span class="card-title">功率曲线</span> <span class="card-title">功率曲线</span>
<date-range-select <date-range-select
ref="dateRangeSelect" ref="dateRangeSelect"
@updateDate="updateDate" @reset="resetTime"
@updateDate="updateDate"
/> />
</div> </div>
<div class="card-main" v-loading="loading"> <div class="card-main" v-loading="loading">
@ -21,13 +22,12 @@
import * as echarts from "echarts"; import * as echarts from "echarts";
import resize from "@/mixins/ems/resize"; import resize from "@/mixins/ems/resize";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getPowerData} from "@/api/ems/dzjk"; import { getPcsNameList, getPowerData } from "@/api/ems/dzjk";
import {formatDate} from "@/filters/ems"; import { formatDate } from "@/filters/ems";
import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue"; import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue";
export default { export default {
name: "DzjkTjbbGlqx", name: "DzjkTjbbGlqx",
components: {DateRangeSelect}, components: { DateRangeSelect },
mixins: [resize, getQuerySiteId], mixins: [resize, getQuerySiteId],
data() { data() {
return { return {
@ -38,6 +38,7 @@ export default {
}, },
dateRange: [], dateRange: [],
loading: false, loading: false,
dateRangeInit: true,
}; };
}, },
methods: { methods: {
@ -46,22 +47,30 @@ export default {
this.dateRange = data || []; this.dateRange = data || [];
this.getData(); this.getData();
}, },
resetTime() {
this.dateRangeInit = true;
},
getData() { getData() {
const {siteId} = this; const { siteId } = this;
let [start = "", end = ""] = this.dateRange || []; let [start = "", end = ""] = this.dateRange || [];
//接口调用完成之后 设置图表、结束loading //接口调用完成之后 设置图表、结束loading
this.loading = true; this.loading = true;
if (this.dateRangeInit) {
start = "";
end = "";
this.dateRangeInit = false;
}
getPowerData({ getPowerData({
siteId, siteId,
startDate: formatDate(start), startDate: formatDate(start),
endDate: formatDate(end), endDate: formatDate(end),
}) })
.then((response) => { .then((response) => {
this.setOption(response?.data || []); this.setOption(response?.data || []);
}) })
.finally(() => { .finally(() => {
this.loading = false; this.loading = false;
}); });
}, },
setOption(data) { setOption(data) {
const source = [["日期", "电网功率", "负载功率", "储能功率", "光伏功率"]]; const source = [["日期", "电网功率", "负载功率", "储能功率", "光伏功率"]];
@ -75,74 +84,47 @@ export default {
]); ]);
}); });
this.chart.setOption( this.chart.setOption(
{ {
grid: { grid: {
containLabel: true, containLabel: true,
},
legend: {
left: "center",
top: "10",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataset: {source},
dataZoom: [
{
type: "inside",
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
series: [
{
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
},
{
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
},
{
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
},
{
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
},
],
}, },
true legend: {
left: "center",
bottom: "15",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataset: { source },
series: [
{
type: "line",
},
{
type: "line",
},
{
type: "line",
},
{
type: "line",
},
],
},
true
); );
}, },
initChart() { initChart() {
@ -151,6 +133,7 @@ export default {
}, },
init() { init() {
this.$nextTick(() => { this.$nextTick(() => {
this.dateRangeInit = true;
this.initChart(); this.initChart();
this.$refs.dateRangeSelect.init(); this.$refs.dateRangeSelect.init();
}); });

View File

@ -7,47 +7,55 @@
text-color="#666666" text-color="#666666"
active-text-color="#ffffff" active-text-color="#ffffff"
> >
<el-menu-item :index="item.name" v-for="(item,index) in childrenRoute" :key="index+'tjbbChildrenRoute'"> <el-menu-item
<router-link style="height: 100%;width: 100%;display: block;" :to="{path:item.path,query:$route.query}"> :index="item.name"
{{item.meta.title}} v-for="(item, index) in childrenRoute"
:key="index + 'tjbbChildrenRoute'"
>
<router-link
style="height: 100%; width: 100%; display: block"
:to="{ path: item.path, query: $route.query }"
>
{{ item.meta.title }}
</router-link> </router-link>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>
<div class="ems-content-container ems-content-container-padding tjbb-ems-content-container"> <div
class="ems-content-container ems-content-container-padding tjbb-ems-content-container"
>
<keep-alive> <keep-alive>
<router-view></router-view> <router-view></router-view>
</keep-alive> </keep-alive>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { dzjk } from '@/router/ems' import { dzjk } from "@/router/ems";
const childrenRoute = dzjk[0].children[0].children.find(item=> item.name==='DzjkTjbb').children//获取到统计报表下面的字路由 const childrenRoute = dzjk[0].children.find(
console.log('设备监控子路由',childrenRoute) (item) => item.name === "DzjkTjbb"
).children; //获取到统计报表下面的字路由
console.log("设备监控子路由", childrenRoute);
export default { export default {
name:'DzjkTjbb', name: "DzjkTjbb",
data(){ data() {
return { return {
childrenRoute, childrenRoute,
activeMenu:'' activeMenu: "",
} };
}, },
mounted() { mounted() {
console.log('当前统计报表页面路由',this.$route) console.log("当前统计报表页面路由", this.$route);
} },
};
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.tjbb-ems-content-container{ .tjbb-ems-content-container {
margin-top:0; margin-top: 0;
padding-top:0; padding-top: 0;
padding-right: 0; padding-right: 0;
flex: 1; flex: 1;
} }
</style> </style>

View File

@ -1,23 +1,22 @@
<template> <template>
<el-card <el-card
shadow="always" shadow="always"
class="common-card-container time-range-card" class="common-card-container time-range-card"
style="margin-top: 20px" style="margin-top: 20px"
> >
<div slot="header" class="time-range-header"> <div slot="header" class="time-range-header">
<span class="card-title"> </span> <span class="card-title"> </span>
<date-range-select ref="dateRangeSelect" @updateDate="updateDate"/> <date-range-select ref="dateRangeSelect" @updateDate="updateDate" />
</div> </div>
<div class="card-main" v-loading="loading"> <div class="card-main" v-loading="loading">
<el-button-group class="ems-btns-group"> <el-button-group class="ems-btns-group">
<el-button <el-button
v-for="(item, index) in btnList" v-for="(item, index) in btnList"
:key="index + 'flqxcBtns'" :key="index + 'flqxcBtns'"
size="mini" size="mini"
:class="{ activeBtn: activeBtn === item.id }" :class="{ activeBtn: activeBtn === item.id }"
@click="changeDataType(item.id)" @click="changeDataType(item.id)"
>{{ item.name }} >{{ item.name }}</el-button
</el-button
> >
</el-button-group> </el-button-group>
<div id="pcsEchart" style="height: 310px"></div> <div id="pcsEchart" style="height: 310px"></div>
@ -29,13 +28,12 @@
import * as echarts from "echarts"; import * as echarts from "echarts";
import resize from "@/mixins/ems/resize"; import resize from "@/mixins/ems/resize";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId"; import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {getPCSData} from "@/api/ems/dzjk"; import { getPCSData, getPcsNameList } from "@/api/ems/dzjk";
import {formatDate} from "@/filters/ems"; import { formatDate } from "@/filters/ems";
import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue"; import DateRangeSelect from "@/components/Ems/DateRangeSelect/index.vue";
export default { export default {
name: "DzjkTjbbPcsqx", name: "DzjkTjbbPcsqx",
components: {DateRangeSelect}, components: { DateRangeSelect },
mixins: [resize, getQuerySiteId], mixins: [resize, getQuerySiteId],
data() { data() {
return { return {
@ -84,7 +82,7 @@ export default {
this.getData(); this.getData();
}, },
getData() { getData() {
const {siteId, activeBtn} = this; const { siteId, activeBtn } = this;
const [start = "", end = ""] = this.dateRange || []; const [start = "", end = ""] = this.dateRange || [];
this.loading = true; this.loading = true;
//接口调用完成之后 设置图表、结束loading //接口调用完成之后 设置图表、结束loading
@ -94,12 +92,12 @@ export default {
endTime: formatDate(end), endTime: formatDate(end),
dataType: activeBtn, dataType: activeBtn,
}) })
.then((response) => { .then((response) => {
this.setOption(response?.data || []); this.setOption(response?.data || []);
}) })
.finally(() => { .finally(() => {
this.loading = false; this.loading = false;
}); });
}, },
compareDate(date1, date2) { compareDate(date1, date2) {
console.log("比较时间", date1, date2); console.log("比较时间", date1, date2);
@ -110,9 +108,9 @@ export default {
const [date1_Y = "", date1_M = "", date1_D = ""] = date1.split("-"); //根据空格区分[年月日,小时] const [date1_Y = "", date1_M = "", date1_D = ""] = date1.split("-"); //根据空格区分[年月日,小时]
const [date2_Y = "", date2_M = "", date2_D = ""] = date2.split("-"); //根据空格区分[年月日,小时] const [date2_Y = "", date2_M = "", date2_D = ""] = date2.split("-"); //根据空格区分[年月日,小时]
return ( return (
(date1_Y === date2_Y && date1_M === date2_M && date1_D - date2_D) || (date1_Y === date2_Y && date1_M === date2_M && date1_D - date2_D) ||
(date1_Y === date2_Y && date1_M - date2_M) || (date1_Y === date2_Y && date1_M - date2_M) ||
date1_Y - date2_Y date1_Y - date2_Y
); );
}, },
setOption(data) { setOption(data) {
@ -124,7 +122,7 @@ export default {
const source = []; const source = [];
const sourceTop = ["日期"]; const sourceTop = ["日期"];
let map = {}, let map = {},
mapArr = []; mapArr = [];
// 生成所有{日期:[],日期:[]}格式的对象和所有包含所有日期的[日期1,日期2...] // 生成所有{日期:[],日期:[]}格式的对象和所有包含所有日期的[日期1,日期2...]
data.forEach((item) => { data.forEach((item) => {
item.dataList.forEach((inner) => { item.dataList.forEach((inner) => {
@ -154,53 +152,38 @@ export default {
}); });
source.unshift(sourceTop); source.unshift(sourceTop);
this.chart.setOption( this.chart.setOption(
{ {
grid: { grid: {
containLabel: true, containLabel: true,
},
legend: {
left: "center",
top: "10",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataZoom: [
{
type: "inside",
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
dataset: {source},
series: source[0].slice(1).map((item) => {
return {
type: "line",
smooth: true,
areaStyle: {
opacity: 0.7,
},
};
}),
}, },
true legend: {
left: "center",
bottom: "15",
},
tooltip: {
trigger: "axis",
axisPointer: {
// 坐标轴指示器,坐标轴触发有效
type: "shadow", // 默认为直线,可选为:'line' | 'shadow'
},
},
textStyle: {
color: "#333333",
},
xAxis: {
type: "category",
},
yAxis: {
type: "value",
},
dataset: { source },
series: source[0].slice(1).map((item) => {
return {
type: "line",
};
}),
},
true
); );
}, },
initChart() { initChart() {
@ -209,7 +192,7 @@ export default {
init() { init() {
this.$nextTick(() => { this.$nextTick(() => {
this.initChart(); this.initChart();
this.$refs.dateRangeSelect.init(true); this.$refs.dateRangeSelect.init();
}); });
}, },
}, },

View File

@ -21,23 +21,19 @@
<el-form-item> <el-form-item>
<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-item>
<el-button type="primary" @click="exportTable" native-type="button">导出</el-button>
</el-form-item>
</el-form> </el-form>
<!--表格--> <!--表格-->
<el-table <el-table
class="common-table" class="common-table"
:data="tableData" :data="tableData"
show-summary
stripe stripe
style="width: 100%;margin-top:25px;"> style="width: 100%;margin-top:25px;">
<!-- 汇总列--> <!-- 汇总列-->
<el-table-column label="汇总" min-width="100px" align="center"> <el-table-column label="汇总">
<el-table-column <el-table-column
prop="dataTime" prop="dataTime"
label="日期" label="日期"
min-width="100px" align="center"> width="120">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!--充电量列--> <!--充电量列-->
@ -96,14 +92,13 @@
label="总"> label="总">
</el-table-column> </el-table-column>
</el-table-column> </el-table-column>
<!-- 实际收益--> <!-- 效率-->
<el-table-column label="" align="center" fixed="right"> <!-- <el-table-column label="效率(%)" align="center">-->
<el-table-column <!-- <el-table-column-->
prop="actualRevenue" <!-- align="center"-->
label="实际收益" <!-- prop="effect">-->
align="center"> <!-- </el-table-column>-->
</el-table-column> <!-- </el-table-column>-->
</el-table-column>
</el-table> </el-table>
<el-pagination <el-pagination
v-show="tableData.length>0" v-show="tableData.length>0"
@ -147,16 +142,6 @@ export default {
} }
}, },
methods: { methods: {
// 导出表格
exportTable() {
if (!this.dateRange?.length) return
const [startTime, endTime] = this.dateRange
this.download('ems/statsReport/exportAmmeterRevenueData', {
siteId: this.siteId,
startTime,
endTime,
}, `收益报表_${startTime}-${endTime}.xlsx`)
},
// 搜索 // 搜索
onSearch() { onSearch() {
this.pageNum = 1//每次搜索从1开始搜索 this.pageNum = 1//每次搜索从1开始搜索
@ -186,6 +171,7 @@ export default {
this.loading = true this.loading = true
const {siteId, pageNum, pageSize} = this const {siteId, pageNum, pageSize} = this
const [startTime = '', endTime = ''] = (this.dateRange || []) const [startTime = '', endTime = ''] = (this.dateRange || [])
//http://localhost:8089/ems/statsReport/getAmmeterRevenueData?siteId=021_DDS_01&startTime=2025-10-14&endTime=2025-10-15&pageSize=10&pageNum=1
getAmmeterRevenueData({siteId: siteId, startTime, endTime, pageSize, pageNum}).then(response => { getAmmeterRevenueData({siteId: siteId, startTime, endTime, pageSize, pageNum}).then(response => {
this.tableData = response?.rows || []; this.tableData = response?.rows || [];
this.totalSize = response?.total || 0 this.totalSize = response?.total || 0
@ -199,9 +185,10 @@ export default {
this.totalSize = 0 this.totalSize = 0
this.pageSize = 10 this.pageSize = 10
this.pageNum = 1 this.pageNum = 1
let now = new Date(), lastDay = now.getTime(), firstDay = new Date(now.setDate(1)).getTime(); const now = new Date().getTime();
this.defaultDateRange = [formatDate(firstDay), formatDate(lastDay)]; const lastMonth = new Date(now - 30 * 24 * 60 * 60 * 1000).getTime();
this.dateRange = [formatDate(firstDay), formatDate(lastDay)]; this.defaultDateRange = [formatDate(lastMonth), formatDate(now)];
this.dateRange = [formatDate(lastMonth), formatDate(now)];
this.getData() this.getData()
}, },
}, },
@ -210,19 +197,9 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
::v-deep { ::v-deep {
.common-table.el-table { .common-table.el-table .el-table__header-wrapper th, .common-table.el-table .el-table__fixed-header-wrapper th {
.el-table__header-wrapper th, .common-table.el-table .el-table__fixed-header-wrapper th { border-bottom: 1px solid #dfe6ec;
border-bottom: 1px solid #dfe6ec;
}
.el-table__footer-wrapper {
tbody td.el-table__cell {
color: #000;
font-weight: bolder;
}
}
} }
} }
</style> </style>

View File

@ -0,0 +1,577 @@
<template>
<div class="ems-dashboard-editor-container" v-loading="loading">
<div class="container" v-show="!empty">
<!-- 电脑 -->
<div class="top">
<div class="cloud-container">
<div class="cloud">
<span style="z-index: 2; position: relative"></span>
</div>
</div>
<div class="double-arrows">
<div class="top-arrows"></div>
<div class="bottom-arrows"></div>
</div>
<div class="computer">
<img src="@/assets/images/ems/computer.png" alt="" />
<span style="z-index: 2; position: relative">ems</span>
</div>
</div>
<div class="outer-border">
<!-- 电表-->
<div class="row-lists-container" v-if="showDb">
<div class="row-title">电表({{ db.length }})</div>
<div class="row-lists">
<div v-for="item in db" :key="item.deviceId" class="row-items">
<div
class="status"
:class="
item.communicationStatus === '0' ? 'status-running' : ''
"
>
{{ communicationStatusOptions[item.communicationStatus] }}
</div>
<div class="row-items-img">
<img
class="img-db"
:src="require('@/assets/images/ems/db.png')"
/>
<div class="name">{{ item.deviceName }}</div>
</div>
</div>
</div>
</div>
<!-- 液冷-->
<div class="row-lists-container" v-if="showLq">
<div class="row-title">冷却({{ lq.length }})</div>
<div class="row-lists">
<div v-for="item in lq" :key="item.deviceId" class="row-items">
<div
class="status"
:class="
item.communicationStatus === '0' ? 'status-running' : ''
"
>
{{ communicationStatusOptions[item.communicationStatus] }}
</div>
<div class="row-items-img">
<img
class="img-lq"
:src="require('@/assets/images/ems/lq.png')"
/>
<div class="name">{{ item.deviceName }}</div>
</div>
</div>
</div>
</div>
<!-- PCS-->
<div class="row-lists-container" v-if="showPcs">
<div class="row-lists">
<div class="row-title">PCS({{ pcs.length }})</div>
<div
v-for="(item, index) in pcs"
:key="item.deviceId"
class="row-items row-items-pcs"
>
<!-- pcs -->
<div class="parent-dash">
<div
class="status"
:class="
item.communicationStatus === '0' ? 'status-running' : ''
"
>
{{ communicationStatusOptions[item.communicationStatus] }}
</div>
<div class="row-items-img">
<img
class="img-pcs"
:src="require('@/assets/images/ems/pcs.png')"
/>
<div class="name">{{ item.deviceName }}</div>
</div>
</div>
<!-- 子设备 bms -->
<div
v-if="item.children && item.children.length > 0"
class="children-dash"
>
<div
class="row-children-title"
v-if="bmsHasParentLength > 0 && index === 0"
>
BMS({{ bmsHasParentLength }})
</div>
<div
v-for="(childrenItem, childrenIndex) in item.children"
:key="childrenIndex + 'childrenBms'"
class="children-dash-items"
>
<div
class="status"
:class="
childrenItem.communicationStatus === '0'
? 'status-running'
: ''
"
>
{{
communicationStatusOptions[
childrenItem.communicationStatus
]
}}
</div>
<div class="row-items-img">
<img
class="img-pcs"
:src="require('@/assets/images/ems/bms.png')"
/>
<div class="name">{{ childrenItem.deviceName }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row-lists-container" v-if="showPcs">
<div class="row-title">PCS({{ pcs.length }})</div>
<div class="row-lists">
<div
v-for="item in bmsNoParent"
:key="item.deviceId"
class="row-items row-items-pcs"
>
<!-- pcs -->
<div class="parent-dash">
<div
class="status"
:class="
item.communicationStatus === '0' ? 'status-running' : ''
"
>
{{ communicationStatusOptions[item.communicationStatus] }}
</div>
<div class="row-items-img">
<img :src="require('@/assets/images/ems/bms.png')" />
<div class="name">{{ item.deviceName }}</div>
</div>
</div>
</div>
</div>
</div>
<!-- bms没有上级设备-->
<div class="row-lists-container" v-if="bmsNoParent.length > 0">
<div class="row-title">BMS({{ bmsNoParent.length }})</div>
<div class="row-lists">
<div
v-for="item in bmsNoParent"
:key="item.deviceId"
class="row-items row-items-pcs"
>
<!-- pcs -->
<div class="parent-dash">
<div
class="status"
:class="
item.communicationStatus === '0' ? 'status-running' : ''
"
>
{{ communicationStatusOptions[item.communicationStatus] }}
</div>
<div class="row-items-img">
<img :src="require('@/assets/images/ems/bms.png')" />
<div class="name">{{ item.deviceName }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<el-empty v-show="empty" :image-size="200"></el-empty>
</div>
</template>
<script>
import { getDeviceList } from "@/api/ems/site";
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import { mapState } from "vuex";
export default {
name: "DzjkZxlt",
mixins: [getQuerySiteId],
data() {
return {
loading: false,
pcs: [],
bms: [],
db: [],
lq: [],
pcsHasChildren: [],
pcsNoChildren: [],
bmsNoParent: [],
};
},
computed: {
...mapState({
communicationStatusOptions: (state) =>
state.ems.communicationStatusOptions,
}),
showPcs() {
return this.pcs.length > 0;
},
showBms() {
return this.bms.length > 0;
},
showDb() {
return this.db.length > 0;
},
showLq() {
return this.lq.length > 0;
},
bmsHasParentLength() {
let count = 0;
this.pcs.forEach((item) => (count += item.children.length));
return count;
},
empty() {
return !this.showBms && !this.showPcs && !this.showDb && !this.showLq;
},
},
methods: {
init() {
this.pcs = [];
this.bms = [];
this.lq = [];
this.db = [];
this.bmsNoParent = [];
this.loading = true;
getDeviceList(this.siteId)
.then((response) => {
const data = JSON.parse(JSON.stringify(response?.data || []));
let pcs = [],
bms = [],
db = [],
lq = [],
bmsNoParent = [];
data.forEach((item) => {
// 电表
if (item.deviceCategory === "AMMETER") {
db.push({ ...item, children: [] });
} else if (item.deviceCategory === "PCS") {
// pcs
pcs.push({ ...item, children: [] });
} else if (item.deviceCategory === "STACK") {
// bms
bms.push({ ...item, children: [] });
} else if (item.deviceCategory === "COOLING") {
// 液冷
lq.push({ ...item, children: [] });
}
});
bms.forEach((item, index) => {
if (item.parentId) {
pcs
.find((pcsItem) => pcsItem.deviceId === item.parentId)
.children.push(item);
} else {
bmsNoParent.push(item);
}
});
this.pcs = pcs;
this.bms = bms;
this.lq = lq;
this.db = db;
this.pcsHasChildren = pcs.filter((item) => item.children.length > 0);
this.pcsNoChildren = pcs.filter((item) => item.children.length === 0);
this.bmsNoParent = bmsNoParent;
})
.finally(() => {
this.loading = false;
});
},
},
};
</script>
<style lang="scss" scoped>
$sqDistance: 30px;
$borderColor: #174a8e;
$lineColor: #86bcc7;
.ems-dashboard-editor-container {
background-color: #ffffff;
padding: 0;
color: #666666;
.container {
display: flex;
position: relative;
}
//云 、计算机 、箭头
.top {
z-index: 2;
width: fit-content;
display: flex;
justify-content: center;
align-items: center;
// position: absolute;
// top: 50%;
// left: 0;
// transform: translateY(-50%);
//云 样式
.cloud-container {
margin: 0 auto;
.cloud {
width: 60px;
height: 26px;
background: #cbebfd;
border-radius: 100px;
position: relative;
text-align: center;
font-weight: bold;
font-size: 14px;
line-height: 26px;
}
.cloud:before,
.cloud:after {
content: "";
position: absolute;
background: #cbebfd;
width: 30px;
height: 30px;
border-radius: 100%;
}
.cloud:before {
top: -9px;
left: 8px;
}
.cloud:after {
top: -6px;
right: 9px;
}
}
//双箭头
.double-arrows {
height: fit-content;
margin: 0 10px;
text-align: center;
.top-arrows,
.bottom-arrows {
height: 4px;
width: 30px;
background-color: #5ea9df;
margin: 0 10px;
position: relative;
&::after {
content: "";
position: absolute;
left: 0;
width: 0;
height: 0;
}
}
.top-arrows {
vertical-align: super;
}
.top-arrows::after {
top: -4px;
border-bottom: 6px solid transparent;
border-left: 6px solid transparent;
border-right: 6px solid #5ea9df;
border-top: 6px solid transparent;
left: -11px;
}
.bottom-arrows {
margin-top: 8px;
&::after {
top: -4px;
border-top: 6px solid transparent;
border-left: 6px solid #5ea9df;
border-right: 6px solid transparent;
border-bottom: 6px solid transparent;
right: -11px;
left: auto;
}
}
}
//电脑
.computer {
text-align: center;
font-size: 14px;
line-height: 16px;
font-weight: bold;
position: relative;
background: #fff;
img {
width: 80px;
height: auto;
display: block;
}
}
}
.outer-border {
position: relative;
width: fit-content;
border: 1.5px solid $borderColor;
border-radius: 5px;
padding-left: 120px;
padding-right: 20px;
margin-left: -40px;
}
// 设备列表
.row-lists-container {
font-size: 10px;
position: relative;
padding: 10px;
.row-title {
position: absolute;
left: -$sqDistance - 30px;
top: calc(50% + 10px);
transform: translateY(-50%);
color: #000;
font-weight: bolder;
}
.row-lists {
display: flex;
position: relative;
.row-items {
position: relative;
padding: 5px 0;
&:not(:first-child) {
margin-left: $sqDistance; //和外层父元素上下padding一致
}
&::before {
content: "";
display: block;
height: 3px;
width: $sqDistance - 2px;
background: $lineColor;
position: absolute;
left: -$sqDistance;
top: calc(50% + 10px);
transform: scale(1, 0.4);
}
// 一列 第一个设备最上面的线
&:first-child {
&::before {
width: $sqDistance + 20px;
// top: -$sqDistance - 20px;
}
}
// 一列 最后一个设备最下面的线
// &:last-child {
// &::after {
// content: "";
// display: block;
// width: 3px;
// height: $sqDistance - 2px;
// background: $lineColor;
// position: absolute;
// bottom: -$sqDistance;
// left: 50%;
// transform: scale(0.4, 1);
// }
// }
// 设备状态
.status {
margin: 0 auto 4px;
width: fit-content;
height: 18px;
padding: 0 8px;
box-sizing: border-box;
text-align: center;
font-size: 8px;
line-height: 18px;
border: 1px solid #08ffff;
border-radius: 2px;
background: #aaaaaa;
color: #ffffff;
&.status-running {
background: #00c69c;
}
}
// 图片+设备名称
.row-items-img {
position: relative;
padding-top: 12px;
img {
width: 80px;
height: auto;
display: block;
&.img-lq {
width: 50px;
}
&.img-pcs {
width: 50px;
}
&.img-db {
width: 56px;
}
}
.name {
position: absolute;
top: 1px;
left: 0;
color: #666;
white-space: nowrap;
}
}
}
}
}
//子设备
.row-lists-container-children {
margin: 10px 0 0 $sqDistance;
.parent-dash {
position: relative;
&::before {
content: "";
display: block;
height: 40px;
width: 3px;
background: #ec7f8c;
position: absolute;
left: 20%;
top: -40px;
transform: scale(0.4, 1) rotate(-40deg);
}
}
}
.parent-dash {
width: fit-content;
}
.children-dash {
margin: $sqDistance 0 0 $sqDistance;
position: relative;
.row-children-title {
position: absolute;
left: -$sqDistance - 30px;
top: calc(50% + 10px);
transform: translateY(-50%);
color: #000;
font-weight: bolder;
}
.children-dash-items {
position: relative;
&::before {
content: "";
display: block;
height: $sqDistance;
width: 3px;
background: #ec7f8c;
position: absolute;
left: 20%;
top: -$sqDistance;
transform: scale(0.4, 1) rotate(-40deg);
}
}
}
}
</style>

View File

@ -0,0 +1,614 @@
<template>
<div class="ems-dashboard-editor-container" v-loading="loading" >
<div class="container" v-show="!empty">
<div class="top">
<div class="cloud-container">
<div class="cloud">
<span style="z-index:2;position: relative;"></span>
</div>
</div>
<div class="double-arrows">
<div class="top-arrows"></div>
<div class="bottom-arrows"></div>
</div>
<div class="computer">
<img src="@/assets/images/ems/computer.png" alt="">
<span style="z-index:2;position: relative;">ems</span>
</div>
<div class="arrow"></div>
</div>
<div class="bottom">
<!-- 四列设备-->
<div class="zxlt-row">
<!-- bmspcs 下级和上级在一列 -->
<div class="row-lists pcs-row-lists" v-if="showPcsAndBms">
<div class="item-square">
<div class="row-lists-title" v-if="showPcs">PCS({{pcs.length}})</div>
<div class="row-lists-title" v-if="showBms">BMS({{bms.length}})</div>
</div>
<!-- 上下级块 class区分-->
<div class="item-square pcs-has-children-item-square" :class="{'no-bms-list':!showBms}" v-for="(item,index) in pcsHasChildren" :key="index+'pcsHasChildren'">
<!-- 左边的上级 上级只有一个-->
<div class="item-lists parent-item-lists">
<!-- 上级设备-->
<div class="items normal-items-arrow">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
</div>
<img v-if="item.pictureUrl" :src="item.pictureUrl">
<img v-else :src="require('@/assets/images/ems/pcs.png')"/>
<div class="name">{{item.deviceName}}</div>
</div>
</div>
</div>
<!-- 右边的下级 下级有多个-->
<div class="item-lists children-item-lists">
<!-- 下级设备 循环生成-->
<div class="items children-items-arrow bms-children-arrow" v-for="children in item.children" :key="children.deviceId">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="children.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[children.communicationStatus] || '-'}}</div>
</div>
<img v-if="children.pictureUrl" :src="children.pictureUrl">
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
<div class="name">{{children.deviceName}}</div>
</div>
</div>
</div>
</div>
<!-- 没有上下级关系的bmspcs-->
<div class="item-square" :class="{'no-bms-list':!showBms}">
<!-- 左边没有下级的pcs-->
<div class="item-lists">
<div class="items normal-items-arrow" v-for="item in pcsNoChildren" :key="item.deviceId">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
</div>
<img v-if="item.pictureUrl" :src="item.pictureUrl">
<img v-else :src="require('@/assets/images/ems/pcs.png')"/>
<div class="name">{{item.deviceName}}</div>
</div>
</div>
</div>
<!-- 右边没有上级的bms-->
<div class="item-lists">
<!-- 下级设备 循环生成-->
<div class="items children-items-arrow" v-for="item in bmsNoParent" :key="item.deviceId">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
</div>
<img v-if="item.pictureUrl" :src="item.pictureUrl">
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
<div class="name">{{item.deviceName}}</div>
</div>
</div>
</div>
</div>
</div>
<!-- 电表-->
<div class="row-lists" v-if="showDb">
<div class="item-square">
<div class="row-lists-title" style="width:100%;">电表({{db.length}})</div>
</div>
<div class="item-square">
<!-- 左边的下级 下级有多个-->
<div class="item-lists">
<!-- 下级设备 循环生成-->
<div class="items normal-items-arrow" v-for="item in db" :key="item.deviceId">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
</div>
<img v-if="item.pictureUrl" :src="item.pictureUrl">
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
<div class="name">{{item.deviceName}}</div>
</div>
</div>
</div>
</div>
</div>
<!--冷却-->
<div class="row-lists" v-if="showLq">
<div class="item-square">
<div class="row-lists-title" style="width:100%;">冷却({{lq.length}})</div>
</div>
<div class="item-square">
<div class="item-lists">
<div class="items normal-items-arrow" v-for="item in lq" :key="item.deviceId">
<div class="items-inner">
<div style="text-align: center;margin-bottom:10px;">
<div class="status" :class="item.communicationStatus === '0' ?'status-normal' : 'status-warn'">通讯状态:{{communicationStatusOptions[item.communicationStatus] || '-'}}</div>
</div>
<img v-if="item.pictureUrl" :src="item.pictureUrl">
<img v-else :src="require('@/assets/images/ems/bms.png')"/>
<div class="name">{{item.deviceName}}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<el-empty v-show="empty" :image-size="200"></el-empty>
</div>
</template>
<script>
import {getDeviceList} from'@/api/ems/site'
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
import {mapState} from "vuex";
export default {
name: 'DzjkZxlt',
mixins: [getQuerySiteId],
data() {
return {
loading:false,
pcs :[],
bms:[],
db:[],
lq:[],
pcsHasChildren:[],
pcsNoChildren:[],
bmsNoParent:[]
}
},
computed:{
...mapState({
communicationStatusOptions:(state)=>state.ems.communicationStatusOptions
}),
showPcs(){
return this.pcs.length>0
},
showBms(){
return this.bms.length>0
},
showDb(){
return this.db.length>0
},
showLq(){
return this.lq.length>0
},
showPcsAndBms(){
return this.showPcs || this.showBms
},
empty(){
return !this.showBms && !this.showPcs && !this.showDb && !this.showLq
},
},
methods: {
init(){
this.pcs = []
this.bms = []
this.lq=[]
this.db=[]
this.bmsNoParent=[]
this.loading = true
getDeviceList(this.siteId).then(response => {
const data =JSON.parse(JSON.stringify(response?.data || []))
let pcs = [],bms=[],db=[],lq=[],bmsNoParent=[]
data.forEach(item=>{
// 电表
if(item.deviceCategory === 'AMMETER'){
db.push({...item,children:[]})
}else if(item.deviceCategory === 'PCS'){
// pcs
pcs.push({...item,children:[]})
}else if(item.deviceCategory === 'STACK'){
// bms
bms.push({...item,children:[]})
}else if(item.deviceCategory === 'COOLING'){
// 液冷
lq.push({...item,children:[]})
}
})
bms.forEach((item,index)=>{
if(item.parentId){
pcs.find(pcsItem=>pcsItem.deviceId === item.parentId).children.push(item)
}else{
bmsNoParent.push(item)
}
})
this.pcs = pcs
this.bms = bms
this.lq=lq
this.db=db
this.pcsHasChildren = pcs.filter(item=>item.children.length > 0)
this.pcsNoChildren = pcs.filter(item=>item.children.length === 0)
this.bmsNoParent = bmsNoParent
}).finally(() => {
this.loading = false
})
}
},
}
</script>
<style lang="scss" scoped>
$distance:60px;
$arrowDistance:80px;//margin:60+quare的padding10
$arrowColoe:#5ea9df;
$lineColoe:#5ea9df;
.ems-dashboard-editor-container {
background-color: #ffffff;
padding:0;
.container{
position: relative;
overflow-x: auto;
}
//云 、计算机 、箭头
.top{
width: 280px;
font-size: 30px;
line-height: 40px;
font-weight: 500;
display: flex;
flex-direction: column;
//云 样式
.cloud-container{
padding-top:40px;
margin:0 auto;
.cloud {
width: 150px;
height: 60px;
background: #cbebfd;
border-radius: 200px;
position: relative;
text-align: center;
color:#666666;
}
.cloud:before, .cloud:after {
content: '';
position: absolute;
background:#cbebfd;
width: 80px;
height: 80px;
border-radius: 50%;
}
.cloud:before {
top: -28px;
left: 20px;
}
.cloud:after {
top: -31px;
right: 20px;
}
}
//双箭头
.double-arrows {
height: 50px;
margin:20px 0;
text-align: center;
.top-arrows,.bottom-arrows{
height: 100%;
width: 6px;
background-color: $arrowColoe;
display: inline-block;
margin: 0 10px;
position: relative;
vertical-align: super;
&::after {
content: '';
position: absolute;
left:0;
width: 0;
height: 0;
}
}
.top-arrows{
vertical-align: super;
}
.top-arrows::after {
bottom: -24px;
border-bottom: 12px solid transparent;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-top: 14px solid $arrowColoe;
left: -9px;
}
.bottom-arrows{
margin-top:12px;
&::after {
top: -24px;
border-top: 12px solid transparent;
border-left: 12px solid transparent;
border-right: 12px solid transparent;
border-bottom: 14px solid $arrowColoe;
left: -9px;
}
}
}
//电脑
.computer{
margin:20px auto;
text-align: center;
color:#666666;
position: relative;
img {
width: auto;
height: 100px;
display: block;
}
}
.arrow{
height: 50px;
width: 30px;
border-radius: 5px;
background-color: $arrowColoe;
position: relative;
margin:0 auto;
&::after{
content: "";
position: absolute;
width: 0;
height: 0;
left: -9px;
border-top: 24px solid $arrowColoe;
border-left: 24px solid transparent;
border-bottom: 24px solid transparent;
border-right: 24px solid transparent;
bottom: -44px;
}
}
}
.bottom{
z-index:1;
box-sizing: border-box;
margin-top:50px;
.zxlt-row{
display: flex;
padding:20px $distance;
position: relative;
width: fit-content;
&:before{
content: '';
display: block;
width:calc(100% - 100px);
height:1px;
background-color: $lineColoe;
position:absolute;
top:0;
left: $distance/2;
}
.row-lists{
height: fit-content;
position: relative;
&:before{
content: '';
display: block;
height: 100%;
width: 1px;
position: absolute;
left:-($distance/2);
top:-20px;
background-color: $lineColoe;
}
//pcs列 bms右侧的边框
&.pcs-row-lists{
&:after{
content: '';
display: block;
height: 100%;
width: 1px;
position: absolute;
right:-(($distance/2) + 1);
top:-20px;
background-color: $lineColoe;
}
}
&:not(:last-child){
margin-right: $distance;
}
.item-square{
//左右 两列
display: flex;
vertical-align: middle;
align-items: flex-start;
padding:10px;
border-radius: 5px;
&:not(:last-child){
margin-bottom: 40px;
}
.row-lists-title{
font-size: 20px;
line-height: 20px;
color: #333333;
font-weight: 500;
text-align: center;
flex: 1;
}
.item-lists{
position: relative;
&:not(:last-child){
margin-right:$distance;
}
//每个设备
.items{
background-color: #cbebfd;
position: relative;
border-radius: 5px;
padding: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1), 0 0 0 rgba(0, 0, 0, 0.5);
//普通设备 箭头方向
&.normal-items-arrow{
&:before{
content: '';
display: block;
width:($arrowDistance/2) - 15;
height: 4px;
background-color: $arrowColoe;
position: absolute;
top:50%;
left: -($arrowDistance/2);
transform: translateY(-50%);
}
&:after{
content: '';
display: block;
height: 0;
width: 0;
border-left: 10px solid #5ea9df;
border-right: 10px solid transparent;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
position: absolute;
top: 50%;
left: -15px;
transform: translateY(-50%);
}
}
//下级的箭头
&.children-items-arrow{
&:before{
content: '';
display: block;
width:($arrowDistance/2) - 15;
height: 4px;
background-color: $arrowColoe;
position: absolute;
top:50%;
right: -($arrowDistance/2);
transform: translateY(-50%);
}
&:after{
content: '';
display: block;
height: 0;
width: 0;
border-right: 10px solid #5ea9df;
border-left: 10px solid transparent;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
position: absolute;
top: 50%;
right: -15px;
transform: translateY(-50%);
}
}
&:not(:last-child){
margin-bottom: 15px;
}
.items-inner{
background-color: #ffffff;
border-radius: 5px;
padding:10px;
width:130px;
text-align: center;
}
img{
width: 80px;
height: auto;
display: block;
z-index:2;
margin: 0 auto;
}
.name{
text-align: center;
margin-top:10px;
font-size: 14px;
line-height: 20px;
z-index:2;
}
.status{
z-index:2;
margin-top:10px;
font-size: 14px;
line-height: 20px;
position: relative;
padding-left:20px;
display: inline;
&.status-normal {
&:before {
content: "";
display: block;
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #05AEA3;
position: absolute;
top:50%;
left:0;
transform: translate(0,-50%);
}
}
&.status-warn{
&:before{
content: "";
display: inline-block;
width: 15px;
height: 15px;
border-radius: 50%;
background-color: #FC6B69;
position: absolute;
top:50%;
left:0;
transform: translate(0,-50%);
}
}
}
}
}
.children-item-lists{
//todo 手动修改
&:before{
content: '';
display: block;
width:40px;
height: 4px;
background-color: $arrowColoe;
position: absolute;
top:50%;
left: -50px;
transform:translateY(-50%);
}
&:after{
content: '';
display: block;
height: 0;
width: 0;
border-left: 10px solid #5ea9df;
border-right: 10px solid transparent;
border-bottom: 10px solid transparent;
border-top: 10px solid transparent;
position: absolute;
top: 50%;
left: -14px;
transform:translateY(-50%);
}
}
}
.pcs-has-children-item-square{
vertical-align: middle;
align-items: center;
background-color: #ffefad;
}
.no-bms-list{
.item-lists{
&:not(:last-child){
margin-right:0;
}
}
}
}
}
}
}
</style>

View File

@ -34,7 +34,7 @@
<div <div
class="status" class="status"
:class=" :class="
item.deviceStatus === '1' ? 'status-running' : '' item.deviceStatus === '2' ? 'status-running' : ''
" "
> >
{{ deviceStatusOptions[item.deviceStatus] }} {{ deviceStatusOptions[item.deviceStatus] }}
@ -68,7 +68,7 @@
<div <div
class="status" class="status"
:class=" :class="
item.deviceStatus === '1' ? 'status-running' : '' item.deviceStatus === '2' ? 'status-running' : ''
" "
> >
{{ deviceStatusOptions[item.deviceStatus] }} {{ deviceStatusOptions[item.deviceStatus] }}
@ -107,7 +107,7 @@
<div <div
class="status" class="status"
:class=" :class="
item.deviceStatus === '1' ? 'status-running' : '' item.deviceStatus === '2' ? 'status-running' : ''
" "
> >
{{ deviceStatusOptions[item.deviceStatus] }} {{ deviceStatusOptions[item.deviceStatus] }}
@ -150,7 +150,7 @@
<div <div
class="status" class="status"
:class=" :class="
item.deviceStatus === '1' ? 'status-running' : '' item.deviceStatus === '2' ? 'status-running' : ''
" "
> >
{{ deviceStatusOptions[item.deviceStatus] }} {{ deviceStatusOptions[item.deviceStatus] }}
@ -171,7 +171,7 @@
<div <div
class="status" class="status"
:class=" :class="
item.children[0].deviceStatus === '1' item.children[0].deviceStatus === '2'
? 'status-running' ? 'status-running'
: '' : ''
" "
@ -323,7 +323,7 @@ $lineColor: #86bcc7;
.ems-dashboard-editor-container { .ems-dashboard-editor-container {
background-color: #ffffff; background-color: #ffffff;
padding: 0; padding: 30px;
color: #666666; color: #666666;
.container { .container {

View File

@ -1,42 +1,42 @@
<template> <template>
<el-dialog <el-dialog
v-loading="loading" v-loading="loading"
width="90%" width="90%"
:visible.sync="dialogTableVisible" :visible.sync="dialogTableVisible"
class="ems-dialog" class="ems-dialog"
title="保护方案" title="保护方案"
:close-on-click-modal="false" :close-on-click-modal="false"
:show-close="false" :show-close="false"
> >
<el-form <el-form
v-loading="loading > 0" v-loading="loading > 0"
ref="addTempForm" ref="addTempForm"
:model="formData" :model="formData"
:rules="rules" :rules="rules"
size="medium" size="medium"
label-width="140px" label-width="140px"
> >
<el-form-item label="站点" prop="siteId"> <el-form-item label="站点" prop="siteId">
<el-select <el-select
v-model="formData.siteId" v-model="formData.siteId"
placeholder="请选择" placeholder="请选择"
:style="{ width: '50%' }" :style="{ width: '50%' }"
@change="changeType" @change="changeType"
> >
<el-option <el-option
:label="item.siteName" :label="item.siteName"
:value="item.siteId" :value="item.siteId"
v-for="(item, index) in siteList" v-for="(item, index) in siteList"
:key="index + 'siteOptions'" :key="index + 'siteOptions'"
></el-option> ></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="设备保护名称" prop="faultName"> <el-form-item label="设备保护名称" prop="faultName">
<el-input <el-input
v-model="formData.faultName" v-model="formData.faultName"
placeholder="请输入" placeholder="请输入"
clearable clearable
:style="{ width: '50%' }" :style="{ width: '50%' }"
> >
</el-input> </el-input>
</el-form-item> </el-form-item>
@ -53,9 +53,9 @@
</el-form-item> </el-form-item>
<el-form-item label="是否告警" prop="isAlert"> <el-form-item label="是否告警" prop="isAlert">
<el-checkbox <el-checkbox
v-model="formData.isAlert" v-model="formData.isAlert"
:true-label="1" :true-label="1"
:false-label="0" :false-label="0"
></el-checkbox> ></el-checkbox>
</el-form-item> </el-form-item>
<el-form-item label="告警等级" prop="faultLevel"> <el-form-item label="告警等级" prop="faultLevel">
@ -81,11 +81,11 @@
</div> </div>
<div> <div>
<el-button <el-button
@click.native.prevent="addRow('protectionSettings')" @click.native.prevent="addRow('protectionSettings')"
block block
type="primary" type="primary"
size="mini" size="mini"
style="margin-bottom: 20px" style="margin-bottom: 20px"
> >
新增保护前提 新增保护前提
</el-button> </el-button>
@ -103,40 +103,38 @@
<div>操作</div> <div>操作</div>
</div> </div>
<div <div
class="time-lists" class="time-lists"
v-for="(item, index) in protectionSettings" v-for="(item, index) in protectionSettings"
:key="'protectionSettings' + index" :key="'protectionSettings' + index"
> >
<div> <div>
<el-cascader <el-cascader
v-model="item.deviceId" v-model="item.deviceId"
:options="childOptions" :options="childOptions"
:props="props"
:show-all-levels="false" :show-all-levels="false"
:ref="'protectionSettings'+index"
@change="(v)=>handleChange(v,'protectionSettings',index)" @change="(v)=>handleChange(v,'protectionSettings',index)"
></el-cascader> ></el-cascader>
</div> </div>
<div> <div>
<el-autocomplete <el-autocomplete
v-model="item.point" v-model="item.point"
placeholder="请输入点位" placeholder="请输入点位"
clearable clearable
:fetch-suggestions=" :fetch-suggestions="
(q, c) => (q, c) =>
querySearchAsync(q, c, index, 'protectionSettings') querySearchAsync(q, c, index, 'protectionSettings')
" "
@select="(v) => handleSelect(v, index, 'protectionSettings')" @select="(v) => handleSelect(v, index, 'protectionSettings')"
></el-autocomplete> ></el-autocomplete>
</div> </div>
<div> <div>
<el-select v-model="item.faultOperator" placeholder="请选择"> <el-select v-model="item.faultOperator" placeholder="请选择">
<el-option <el-option
v-for="(value, key) in comparisonOperatorOptions" v-for="(value, key) in comparisonOperatorOptions"
:key="key + 'faultOperator'" :key="key + 'faultOperator'"
:label="key" :label="key"
:value="value" :value="value"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
@ -147,35 +145,35 @@
<div> <div>
<el-select v-model="item.releaseOperator" placeholder="请选择"> <el-select v-model="item.releaseOperator" placeholder="请选择">
<el-option <el-option
v-for="(value, key) in comparisonOperatorOptions" v-for="(value, key) in comparisonOperatorOptions"
:key="key + 'releaseOperator'" :key="key + 'releaseOperator'"
:label="key" :label="key"
:value="value" :value="value"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
<div> <div>
<el-input <el-input
placeholder="请输入释放值" placeholder="请输入释放值"
v-model="item.releaseValue" v-model="item.releaseValue"
> >
</el-input> </el-input>
</div> </div>
<div> <div>
<el-select v-model="item.relationNext" placeholder="请选择"> <el-select v-model="item.relationNext" placeholder="请选择">
<el-option <el-option
v-for="(value, key) in relationWithPoint" v-for="(value, key) in relationWithPoint"
:key="key + 'relation'" :key="key + 'relation'"
:label="key" :label="key"
:value="value" :value="value"
></el-option> ></el-option>
</el-select> </el-select>
</div> </div>
<div> <div>
<el-button <el-button
@click.native.prevent="deleteRow(index,'protectionSettings')" @click.native.prevent="deleteRow(index,'protectionSettings')"
type="warning" type="warning"
size="mini" size="mini"
> >
删除 删除
</el-button> </el-button>
@ -200,11 +198,11 @@
</div> </div>
<div> <div>
<el-button <el-button
@click.native.prevent="addRow('protectionPlan')" @click.native.prevent="addRow('protectionPlan')"
block block
type="primary" type="primary"
size="mini" size="mini"
style="margin-bottom: 20px" style="margin-bottom: 20px"
> >
新增保护方案 新增保护方案
</el-button> </el-button>
@ -219,29 +217,27 @@
<div>操作</div> <div>操作</div>
</div> </div>
<div <div
class="time-lists" class="time-lists"
v-for="(item, index) in protectionPlan" v-for="(item, index) in protectionPlan"
:key="'protectionPlan' + index" :key="'protectionPlan' + index"
> >
<div> <div>
<el-cascader <el-cascader
v-model="item.deviceId" v-model="item.deviceId"
:show-all-levels="false" :show-all-levels="false"
:options="childOptions" :options="childOptions"
:props="props"
:ref="'protectionPlan'+index"
@change="(v)=>handleChange(v,'protectionPlan',index)" @change="(v)=>handleChange(v,'protectionPlan',index)"
></el-cascader> ></el-cascader>
</div> </div>
<div> <div>
<el-autocomplete <el-autocomplete
v-model="item.point" v-model="item.point"
placeholder="请输入点位" placeholder="请输入点位"
clearable clearable
:fetch-suggestions=" :fetch-suggestions="
(q, c) => querySearchAsync(q, c, index, 'protectionPlan') (q, c) => querySearchAsync(q, c, index, 'protectionPlan')
" "
@select="(v) => handleSelect(v, index, 'protectionPlan')" @select="(v) => handleSelect(v, index, 'protectionPlan')"
></el-autocomplete> ></el-autocomplete>
</div> </div>
@ -252,9 +248,9 @@
</div> </div>
<div> <div>
<el-button <el-button
@click.native.prevent="deleteRow(index,'protectionPlan')" @click.native.prevent="deleteRow(index,'protectionPlan')"
type="warning" type="warning"
size="mini" size="mini"
> >
删除 删除
</el-button> </el-button>
@ -271,12 +267,16 @@
</el-dialog> </el-dialog>
</template> </template>
<script> <script>
import {mapState} from "vuex"; import { mapState } from "vuex";
import {getAllSites} from "@/api/ems/zddt"; 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 {
import {getAllDeviceCategory, pointFuzzyQuery} from "@/api/ems/search"; updateProtectPlan,
addProtectPlan,
getProtectPlan,
getDeviceListBySiteAndCategory
} from "@/api/ems/site";
import { getAllDeviceCategory, pointFuzzyQuery } from "@/api/ems/search";
export default { export default {
data() { data() {
const validateText = (rule, value, callback) => { const validateText = (rule, value, callback) => {
@ -287,17 +287,9 @@ export default {
} }
}; };
return { return {
props: { mode:'',
// emitPath: false,//在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false则只返回该节点的值
lazy: true,
lazyLoad: (node, resolve) => {
console.log('---------node', node)
this.getDeviceList(node, resolve)
}
},
mode: '',
loading: 0, loading: 0,
childOptions: [], childOptions:[],
protectionSettings: [], protectionSettings: [],
protectionPlan: [], protectionPlan: [],
dialogTableVisible: false, dialogTableVisible: false,
@ -310,7 +302,7 @@ export default {
faultLevel: 1, //告警等级 faultLevel: 1, //告警等级
faultDelaySeconds: "", //故障延时 faultDelaySeconds: "", //故障延时
releaseDelaySeconds: "", //释放延时 releaseDelaySeconds: "", //释放延时
description: '',//方案描述 description:'',//方案描述
}, },
rules: { rules: {
siteId: [ siteId: [
@ -321,22 +313,22 @@ export default {
}, },
], ],
faultName: [ faultName: [
{required: true, message: "请输入设备保护名称", trigger: "blur"}, { required: true, message: "请输入设备保护名称", trigger: "blur" },
], ],
isAlert: [ isAlert: [
{required: true, message: "请选择是否告警", trigger: "blur"}, { required: true, message: "请选择是否告警", trigger: "blur" },
], ],
description: [ description: [
{required: true, message: "请输入设备描述", trigger: "blur"}, { required: true, message: "请输入设备描述", trigger: "blur" },
{validator: validateText, trigger: "blur"}, { validator: validateText, trigger: "blur" },
], ],
faultDelaySeconds: [ faultDelaySeconds: [
{required: true, message: "请输入保护前提延时", trigger: "blur"}, { required: true, message: "请输入保护前提延时", trigger: "blur" },
{validator: validateText, trigger: "blur"}, { validator: validateText, trigger: "blur" },
], ],
releaseDelaySeconds: [ releaseDelaySeconds: [
{required: true, message: "请输入保护方案延时", trigger: "blur"}, { required: true, message: "请输入保护方案延时", trigger: "blur" },
{validator: validateText, trigger: "blur"}, { validator: validateText, trigger: "blur" },
], ],
}, },
}; };
@ -344,24 +336,24 @@ export default {
computed: { computed: {
...mapState({ ...mapState({
communicationStatusOptions: (state) => communicationStatusOptions: (state) =>
state?.ems?.communicationStatusOptions || {}, state?.ems?.communicationStatusOptions || {},
deviceTypeOptions: (state) => state?.ems?.deviceTypeOptions || {}, deviceTypeOptions: (state) => state?.ems?.deviceTypeOptions || {},
comparisonOperatorOptions: (state) => comparisonOperatorOptions: (state) =>
state?.ems?.comparisonOperatorOptions || {}, state?.ems?.comparisonOperatorOptions || {},
relationWithPoint: (state) => state?.ems?.relationWithPoint || {}, relationWithPoint: (state) => state?.ems?.relationWithPoint || {},
}), }),
}, },
methods: { methods: {
open(id, siteId) { open(id,siteId){
this.dialogTableVisible = true this.dialogTableVisible=true
this.getZdList(); this.getZdList();
this.getDeviceCategoryList().then(() => { this.getDeviceCategoryList().then(()=>{
if (id && siteId) { if(id && siteId) {
// this.getDeviceList('PCS', siteId) this.getDeviceList('PCS',siteId)
// this.getDeviceList('STACK', siteId) this.getDeviceList('STACK',siteId)
} }
}); });
if (id) { if(id){
this.formData.id = id this.formData.id = id
this.mode = 'edit' this.mode = 'edit'
getProtectPlan(id).then(response => { getProtectPlan(id).then(response => {
@ -373,74 +365,53 @@ export default {
isAlert: data?.isAlert || 0, //是否告警 isAlert: data?.isAlert || 0, //是否告警
faultLevel: data?.faultLevel || 1, //告警等级 faultLevel: data?.faultLevel || 1, //告警等级
faultDelaySeconds: data?.faultDelaySeconds || "", //故障延时 faultDelaySeconds: data?.faultDelaySeconds || "", //故障延时
releaseDelaySeconds: data?.releaseDelaySeconds || "", //释放延时 releaseDelaySeconds: data?.releaseDelaySeconds ||"", //释放延时
description: data?.description || '',//方案描述 description: data?.description ||'',//方案描述
} }
const plan = (JSON.parse(data?.protectionPlan || [])).map(item => { const plan =(JSON.parse(data?.protectionPlan || [])).map(item=>{
const index = this.childOptions.findIndex(i => i.value === item.deviceCategory) return Object.assign({},item,{
if (index > -1) { deviceId:[item.deviceCategory || '',item.deviceId || ''],
!this.childOptions[index].children.find(i => i.value === item.deviceId) && this.childOptions[index].children.push({
value: item.deviceId,
label: item.deviceName,
leaf: true
})
}
return Object.assign({}, item, {
deviceId: [item.deviceCategory || '', item.deviceId || ''],
deviceName: [item.categoryName || '', item.deviceName || ''],
}) })
}) })
const settings = (JSON.parse(data?.protectionSettings || [])).map(item => { const settings =(JSON.parse(data?.protectionSettings || [])).map(item=>{
const index = this.childOptions.findIndex(i => i.value === item.deviceCategory) return Object.assign({},item,{
if (index > -1) { deviceId:[item.deviceCategory || '',item.deviceId || ''],
!this.childOptions[index].children.find(i => i.value === item.deviceId) && this.childOptions[index].children.push({
value: item.deviceId,
label: item.deviceName,
leaf: true
})
}
return Object.assign({}, item, {
deviceId: [item.deviceCategory || '', item.deviceId || ''],
deviceName: [item.categoryName || '', item.deviceName || ''],
}) })
}) })
this.$nextTick(() => { this.$nextTick(()=>{
this.protectionPlan.splice(0, 0, ...plan) this.protectionPlan.splice(0,0,...plan)
this.protectionSettings.splice(0, 0, ...settings) this.protectionSettings.splice(0,0,...settings)
}) })
console.log('获取设备保护详情并初始化', this.formData, this.protectionPlan, this.protectionSettings, this.childOptions) console.log('获取设备保护详情并初始化',this.formData,this.protectionPlan,this.protectionSettings)
}) })
} else { }else{
this.mode = 'add' this.mode = 'add'
} }
}, },
// 新增设备保护前提、设备保护方案 // 新增设备保护前提、设备保护方案
addRow(type) { addRow(type) {
const item = type === 'protectionSettings' ? { const item = type === 'protectionSettings' ? {
deviceId: [],//设备ID deviceId:[],//设备ID
deviceName: [],
deviceCategory: "",//设备类型 英文 deviceCategory: "",//设备类型 英文
categoryName: '',//设备类型名称 中文 categoryName:'',//设备类型名称 中文
point: "",//点位 英文 point: "",//点位 英文
pointName: "",//点位 中文 pointName:"",//点位 中文
faultValue: "",//故障值 faultValue: "",//故障值
releaseValue: "",//释放值 releaseValue: "",//释放值
faultOperator: "",//故障值比较关系 faultOperator: "",//故障值比较关系
releaseOperator: "",//释放值比较关系 releaseOperator: "",//释放值比较关系
relationNext: "",//与下一个点位的关系 relationNext: "",//与下一个点位的关系
} : { } : {
deviceId: [], deviceId:[],
deviceName: [],
deviceCategory: "",//设备类型 英文 deviceCategory: "",//设备类型 英文
categoryName: '',//设备类型名称 中文 categoryName:'',//设备类型名称 中文
point: "", point: "",
pointName: "", pointName:"",
value: "",//设置值 value: "",//设置值
} }
// this.$set(this[type], this[type].length, item); // this.$set(this[type], this[type].length, item);
this[type].splice(this[type].length, 0, item) this[type].splice(this[type].length,0,item)
console.log('新增设备保护前提、方案', type, this[type]) console.log('新增设备保护前提、方案',type,this[type])
}, },
// 删除设备保护前提、设备保护方案 // 删除设备保护前提、设备保护方案
deleteRow(index, type) { deleteRow(index, type) {
@ -464,25 +435,25 @@ export default {
}).then((response) => { }).then((response) => {
const data = response?.data || []; const data = response?.data || [];
cb( cb(
data.map((item) => { data.map((item) => {
return {name: item, value: item}; return { name: item, value: item };
}) })
); );
}); });
}, },
// 点位选择 // 点位选择
handleSelect(data, index, type) { handleSelect(data, index, type) {
console.log('选择点位', data, index, type) console.log('选择点位',data,index,type)
// this.$set(this[type], index, Object.assign({},this[type][index],{ // this.$set(this[type], index, Object.assign({},this[type][index],{
// point:data.value, // point:data.value,
// pointName:data.value, // pointName:data.value,
// })); // }));
let line = Object.assign({}, this[type][index], { let line = Object.assign({},this[type][index],{
point: data.value, point:data.value,
pointName: data.value, pointName:data.value,
}) })
this[type].splice(index, 1, line); this[type].splice(index,1,line);
console.log('选择点位配置完成', this[type][index]) console.log('选择点位配置完成',this[type][index])
}, },
// 获取设备类别-不区分站点 // 获取设备类别-不区分站点
@ -490,86 +461,79 @@ export default {
this.loading += 1; this.loading += 1;
return getAllDeviceCategory() return getAllDeviceCategory()
.then((response) => { .then((response) => {
const data = (response?.data || []); const data = (response?.data || []).filter(item => ['PCS','STACK'].includes(item.code));
this.$set(this, 'childOptions', []) // this.childOptions=[]
let arr = [] this.$set(this,'childOptions',[])
let arr =[]
data.forEach((item) => { data.forEach((item) => {
arr.push({ arr.push({
value: item.code, value: item.code,
label: item.name, label: item.name,
leaf: false, children:[]
children: []
}) })
}) })
this.childOptions.splice(0, 0, ...arr) this.childOptions.splice(0,0,...arr)
console.log('获取设备类型', data, this.childOptions) console.log('获取设备类型',data,this.childOptions)
}) })
.finally(() => { .finally(() => {
this.loading -= 1; this.loading -= 1;
}); });
}, },
//获取设备列表-区分站点 //获取设备列表-区分站点
getDeviceList(node, resolve) { getDeviceList(deviceCategory,siteId){
if (!this.formData.siteId) { this.$nextTick(()=>{
this.$message({ getDeviceListBySiteAndCategory({siteId:siteId || this.formData.siteId,deviceCategory}).then((response) => {
type: "warning", const data = (response?.data || []).map(item => {
message: "请先选择站点", return {
}); label: item.deviceName,
return resolve([]) value: item.id,
} }
getDeviceListBySiteAndCategory({ })
siteId: this.formData.siteId, const index = this.childOptions.findIndex(item=>item.value === deviceCategory)
deviceCategory: node.value if(index>-1){
}).then((response) => { const length = this.childOptions[index].children.length
const data = (response?.data || []).map(item => { this.childOptions[index].children.splice(0,length,...data)
return {
label: item.deviceName,
value: item.id,
leaf: true
} }
}) })
resolve(data)
}).catch(() => {
resolve([])
}) })
}, },
//更新站点下面的设备列表 //更新站点下面的设备列表
updateSiteDeviceList() { updateSiteDeviceList(){
this.childOptions.forEach(item => { this.childOptions.forEach(item => {
const length = item.children.length const length = item.children.length
item.children.splice(0, length) item.children.splice(0,length)
}) })
this.getDeviceList('PCS')
this.getDeviceList('STACK')
}, },
//选中设备类型、设备 //选中设备类型、设备
handleChange(data, type, index) { handleChange(data,type,index){
console.log('设置选中设备类型、设备', data, type, index) const deviceCategory = data[0],deviceId=data[1]
const {label = '', parent = {}} = this.$refs[type + index][0].getCheckedNodes()[0] console.log('设置选中设备类型、设备',deviceCategory,deviceId,type,index)
console.log('选中设备的名称', parent.label, label) const item = Object.assign({},this[type][index],{
const item = Object.assign({}, this[type][index], { deviceId:data,
deviceId: data, deviceCategory,
deviceName: [parent.label, label], categoryName : this.childOptions.find(i=>i.value === deviceCategory).label,
deviceCategory: data[0], pointName:'',
categoryName: parent.label, point:''
pointName: '',
point: ''
}) })
this.$nextTick(() => { this.$nextTick(()=>{
// this.$set(this[type], index, item); // this.$set(this[type], index, item);
this[type].splice(index, 1, item); this[type].splice(index,1,item);
}) })
console.log('设置选中设备类型、设备配置完成', this[type][index]) console.log('设置选中设备类型、设备配置完成',this[type][index])
}, },
//获取站点列表 //获取站点列表
getZdList() { getZdList() {
this.loading += 1; this.loading += 1;
getAllSites() getAllSites()
.then((response) => { .then((response) => {
this.siteList = response?.data || []; this.siteList = response?.data || [];
}) })
.finally(() => { .finally(() => {
this.loading -= 1; this.loading -= 1;
}); });
}, },
// 切换站点 // 切换站点
// 重新获取设备列表 // 重新获取设备列表
@ -577,65 +541,62 @@ export default {
changeType() { changeType() {
//获取当前站点下的pcs和bms //获取当前站点下的pcs和bms
this.updateSiteDeviceList() this.updateSiteDeviceList()
if (this.protectionSettings.length > 0) { if(this.protectionSettings.length>0){
const list = this.protectionSettings const list =this.protectionSettings
list.forEach((item) => { list.forEach((item) => {
item.point = "" item.point = ""
item.pointName = "" item.pointName = ""
item.deviceId = [] item.deviceId=[]
item.deviceName = [] item.categoryName=''
item.categoryName = '' item.deviceCategory=''
item.deviceCategory = ''
}); });
// this.$set(this,'protectionSettings',list) // this.$set(this,'protectionSettings',list)
this.$nextTick(() => { this.$nextTick(()=>{
this.protectionSettings.splice(0, this.protectionSettings.length, ...list) this.protectionSettings.splice(0,this.protectionSettings.length,...list)
}) })
} }
if (this.protectionPlan.length > 0) { if(this.protectionPlan.length>0){
const list = this.protectionPlan const list =this.protectionPlan
list.forEach((item) => { list.forEach((item) => {
item.point = "" item.point = ""
item.pointName = "" item.pointName = ""
item.deviceId = [] item.deviceId=[]
item.deviceName = [] item.categoryName=''
item.categoryName = '' item.deviceCategory=''
item.deviceCategory = ''
}); });
// this.$set(this,'protectionPlan',list) // this.$set(this,'protectionPlan',list)
this.$nextTick(() => { this.$nextTick(()=>{
this.protectionPlan.splice(0, this.protectionPlan.length, ...list) this.protectionPlan.splice(0,this.protectionPlan.length,...list)
}) })
} }
}, },
saveDialog() { saveDialog() {
function getToastMsg(name, type, index) { function getToastMsg(name,type,index){
return { return {
protectionSettings: { protectionSettings:{
deviceId: `请选择保护前提第${index}行的设备`,//设备ID deviceId:`请选择保护前提第${index}行的设备`,//设备ID
deviceCategory: `请选择保护前提第${index}行的设备类型`,//设备类型 英文 deviceCategory: `请选择保护前提第${index}行的设备类型`,//设备类型 英文
categoryName: `请选择保护前提第${index}行的设备类型`,//设备类型名称 中文 categoryName:`请选择保护前提第${index}行的设备类型`,//设备类型名称 中文
point: `请选择保护前提第${index}行的点位`,//点位 英文 point: `请选择保护前提第${index}行的点位`,//点位 英文
pointName: `请选择保护前提第${index}行的点位`,//点位 中文 pointName:`请选择保护前提第${index}行的点位`,//点位 中文
faultValue: `请输入保护前提第${index}行的故障值`,//故障值 faultValue: `请输入保护前提第${index}行的故障值`,//故障值
releaseValue: `请输入保护前提第${index}行的释放值`,//释放值 releaseValue: `请输入保护前提第${index}行的释放值`,//释放值
faultOperator: `请选择保护前提第${index}行的故障值比较关系`,//故障值比较关系 faultOperator: `请选择保护前提第${index}行的故障值比较关系`,//故障值比较关系
releaseOperator: `请选择保护前提第${index}行的释放值比较关系`,//释放值比较关系 releaseOperator: `请选择保护前提第${index}行的释放值比较关系`,//释放值比较关系
relationNext: `请选择保护前提第${index}行与下一个点位的关系`,//与下一个点位的关系 relationNext: `请选择保护前提第${index}行与下一个点位的关系`,//与下一个点位的关系
}, },
protectionPlan: { protectionPlan :{
deviceId: `请选择保护方案第${index}行的设备`, deviceId:`请选择保护方案第${index}行的设备`,
deviceCategory: `请选择保护方案第${index}行的设备类型`,//设备类型 英文 deviceCategory: `请选择保护方案第${index}行的设备类型`,//设备类型 英文
categoryName: `请选择保护方案第${index}行的设备类型`,//设备类型名称 中文 categoryName:`请选择保护方案第${index}行的设备类型`,//设备类型名称 中文
point: `请选择保护方案第${index}行的点位`, point: `请选择保护方案第${index}行的点位`,
pointName: `请选择保护方案第${index}行的点位`, pointName:`请选择保护方案第${index}行的点位`,
value: `请输入保护方案第${index}行的故障值`,//设置值 value: `请输入保护方案第${index}行的故障值`,//设置值
} }
}[type][name] }[type][name]
} }
this.$refs.addTempForm.validate((valid) => { this.$refs.addTempForm.validate((valid) => {
if (!valid) return; if (!valid) return;
const { const {
@ -646,69 +607,67 @@ export default {
faultLevel = 1, //告警等级 faultLevel = 1, //告警等级
faultDelaySeconds = "", //故障延时 faultDelaySeconds = "", //故障延时
releaseDelaySeconds = "", //释放延时 releaseDelaySeconds = "", //释放延时
description = "",//方案描述 description="",//方案描述
} = this.formData; } = this.formData;
const {protectionSettings, protectionPlan} = this const {protectionSettings,protectionPlan} = this
let protectionSettingsValidateStatus = true, protectionPlanValidateStatus = true let protectionSettingsValidateStatus= true , protectionPlanValidateStatus= true
for (let i = 0; i < protectionSettings.length; i++) { for(let i = 0;i<protectionSettings.length;i++){
let valueMap = Object.entries(protectionSettings[i]); let valueMap = Object.entries(protectionSettings[i]);
for (let inner = 0; inner < valueMap.length; inner++) { for(let inner = 0;inner < valueMap.length;inner++){
const key = valueMap[inner][0], value = valueMap[inner][1] const key =valueMap[inner][0],value =valueMap[inner][1]
if (key === 'relationNext') { if(key === 'relationNext'){
if (protectionSettings[i + 1] && !value) {//有下一个点位 if(protectionSettings[i+1] && !value){//有下一个点位
this.$message.error(getToastMsg(key, 'protectionSettings', i + 1)) this.$message.error(getToastMsg(key,'protectionSettings',i+1))
protectionSettingsValidateStatus = false protectionSettingsValidateStatus=false
break break
} }
} else { }else{
if (![0, '0'].includes(value) && !value) { if(![0,'0'].includes(value) && !value){
this.$message.error(getToastMsg(key, 'protectionSettings', i + 1)) this.$message.error(getToastMsg(key,'protectionSettings',i+1))
protectionSettingsValidateStatus = false protectionSettingsValidateStatus=false
break break
} }
} }
} }
if (!protectionSettingsValidateStatus) break if(!protectionSettingsValidateStatus) break
} }
for (let i = 0; i < protectionPlan.length; i++) { for(let i = 0;i<protectionPlan.length;i++){
let valueMap = Object.entries(protectionPlan[i]); let valueMap = Object.entries(protectionPlan[i]);
for (let inner = 0; inner < valueMap.length; inner++) { for(let inner = 0;inner < valueMap.length;inner++){
const key = valueMap[inner][0], value = valueMap[inner][1] const key =valueMap[inner][0],value =valueMap[inner][1]
if (key === 'relationNext') { if(key === 'relationNext'){
if (protectionPlan[i + 1] && !value) {//有下一个点位 if(protectionPlan[i+1] && !value){//有下一个点位
this.$message.error(getToastMsg(key, 'protectionPlan', i + 1)) this.$message.error(getToastMsg(key,'protectionPlan',i+1))
protectionPlanValidateStatus = false protectionPlanValidateStatus=false
break break
} else { }else{
// protectionPlan[i][key] = ''//清空选择的关系 // protectionPlan[i][key] = ''//清空选择的关系
} }
} else { }else{
if (![0, '0'].includes(value) && !value) { if(![0,'0'].includes(value) && !value){
this.$message.error(getToastMsg(key, 'protectionPlan', i + 1)) this.$message.error(getToastMsg(key,'protectionPlan',i+1))
protectionPlanValidateStatus = false protectionPlanValidateStatus=false
break break
} }
} }
} }
if (!protectionPlanValidateStatus) break if(!protectionPlanValidateStatus) break
} }
if (!protectionSettingsValidateStatus || !protectionPlanValidateStatus) return if(!protectionSettingsValidateStatus || !protectionPlanValidateStatus) return
const settings = protectionSettings.map(item => { const settings = protectionSettings.map(item=>{
return Object.assign({}, item, { return Object.assign({},item,{
deviceId: item.deviceId[1], deviceId:item.deviceId[1],
deviceName: item.deviceName[1],
}) })
}) })
const plan = protectionPlan.map(item => { const plan = protectionPlan.map(item=>{
return Object.assign({}, item, { return Object.assign({},item,{
deviceId: item.deviceId[1], deviceId:item.deviceId[1],
deviceName: item.deviceName[1],
}) })
}) })
this.loading += 1; this.loading += 1;
const params = { const params= {
siteId, siteId,
faultName, faultName,
isAlert, isAlert,
@ -716,49 +675,49 @@ export default {
faultDelaySeconds, faultDelaySeconds,
releaseDelaySeconds, releaseDelaySeconds,
description, description,
protectionSettings: JSON.stringify(settings), protectionSettings:JSON.stringify(settings),
protectionPlan: JSON.stringify(plan), protectionPlan:JSON.stringify(plan),
} }
if (this.mode === "add") { if (this.mode === "add") {
addProtectPlan(params) addProtectPlan(params)
.then((response) => { .then((response) => {
if (response.code === 200) { if (response.code === 200) {
//新增成功 //新增成功
// 关闭弹窗 更新表格 // 关闭弹窗 更新表格
this.$emit("update"); this.$emit("update");
this.closeDialog(); this.closeDialog();
} }
}) })
.finally(() => { .finally(() => {
this.loading -= 1; this.loading -= 1;
}); });
} else { } else {
params.id = id params.id = id
updateProtectPlan(params) updateProtectPlan(params)
.then((response) => { .then((response) => {
if (response.code === 200) { if (response.code === 200) {
//新增成功 //新增成功
// 关闭弹窗 更新表格 // 关闭弹窗 更新表格
this.$emit("update"); this.$emit("update");
this.closeDialog(); this.closeDialog();
} }
}) })
.finally(() => { .finally(() => {
this.loading -= 1; this.loading -= 1;
}); });
} }
}); });
}, },
closeDialog() { closeDialog() {
this.$emit("clear"); this.$emit("clear");
// 清空所有数据 // 清空所有数据
for (let key in this.formData) { for(let key in this.formData) {
this.formData[key] = key === 'isAlert' ? 0 : key === 'faultLevel' ? 1 : '' this.formData[key] = key === 'isAlert' ? 0 : key === 'faultLevel' ? 1 : ''
} }
this.$refs.addTempForm.resetFields(); this.$refs.addTempForm.resetFields();
this.$set(this, 'protectionSettings', []) this.$set(this,'protectionSettings',[])
this.$set(this, 'protectionPlan', []) this.$set(this,'protectionPlan',[])
this.$set(this, 'childOptions', []) this.$set(this,'childOptions',[])
this.dialogTableVisible = false; this.dialogTableVisible = false;
}, },
}, },
@ -768,43 +727,35 @@ export default {
.items-container { .items-container {
margin-top: 40px; margin-top: 40px;
margin-bottom: 20px; margin-bottom: 20px;
.item-title { .item-title {
line-height: 16px; line-height: 16px;
padding: 10px 0; padding: 10px 0;
color: #000; color: #000;
} }
} }
.time-lists-container { .time-lists-container {
width: 100%; width: 100%;
border: 1px solid #eee; border: 1px solid #eee;
.time-lists { .time-lists {
&:not(:last-child) { &:not(:last-child) {
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
display: flex; display: flex;
& > div { & > div {
width: 16%; width: 16%;
box-sizing: border-box; box-sizing: border-box;
text-align: center; text-align: center;
padding: 10px 15px; padding: 10px 15px;
&:not(:last-child) { &:not(:last-child) {
width: 28%; width: 28%;
border-right: 1px solid #eee; border-right: 1px solid #eee;
} }
.el-date-editor.el-input, .el-date-editor.el-input,
.el-date-editor.el-input__inner { .el-date-editor.el-input__inner {
width: 100%; width: 100%;
} }
} }
} }
.time-lists-title { .time-lists-title {
color: #000; color: #000;
font-size: 12px; font-size: 12px;

View File

@ -1,136 +1,77 @@
<template> <template>
<el-dialog :visible.sync="dialogTableVisible" :close-on-press-escape="false" :close-on-click-modal="false" <el-dialog :visible.sync="dialogTableVisible" :close-on-press-escape="false" :close-on-click-modal="false" :show-close="false" destroy-on-close lock-scroll append-to-body width="600px" class="ems-dialog" :title="mode === 'add'?'新增设备':`编辑设备` " >
:show-close="false" destroy-on-close lock-scroll append-to-body width="800px" class="ems-dialog" <el-form v-loading="loading>0" ref="addTempForm" :model="formData" :rules="rules" size="medium" label-width="140px">
:title="mode === 'add'?'新增设备':`编辑设备` "> <el-form-item label="站点" prop="siteId">
<div v-loading="loading>0"> <el-select v-model="formData.siteId" placeholder="请选择" :style="{width: '100%'}" @change="changeType">
<el-form v-loading="loading>0" ref="addTempForm" inline :model="formData" :rules="rules" size="medium" <el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" :key="index+'siteOptions'"></el-option>
label-width="120px" class="device-form"> </el-select>
<el-form-item label="站点" prop="siteId"> </el-form-item>
<el-select v-model="formData.siteId" placeholder="请选择" :style="{width: '100%'}" @change="changeType"> <el-form-item label="设备id" prop="deviceId" >
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList" <el-input v-model="formData.deviceId" placeholder="请输入" maxlength="60" clearable :style="{width: '100%'}">
:key="index+'siteOptions'"></el-option> </el-input>
</el-select> </el-form-item>
</el-form-item> <el-form-item label="设备名称" prop="deviceName">
<el-form-item label="设备id" prop="deviceId"> <el-input v-model="formData.deviceName" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="formData.deviceId" placeholder="请输入" maxlength="60" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="设备描述" prop="description">
<el-form-item label="设备名称" prop="deviceName"> <el-input v-model="formData.description" type="textarea" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="formData.deviceName" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="工作状态" prop="communicationStatus">
<el-form-item label="设备描述" prop="description"> <el-select v-model="formData.communicationStatus" placeholder="请选择" :style="{width: '100%'}">
<el-input v-model="formData.description" type="textarea" placeholder="请输入" clearable <el-option :label="value" :value="key" v-for="(value,key) in communicationStatusOptions" :key="key+'communicationStatusOptions'"></el-option>
:style="{width: '100%'}"> </el-select>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="设备类型" prop="deviceType">
<el-form-item label="工作状态" prop="communicationStatus"> <el-select v-model="formData.deviceType" placeholder="请选择" :style="{width: '100%'}">
<el-select v-model="formData.communicationStatus" placeholder="请选择" :style="{width: '100%'}"> <el-option :label="value" :value="key" v-for="(value,key) in deviceTypeOptions" :key="key+'deviceTypeOptions'"></el-option>
<el-option :label="value" :value="key" v-for="(value,key) in communicationStatusOptions" </el-select>
:key="key+'communicationStatusOptions'"></el-option> </el-form-item>
</el-select> <el-form-item label="设备类别" prop="deviceCategory">
</el-form-item> <el-select v-model="formData.deviceCategory" placeholder="请选择" :style="{width: '100%'}" @change="changeType">
<el-form-item label="设备类型" prop="deviceType"> <el-option :label="item.name" :value="item.code" v-for="(item,index) in deviceCategoryList" :key="index+'deviceCategoryList'"></el-option>
<el-select v-model="formData.deviceType" placeholder="请选择" :style="{width: '100%'}"> </el-select>
<el-option :label="value" :value="key" v-for="(value,key) in deviceTypeOptions" </el-form-item>
:key="key+'deviceTypeOptions'"></el-option> <el-form-item label="上级设备" prop="parentId" v-if="dccDeviceCategoryList.includes(formData.deviceCategory)">
</el-select> <el-select v-model="formData.parentId" :placeholder="parentDeviceList.length === 0 && !formData.siteId ? '请先选择站点' : '请选择'" :style="{width: '100%'}">
</el-form-item> <el-option :label="item.deviceName" :value="item.id" v-for="(item,index) in parentDeviceList" :key="index+'parentDeviceList'" ></el-option>
<el-form-item label="设备类别" prop="deviceCategory"> </el-select>
<el-select v-model="formData.deviceCategory" placeholder="请选择" :style="{width: '100%'}" </el-form-item>
@change="changeType"> <el-form-item label="TCP设备的ip地址" prop="ipAddress" v-if="formData.deviceType === 'TCP'">
<el-option :label="item.name" :value="item.code" v-for="(item,index) in deviceCategoryList" <el-input v-model="formData.ipAddress" placeholder="请输入" clearable :style="{width: '100%'}">
:key="index+'deviceCategoryList'"></el-option> </el-input>
</el-select> </el-form-item>
</el-form-item> <el-form-item label="TCP设备的端口号" prop="ipPort" v-if="formData.deviceType === 'TCP'">
<el-form-item label="上级设备" prop="parentId" v-if="dccDeviceCategoryList.includes(formData.deviceCategory)"> <el-input v-model="formData.ipPort" placeholder="请输入" clearable :style="{width: '100%'}">
<el-select v-model="formData.parentId" </el-input>
:placeholder="parentDeviceList.length === 0 && !formData.siteId ? '请先选择站点' : '请选择'" </el-form-item>
: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> <el-form-item label="串口路径" prop="serialPort">
<!-- pcs配置--> <el-input v-model="formData.serialPort" placeholder="请输入" clearable :style="{width: '100%'}">
<el-form v-if="isPcs" ref="pcsSettingForm" inline :model="pcsSetting" size="medium" </el-input>
label-width="120px" class="device-form" :rules="pcsSettingRules"> </el-form-item>
<div style="font-size: 14px;padding: 10px 0 20px;font-weight: 600;">PCS配置</div> <el-form-item label="波特率" prop="baudRate">
<el-form-item label="开关机地址" prop="pointAddress"> <el-input v-model="formData.baudRate" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="pcsSetting.pointAddress" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="数据位" prop="dataBits">
<el-form-item label="功率地址" prop="powerAddress"> <el-input v-model="formData.dataBits" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="pcsSetting.powerAddress" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="停止位" prop="stopBits">
<el-form-item label="开机指令" prop="startCommand"> <el-input v-model="formData.stopBits" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="pcsSetting.startCommand" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="校验位" prop="parity">
<el-form-item label="开机目标功率" prop="startPower"> <el-input v-model="formData.parity" placeholder="请输入" clearable :style="{width: '100%'}">
<el-input v-model="pcsSetting.startPower" placeholder="请输入" clearable :style="{width: '100%'}"> </el-input>
</el-input> </el-form-item>
</el-form-item> <el-form-item label="图片" prop="pictureUrl">
<el-form-item label="关机指令" prop="stopCommand"> <image-upload :limit="1" :drag="false" @input="uploadImage" :value="formData.pictureUrl"/>
<el-input v-model="pcsSetting.stopCommand" placeholder="请输入" clearable :style="{width: '100%'}"> </el-form-item>
</el-input>
</el-form-item> </el-form>
<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%'}">
</el-input>
</el-form-item>
</template>
</el-form>
</div>
<div slot="footer"> <div slot="footer">
<el-button @click="closeDialog">取消</el-button> <el-button @click="closeDialog">取消</el-button>
<el-button type="primary" @click="saveDialog">确定</el-button> <el-button type="primary" @click="saveDialog">确定</el-button>
@ -141,404 +82,257 @@
import {mapState} from "vuex"; import {mapState} from "vuex";
import {getAllSites} from '@/api/ems/zddt' import {getAllSites} from '@/api/ems/zddt'
import {validText} from '@/utils/validate' import {validText} from '@/utils/validate'
import {addDevice, getDeviceDetailInfo, getParentDeviceId, updateDevice} from "@/api/ems/site"; import {getDeviceDetailInfo,updateDevice,addDevice,getParentDeviceId} from "@/api/ems/site";
import {getAllDeviceCategory} from '@/api/ems/search' import {getAllDeviceCategory} from '@/api/ems/search'
export default { export default {
props: { props:{
mode: { mode:{
type: String, type:String,
default: "add" default:"add"
}, },
id: { id:{
type: String | Number, type:String|Number,
required: false required:false
} }
}, },
data() { data() {
const validateText = (rule, value, callback) => { const validateText=(rule, value, callback) =>{
if (value !== '' && !validText(value)) { if (value !== '' && !validText(value)) {
callback(new Error('只能输入中文、英文、数字和特殊字符!')); callback(new Error('只能输入中文、英文、数字和特殊字符!'));
} else { } else {
callback(); callback();
} }
} }
const validateDeviceId = (rule, value, callback) => { const validateDeviceId=(rule, value, callback) =>{
if (value !== '' && !/^[a-zA-Z0-9]+$/.test(value)) { if (value !== '' && !/^[a-zA-Z0-9]+$/.test(value)) {
callback(new Error('只能输入英文和数字!')); callback(new Error('只能输入英文和数字!'));
} else { } else {
callback(); callback();
} }
} }
const validateNumber = (rule, value, callback) => {
if (value !== '' && !/^[0-9]+$/.test(value)) {
callback(new Error('只能输入数字!'));
} else {
callback();
}
}
return { return {
loading: 0, loading:0,
dccDeviceCategoryList: ['CLUSTER', 'BATTERY'],//需要展示上级设备的设备类型 dccDeviceCategoryList:['CLUSTER','BATTERY'],//需要展示上级设备的设备类型
dialogTableVisible: false, dialogTableVisible:false,
parentDeviceList: [],//上级设备列表 从接口获取数据 parentDeviceList:[],//上级设备列表 从接口获取数据
siteList: [],//站点列表 从接口获取数据 siteList:[],//站点列表 从接口获取数据
deviceCategoryList: [],//设备类别列表 从接口获取数据 deviceCategoryList:[],//设备类别列表 从接口获取数据
formData: { formData: {
id: '',//设备唯一标识 id:'',//设备唯一标识
siteId: '',//站点ID siteId:'',//站点ID
deviceId: '',//设备id deviceId:'',//设备id
deviceName: '',//设备名称 deviceName:'',//设备名称
description: '',//设备描述 description:'',//设备描述
communicationStatus: '',//工作状态 communicationStatus:'',//工作状态
deviceType: '',//设备类型 deviceType:'',//设备类型
deviceCategory: '',//设备类别 deviceCategory:'',//设备类别
parentId: '',//上级设备id parentId:'',//上级设备id
ipAddress: '',//TCP设备的ip地址 ipAddress:'',//TCP设备的ip地址
ipPort: "",//TCP端口号 ipPort:"",//TCP端口号
serialPort: '',//串口路径 serialPort:'',//串口路径
baudRate: '',//波特率 baudRate:'',//波特率
dataBits: '',//数据位 dataBits:'',//数据位
stopBits: '',//停止位 stopBits:'',//停止位
parity: '',//校验位 parity:'',//校验位
pictureUrl: '',//设备图片 pictureUrl:'',//设备图片
slaveId: '',//从站地址
},
pcsSetting: {
deviceSettingId: '',
powerAddress: '',//功率地址
pointAddress: "",//开关机地址
startCommand: "",//开机指令
stopCommand: "",//关机指令
startPower: '',//开机目标功率
stopPower: '',//关机目标功率
clusterNum: '',//电池簇数
clusterPointAddress: []//电池簇地址
}, },
rules: { rules: {
siteId: [ siteId:[
{required: true, message: '请选择站点', trigger: ['blur', 'change']} { required: true, message: '请选择站点', trigger: ['blur','change']}
], ],
deviceId: [ deviceId:[
{required: true, message: '请输入设备id', trigger: 'blur'}, { required: true, message: '请输入设备id', trigger: 'blur'},
{validator: validateDeviceId, trigger: 'blur'} { validator: validateDeviceId, trigger: 'blur' }
], ],
deviceName: [ deviceName:[
{required: true, message: '请输入设备名称', trigger: 'blur'}, { required: true, message: '请输入设备名称', trigger: 'blur'},
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
description: [ description:[
{required: true, message: '请输入设备描述', trigger: 'blur'}, { required: true, message: '请输入设备描述', trigger: 'blur'},
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
communicationStatus: [ communicationStatus:[
{required: true, message: '请选择工作状态', trigger: ['blur', 'change']} { required: true, message: '请选择工作状态', trigger: ['blur','change']}
], ],
deviceType: [ deviceType:[
{required: true, message: '请选择设备类型', trigger: ['blur', 'change']} { required: true, message: '请选择设备类型', trigger:['blur','change']}
], ],
deviceCategory: [ deviceCategory:[
{required: true, message: '请选择设备类别', trigger: ['blur', 'change']} { required: true, message: '请选择设备类别', trigger: ['blur','change']}
], ],
ipAddress: [ ipAddress:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
ipPort: [ ipPort:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
slaveId: [ serialPort:[
{validator: validateNumber, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
serialPort: [ baudRate:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
baudRate: [ dataBits:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
dataBits: [ stopBits:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
], ],
stopBits: [ parity:[
{validator: validateText, trigger: 'blur'} { validator: validateText, trigger: 'blur' }
],
parity: [
{validator: validateText, trigger: 'blur'}
], ],
// pictureUrl:[ // pictureUrl:[
// { required: true, message: '请上传图片', trigger: ['blur', 'change']} // { required: true, message: '请上传图片', trigger: ['blur', 'change']}
// ], // ],
}, },
pcsSettingRules: {
pointAddress: [
{required: true, message: '请输入开关机地址', trigger: 'blur'},
{validator: validateText, trigger: 'blur'}
],
powerAddress: [
{validator: validateText, trigger: 'blur'}
],
startCommand: [
{required: true, message: '请输入开机指令', trigger: 'blur'},
{validator: validateText, trigger: 'blur'}
],
startPower: [
{validator: validateText, trigger: 'blur'}
],
stopCommand: [
{required: true, message: '请输入关机指令', trigger: 'blur'},
{validator: validateText, trigger: 'blur'}
],
stopPower: [
{validator: validateText, trigger: 'blur'}
],
clusterNum: [
{required: true, message: '请输入电池簇数', trigger: 'blur'},
{validator: validateNumber, trigger: 'blur'}
],
clusterPointAddress: [
{required: true, message: '请输入电池簇地址', trigger: 'blur'},
{validator: validateText, trigger: 'blur'}
]
}
} }
}, },
computed: { computed: {
...mapState({ ...mapState({
communicationStatusOptions: state => state?.ems?.communicationStatusOptions || {}, communicationStatusOptions: state => state?.ems?.communicationStatusOptions || {},
deviceTypeOptions: state => state?.ems?.deviceTypeOptions || {} deviceTypeOptions:state=>state?.ems?.deviceTypeOptions || {}
}), })
isPcs() {
return this.formData.deviceCategory === 'PCS'
}
}, },
watch: { watch:{
dialogTableVisible: { dialogTableVisible:{
handler(newVal) { handler(newVal){
//打开弹窗 //打开弹窗
if (newVal) { if(newVal){
this.getZdList() this.getZdList()
this.getDeviceCategoryList() this.getDeviceCategoryList()
} }
}, },
immediate: true, immediate: true,
}, },
id: { id:{
handler(newVal) { handler(newVal){
if ((newVal || newVal === 0) && this.mode !== 'add') { if((newVal || newVal===0) && this.mode !== 'add'){
this.loading += 1 this.loading+=1
getDeviceDetailInfo(newVal).then(response => { getDeviceDetailInfo(newVal).then(response => {
const {pcsSetting, ...data} = JSON.parse(JSON.stringify(response?.data || {})) this.formData = JSON.parse(JSON.stringify(response?.data || {}));
this.formData = data; if(this.dccDeviceCategoryList.includes(this.formData.deviceCategory)){
if (pcsSetting && JSON.stringify(pcsSetting) !== '{}') {
this.pcsSetting = JSON.parse(JSON.stringify({
...pcsSetting,
clusterPointAddress: JSON.parse(pcsSetting.clusterPointAddress || [])
}));
}
if (this.dccDeviceCategoryList.includes(this.formData.deviceCategory)) {
this.getParentDeviceList(true) this.getParentDeviceList(true)
} }
}).finally(() => { }).finally(() => {this.loading-=1})
this.loading -= 1
})
} }
}, },
immediate: true, immediate: true,
} }
}, },
methods: { methods: {
changeType() { changeType(){
if (this.dccDeviceCategoryList.includes(this.formData.deviceCategory)) { if(this.dccDeviceCategoryList.includes(this.formData.deviceCategory)){
this.getParentDeviceList() this.getParentDeviceList()
} }
}, },
uploadImage(data) { uploadImage(data){
this.formData.pictureUrl = data this.formData.pictureUrl = data
}, },
//获取站点列表 //获取站点列表
getZdList() { getZdList(){
this.loading += 1 this.loading+=1
getAllSites().then(response => { getAllSites().then(response => {
this.siteList = response?.data || [] this.siteList = response?.data || []
}).finally(() => { }).finally(() => {this.loading-=1})
this.loading -= 1
})
}, },
// 获取设备类别 // 获取设备类别
getDeviceCategoryList() { getDeviceCategoryList(){
this.loading += 1 this.loading+=1
getAllDeviceCategory().then(response => { getAllDeviceCategory().then(response => {
this.deviceCategoryList = response?.data || [] this.deviceCategoryList = response?.data || []
}).finally(() => { }).finally(() => {this.loading-=1})
this.loading -= 1
})
}, },
//获取上级id列表 //获取上级id列表
getParentDeviceList(init = false) { getParentDeviceList(init=false){
if (!this.formData.siteId) { if(!this.formData.siteId){
return console.log('请先选择站点') return console.log('请先选择站点')
} }
!init && (this.formData.parentId = '') !init && (this.formData.parentId='')
this.loading = this.loading + 1 this.loading= this.loading+1
getParentDeviceId({siteId: this.formData.siteId, deviceCategory: this.formData.deviceCategory}).then(response => { getParentDeviceId({siteId:this.formData.siteId,deviceCategory:this.formData.deviceCategory}).then(response => {
this.parentDeviceList = JSON.parse(JSON.stringify(response?.data || [])); this.parentDeviceList = JSON.parse(JSON.stringify(response?.data || []));
}).finally(() => { }).finally(() => {
this.loading = this.loading - 1 this.loading=this.loading -1
}) })
}, },
saveData() {
this.loading += 1
const {
id = '',
siteId = '',//站点ID
deviceId = '',//设备id
deviceName = '',//设备名称
description = '',//设备描述
communicationStatus = '',//工作状态
deviceType = '',//设备类型
deviceCategory = '',//设备类别
parentId = '',//上级设备id
ipAddress = '',//TCP设备的ip地址
ipPort = "",//TCP端口号
serialPort = '',//串口路径
baudRate = '',//波特率
dataBits = '',//数据位
stopBits = '',//停止位
parity = '',//校验位
pictureUrl = '',//设备图片
slaveId = '',//从站地址
} = this.formData;
const {
deviceSettingId,
powerAddress,
pointAddress,
startCommand,
stopCommand,
startPower,
stopPower,
clusterNum,
clusterPointAddress
} = this.pcsSetting
let params = {
siteId,
deviceId,
deviceName,
description,
communicationStatus,
deviceType,
deviceCategory,
parentId,
ipAddress,
ipPort,
serialPort,
baudRate,
dataBits,
stopBits,
parity,
pictureUrl,
slaveId,
}
if (this.isPcs) {
params.pcsSetting = {
powerAddress,
pointAddress,
startCommand,
stopCommand,
startPower,
stopPower,
clusterNum,
clusterPointAddress: JSON.stringify(!clusterNum ? [] : (clusterPointAddress || []).slice(0, clusterNum))
}
}
if (this.mode === 'add') {
addDevice(params).then(response => {
if (response.code === 200) {
//新增成功
// 关闭弹窗 更新表格
this.$emit('update')
this.closeDialog()
}
}).finally(() => {
this.loading -= 1
})
} else {
params.id = id
params.pcsSetting && (params.pcsSetting.deviceSettingId = deviceSettingId)
updateDevice(params).then(response => {
if (response.code === 200) {
//新增成功
// 关闭弹窗 更新表格
this.$emit('update')
this.closeDialog()
}
}).finally(() => {
this.loading -= 1
})
}
},
saveDialog() { saveDialog() {
this.$refs.addTempForm.validate(valid => { this.$refs.addTempForm.validate(valid => {
if (!valid) return if (!valid) return
if (this.isPcs) { this.loading+=1
this.$refs.pcsSettingForm.validate(pcsValidate => { const {
if (!pcsValidate) return id='',
this.saveData() siteId='',//站点ID
deviceId='',//设备id
deviceName='',//设备名称
description='',//设备描述
communicationStatus='',//工作状态
deviceType='',//设备类型
deviceCategory='',//设备类别
parentId='',//上级设备id
ipAddress='',//TCP设备的ip地址
ipPort="",//TCP端口号
serialPort='',//串口路径
baudRate='',//波特率
dataBits='',//数据位
stopBits='',//停止位
parity='',//校验位
pictureUrl='',//设备图片
}= this.formData;
if(this.mode === 'add'){
addDevice({siteId,deviceId,deviceName,description,communicationStatus,deviceType,deviceCategory,parentId,ipAddress,ipPort,serialPort,baudRate,dataBits,stopBits,parity,pictureUrl}).then(response => {
if(response.code === 200){
//新增成功
// 关闭弹窗 更新表格
this.$emit('update')
this.closeDialog()
}
}).finally(() => {
this.loading-=1
})
}else{
updateDevice({id,siteId,deviceId,deviceName,description,communicationStatus,deviceType,deviceCategory,parentId,ipAddress,ipPort,serialPort,baudRate,dataBits,stopBits,parity,pictureUrl}).then(response => {
if(response.code === 200){
//新增成功
// 关闭弹窗 更新表格
this.$emit('update')
this.closeDialog()
}
}).finally(() => {
this.loading-=1
}) })
} else {
this.saveData()
} }
}) })
}, },
closeDialog() { closeDialog(){
this.$emit('clear') this.$emit('clear')
// 清空所有数据 // 清空所有数据
this.formData = { this.formData= {
id: '',//设备唯一标识 id:'',//设备唯一标识
siteId: '',//站点ID siteId:'',//站点ID
deviceId: '',//设备id deviceId:'',//设备id
deviceName: '',//设备名称 deviceName:'',//设备名称
description: '',//设备描述 description:'',//设备描述
communicationStatus: '',//工作状态 communicationStatus:'',//工作状态
deviceType: '',//设备类型 deviceType:'',//设备类型
deviceCategory: '',//设备类别 deviceCategory:'',//设备类别
parentId: '',//上级设备id parentId:'',//上级设备id
ipAddress: '',//TCP设备的ip地址 ipAddress:'',//TCP设备的ip地址
ipPort: "",//TCP端口号 ipPort:"",//TCP端口号
serialPort: '',//串口路径 serialPort:'',//串口路径
baudRate: '',//波特率 baudRate:'',//波特率
dataBits: '',//数据位 dataBits:'',//数据位
stopBits: '',//停止位 stopBits:'',//停止位
parity: '',//校验位 parity:'',//校验位
pictureUrl: '',//设备图片 pictureUrl:'',//设备图片
slaveId: '',//从站地址
}
this.pcsSetting = {
deviceSettingId: '',
powerAddress: '',//功率地址
pointAddress: "",//开关机地址
startCommand: "",//开机指令
stopCommand: "",//关机指令
startPower: '',//开机目标功率
stopPower: '',//关机目标功率
clusterNum: '',//电池簇数
clusterPointAddress: []//电池簇地址
} }
this.$refs.addTempForm.resetFields() this.$refs.addTempForm.resetFields()
this.$refs?.pcsSettingForm?.resetFields() this.dialogTableVisible=false
this.dialogTableVisible = false
} }
} }
} }
</script> </script>
<style scoped lang="scss"> <style scoped>
.device-form {
::v-deep .el-form-item--medium .el-form-item__content {
width: 260px;
}
.el-form-item {
width: 50%;
margin-right: 0;
}
}
</style> </style>

View File

@ -32,7 +32,7 @@ export default {
type: Object, type: Object,
default: () => { default: () => {
return { return {
workStatus: null, deviceStatus: null,
deviceId: null, deviceId: null,
deviceName: null, deviceName: null,
} }
@ -42,13 +42,13 @@ export default {
}, },
computed: { computed: {
label() { label() {
return this.data.workStatus === '0' ? '机' : '机' return this.data.deviceStatus === '4' ? '机' : '机'
} }
}, },
methods: { methods: {
switchStatus() { switchStatus() {
console.log(this.data, 11111111) console.log(this.data, 11111111)
const {workStatus, deviceId, deviceName, siteId} = this.data const {deviceStatus, deviceId, deviceName, siteId} = this.data
this.$confirm(`确认要${this.label}设备${deviceName || ''}吗?`, { this.$confirm(`确认要${this.label}设备${deviceName || ''}吗?`, {
confirmButtonText: "确定", confirmButtonText: "确定",
cancelButtonText: "取消", cancelButtonText: "取消",
@ -61,7 +61,7 @@ export default {
//做开关机操作,更新成功后刷新表格 //做开关机操作,更新成功后刷新表格
updateDeviceStatus({ updateDeviceStatus({
siteId, siteId,
workStatus: workStatus === '0' ? "1" : '0', deviceStatus,
deviceId deviceId
}) })
.then((response) => { .then((response) => {

View File

@ -80,7 +80,7 @@
<el-table-column label="数据点位" prop="dataPoint"></el-table-column> <el-table-column label="数据点位" prop="dataPoint"></el-table-column>
<el-table-column <el-table-column
label="数据点位名称" label="数据点位名称"
prop="dataPointName" prop="pointName"
></el-table-column> ></el-table-column>
<!-- <el-table-column label="modbus地址">--> <!-- <el-table-column label="modbus地址">-->
<!-- <template slot-scope="scope">--> <!-- <template slot-scope="scope">-->
@ -88,8 +88,8 @@
<!-- `${scope.row.ipAddress || ""} ${scope.row.ipPort || ""}`--> <!-- `${scope.row.ipAddress || ""} ${scope.row.ipPort || ""}`-->
<!-- }}</span>--> <!-- }}</span>-->
<!-- </template>--> <!-- </template>-->
<!-- </el-table-column> <!-- </el-table-column>-->
<el-table-column label="寄存器地址" prop="寄存器地址"></el-table-column>--> <el-table-column label="寄存器地址" prop="寄存器地址"></el-table-column>
<el-table-column <el-table-column
label="最新值" label="最新值"
prop="pointValue" prop="pointValue"

View File

@ -84,10 +84,10 @@
label="在线状态"> label="在线状态">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ $store.state.ems.deviceStatusOptions[scope.row.deviceStatus] }}</span> <span>{{ $store.state.ems.deviceStatusOptions[scope.row.deviceStatus] }}</span>
<!-- <pcs-switch v-if="scope.row.deviceCategory === 'PCS' && ![null,'',undefined].includes(scope.row.deviceStatus)"--> <pcs-switch v-if="scope.row.deviceCategory === 'PCS' && ![null,'',undefined].includes(scope.row.deviceStatus)"
<!-- style="margin-left:5px;"--> style="margin-left:5px;"
<!-- :data="{siteId:scope.row.siteId,deviceStatus:scope.row.deviceStatus,deviceId:scope.row.deviceId,deviceName:scope.row.deviceName}"--> :data="{siteId:scope.row.siteId,deviceStatus:scope.row.deviceStatus,deviceId:scope.row.deviceId,deviceName:scope.row.deviceName}"
<!-- @updateSuccess="getData"/>--> @updateSuccess="getData"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -180,11 +180,11 @@ import {getAllDeviceCategory} from '@/api/ems/search'
import PointTable from './PointTable.vue' import PointTable from './PointTable.vue'
import AddDevice from "./AddDevice.vue"; import AddDevice from "./AddDevice.vue";
import PointUpload from "./PointUpload.vue"; import PointUpload from "./PointUpload.vue";
// import PcsSwitch from "./PcsSwitch.vue"; import PcsSwitch from "./PcsSwitch.vue";
export default { export default {
name: "Sblb", name: "Sblb",
components: {AddDevice, PointTable, PointUpload}, components: {AddDevice, PointTable, PointUpload, PcsSwitch},
data() { data() {
return { return {
loading: false, loading: false,

View File

@ -6,39 +6,30 @@
<pane size="16"> <pane size="16">
<el-col> <el-col>
<div class="head-container"> <div class="head-container">
<el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" <el-input v-model="deptName" placeholder="请输入部门名称" clearable size="small" prefix-icon="el-icon-search" style="margin-bottom: 20px" />
prefix-icon="el-icon-search" style="margin-bottom: 20px"/>
</div> </div>
<div class="head-container"> <div class="head-container">
<el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false" <el-tree :data="deptOptions" :props="defaultProps" :expand-on-click-node="false" :filter-node-method="filterNode" ref="tree" node-key="id" default-expand-all highlight-current @node-click="handleNodeClick" />
:filter-node-method="filterNode" ref="tree" node-key="id" default-expand-all highlight-current
@node-click="handleNodeClick"/>
</div> </div>
</el-col> </el-col>
</pane> </pane>
<!--用户数据--> <!--用户数据-->
<pane size="84"> <pane size="84">
<el-col> <el-col>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
label-width="68px">
<el-form-item label="用户名称" prop="userName"> <el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
@keyup.enter.native="handleQuery"/>
</el-form-item> </el-form-item>
<el-form-item label="手机号码" prop="phonenumber"> <el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" <el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable style="width: 240px" @keyup.enter.native="handleQuery" />
@keyup.enter.native="handleQuery"/>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px"> <el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
<el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" <el-option v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
:value="dict.value"/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="创建时间"> <el-form-item label="创建时间">
<el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" <el-date-picker v-model="dateRange" style="width: 240px" value-format="yyyy-MM-dd" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
range-separator="-" start-placeholder="开始日期"
end-placeholder="结束日期"></el-date-picker>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -48,48 +39,33 @@
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['system:user:add']">新增</el-button>
v-hasPermi="['system:user:add']">新增
</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['system:user:edit']">修改</el-button>
v-hasPermi="['system:user:edit']">修改
</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['system:user:remove']">删除</el-button>
@click="handleDelete" v-hasPermi="['system:user:remove']">删除
</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport" v-hasPermi="['system:user:import']">导入</el-button>
v-hasPermi="['system:user:import']">导入
</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['system:user:export']">导出</el-button>
v-hasPermi="['system:user:export']">导出
</el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row> </el-row>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center"/> <el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible"/> <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" <el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
:show-overflow-tooltip="true"/> <el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" <el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
:show-overflow-tooltip="true"/> <el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible"
:show-overflow-tooltip="true"/>
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber"
v-if="columns[4].visible" width="120"/>
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible"> <el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.status" active-value="0" inactive-value="1" <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
@change="handleStatusChange(scope.row)"></el-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160"> <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
@ -99,30 +75,20 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" width="160" class-name="small-padding fixed-width">
<template slot-scope="scope" v-if="scope.row.userId !== 1"> <template slot-scope="scope" v-if="scope.row.userId !== 1">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:user:edit']">修改</el-button>
v-hasPermi="['system:user:edit']">修改 <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']">删除</el-button>
</el-button> <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
v-hasPermi="['system:user:remove']">删除
</el-button>
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)"
v-hasPermi="['system:user:resetPwd', 'system:user:edit']">
<el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button> <el-button size="mini" type="text" icon="el-icon-d-arrow-right">更多</el-button>
<el-dropdown-menu slot="dropdown"> <el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleResetPwd" icon="el-icon-key" <el-dropdown-item command="handleResetPwd" icon="el-icon-key" v-hasPermi="['system:user:resetPwd']">重置密码</el-dropdown-item>
v-hasPermi="['system:user:resetPwd']">重置密码 <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" v-hasPermi="['system:user:edit']">分配角色</el-dropdown-item>
</el-dropdown-item>
<el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check"
v-hasPermi="['system:user:edit']">分配角色
</el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
:limit.sync="queryParams.pageSize" @pagination="getList"/>
</el-col> </el-col>
</pane> </pane>
</splitpanes> </splitpanes>
@ -134,38 +100,36 @@
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="用户昵称" prop="nickName"> <el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30"/> <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="归属部门" prop="deptId"> <el-form-item label="归属部门" prop="deptId">
<treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" <treeselect v-model="form.deptId" :options="enabledDeptOptions" :show-count="true" placeholder="请选择归属部门" />
placeholder="请选择归属部门"/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="手机号码" prop="phonenumber"> <el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11"/> <el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="邮箱" prop="email"> <el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50"/> <el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName"> <el-form-item v-if="form.userId == undefined" label="用户名称" prop="userName">
<el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30"/> <el-input v-model="form.userName" placeholder="请输入用户名称" maxlength="30" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password"> <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password />
show-password/>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -173,17 +137,14 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="用户性别"> <el-form-item label="用户性别">
<el-select v-model="form.sex" placeholder="请选择性别"> <el-select v-model="form.sex" placeholder="请选择性别">
<el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" <el-option v-for="dict in dict.type.sys_user_sex" :key="dict.value" :label="dict.label" :value="dict.value"></el-option>
:value="dict.value"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="状态"> <el-form-item label="状态">
<el-radio-group v-model="form.status"> <el-radio-group v-model="form.status">
<el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value"> <el-radio v-for="dict in dict.type.sys_normal_disable" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio>
{{ dict.label }}
</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -192,33 +153,14 @@
<el-col :span="12"> <el-col :span="12">
<el-form-item label="岗位"> <el-form-item label="岗位">
<el-select v-model="form.postIds" multiple placeholder="请选择岗位"> <el-select v-model="form.postIds" multiple placeholder="请选择岗位">
<el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" <el-option v-for="item in postOptions" :key="item.postId" :label="item.postName" :value="item.postId" :disabled="item.status == 1" ></el-option>
:disabled="item.status == 1"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="角色"> <el-form-item label="角色">
<el-select v-model="form.roleIds" multiple placeholder="请选择角色"> <el-select v-model="form.roleIds" multiple placeholder="请选择角色">
<el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1"></el-option>
:disabled="item.status == 1"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="归属站点" name="belongSite">
<el-select
v-model="form.belongSite"
multiple
collapse-tags
placeholder="请选择"
style="width:100%"
@change="selectBelongSite">
<el-option :label="item.siteName" :value="item.siteId" v-for="(item,index) in siteList"
:disabled="item.siteId!== 'all' && (form.belongSite || []).includes('all')"
:key="index+'zdxeSelect'"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
@ -239,20 +181,15 @@
<!-- 用户导入对话框 --> <!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body> <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
:action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading"
:on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip"> <div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip"> <div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport"/> <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
是否更新已经存在的用户数据
</div> </div>
<span>仅允许导入xlsxlsx格式文件</span> <span>仅允许导入xlsxlsx格式文件</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate">下载模板</el-link>
@click="importTemplate">下载模板
</el-link>
</div> </div>
</el-upload> </el-upload>
<div slot="footer" class="dialog-footer"> <div slot="footer" class="dialog-footer">
@ -264,27 +201,17 @@
</template> </template>
<script> <script>
import { import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user"
addUser, import { getToken } from "@/utils/auth"
changeUserStatus,
delUser,
deptTreeSelect,
getUser,
listUser,
resetUserPwd,
updateUser
} from "@/api/system/user"
import {getAllSites} from '@/api/ems/zddt'
import {getToken} from "@/utils/auth"
import Treeselect from "@riophae/vue-treeselect" import Treeselect from "@riophae/vue-treeselect"
import "@riophae/vue-treeselect/dist/vue-treeselect.css" import "@riophae/vue-treeselect/dist/vue-treeselect.css"
import {Pane, Splitpanes} from "splitpanes" import { Splitpanes, Pane } from "splitpanes"
import "splitpanes/dist/splitpanes.css" import "splitpanes/dist/splitpanes.css"
export default { export default {
name: "User", name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'], dicts: ['sys_normal_disable', 'sys_user_sex'],
components: {Treeselect, Splitpanes, Pane}, components: { Treeselect, Splitpanes, Pane },
data() { data() {
return { return {
// 遮罩层 // 遮罩层
@ -301,8 +228,6 @@ export default {
total: 0, total: 0,
// 用户表格数据 // 用户表格数据
userList: null, userList: null,
// 站点列表数据
siteList: [],
// 弹出层标题 // 弹出层标题
title: "", title: "",
// 所有部门树选项 // 所有部门树选项
@ -338,7 +263,7 @@ export default {
// 是否更新已经存在的用户数据 // 是否更新已经存在的用户数据
updateSupport: 0, updateSupport: 0,
// 设置上传的请求头部 // 设置上传的请求头部
headers: {Authorization: "Bearer " + getToken()}, headers: { Authorization: "Bearer " + getToken() },
// 上传的地址 // 上传的地址
url: process.env.VUE_APP_BASE_API + "/system/user/importData" url: process.env.VUE_APP_BASE_API + "/system/user/importData"
}, },
@ -353,27 +278,27 @@ export default {
}, },
// 列信息 // 列信息
columns: [ columns: [
{key: 0, label: `用户编号`, visible: true}, { key: 0, label: `用户编号`, visible: true },
{key: 1, label: `用户名称`, visible: true}, { key: 1, label: `用户名称`, visible: true },
{key: 2, label: `用户昵称`, visible: true}, { key: 2, label: `用户昵称`, visible: true },
{key: 3, label: `部门`, visible: true}, { key: 3, label: `部门`, visible: true },
{key: 4, label: `手机号码`, visible: true}, { key: 4, label: `手机号码`, visible: true },
{key: 5, label: `状态`, visible: true}, { key: 5, label: `状态`, visible: true },
{key: 6, label: `创建时间`, visible: true} { key: 6, label: `创建时间`, visible: true }
], ],
// 表单校验 // 表单校验
rules: { rules: {
userName: [ userName: [
{required: true, message: "用户名称不能为空", trigger: "blur"}, { required: true, message: "用户名称不能为空", trigger: "blur" },
{min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur'} { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur' }
], ],
nickName: [ nickName: [
{required: true, message: "用户昵称不能为空", trigger: "blur"} { required: true, message: "用户昵称不能为空", trigger: "blur" }
], ],
password: [ password: [
{required: true, message: "用户密码不能为空", trigger: "blur"}, { required: true, message: "用户密码不能为空", trigger: "blur" },
{min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur'}, { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
{pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur"} { pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
], ],
email: [ email: [
{ {
@ -388,8 +313,7 @@ export default {
message: "请输入正确的手机号码", message: "请输入正确的手机号码",
trigger: "blur" trigger: "blur"
} }
], ]
} }
} }
}, },
@ -400,7 +324,6 @@ export default {
} }
}, },
created() { created() {
this.getZdList()
this.getList() this.getList()
this.getDeptTree() this.getDeptTree()
this.getConfigKey("sys.user.initPassword").then(response => { this.getConfigKey("sys.user.initPassword").then(response => {
@ -408,37 +331,14 @@ export default {
}) })
}, },
methods: { methods: {
selectBelongSite(data) {
console.log('选中的站点', data)
if (data.includes("all")) {
this.form.belongSite = ['all']
return
}
if (this.siteList.length && data.length === (this.siteList.length - 1)) {
this.form.belongSite = ['all']
}
},
//获取站点列表
getZdList() {
return getAllSites().then(response => {
this.siteList = response?.data || []
if (this.siteList.length > 0) {
this.siteList.unshift({
id: 'all',
siteId: "all",
siteName: "全部"
})
}
})
},
/** 查询用户列表 */ /** 查询用户列表 */
getList() { getList() {
this.loading = true this.loading = true
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows this.userList = response.rows
this.total = response.total this.total = response.total
this.loading = false this.loading = false
} }
) )
}, },
/** 查询部门下拉树结构 */ /** 查询部门下拉树结构 */
@ -473,11 +373,11 @@ export default {
// 用户状态修改 // 用户状态修改
handleStatusChange(row) { handleStatusChange(row) {
let text = row.status === "0" ? "启用" : "停用" let text = row.status === "0" ? "启用" : "停用"
this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function () { this.$modal.confirm('确认要"' + text + '""' + row.userName + '"用户吗?').then(function() {
return changeUserStatus(row.userId, row.status) return changeUserStatus(row.userId, row.status)
}).then(() => { }).then(() => {
this.$modal.msgSuccess(text + "成功") this.$modal.msgSuccess(text + "成功")
}).catch(function () { }).catch(function() {
row.status = row.status === "0" ? "1" : "0" row.status = row.status === "0" ? "1" : "0"
}) })
}, },
@ -500,8 +400,7 @@ export default {
status: "0", status: "0",
remark: undefined, remark: undefined,
postIds: [], postIds: [],
roleIds: [], roleIds: []
belongSite: []
} }
this.resetForm("form") this.resetForm("form")
}, },
@ -556,7 +455,6 @@ export default {
this.form = response.data this.form = response.data
this.postOptions = response.posts this.postOptions = response.posts
this.roleOptions = response.roles this.roleOptions = response.roles
this.$set(this.form, "belongSite", response?.data?.belongSite ? JSON.parse(response.data.belongSite) : [])
this.$set(this.form, "postIds", response.postIds) this.$set(this.form, "postIds", response.postIds)
this.$set(this.form, "roleIds", response.roleIds) this.$set(this.form, "roleIds", response.roleIds)
this.open = true this.open = true
@ -577,30 +475,29 @@ export default {
return "不能包含非法字符:< > \" ' \\\ |" return "不能包含非法字符:< > \" ' \\\ |"
} }
}, },
}).then(({value}) => { }).then(({ value }) => {
resetUserPwd(row.userId, value).then(response => { resetUserPwd(row.userId, value).then(response => {
this.$modal.msgSuccess("修改成功,新密码是:" + value) this.$modal.msgSuccess("修改成功,新密码是:" + value)
}) })
}).catch(() => { }).catch(() => {})
})
}, },
/** 分配角色操作 */ /** 分配角色操作 */
handleAuthRole: function (row) { handleAuthRole: function(row) {
const userId = row.userId const userId = row.userId
this.$router.push("/system/user-auth/role/" + userId) this.$router.push("/system/user-auth/role/" + userId)
}, },
/** 提交按钮 */ /** 提交按钮 */
submitForm: function () { submitForm: function() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
if (this.form.userId != undefined) { if (this.form.userId != undefined) {
updateUser({...this.form, belongSite: JSON.stringify(this.form.belongSite)}).then(response => { updateUser(this.form).then(response => {
this.$modal.msgSuccess("修改成功") this.$modal.msgSuccess("修改成功")
this.open = false this.open = false
this.getList() this.getList()
}) })
} else { } else {
addUser({...this.form, belongSite: JSON.stringify(this.form.belongSite)}).then(response => { addUser(this.form).then(response => {
this.$modal.msgSuccess("新增成功") this.$modal.msgSuccess("新增成功")
this.open = false this.open = false
this.getList() this.getList()
@ -612,13 +509,12 @@ export default {
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const userIds = row.userId || this.ids const userIds = row.userId || this.ids
this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function () { this.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() {
return delUser(userIds) return delUser(userIds)
}).then(() => { }).then(() => {
this.getList() this.getList()
this.$modal.msgSuccess("删除成功") this.$modal.msgSuccess("删除成功")
}).catch(() => { }).catch(() => {})
})
}, },
/** 导出按钮操作 */ /** 导出按钮操作 */
handleExport() { handleExport() {
@ -633,7 +529,8 @@ export default {
}, },
/** 下载模板操作 */ /** 下载模板操作 */
importTemplate() { importTemplate() {
this.download('system/user/importTemplate', {}, `user_template_${new Date().getTime()}.xlsx`) this.download('system/user/importTemplate', {
}, `user_template_${new Date().getTime()}.xlsx`)
}, },
// 文件上传中处理 // 文件上传中处理
handleFileUploadProgress(event, file, fileList) { handleFileUploadProgress(event, file, fileList) {
@ -644,7 +541,7 @@ export default {
this.upload.open = false this.upload.open = false
this.upload.isUploading = false this.upload.isUploading = false
this.$refs.upload.clearFiles() this.$refs.upload.clearFiles()
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", {dangerouslyUseHTMLString: true}) this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true })
this.getList() this.getList()
}, },
// 提交上传文件 // 提交上传文件