<template>
|
<div class="main">
|
<!-- <div class="title vertical_middle">负载柜手动加载画面</div> -->
|
<div class="flex_contain">
|
<div class="item border-angle" v-for="(item, index) in list" :key="index">
|
<div class="item-inner">
|
<!-- 主开关 -->
|
<div class="btn_main">
|
<div class="lay_label vertical_middle">{{item.dev_name}}</div>
|
<div class="lay_content vertical_middle">
|
<div class="btn" :disabled="!$root.authorization" v-btn-confirm="$root.authorization ? handleConfirm : $root.notAllow" data-fn="switchOff" data-confirmTxt="全部分闸确认" :param="JSON.stringify(['CONTEXT.list[' + index + ']'])">全部分闸</div>
|
<div class="btn btn_export" @click="exportData(item)">数据导出</div>
|
</div>
|
</div>
|
<!-- 是否允许合闸 -->
|
<div class="info_voltage">
|
<div class="lay_label vertical_middle">
|
是否允许合闸
|
</div>
|
<div class="lay_content vertical_middle">
|
<div class="indicator" :class="{'status_off': !item.allow_close, 'status_normal': item.allow_close}"></div>
|
</div>
|
</div>
|
<!-- 电压 -->
|
<div class="info_voltage">
|
<div class="lay_label vertical_middle">
|
电压
|
</div>
|
<div class="lay_content txt_strong vertical_middle">
|
{{item.actual_mov}} V
|
</div>
|
</div>
|
<!-- 电流 -->
|
<div class="info_electricity">
|
<div class="lay_label vertical_middle">
|
电流
|
</div>
|
<div class="lay_content txt_strong vertical_middle">
|
{{item.actual_curr}} A
|
</div>
|
</div>
|
<!-- 已输出功率 -->
|
<div class="info_power">
|
<div class="lay_label bdb vertical_middle">
|
已输出功率
|
</div>
|
<div class="lay_content txt_strong vertical_middle">
|
{{item.output_power}} kVA
|
</div>
|
</div>
|
<!-- 状态 -->
|
<div class="btn_sub_grp">
|
<div class="row" v-for="idx of max_button_num" :key="idx">
|
<div class="lay_label vertical_middle" v-if="idx <= item.FZ_button_num">KM{{idx}} ({{item['FZ_b' + idx + '_power']}}kVA)</div>
|
<div class="lay_label vertical_middle" v-else></div>
|
<div class="lay_content">
|
<div class="vertical_middle">
|
<div class="switch_yc" v-if="idx <= item.FZ_button_num">
|
<label @click="$root.authorization ? $root.doNothing() : $root.notAllow()" class="checkbox">
|
<input type="checkbox"
|
:disabled="!$root.authorization"
|
@click="switch3DHandle(item, idx)"
|
v-model="item['FZ_b' + idx]" value="1" class="input" />
|
<span class="handle">
|
<span class="active">ON</span>
|
<span class="core"></span>
|
<span class="inactive">OFF</span>
|
</span>
|
<span class="bg"></span>
|
</label>
|
</div>
|
</div>
|
<div class="vertical_middle">
|
<div class="indicator" v-if="idx <= item.FZ_button_num" :class="{'status_off': !item['FZ_fw' + idx], 'status_normal': item['FZ_fw' + idx]}"></div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
<!-- 无数据 -->
|
<div class="data_empty vertical_middle" v-if="!list.length">暂无数据</div>
|
</div>
|
<div class="footer">
|
<div class="btn-grp">
|
<div class="btn" @click="goTo('/load/main')">主画面</div>
|
<div class="btn">手动加载</div>
|
<div class="btn" @click="goTo('/load/auto')">自动加载</div>
|
<div class="btn" @click="goTo('/load/burst')">突加突卸</div>
|
</div>
|
</div>
|
<!-- 弹窗 -->
|
<el-dialog class="el-dialog-center" top="0vh" v-cloak title='操作失败'
|
:visible.sync="confirm.show" width="5.2rem"
|
:close-on-click-modal='false'
|
:close-on-press-escape='true'
|
:show-close='false'
|
@closed="confirm.show = false">
|
<flex-layout>
|
<div class="color-black">
|
<div class="dialog_content">{{confirm.txt}}操作失败, 点击确认后撤销操作</div>
|
</div>
|
<div slot="footer" class="color-black dialog-footer">
|
<el-button type="primary" size="small" @click="confirmOk">确定</el-button>
|
</div>
|
</flex-layout>
|
</el-dialog>
|
<!-- 按钮二次确认 -->
|
<el-dialog
|
:title="confirmTxt"
|
:visible.sync="confirmVisible"
|
width="300px">
|
<!-- <span>{{}}</span> -->
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="confirmVisible = false">取 消</el-button>
|
<el-button type="primary" @click="callBack">确 定</el-button>
|
</span>
|
</el-dialog>
|
<!-- 导出数据弹窗 -->
|
<el-dialog
|
title="数据导出"
|
:visible.sync="exportDialogVisible"
|
width="400px" >
|
<label class="pr_o6em">选择日期</label>
|
<el-date-picker
|
v-model="export_date"
|
value-format="yyyy-MM-dd"
|
type="date"
|
size="small"
|
:picker-options="pickerOptions"
|
placeholder="选择日期" >
|
</el-date-picker>
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="exportDialogVisible = false">关 闭</el-button>
|
<el-button type="primary" @click="exportCsv">导 出</el-button>
|
</span>
|
</el-dialog>
|
<progress-load
|
:show="progress.show"
|
:percentage="progress.value"
|
:text="progress.text"></progress-load>
|
</div>
|
</template>
|
|
<script>
|
|
import FlexLayout from '@/components/FlexLayout'
|
import ProgressLoad from '@/components/ProgressLoad'
|
|
export default {
|
name: 'ManualLoad',
|
components: {
|
ProgressLoad
|
,FlexLayout
|
},
|
data () {
|
return {
|
progress: {
|
show: false,
|
value: 0,
|
text: '',
|
},
|
export_id: 0,
|
export_name: '',
|
exportDialogVisible: false,
|
export_date: new Date().format('yyyy-MM-dd'),
|
pickerOptions: {
|
disabledDate (data) {
|
return data && data.valueOf() > Date.now().valueOf() || data.valueOf() < Date.now().valueOf() - 1000 * 60 * 60 * 24 * 30;
|
}
|
},
|
confirmTxt: '',
|
confirmVisible: false,
|
cbFn: null,
|
cbParam: null,
|
max_button_num: 0,
|
timer: new this.$common.Timeout(),
|
info: [],
|
list: [],
|
FzBList: {},
|
FzBIgnore: {},
|
confirm: {
|
btnList: {
|
a: {name: 'KM' + 1,
|
dev_id: 1,
|
FzB: 'FzB11'}
|
},
|
curBtnList: {},
|
show: false,
|
txt: ''
|
}
|
}
|
},
|
methods: {
|
goTo (path) {
|
this.$router.push({path});
|
}
|
,callBack () {
|
this.confirmVisible = false;
|
let cbParam = [];
|
this.cbParam.forEach((v) => {
|
if ('string' == typeof v && v.indexOf('CONTEXT') > -1) {
|
let arr = v.split('.');
|
if (arr.length > 2) {
|
console.warn('目前不支持深层属性参数');
|
}
|
let _param = arr[1];
|
if (_param.indexOf('[') > -1) {
|
const reg = /\[|\]/;
|
let _arr = _param.split(reg);
|
cbParam.push(this[_arr[0]][_arr[1]]);
|
} else {
|
cbParam.push(this[_param]);
|
}
|
// console.log(this[arr[1]], 99);
|
} else {
|
cbParam.push(v);
|
}
|
});
|
|
this[this.cbFn](...cbParam);
|
}
|
,handleConfirm (obj) {
|
// console.log(obj, 9090);
|
this.confirmTxt = obj.confirmTxt;
|
this.cbFn = obj.cbFn;
|
this.cbParam = obj.cbParam;
|
this.confirmVisible = true;
|
}
|
,getInfo () {
|
return this.$api.load.getInfo().then((res) => {
|
res = JSON.parse(res.data.result);
|
if (res.code) {
|
this.info = res.data;
|
}
|
});
|
}
|
// 全部分闸
|
,switchOff (obj) {
|
// 根据机柜信息构造查询条件
|
let searchParams = {
|
all_open: '1',
|
dev_name: obj.dev_name,
|
dev_id: obj.dev_id,
|
dev_ip: obj.dev_ip
|
};
|
// 查询后台
|
this.$api.load.allBtnControl(searchParams).then(res=>{
|
res = JSON.parse(res.data.result);
|
if(res.code) {
|
this.$message({
|
type: 'success',
|
message: res.msg
|
});
|
}else {
|
this.$message({
|
type: 'error',
|
message: res.msg
|
});
|
}
|
}).catch(error=>{
|
console.warn(error);
|
});
|
}
|
// 查询显示数据
|
,getStatus () {
|
this.$api.load.getManualStatus().then((res) => {
|
let re = JSON.parse(res.data.result);
|
let list = [];
|
// console.log(re, 999999);
|
if (re.code) {
|
this.info.forEach((v, idx) => {
|
list[idx] = {};
|
this.max_button_num = this.max_button_num > v.FZ_button_num ? this.max_button_num : v.FZ_button_num;
|
|
for (let i = 0, j = re.data.length; i < j; i++) {
|
if (re.data[i].dev_id == v.dev_id) {
|
let data = re.data[i];
|
|
// 更改 FZ_b 的值 2,0 => false 1 => true
|
let reg = /^FZ_b\d+$/;
|
Object.keys(data).forEach((val) => {
|
// debugger;
|
if (reg.test(val)) {
|
if (this.checkFzBIgnore(data.dev_id, val)) {
|
// 赋值
|
data[val] = this.FzBIgnore[val + data.dev_id].value;
|
// 倒计时减1
|
this.FzBIgnore[val + data.dev_id].time--;
|
// 如果计数器为0 则清除项
|
if (0 == this.FzBIgnore[val + data.dev_id].time) {
|
delete this.FzBIgnore[val + data.dev_id];
|
}
|
} else if (this.checkFzBIsChange(data.dev_id, val)) {
|
data[val] = data[val] == 1;
|
} else {
|
data[val] = this.FzBList[val+data.dev_id];
|
}
|
}
|
});
|
|
list[idx] = data;
|
list[idx]['dev_ip'] = v.dev_ip;
|
// list[idx]['FZ_button_num'] = v.FZ_button_num;
|
break;
|
}
|
}
|
});
|
this.list = list;
|
}
|
});
|
}
|
// 轮询
|
,loop () {
|
this.timer.start(() => {
|
this.getStatus();
|
this.timer.open();
|
}, 1000);
|
}
|
,checkFzBIsChange(dev_id, val) {
|
let change = true;
|
// 遍历FzBList
|
Object.keys(this.FzBList).forEach(key=>{
|
if(key == val+dev_id) {
|
change = false;
|
}
|
});
|
return change;
|
}
|
// 查询忽略
|
,checkFzBIgnore (dev_id, val) {
|
let flag = false;
|
Object.keys(this.FzBIgnore).forEach((key) => {
|
if (key == val + dev_id) {
|
flag = true;
|
}
|
});
|
return flag;
|
}
|
// KM开关切换
|
,switch3DHandle (item, index) {
|
// 根据机柜信息和点击的按钮的编号构造查询条件
|
let searchParams = {
|
dev_id: item.dev_id,
|
dev_name: item.dev_name,
|
num: index,
|
dev_ip: item.dev_ip
|
};
|
// 设置FZ_b的值
|
let FzB = 'FZ_b'+index;
|
// console.log(item[FzB], '===状态');
|
/*if (!FzB && !item.allow_close) {
|
this.$message({
|
type: 'warning',
|
message: '当前机柜不允许合闸'
|
});
|
return false;
|
}*/
|
|
// 设置FzB的值
|
searchParams[FzB] = item[FzB]?2:1;
|
// 设置等待的按钮
|
this.$set(this.FzBList, FzB+item.dev_id, searchParams[FzB]==1?1:0);
|
|
// 请求后台
|
this.$api.load.btnControl(searchParams).then(res=>{
|
res = JSON.parse(res.data.result);
|
if(res.code) {
|
this.$message({
|
type: 'success',
|
message: res.msg
|
});
|
// 删除等待指定的等待按钮
|
delete this.FzBList[FzB+item.dev_id];
|
// debugger;
|
// 加状态 延时轮询 5秒内的查询忽略此条
|
this.$set(this.FzBIgnore, FzB+item.dev_id, {time: 5, value: searchParams[FzB] == 1});
|
}else {
|
this.$message({
|
type: 'error',
|
message: res.msg
|
});
|
// 如果当前提示窗已开 正在处理 则放入btnList;
|
// 否则 直接弹窗处理
|
this.confirm.btnList[FzB + item.dev_id] = {
|
name: 'KM' + index,
|
dev_id: item.dev_id,
|
FzB: FzB + item.dev_id
|
};
|
if (!this.confirm.show) {
|
let txt = '';
|
Object.keys(this.confirm.btnList).forEach((v) => {
|
txt += (txt != '' ? '、' : '') + '机柜' + this.confirm.btnList[v].dev_id + ': ' + this.confirm.btnList[v].name;
|
this.confirm.curBtnList[v] = this.confirm.btnList[v];
|
});
|
|
this.confirm.txt = txt;
|
this.confirm.show = true;
|
}
|
}
|
}).catch(error=>{
|
console.warn(error);
|
})
|
}
|
,confirmOk () {
|
//
|
Object.keys(this.confirm.curBtnList).forEach((v) => {
|
let item = this.confirm.curBtnList[v];
|
delete this.FzBList[item.FzB];
|
delete this.confirm.btnList[v];
|
});
|
|
this.confirm.curBtnList = {};
|
|
this.confirm.show = false;
|
// 检查btnList 如果元素个数不为空 则再弹窗 200ms后
|
if (Object.keys(this.confirm.btnList).length) {
|
setTimeout(() => {
|
if (!this.confirm.show) {
|
let txt = '';
|
Object.keys(this.confirm.btnList).forEach((v) => {
|
txt += '机柜' + this.confirm.btnList[v].dev_id + ': ' + this.confirm.btnList[v].name;
|
this.confirm.curBtnList[v] = this.confirm.btnList[v];
|
});
|
|
this.confirm.txt = txt;
|
this.confirm.show = true;
|
}
|
}, 100);
|
}
|
}
|
// 数据导出
|
,exportData (obj) {
|
this.export_id = obj.dev_id;
|
this.export_name = obj.dev_name;
|
this.exportDialogVisible = true;
|
}
|
,getProgress () {
|
this.exportDialogVisible = false;
|
this.$api.common.getProgress().then((res) => {
|
res = JSON.parse(res.data.result);
|
let percentage = !res.data[0] ? 0 : Number(res.data[0].toFixed(0));
|
this.progress.value = percentage;
|
// console.log(res);
|
if(percentage == 0) {
|
this.progress.text="数据加载中...";
|
}else {
|
this.progress.text="文件下载中...";
|
}
|
|
if(res.data<100 && this.progress.show) {
|
setTimeout(this.getProgress, 50);
|
}else {
|
this.progress.value = 100;
|
}
|
});
|
}
|
,exportCsv () {
|
let param = {
|
dev_name: this.export_name.replace(/#/g, '号'),
|
dev_id: this.export_id,
|
export_num: 1,
|
table_name: this.export_date.replace(/-/g, '_'),
|
record_time: this.export_date + " 00:00:00"
|
};
|
// 显示进度条
|
this.progress.show = true;
|
// 请求后台
|
this.$api.common.clearProgress().then(() => {
|
this.getProgress();
|
this.$api.common.download(param).then((res) => {
|
res = JSON.parse(res.data.result);
|
// console.log(res, 'download res');
|
if(res.code == 1) {
|
// 关闭进度条
|
this.progress.show = false;
|
this.progress.value = 0;
|
let data = res.data[0];
|
const link = document.createElement("a");
|
link.href = encodeURI(this.$config.url + 'tomcat7_csv/' + data.fileName);
|
link.download = data.fileName;
|
document.body.appendChild(link);
|
link.click();
|
document.body.removeChild(link);
|
setTimeout(()=>{
|
// 关闭进度条
|
this.progress.show = false;
|
this.progress.value = 0;
|
}, 1000);
|
}else {
|
// 关闭进度条
|
this.progress.show = false;
|
this.progress.value = 0;
|
this.$layer.msg('生成文件失败!');
|
}
|
}).catch(error=>{
|
// 关闭进度条
|
this.progress.show = false;
|
this.progress.value = 0;
|
this.$layer.msg('生成文件失败!');
|
console.warn(error);
|
});
|
});
|
}
|
},
|
mounted () {
|
this.getInfo().then(() => {
|
this.loop();
|
});
|
},
|
destroyed () {
|
this.timer.stop();
|
}
|
|
}
|
</script>
|
<style scoped>
|
.main {
|
margin: 0;
|
padding: 0 0 26px 0;
|
width: 100%;
|
height: 100%;
|
display: -webkit-flex;
|
display: flex;
|
flex-direction: column;
|
|
/* background: radial-gradient(circle, rgba(0, 0, 20, .1) 30%,transparent 0) 0 0, radial-gradient(circle, rgba(0, 0, 200, .1) 30%,transparent 0) 10px 10px;
|
background-size: 20px 20px;*/
|
}
|
.title {
|
height: 60px;
|
flex-shrink: 0;
|
text-align: center;
|
}
|
.flex_contain {
|
flex: auto;
|
display: -webkit-flex;
|
display: flex;
|
padding: 0 10px;
|
}
|
.vertical_middle {
|
display: -webkit-flex;
|
display: flex;
|
/*flex-direction: column;*/
|
justify-content: center;
|
align-items: center;
|
}
|
.data_empty {
|
flex: auto;
|
background: rgba(0, 0, 0, .5);
|
}
|
.item {
|
flex: auto;
|
margin: 8px;
|
/*border: 2px #fff solid;*/
|
/*color: #6963bd;*/
|
font-size: .16rem;
|
background: linear-gradient(0deg, rgba(0, 247, 249, .3) 0, rgba(0, 247, 249, .1) 50%, rgba(0, 247, 249, .3) 100%);
|
/*padding: 14px;*/
|
position: relative;
|
}
|
.item-inner {
|
position: absolute;
|
left: 14px;
|
right: 14px;
|
top: 14px;
|
bottom: 14px;
|
border: 1px #00f7f9 solid;
|
display: -webkit-flex;
|
display: flex;
|
flex-direction: column;
|
text-align: center;
|
|
}
|
.btn_sub_grp .row:nth-child(2n-1),
|
.item-inner > div:nth-child(2n) {
|
background: rgba(0, 247, 249, .1);
|
}
|
|
|
.lay_label {
|
flex: 1;
|
border-right: 1px #00f7f9 solid;
|
justify-content: flex-start;
|
padding-left: .4em;
|
}
|
.lay_content {
|
flex: 1.6;
|
}
|
.btn_main,
|
.info_voltage,
|
.info_electricity,
|
.btn_sub_grp .row,
|
.bdb {
|
border-bottom: 1px solid #083458;
|
}
|
/* .btn_sub_grp .row,
|
.info_electricity,
|
.info_voltage, */
|
.info_power .lay_content {
|
border-bottom: 1px #00f7f9 solid;
|
}
|
.btn_sub_grp .row:last-of-type {
|
border: 0 none;
|
}
|
.btn_sub_grp .row .lay_content {
|
flex: 1.6;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.btn_sub_grp .row .lay_content > div {
|
flex: 1;
|
}
|
.btn_sub_grp .row .lay_content > div:first-of-type {
|
border-right: 1px #00f7f9 solid;
|
}
|
|
.btn_main {
|
flex: 1;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.info_voltage {
|
flex: 1;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.info_electricity {
|
flex: 1;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.info_power {
|
flex: 1;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.btn_sub_grp {
|
flex: 12;
|
display: -webkit-flex;
|
display: flex;
|
flex-direction: column;
|
}
|
.btn_sub_grp .row {
|
flex: 1;
|
display: -webkit-flex;
|
display: flex;
|
}
|
.indicator,
|
.nowrap_indicator {
|
width: 18px;
|
height: 18px;
|
}
|
|
.footer {
|
height: 58px;
|
/*background: rgba(0, 0, 0, .3);*/
|
flex-shrink: 0;
|
display: -webkit-flex;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
}
|
.footer .btn-grp {
|
display: -webkit-flex;
|
display: flex;
|
|
justify-content: space-around;
|
padding: 0 18%;
|
}
|
.btn {
|
display: inline-block;
|
background: #f69f41;
|
color: #041b3f;
|
width: 6em;
|
height: 30px;
|
line-height: 30px;
|
-webkit-border-radius: 4px;
|
border-radius: 4px;
|
}
|
.footer .btn-grp .btn {
|
height: 40px;
|
line-height: 40px;
|
text-align: center;
|
-webkit-border-radius: 4px;
|
border-radius: 4px;
|
background: #90ed7d;
|
color: #041b3f;
|
}
|
.dialog_content {
|
color: #333;
|
padding: .1rem;
|
}
|
.dialog-footer {
|
padding: .1rem;
|
text-align: right;
|
}
|
|
|
.btn.btn_export {
|
margin-left: 1em;
|
}
|
.btn_sub_grp {
|
background-color: transparent;
|
}
|
</style>
|