济菏高速业务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

672 lines
21 KiB

<template>
<div class="HomeFrameControl">
<ElPopover trigger="manual" :value="activeIcon === 'FrameControl'" :visibleArrow="false" placement="left"
popper-class="global-input-search-popover" @hide="onHide()">
<Button :class="['btn', { 'btn-active': activeIcon }]" slot="reference"
@click.native="handleClick('FrameControl')">
<img src="@screen/images/home-FrameControl/FrameControl.svg" />
</Button>
<el-tabs v-model="tabAction" @tab-click="tabClick">
<el-tab-pane label="批量管控" name="1">{{ }}</el-tab-pane>
<el-tab-pane label="定时管控" name="2"></el-tab-pane>
<el-tab-pane label="管控记录" name="3"></el-tab-pane>
</el-tabs>
<div class="body">
<div class="title">批量控制</div>
<span class="close" @click="() => { this.activeIcon = null; }">
<i class="el-icon-close" />
</span>
<div v-if="tabAction === '1'" style="width:70vw; min-height: 500px;">
<Form v-model="data" labelWidth="90px" column="2" class="form" ref="FormConfigRef" :formList="formList" />
<component ref="ControlComponent" :is="componentMap[DeviceTopics[data.deviceType]]" :isMultiControl="true"
:visible="true" :selectItems="data.childType" @update:activeIcon="(val) => { this.activeIcon = val }"
@update:submitting="(val) => { submitting = val }"></component>
<div v-if="hiddenDevices.indexOf(componentMap[DeviceTopics[data.deviceType]]) == -1" class="footer">
<Button @click.native="submitClick" :loading="submitting">
确认
</Button>
<Button style="background-color: rgba(0, 179, 204, 0.3)" @click.native="cancelClick"> 取消 </Button>
</div>
</div>
<div v-if="tabAction === '2'" style="width:70vw;height: 500px; overflow-y:auto" class="cardPanel">
<Empty v-if="!data.length" class="no-data" style="position: absolute">暂无数据</Empty>
<template v-else>
<div class="cardBox" v-for="(item, index) in data2" :key="index">
<Card :buttonIcon="null" :keyMap="keyMap" :cardData="item" class="card" buttonText="详情">
<template #form-remark="{ data }">
<div class="remark">
{{ data.remark }}
</div>
</template>
<template #button>
<el-switch v-model="item.status" active-color="#0BD" inactive-color="#999" active-value="0"
inactive-value="1" @change="(value) => handleSwitcherChange(value, item) ">
</el-switch>
<Button @click.native="() => goStrategy(item)">
查看
</Button>
</template>
</Card>
</div>
</template>
</div>
<div v-if="tabAction === '3'" style="width:70vw;height: 500px;display: flex;flex-direction: column; justify-content: center;align-items: flex-start;" >
<Form v-model="dataRecord" style="width:100%;" labelWidth="90px" column="2" class="form" ref="FormRecordRef" :formList="formRecord" />
<Table :data="tableData" height="500px" style="margin: 20px;width:95%">
<ElTableColumn label="管控时间" prop="operTime" width="300"/>
<ElTableColumn label="设备名称" prop="dcDeviceName"/>
<ElTableColumn label="管控方式" prop="operType" width="200"/>
<ElTableColumn label="操作人" prop="operName" width="200"/>
<ElTableColumn label="执行结果" prop="stakeMark" width="150" >
<template slot-scope="scope">
<el-popover
placement="top-start"
width="400"
trigger="hover"
:content="scope.row.jsonResult">
<el-button slot="reference" class="btnResult">查看</el-button>
</el-popover>
</template>
</ElTableColumn>
</Table>
<!-- 分页 -->
<div class="footer" style="margin-top:-20px;margin-bottom: 30px">
<ElPagination @current-change="bindRecord" @size-change="onSizeChange" width="'100%'" :page-sizes="[10, 20, 30, 40, 50]"
:page-size="searchData.pageSize" :current-page.sync="searchData.pageNum" layout="total, sizes, prev, pager, next"
:total="tableTotal" class="Pagination">
</ElPagination>
</div>
</div>
</div>
</ElPopover>
</div>
</template>
<script>
import Button from "@screen/components/Buttons/Button.vue";
import Form from "@screen/components/FormConfig";
import Card from "@screen/components/Card1/index.vue";
import * as PresetFormItems from "@screen/common/PresetFormItems.js";
import { merge, cloneDeep } from "lodash";
import { markerClusterIns } from "@screen/pages/Home/components/RoadAndEvents/utils/map.js"
import { ChildTypes } from "@screen/utils/enum.js"
import { getDeviceList } from "@screen/pages/Home/components/RoadAndEvents/utils/httpList.js";
import { delay } from "@screen/utils/common";
import { initSearch } from "@screen/utils/enum/common.js"
import SmartDeviceParams from "@screen/pages/Home/components/Dialogs/SmartDevice/components/DeviceParamsMulti.vue";
import BroadcastParam from "@screen/pages/Home/components/Dialogs/Broadcast/components/BroadcastParamMulti.vue";
import FatigueWakesUpParam from "@screen/pages/Home/components/Dialogs/FatigueWakesUp/components/DeviceParam.vue";
import DrivingGuidanceParam from "@screen/pages/Home/components/Dialogs/DrivingGuidance/components/DeviceParam.vue";
import InfoBoardParam from "@screen/pages/Home/components/InfoBoard/InfoBoard.vue";
import request from "@/utils/request";
import { DeviceForMap } from "@screen/pages/Home/components/RoadAndEvents/utils/buttonEvent";
import { Message } from "element-ui";
import Table from '@screen/components/Table.vue';
import moment from "moment";
import _ from "lodash";
import Pagination from '@screen/components/Pagination.vue';
const componentMap = {
"设备箱": "SmartDeviceParams", "语音广播": "BroadcastParam", "疲劳唤醒": "FatigueWakesUpParam",
"行车诱导": "DrivingGuidanceParam", "情报板": "InfoBoardParam",
} //DeviceTopics[deviceType]
// , , "合流区": undefined,
const hiddenDevices = ["SmartDeviceParams", "InfoBoardParam"];
const controlMulti = Object.keys(componentMap);//6种批量控制
const DeviceTopics = {};//6种批量控制 事件专题 {key:label}
Object.keys(DeviceForMap).forEach(DeviceLabel => {
controlMulti.indexOf(DeviceLabel) !== -1 && (DeviceTopics[DeviceForMap[DeviceLabel].deviceType] = DeviceLabel);
});
const deviceTypeDefault = Object.keys(DeviceTopics)[1];
async function setDeviceOptions(config, filterData, formList) {
const data = await getDeviceList(config.deviceType, filterData).then(async (data) => {
await delay(600);
return data;
});
formList[4].options.options = data.map(item => {
return { label: `${item.deviceName}`, value: JSON.stringify({ id: item.id, iotDeviceId: item.iotDeviceId, deviceType: item.deviceType, otherConfig: item.otherConfig }), disabled: item.deviceState != 1 }
})
};
function changeHandle(data, formList) {
const filterData = {};
data.direction && (filterData.direction = data.direction);
data.startStakeMark && (filterData.startStakeMark = data.startStakeMark);
data.endStakeMark && (filterData.endStakeMark = data.endStakeMark);
setDeviceOptions({ deviceType: data.deviceType }, filterData, formList);
data.childType = undefined;
}
export default {
name: "HomeFrameControl",//设备控制
components: {
Button,
Form,
Card,
Table,
SmartDeviceParams,
BroadcastParam,
FatigueWakesUpParam,
DrivingGuidanceParam,
InfoBoardParam
},
watch: {
dataRecord(e) {
this.bindRecord()
},
},
data() {
return {
Enum_ControlType: [
{ key: "0", label: "手动控制" },
{ key: "1", label: "定时控制" },
{ key: "2", label: "批量控制" },
{ key: "3", label: "预案控制" }
],
activeIcon: null,
data: {},
hiddenDevices,
submitting: false,
formList: [
{
label: "设备类型:",
key: "deviceType",
type: "select",
default: deviceTypeDefault,
options: {
clearable: true,
options: Object.keys(DeviceTopics).map(key => { return { label: DeviceTopics[key], value: key } }),
},
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
if (data.deviceType) changeHandle(data, formList);
else data.childType = undefined;
}
},
},
{
label: "设备方向:",
key: "direction",
type: "select",
options: {
options: [
{ key: "1", label: "菏泽方向" },
{ key: "3", label: "济南方向" },
{ key: "2", label: "双向" },
],
},
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
data.deviceType && changeHandle(data, formList);
}
},
},
merge({}, PresetFormItems.startStation,
{
options: {
options: [
{
prefix: {
text: "K",
style: {
color: "#3DE8FF",
},
},
key: "startStakeMark[0]",
default: initSearch.startStakeMark[0],
rules: [
{
message: "请补全桩号",
callback(value, data) {
console.log(value, data.startStakeMark);
if (
!((value + "")?.trim() && (data.startStakeMark[1] + "")?.trim())
)
return false;
else return true;
},
},
],
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
data.deviceType && changeHandle(data, formList);
}
},
},
{
prefix: {
text: "+",
style: {
color: "#3DE8FF",
},
},
default: initSearch.startStakeMark[1],
key: "startStakeMark[1]",
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
data.deviceType && changeHandle(data, formList);
}
},
},
],
}
}),
merge({}, PresetFormItems.endStation, {
options: {
options: [
{
prefix: {
text: "K",
style: {
color: "#3DE8FF",
},
},
key: "endStakeMark[0]",
default: initSearch.endStakeMark[0],
rules: [
{
message: "请补全桩号",
callback(value, data) {
if (
!((value + "")?.trim() && (data.endStakeMark[1] + "")?.trim())
)
return false;
else return true;
},
},
],
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
data.deviceType && changeHandle(data, formList);
}
},
},
{
prefix: {
text: "+",
style: {
color: "#3DE8FF",
},
},
default: initSearch.endStakeMark[1],
key: "endStakeMark[1]",
ons: { //on监听 element事件
change(value, ...args) {
const { data, formList } = args.slice(-1)[0]; //data 为数据 formList为传入的配置项
data.deviceType && changeHandle(data, formList);
}
},
},
],
}
}),
{
label: "设备名称:",
key: "childType",
type: "select",
isAlone: true,
width: '100%',
options: {
clearable: true,
options: [],
multiple: true,
["collapse-tags"]: true
},
visible: data => {
return true;
},
},
// {
// label: "控制操作:",
// key: "controlOp",
// type: "select",
// default: null,
// options: {
// clearable: true,
// options: [{
// label: "在线",
// value: "1"
// }, {
// label: "离线",
// value: "0"
// }]
// },
// },
],
DeviceTopics,
componentMap,
tabAction: "1",
data:[],
keyMap: [
{
key: "groupName",
label: "标题",
},
{
key: "remark",
label: "描述",
},
],
data2:[], //批量管控
dataRecord:{
operType: "0",
operTime:[]
},
formRecord:[
{
label: "管控方式:",
key: "operType",
type: "select",
options: {
options: [
{ key: "0", label: "手动控制" },
{ key: "1", label: "定时控制" },
{ key: "2", label: "批量控制" },
{ key: "3", label: "预案控制" }
],
},
},
{
label: "管控时间:",
key: "operTime",
required: false,
type: "datePicker",
options: {
style: "width: 96%",
type: "datetimerange",
format: "yyyy-MM-dd HH:mm:ss",
valueFormat: "yyyy-MM-dd HH:mm:ss",
},
},
],
tableTotal: 0,
tableData:[],
searchData: {
pageSize: 20,
pageNum: 1,
},
digResultVisible: false
}
},
// inject: ["activeDeviceTypes"],
// watch: {
// activeDeviceTypes: {
// handler(val) {
// const activeTopicOptions = []
// this.activeDeviceTypes.filter(activeDeviceType => {
// const match = activeDeviceType.match(/路测设备_(\d+)/);
// if (match) {
// const deviceType = match[1];
// DeviceTopics[deviceType] && activeTopicOptions.push({ label: DeviceTopics[deviceType], value: deviceType });
// }
// });
// this.formList[0].options.options = activeTopicOptions;
// },
// immediate: true,
// deep: true
// }
// },
mounted() {
changeHandle(this.data, this.formList);
},
methods: {
onHide(){
this.data['deviceType']=deviceTypeDefault;
changeHandle(this.data, this.formList);
},
submitClick() {
this.$refs.ControlComponent?.handleSubmit();
},
cancelClick() {
this.activeIcon = null;
},
tabClick() {
if(this.tabAction === '2'){
this.bindTimeing();
} else if(this.tabAction === '3'){
this.dataRecord.operTime = [moment().startOf('month').format('YYYY-MM-DD 00:00:00'),moment().endOf('month').format('YYYY-MM-DD 23:59:59'),]
this.bindRecord();
} else if(this.tabAction === '1'){
// this.data['deviceType']=deviceTypeDefault;
// changeHandle(this.data, this.formList);
}
},
handleClick(type) {
this.activeIcon = this.activeIcon === type ? null : type;
},
filterEnd(data) {
this.activeIcon = null;
// this.filterData = data;
this.$parent.$refs.RoadAndEventsRef?.setFilterData?.(data);
},
goStrategy(item){
this.$router.push(`/control/device/strategy?id=${item.id}`);
},
async handleSwitcherChange(value, item) {
request({
url: `/business/dcBatchFunctionsJobGroup`,
method: "PUT",
data: {
id:item.id,
status:value
},
})
.then((result) => {
item.status = result.data.status;
if (result.code != 200) return;
Message.success(`操作成功!`);
})
},
bindTimeing(){
request({
url: `/business/dcBatchFunctionsJobGroup/list`,
method: "get",
params: {},
})
.then((result) => {
if (result.code != 200) return;
this.tableTotal = result.total;
this.data2 = result.rows;
})
.finally(() => {
});
},
bindRecord(){
request({
url: `/business/dcOperLog/list`,
method: "get",
params: {
...this.searchData,
operType:this.dataRecord.operType,
startTime:this.dataRecord.operTime[0],
endTime:this.dataRecord.operTime[1]}
})
.then((result) => {
if (result.code != 200) return;
result.rows.forEach(e => {
e.operTime = moment(e.operTime).format('YYYY-MM-DD HH:mm:ss')
e.operType = _.find(this.Enum_ControlType,{key:e.operType}).label
});
this.tableData = result.rows;
this.tableTotal = result.total;
})
.finally(() => {
});
},
onSizeChange(pageSize) {
this.tableData = [];
this.searchData.pageSize = pageSize;
this.searchData.pageNum = 1;
this.bindRecord();
},
showResult(res){
this.digResultVisible = true
}
},
};
</script>
<style lang="scss">
div.el-popper.global-input-search-popover {
background: rgba(6, 66, 88, 0.8);
border: 1px solid rgba(42, 217, 253, 0.6);
position: relative;
padding-top: 36px;
transform: translateY(24px);
// margin-top: 6vh;
.body {
.title {
background: linear-gradient(90deg,
#237e9b 0%,
rgba(23, 145, 184, 0) 100%);
padding: 3px 9px;
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.close {
padding: 3px 9px;
cursor: pointer;
position: absolute;
top: 0;
right: 0;
width: fit-content;
}
}
}
</style>
<style lang="scss" scoped>
.image {
width: 50vw;
height: 65vh;
}
.HomeFrameControl {
.btn {
padding: 9px;
background: linear-gradient(180deg, #152e3c 0%, #163a45 100%);
border-radius: 4px;
overflow: hidden;
height: unset;
border: 1px solid rgba(40, 144, 167, 1);
}
.btn-active {
background: linear-gradient(180deg, #005c79 0%, #009bcc 100%);
}
}
.cardPanel{
display: flex;
flex-wrap: wrap;
}
.cardBox {
flex-basis: percentage(1/4);
padding-right: 10px;
padding-bottom: 10px;
}
.remark {
font-size: 14px; line-height: 20px; height: 40px; overflow: hidden;
color: #00b3cc;
}
.btnResult{
background-color:#00b3cc;
color: white;
border: none;
padding: 5px 20px;
}
</style>
<style lang="scss" scoped>
.Pagination {
// color: #fff;
::v-deep {
> button,
> ul li {
background: #064258;
border-radius: 2px 2px 2px 2px;
opacity: 1;
color: #fff;
}
> button {
padding: 0 3px;
border: 1px solid #00b3cc;
}
> ul li {
background: linear-gradient(180deg, #004960 0%, #004b62 100%);
margin: 0 1.5px;
&.active {
background: linear-gradient(180deg, #005c79 0%, #009bcc 100%);
}
}
.el-pagination__total {
color: #fff;
}
.el-pagination__sizes {
.el-select {
.el-input {
width: 81px;
.el-input__inner {
font-size: 12px;
height: 23px;
background-color: #064258 !important;
}
}
.el-input__suffix {
.el-input__icon {
line-height: 23px;
}
}
}
}
.el-pagination__jump {
margin-left: 10px;
color: #fff;
font-size: 12px;
.el-input {
width: 27px;
margin: 0 3px;
.el-input__inner {
font-size: 12px;
background-color: #064258 !important;
border-radius: 2px 2px 2px 2px;
}
}
}
.btn-next {
margin-left: 6px;
}
.btn-prev {
margin-right: 6px;
}
}
::v-deep .el-pagination__total {
margin-left: 10px;
}
}
</style>