zhgdyun/src/views/projectAdmin/dataBoard/AiAnalysisCopy.vue
2022-06-08 14:51:11 +08:00

935 lines
34 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 进度管理 -->
<div class="fullHeight">
<!-- <vue-scroll>
<img src="@/assets/images/dataBoard/6.png" style="height:auto;width:100%"/>
</vue-scroll> -->
<div class="aside fullHeight">
<div class="blockBox">
<div class="blockTitle">
<!-- 预警统计 -->
{{$t('message.dataBoard.alarmStatistics')}}
</div>
<div class="blockContent flex">
<div class="companyChart" ref="echart"></div>
<div class="right-tg">
<ul>
<li v-for="(item,index) in echartData" :key="index">
<span :style="{'background': colorList[index]}"></span>
{{item.name}}
</li>
</ul>
<ul style="margin-left: 20px">
<li v-for="(item,index) in echartData" :key="index">
{{item.value}}
</li>
</ul>
</div>
</div>
</div>
<div class="blockBox">
<div class="blockTitle">
<!-- 设备情况 -->
{{$t('message.dataBoard.devDetail')}}
</div>
<div class="blockContent dev-status">
<vue-scroll>
<ul>
<li v-if="item" class="flex" v-for="(item,index) in devStatusList" :key="index">
{{item.videoName}}
<!-- {{item.name}} -->
<span>{{item.deviceType == 1?'枪机':item.deviceType == 2?'球机':item.deviceType == 3?'热成像':item.deviceType == 4?'单兵':item.deviceType == 5?'全景':'无人机'}}</span>
<!-- <span>{{item.type}}</span> -->
</li>
</ul>
</vue-scroll>
</div>
</div>
<div class="blockBox">
<div class="blockTitle">
<!-- 预警事件 -->
{{$t('message.dataBoard.alarmEvent')}}
</div>
<div style="overflow:hidden;" class="blockContent">
<!-- :data="10" :class-option="defaultOption"-->
<vue-seamless-scroll :data="earlyWarning" :class-option="defaultOption">
<ul class="earlyWarningList">
<li class="earlyWarningList_item" v-for="(item,index) in earlyWarning" :key="index">
<div class="imgBox">
<!-- <img :src="fileUrl + item.imageUrl"/> -->
<!-- <img :src="item.imageUrl"/> -->
<img src="./../../../assets/images/demo.jpg">
</div>
<div class="content">
<!-- <div v-if="item.hardwareName" :title="'设备' + item.hardwareName + '在' + item.location + '检测到' + alarmTypes(item.alarmType) + ',请及时处理...'" class="list-title">{{'设备' + item.hardwareName + '' + item.location + '检测到' + alarmTypes(item.alarmType) + ',请及时处理...'}}</div> -->
<div class="list-title" :title="item.details">{{item.details}}</div>
<!-- <div class="list-time">识别时间{{item.createTime}}</div> -->
<div class="list-title">{{item.time}}</div>
</div>
</li>
</ul>
</vue-seamless-scroll>
</div>
</div>
</div>
<div class="right fullHeight">
<div class="blockBox blockBox3" style="height: calc(66.66% - 25px)">
<div class="blockTitle">
<!-- 抓拍记录 -->
{{$t('message.dataBoard.captureRecords')}}
</div>
<!-- <div @click="scrollClick($event)" style="overflow:hidden;" class="blockContent">-->
<div style="overflow:hidden;" class="blockContent">
<!-- <vue-seamless-scroll :data="captureRecord" :class-option="defaultOption2"> -->
<vue-scroll>
<div class="captureRecordBox">
<div :title="item.time" :data-name="item.id" :data-type="'all'" @click="selectCaptureRecord(item)" v-for="(item,index) in captureRecord" :key="index" class="captureRecord_item">
<div class="imgBox">
<!-- <img :src="fileUrl + item.imageUrl"/> -->
<img :src="item.imageUrl"/>
<!-- <img src="./../../../assets/images/demo.jpg"> -->
</div>
<div class="captureRecord_itemInfo">
<!-- <div :title="item.hardwareName" class="itemInfo itemInfoId">设备名:{{item.hardwareName}}</div>
<div :title="item.createTime" class="itemInfo itemInfoTime">抓拍时间:{{item.createTime}}</div>
<div :title="item.location" class="itemInfo itemInfoPlace">抓拍点:{{item.location}}</div> -->
<div :title="item.name" class="itemInfo itemInfoId"> {{$t('message.dataBoard.devName')+':'}}<!-- 设备名 -->:{{item.name}}</div>
<div :title="item.time" class="itemInfo itemInfoTime">{{$t('message.dataBoard.captureTime')+':'}}<!-- 抓拍时间: -->{{item.time}}</div>
<div :title="item.place" class="itemInfo itemInfoPlace">{{$t('message.dataBoard.captureLocation')+':'}}<!-- 抓拍点: -->{{item.place}}</div>
<!-- 1-安全帽报警2-明火报警3-聚众报警4-倒地报警5-越界报警6-闯入报警7反光衣报警,8-吸烟报警-->
<!-- <div :title="alarmTypes(item.alarmType)" class="itemInfo itemInfoType">抓拍类型:{{alarmTypes(item.alarmType)}}</div> -->
<div :title="alarmTypes(item.type)" class="itemInfo itemInfoType">{{$t('message.dataBoard.captureType')+':'}}<!-- 抓拍类型: -->{{alarmTypes(item.type)}}</div>
</div>
</div>
</div>
</vue-scroll>
<!-- </vue-seamless-scroll> -->
</div>
</div>
<div class="blockBox blockBox2">
<div class="blockTitle">
<!-- 预警趋势 -->
{{$t('message.dataBoard.warningTrend')}}
</div>
<div class="blockContent blockContent2" >
<div class="optionBox">
<div @click="changeOptionBoxListIndex(index)" v-for="(item,index) in optionBoxList" :key="index" class="optionBox_item" :class="{selectOptionBox_item:optionBoxListIndex === index}">
<span>{{item.text}}</span>
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
</div>
<!-- <div class="optionBox_item">-->
<!-- 近30天-->
<!-- <div class="a"></div>-->
<!-- <div class="b"></div>-->
<!-- <div class="c"></div>-->
<!-- <div class="d"></div>-->
<!-- </div>-->
</div>
<div ref="echart2" style="width: 100%;height: 100%" class="stageBox">
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import echarts from 'echarts4';;
import mqtt from "mqtt";
import vueSeamlessScroll from 'vue-seamless-scroll'
import {
getAiAnalyseHardWareAlarmTotalApi,//查询所有各预警类型预警数 (预警统计)
selectAiAnalyseHardWareAlarmTrendListApi,//查询近七天或近30天报警趋势(预计趋势)
selectAIVideoTypeCountListApi,//按照摄像头类型查询具有AI功能的摄像头数量(设备情况)
selectAiAnalyseHardWareAlarmListApi//查询设备报警记录列表(预警记录&&抓拍记录)
} from "@/assets/js/api/AI";
const options = {
connectTimeout: 40000,
clientId:
"mqttjs_" +
Math.random()
.toString(16)
.substr(2, 8),
username: "root",
password: "123456",
clean: true
};
let client = null;
export default {
data() {
return {
optionBoxList:[
{
text:/* "近7天" */this.$t('message.dataBoard.timeList')[0]
},
{
text:/* "近30天" */this.$t('message.dataBoard.timeList')[1]
}
],
optionBoxListIndex:0,
colorList: ['#44D7B6','#3052B3', '#FE6C7F', '#FAC915','#91c7ae','#749f83','#ca8622','#bda29a'],
chart1: Object,
chart2: Object,
option1:{},
option1:{},
// [
// {
// details:"摄像机一号在钢筋加工棚监测到有未戴安全帽,请及时处理…",
// time:"09-12 13:45:42"
// },
// {
// details:"摄像机一号在钢筋加工棚监测到有未戴安全帽,请及时处理…",
// time:"09-12 13:45:42"
// },
// ],
earlyWarning:this.$t('message.dataBoard.earlyWarning'),
// [
// {value: 0, name: '车辆冲洗'},
// {value: 0, name: '运输车辆密闭运输'},
// {value: 0, name: '裸土覆盖'},
// {value: 0, name: '围挡上报记录'},
// {value: 0, name: '路面硬化上报记录'},
// {value: 0, name: '湿法作业上报记录'},
// ],
echartData: this.$t('message.dataBoard.echartData'),
totalNum:0,
// [
// {
// name: '设备一号',
// type: '枪机'
// },{
// name: '设备二号',
// type: '球机'
// },{
// name: '设备三号',
// type: '无人机'
// }],
devStatusList:this.$t('message.dataBoard.devStatusList2'),
// [
// {
// name: '无人机',
// id:'900',
// time: '09-11 15:00:00',
// place:'施工通道',
// type:1,
// imageUrl: 'http://124.71.178.44:30/image/71b019f8-09ea-42d7-b7cd-842ec34e330b.jpg'
// },
// {
// name: '无人机',
// id:'901',
// time: '09-11 15:00:00',
// place:'施工通道',
// type: 1,
// imageUrl: 'http://124.71.178.44:30/image/14e45426-6d94-4a97-a91e-74c1c9976b56.jpg'
// }
// ],
captureRecord:this.$t('message.dataBoard.captureRecordList'),
userId: "",
topicName: "aiAnalyse",
dataTimeList:[],
alarmTypeNum1:[],
alarmTypeNum2:[],
alarmTypeNum3:[],
alarmTypeNum4:[],
alarmTypeNum5:[],
alarmTypeNum6:[],
alarmTypeNum7:[],
alarmTypeNum8:[],
alarmTotalNum:[],
fileUrl:"",
currentPersonDetail:''
};
},
created(){
this.fileUrl = this.$store.state.FILEURL;
console.log(this.$store.state.userInfo.scope);
this.getAiAnalyseHardWareAlarmTotal()
this.selectAiAnalyseHardWareAlarmTrendList(this.optionBoxListIndex+1)
this.selectAIVideoTypeCountList()
// this.selectAiAnalyseHardWareAlarmList()
},
mounted() {
// client = mqtt.connect("ws://139.159.226.224:8083/mqtt", options);
client = mqtt.connect(mqttUrl, options);
this.mqttMSG();
},
beforeDestroy() {
if(client){
client.unsubscribe(this.topicName + this.$store.state.projectSn);
}
},
components: {
vueSeamlessScroll
},
computed: {
alarmTypes(){
return function (type) {
let alarmType
if(type == 1){
alarmType = /* '车辆冲洗' */this.$t('message.dataBoard.echartData')[0]
}else if (type == 2){
alarmType = /* '运输车辆密闭运输' */this.$t('message.dataBoard.echartData')[1]
} else if (type == 3){
alarmType = /* '裸土覆盖' */this.$t('message.dataBoard.echartData')[2]
}else if (type == 4){
alarmType = /* '围挡上报记录' */this.$t('message.dataBoard.echartData')[3]
}else if (type == 5){
alarmType = /* '路面硬化上报记录' */this.$t('message.dataBoard.echartData')[4]
}else if (type == 6){
alarmType = /* '湿法作业上报记录' */this.$t('message.dataBoard.echartData')[5]
}
return alarmType
}
},
defaultOption () {
return {
step: 0.5, // 数值越大速度滚动越快
limitMoveNum: 3, // 开始无缝滚动的数据量 this.dataList.length
hoverStop: true, // 是否开启鼠标悬停stop
direction: 1, // 0向下 1向上 2向左 3向右
openWatch: true, // 开启数据实时监控刷新dom
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 1000, // 单步运动停止的时间(默认值1000ms)
}
},
defaultOption2 () {
return {
step: 0.5, // 数值越大速度滚动越快
limitMoveNum: 8, // 开始无缝滚动的数据量 this.dataList.length
hoverStop: true, // 是否开启鼠标悬停stop
direction: 1, // 0向下 1向上 2向左 3向右
openWatch: true, // 开启数据实时监控刷新dom
singleHeight: 0, // 单步运动停止的高度(默认值0是无缝不停止的滚动) direction => 0/1
singleWidth: 0, // 单步运动停止的宽度(默认值0是无缝不停止的滚动) direction => 2/3
waitTime: 1000, // 单步运动停止的时间(默认值1000ms)
}
},
},
methods: {
//查询所有各预警类型预警数 (预警统计)
getAiAnalyseHardWareAlarmTotal(){
getAiAnalyseHardWareAlarmTotalApi({
projectSn:this.$store.state.projectSn,
}).then((res) => {
this.echartData[0].value = res.result.alarmTypeNum1
this.echartData[1].value = res.result.alarmTypeNum2
this.echartData[2].value = res.result.alarmTypeNum3
this.echartData[3].value = res.result.alarmTypeNum4
this.echartData[4].value = res.result.alarmTypeNum5
this.echartData[5].value = res.result.alarmTypeNum6
this.totalNum = res.result.totalNum
this.createdEchart1()
console.log(this.echartData);
});
},
changeOptionBoxListIndex(index){
this.optionBoxListIndex = index
this.selectAiAnalyseHardWareAlarmTrendList(index+1)
},
//查询近七天或近30天报警趋势(预计趋势)
selectAiAnalyseHardWareAlarmTrendList(selectType){
selectAiAnalyseHardWareAlarmTrendListApi({
projectSn:this.$store.state.projectSn,
selectType:selectType
}).then((res) => {
this.alarmTypeNum1 = []
this.alarmTypeNum2 = []
this.alarmTypeNum3 = []
this.alarmTypeNum4 = []
this.alarmTypeNum5 = []
this.alarmTypeNum6 = []
this.alarmTypeNum7 = []
this.alarmTypeNum8 = []
this.alarmTotalNum = []
this.dataTimeList = []
res.result.forEach((item) => {
this.alarmTypeNum1.push(item.alarmTypeNum1)
this.alarmTypeNum2.push(item.alarmTypeNum2)
this.alarmTypeNum3.push(item.alarmTypeNum3)
this.alarmTypeNum4.push(item.alarmTypeNum4)
this.alarmTypeNum5.push(item.alarmTypeNum5)
this.alarmTypeNum6.push(item.alarmTypeNum6)
this.alarmTypeNum7.push(item.alarmTypeNum7)
this.alarmTypeNum8.push(item.alarmTypeNum8)
this.alarmTotalNum.push(item.totalNum)
this.dataTimeList.push(item.dayTitle)
this.createdEchart2()
// console.log(item);
})
console.log(res);
});
},
//按照摄像头类型查询具有AI功能的摄像头数量(设备情况)
selectAIVideoTypeCountList(){
selectAIVideoTypeCountListApi({
projectSn:this.$store.state.projectSn
}).then((res) => {
// 1 枪机2球机3热成像4单兵5全景6无人机
this.devStatusList = res.result
console.log(res);
});
},
//查询设备报警记录列表(预警记录&&抓拍记录)
selectAiAnalyseHardWareAlarmList(){
selectAiAnalyseHardWareAlarmListApi({
projectSn:this.$store.state.projectSn,
sizeNum:20
}).then((res) => {
this.earlyWarning = res.result
this.captureRecord = res.result
console.log(res);
});
},
// scrollClick(e) {
// //通过 e.target获取点击的dom
// //通过e.target.dataset获取vuedom中的自定义属性
// let data = e.target.dataset;
// this.$emit("supervise-detail", data.name, data.type);
// console.log(data);
// },
createdEchart1(){
// console.log(this.$refs['echart'])
let chart1 = echarts.init(this.$refs['echart']);
this.chart1 = chart1;
chart1.clear();
this.option1 = {
grid:{
top:"0px",
left:"0px",
right:"0px",
bottom:"0px"
},
tooltip: {
trigger: 'item'
},
legend: {
show: false,
},
graphic:[{
type: 'text',
left: 'center',
top: '38%',
style:{
text: this.totalNum,
textAlign: 'center',
fill: '#fff',
fontSize: 26
}
},{
type: 'text',
left: 'center',
top: '55%',
style:{
text: /* '问题总数', */this.$t('message.dataBoard.questionAllCounts'),
textAlign: 'center',
fill: '#fff',
fontSize: 14
}
}],
color:this.colorList,
series: [
{
type: 'pie',
radius: ['55%', '70%'],
center:['50%','50%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: false,
fontSize: '16',
color: "#fff"
}
},
labelLine: {
show: false
},
data: this.echartData,
stillShowZeroSum: true,
minShowLabelAngle: 10
},
]
}
chart1.setOption(this.option1);
},
createdEchart2(){
// console.log(this.$refs['echart'])
let chart2 = echarts.init(this.$refs['echart2']);
this.chart2 = chart2;
chart2.clear();
this.option2 = {
color:['#557DED','#44D7B6','#3052B3', '#FE6C7F', '#FAC915','#91c7ae','#749f83','#ca8622','#bda29a'],
legend: {
// ['总计', '车辆冲洗','运输车辆密闭运输','裸土覆盖','围挡上报记录','路面硬化上报记录','湿法作业上报记录']
data:this.$t('message.dataBoard.echartNameData'),
textStyle:{
// fontSize: 14,//字体大小
color: '#FEFFFF'//字体颜色
},
left:"10%",
top:"6%"
},
tooltip:{
trigger: 'axis',
position: [20, 20]
},
xAxis: {
type: 'category',
data: this.dataTimeList,
axisLabel : {
formatter: '{value}',
textStyle: { //改变刻度字体样式
color: 'RGB(254,255,255,0.5)'
}
}
},
yAxis: {
type: 'value',
axisLabel : {
formatter: '{value}',
textStyle: { //改变刻度字体样式
color: 'RGB(254,255,255,0.5)'
}
},
splitLine: {
show: true,
lineStyle:{
type:'dashed',
color:"RGB(236,236,236,0.5)"
}
}
},
series: [
{
name:/* "总计", */this.$t('message.dataBoard.echartNameData')[0],
data: this.alarmTotalNum,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#557DED'
}
}
},
},
{
name:/* "车辆冲洗", */this.$t('message.dataBoard.echartNameData')[1],
data: this.alarmTypeNum1,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#44D7B6'
}
}
},
},
{
name:/* "运输车辆密闭运输", */this.$t('message.dataBoard.echartNameData')[2],
data: this.alarmTypeNum2,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#3052B3'
}
}
},
},
{
name:/* "裸土覆盖", */this.$t('message.dataBoard.echartNameData')[3],
data: this.alarmTypeNum3,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#FE6C7F'
}
}
},
},
{
name:/* "围挡上报记录", */this.$t('message.dataBoard.echartNameData')[4],
data: this.alarmTypeNum4,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#FAC915'
}
}
},
},
{
name:/* "路面硬化上报记录", */this.$t('message.dataBoard.echartNameData')[5],
data: this.alarmTypeNum5,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#91c7ae'
}
}
},
},
{
name:/* "湿法作业上报记录", */this.$t('message.dataBoard.echartNameData')[6],
data: this.alarmTypeNum6,
type: 'line',
smooth: true,
itemStyle : {
normal : {
lineStyle:{
color:'#749f83'
}
}
},
}
]
}
chart2.setOption(this.option2);
},
mqttMSG() {
// mqtt连接 +"/#" +workerId
client.on("connect", (e) => {
console.log("连接成功:", this.topicName + this.$store.state.projectSn);
client.subscribe(this.topicName + this.$store.state.projectSn, { qos: 0 }, (error) => {
if (!error) {
console.log("订阅成功");
} else {
console.log("订阅失败");
}
});
});
// 接收消息处理
client.on("message", (topic, message) => {
console.log(message);
message = JSON.parse(message);
this.currentPersonDetail=JSON.parse(message.content)
console.log(this.currentPersonDetail);
if (this.currentPersonDetail){
if(this.earlyWarning.length < 20){
let arr = [this.currentPersonDetail]
this.earlyWarning = arr.concat(this.earlyWarning)
this.captureRecord = arr.concat(this.captureRecord)
}else {
this.earlyWarning.pop()
this.captureRecord.pop()
this.earlyWarning.unshift(this.currentPersonDetail)
this.captureRecord.unshift(this.currentPersonDetail)
}
}
// if(message.content){
// if(message.content.indexOf("火点检测") > -1 || message.content.indexOf("温度报警") > -1){
// this.$emit('sendMsg')
// }
// }
// this.$notify({
// title: message.title,
// message: message.content,
// });
});
// 断开发起重连
// client.on("reconnect", (error) => {
// console.log("正在重连:", error);
// });
// 链接异常处理
client.on("error", (error) => {
console.log("连接失败:", error);
});
},
selectCaptureRecord(e){
console.log(e);
}
},
};
</script>
<style lang="less" scoped>
/deep/ .stageBox{
div{
canvas{
/*left: -70px !important;*/
top: -25px !important;
/*width: 1500px !important;*/
height: 300px !important;
}
}
}
.a {
width: 5px;
height: 5px;
position: absolute;
top: 0;
left: 0;
border-left: 2px solid #EBEBEB;
border-top: 2px solid #EBEBEB;
}
.b {
width: 5px;
height: 5px;
position: absolute;
top: 0;
right: 0;
border-right: 2px solid #EBEBEB;
border-top: 2px solid #EBEBEB;
}
.c {
width: 5px;
height: 5px;
position: absolute;
bottom: 0;
left: 0;
border-bottom: 2px solid #EBEBEB;
border-left: 2px solid #EBEBEB;
}
.d {
width: 5px;
height: 10px;
position: absolute;
bottom: 0;
right: 0;
border-right: 2px solid #EBEBEB;
border-bottom: 2px solid #EBEBEB;
}
.optionBox{
position: absolute;
right: 50px;
top: 0px;
.optionBox_item{
cursor:pointer;
z-index: 100;
padding: 4px;
display: inline-block;
width: 52px;
height: 22px;
font-size: 12px;
line-height: 26px;
margin-right: 10px;
text-align: center;
background: #193B43;
position: relative;
}
.selectOptionBox_item{
background: #393204;
color: #F7D300;
}
}
.earlyWarningList{
.earlyWarningList_item{
padding: 15px ;
height: 95px;
background: #0D192C;
margin-bottom: 5px;
box-sizing: border-box;
.imgBox{
display: inline-block;
box-sizing: border-box;
img{
width: 79px;
height: 67px;
}
}
.content{
height: 100%;
box-sizing: border-box;
margin-left: 17px;
width: 243px;
display: inline-block;
padding-bottom: 13px;
.list-title{
margin-bottom: 13px;
font-size: 15px;
text-overflow: ellipsis;
line-clamp: 2;
overflow: hidden;
color: #C83E50;
}
.list-time{
font-size: 13px;
}
}
}
}
.captureRecordBox{
/*display: flex;*/
.captureRecord_item{
box-sizing: border-box;
display: inline-block;
width: 305px;
height: 247px;
margin-right: 25px;
margin-bottom: 25px;
.captureRecord_itemInfo{
.itemInfo{
font-size: 12px;
display: inline-block;
width: 152px;
overflow: hidden;
text-overflow:ellipsis; white-space: nowrap;
}
.itemInfoId{
}
.itemInfoTime{
}
.itemInfoPlace{
}
.itemInfoType{
}
}
}
.imgBox{
width: 100%;
img{
width: 100%;
height: 190px;
}
}
}
.numContent {
display: flex;
align-items: center;
justify-content: space-around;
p{
font-size: 14px;
opacity: 0.88;
margin-top: 10px;
text-align: center;
}
}
.companyChart{
width: 50%;
height: 100%;
}
/deep/.alarmTypeBox{
position: absolute;
top: 20px;
right: 10px;
width: 66px;
opacity: 0.8;
z-index: 3;
.el-input__inner{
background-color: transparent;
color: white;
height: 24px;
line-height: 24px;
padding: 0 5px;
}
.el-input__suffix{
right: 0px;
}
.el-input__icon{
color: white;
line-height: 24px;
}
}
.right-tg{
// margin-left: 20px;
display: flex;
ul{
display: flex;
height: 100%;
flex-direction: column;
//align-items: center;
justify-content: center;
li{
margin-bottom: 10px;
display: flex;
align-items: center;
span{
width: 6px;
height: 6px;
display: block;
border-radius: 50%;
margin-right: 6px;
}
}
}
}
.configBtn{
position: absolute;
right: 8px;
top: 15px;
font-size: 20px;
cursor: pointer;
z-index: 3;
}
.days{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
.num{
font-size: 46px;
}
}
.daysBG{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.endDate{
position: absolute;
right: 15px;
bottom: 12px;
// font-size: 13px;
}
.Extgantt{
width: 100%;
height: 100% ;
border: none;
}
.flex{
display: flex;
}
.dev-status{
ul{
li{
background: rgba(#2F4988, 0.3);
color: #fff;
justify-content: space-between;
padding-left: 32px;
height: 37px;
line-height: 37px;
margin-bottom: 6px;
span{
display: block;
width: 65px;
text-align: center;
background: rgba(#557DED,0.6);
color: #fff;
}
}
}
}
</style>