邵佳豪 4 years ago
parent
commit
439fca72a6
  1. 15
      .vscode/launch.json
  2. 5
      src/app/canvas-share-data.service.ts
  3. 2
      src/app/navigation/navigation.component.ts
  4. 24
      src/app/ui/disposal-node/disposal-node.component.html
  5. 84
      src/app/ui/disposal-node/disposal-node.component.scss
  6. 110
      src/app/ui/disposal-node/disposal-node.component.ts
  7. 90
      src/app/ui/plan-assistance/plan-assistance.component.html
  8. 218
      src/app/ui/plan-assistance/plan-assistance.component.scss
  9. 765
      src/app/ui/plan-assistance/plan-assistance.component.ts
  10. 14
      src/app/ui/similar-plans/similar-plans.component.html
  11. 19
      src/app/ui/similar-plans/similar-plans.component.scss
  12. 38
      src/app/ui/similar-plans/similar-plans.component.ts
  13. 338
      src/app/working-area/working-area.component.ts
  14. BIN
      src/assets/images/direction.png
  15. BIN
      src/assets/images/route.png
  16. BIN
      src/assets/images/进攻方向.png
  17. 2
      src/index.html

15
.vscode/launch.json vendored

@ -0,0 +1,15 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}"
}
]
}

5
src/app/canvas-share-data.service.ts

@ -25,6 +25,11 @@ export class CanvasShareDataService {
selectPanelPoint:any = {disposalNodeId:''}; //选择当前 数据节点
selectPanelPointBaseData:any = {description: '', notes: '',weather: '',airTemperature: '',windDirection: '',windScale: ''}; //当前 数据节点 所对应的 天气,详情 数据节点
//处置 节点
//预案赋能 选择 车辆
selectCar:any = {Id: '', WaterYield: '', Foam: '', PeopleNum: '', Tonnage: '', Assignment: '', LinkCar: '', WaterOccupy: ''}
//预案赋能 选择 车辆
/**
*
*/

2
src/app/navigation/navigation.component.ts

@ -28,7 +28,7 @@ export class NavigationComponent implements OnInit {
{name:'危化品', url: '/ui/dangerous'},
{name:'类似预案', url: '/ui/similarPlans'},
{name:'真实战例', url: '/ui/realCases'},
{name:'预案辅助', url: '/ui/planAssistance'}
{name:'预案赋能', url: '/ui/planAssistance'}
]
ngOnInit () {

24
src/app/ui/disposal-node/disposal-node.component.html

@ -1 +1,23 @@
<p>disposal-node works!</p>
<!-- 头部操作栏 -->
<div class="headerOperate">
<div id="tedian" class="bigeditdeletebtn" (click)='xianshi(1)' ngClass="buildingbtnchecked">
<span>火灾特点</span>
</div>
<div id="zhuyi" class="bigeditdeletebtn" (click)='xianshi(2)' ngClass="buildingbtnchecked">
<span>注意事项</span>
</div>
<div id="chuzhi" class="bigeditdeletebtn" (click)='xianshi(3)' ngClass="buildingbtnchecked">
<span>处置要点</span>
</div>
<div id="zuzhi" class="bigeditdeletebtn" (click)='xianshi(4)' ngClass="buildingbtnchecked">
<span (click)='this.chooseBiaoti=4'>组织指挥要点</span>
</div>
</div>
<!--中间文字-->
<div class="wenzi" id="aaa">
<div class="scrollbar"></div>
</div>
<div style="width: 100%;">
<button class="button" style="float: right;margin-right: 30px;">分享</button>
</div>

84
src/app/ui/disposal-node/disposal-node.component.scss

@ -0,0 +1,84 @@
.icongray{
color: #D9D0DC;
}
//头部操作栏
.headerOperate {
position: relative;
span{
font-size: 18px;
}
flex: 2%;
display: flex;
align-items:center;
min-height: 40px;
box-sizing: border-box;
margin: 3px 0;
.bigeditdeletebtn{
border:1px solid #0E79A9;
margin-right: 0px;
height: 80%;
display: flex;
flex-direction: column;
// align-items:center;/*由于flex-direction: column,因此align-items代表的是水平方向*/
justify-content: center;
user-select: none;
//background-image: url("../../../assets/images/标签正常.png") ;
background-size:100% 100%;
color: white;
span{
padding: 13px 13px;
//padding-right: 18px;
font-size: 24px;
}
}
.bigeditdeletebtn:hover{
cursor: pointer;
//background-image: url("../../../assets/images/标签经过.png") ;
}
}
//中间文字区域
.wenzi{
overflow:auto;
height: 85%;
width: 100%;
line-height: 35px;
.h3{
color: #CC5D13;
}
.scrollbar{
width: 30px;
height: 300px;
margin: 0 auto;
}
.wenzi::-webkit-scrollbar {/*滚动条整体样式*/
width: 10px; /*高宽分别对应横竖滚动条的尺寸*/
height: 1px;
}
.wenzi::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
border-radius: 10px;
//-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
background: #CC5D13;
}
.wenzi::-webkit-scrollbar-track {/*滚动条里面轨道*/
//-webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
border-radius: 10px;
background: #EDEDED;
}
}
.button {
border-radius: 2px;
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}

110
src/app/ui/disposal-node/disposal-node.component.ts

@ -8,8 +8,118 @@ import { Component, OnInit } from '@angular/core';
export class DisposalNodeComponent implements OnInit {
constructor() { }
setTimeoutObj//延时器需要清除
ngOnInit(): void {
console.log(this.chooseBiaoti)
this.setTimeoutObj = window.setTimeout(()=>{
this.xianshi(1)
},0)
}
ngAfterContentInit (){
//this.xianshi()
}
checkedBuildingIndex:number = -1
chooseBiaoti=1
//鼠标移入边框变颜色
yiru(yirunum){
var tedian=document.getElementById(yirunum)
tedian.style.border="1px solid #C8CE4D"
}
yichu(yichunum){
var tedian=document.getElementById(yichunum)
tedian.style.border="1px solid #0E79A9"
}
//点击切换中间显示的文字
xianshi(biaotinum){
var mianban=document.getElementById('aaa')
var tedian=document.getElementById('tedian')
var zhuyi=document.getElementById('zhuyi')
var chuzhi=document.getElementById('chuzhi')
var zuzhi= document.getElementById('zuzhi')
var chuzhiYuanze='';
if(biaotinum==4){
zuzhi.style.border="1px solid #30BBEC"
tedian.style.border="1px solid #0E79A9"
zhuyi.style.border="1px solid #0E79A9"
chuzhi.style.border="1px solid #0E79A9"
chuzhiYuanze+=`<h3 style="color: #CC5D13">一、处置原则</h3>`;
chuzhiYuanze+='<span style="color: #FFFFFF">(一)灾情处置应坚持“</span>'
chuzhiYuanze+='<span style="color: #F95E5A">救人第一、科学施救</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">”的原则,严禁在不熟悉情况时擅自行动,严禁冒险蛮干。</br></span>'
chuzhiYuanze+='<span style="color: #FFFFFF">(二)现场情况基本清楚,无爆炸等次生灾害风险,灾情易于辨识研判,在技术人员指导下,果断下达指令开展灭火救援行动。</br>'
chuzhiYuanze+='(三)燃烧物不清,现场情况不明,难于辨识研判,参战力量要与现场保持足够的安全距离;如有人员被困,且有希望抢救受困人员生命时,指挥员应视情采取救人措施。</br>'
chuzhiYuanze+='(四)燃烧物不清,现场情况不明,无人员受困,难以研判决策,现场指挥员应及时采取外部控灾措施,并与现场保持适当安全距离。</br>'
chuzhiYuanze+='(五)燃烧物已知,无人员受困,有爆炸伤亡风险,指挥员应采取依托掩体外围抑爆控灾措施,必要时建议指挥部扩大警戒、疏散范围。</br>'
chuzhiYuanze+='<h3 style="color: #CC5D13">二、受理报警</h3>'
chuzhiYuanze+='(一)危险化学品场所发生火灾爆炸,火警等级不应小于四级;危险化学品发生泄漏事故,容易导致火灾爆炸或中毒事故发生,对人员、财产威胁严重或可能出现二次污染等情况特殊、灾情严重的灾害事故,应急救援等级不应小于三级。</br>'
chuzhiYuanze+='(二)事故发生后,指挥中心应迅速准确受理报警,应当询问掌握报警人信息、事故单位基本情况、主要联系方式,</span>'
chuzhiYuanze+='<span style="color: #F95E5A">问清危险化学品的种类、数量、危害特性和储存方式,以及有无人员被困,周边受威胁危险化学品的有关情况,</br></span>'
chuzhiYuanze+='<span style="color: #FFFFFF">及时告知救援人员相关情况和注意事项,同时报告指挥长和全勤指挥部成员。</br>'
chuzhiYuanze+='(三)指挥中心要不间断与辖区消防救援站、报警群众和单位负责人联系,根据现场情况及时调派增援力量,向参战力量推送危险化学品理化性质、处置措施和注意事项,并将灾情按要求上报上级指挥中心。'
chuzhiYuanze+='<h3 style="color: #CC5D13">三、力量调集</h3>'
chuzhiYuanze+='(一)指挥中心应及时调集辖区中队、周边化工灭火救援编队到场处置,全勤指挥部和战勤保障力量遂行出动</span>'
}
else if(biaotinum==1){
zuzhi.style.border="1px solid #0E79A9"
tedian.style.border="1px solid #30BBEC"
zhuyi.style.border="1px solid #0E79A9"
chuzhi.style.border="1px solid #0E79A9"
chuzhiYuanze+='<span style="color: #FFFFFF">(1) 爆炸引起燃烧。油罐发生爆炸后,随即易形成稳定燃烧。爆炸后,从罐顶或裂口处流出的油品或因罐体移位流出的油品,易造成地面流淌性燃烧。</br>'
chuzhiYuanze+='(2) 燃烧引起爆炸。在形成稳定燃烧的油罐的邻近油罐,在热辐射的作用下易发生爆炸,扩大火势。</br>'
chuzhiYuanze+='(3) 火焰高,辐射热强。爆炸后在油罐破裂位置形成的稳定燃烧,其火焰高达几十米,并对其四周产生强烈的热辐射。</br>'
chuzhiYuanze+='(4) 易形成沸溢与喷溅。由于重质油品具有“热波特性”,对含有一定水分或有水垫层的重质油品储罐发生火灾后,如果不能及时进行冷却控制,在其“热波特性”的作用下就会使油品内的乳化水或油层下的水垫层产生过热蒸汽,而导致发生油品的沸溢或喷溅现象。</br>'
chuzhiYuanze+='(5) 易造成大面积燃烧。重质油品储罐发生的沸溢、喷溅现象,在其压力的作用会将大量的油品喷洒在事故区域内,瞬间即可造成大面积燃烧,同时,对在火场内的消防战斗人员、车辆及其他装置、设备造成极大的威胁。</span>'
}
else if(biaotinum==2){
zuzhi.style.border="1px solid #0E79A9"
tedian.style.border="1px solid #0E79A9"
zhuyi.style.border="1px solid #30BBEC"
chuzhi.style.border="1px solid #0E79A9"
chuzhiYuanze+='<span style="color: #FFFFFF">1、油罐火灾的辐射热强,参战人员应配有防高温、防辐射、防毒的防护装备。</br>'
chuzhiYuanze+='2、正确选择停车位置。消防车尽量停在上风或侧上风向,与燃烧油罐保持一定的安全距离。扑救重质油罐火灾时,消防车头应背向油罐,以备紧急撤离。作战行动中的部分车辆动画加上文字配音说明</br>'
chuzhiYuanze+='3、注意观察火场情况变化,及时发现沸溢、喷溅征兆。</br>'
chuzhiYuanze+='4、充分冷却,防止复燃。燃烧罐的火势被扑灭后,要继续对其实施冷却,直至使罐内油品温度降到燃点以下为止。设有保温层的原油罐可不予以冷却。轻质油品罐不会形成高温层,冷却的重点是液面以上的罐壁。救活的图片加上文字配音说明。</br>'
chuzhiYuanze+='5、浮顶油罐在初期火灾时,燃烧仅限于密封围堰部位,应立即启动固定泡沫灭火装置或组织泡沫管枪从固定铁梯进行强攻,消灭围堰内的火灾。作战行动中的动画加文字配音说明。</br>'
chuzhiYuanze+='6、注意观察和选择有利地形,尽量选取上风向处,前沿阵地的战斗人员(水枪手等)要注意利用地形地物掩护自己,并穿着铝箔隔热服。防止坍塌及爆炸对人的危害。作战行动中的动画加文字配音说明。</br>'
chuzhiYuanze+='7、要与工程技术人员联系,充分工艺手段灭火。</br>'
chuzhiYuanze+='8、火情侦察要详细、认真、全面,尤其注意关联设备和邻近装置,注意流淌火的观察和控制,防止沿沟渠蔓延。</br>'
chuzhiYuanze+='9、充分利用固定消防设施。</br>'
chuzhiYuanze+='10、灭火剂要供应充足,兵力部署要符合灭火战斗要求,集中优势兵力,一举扑灭火灾,切忌供应出现中断和零打碎敲。</br>'
chuzhiYuanze+='11、注意第一力量调集,调集兵力的数量要满足灭火需要,但不能过多,以免造成现场拥挤和混乱。7-11用厂区的作战行动动画做背景加上文字配音说明</span>'
}
else if(biaotinum==3){
zuzhi.style.border="1px solid #0E79A9"
tedian.style.border="1px solid #0E79A9"
zhuyi.style.border="1px solid #0E79A9"
chuzhi.style.border="1px solid #30BBEC"
chuzhiYuanze+='<h3 style="color: #CC5D13">1、安全防护</h3>'
chuzhiYuanze+='<span style="color: #FFFFFF">①应综合考虑风力风向、工艺流程、地形地势、封闭管井等因素,</span>'
chuzhiYuanze+='<span style="color: #F95E5A">科学选择车辆站位和阵地设置;</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">②科学设置内、外观察哨,通过单位DCS系统设内观察哨,重点监测着火罐及周边邻近罐的介质、压力、温度、液位以及预警等级;通过在外部设观察哨,实时观察燃烧烟雾、火焰以及罐体外形变化、颤动声响等,确保整个作战行动安全可控;</br>'
chuzhiYuanze+='③实施登罐灭火作业,在</span>'
chuzhiYuanze+='<span style="color: #F95E5A">完成泡沫覆盖完成后,现场人员应迅速佩戴空气呼吸器,第一时间撤离,防止硫化氢中毒。</span>'
chuzhiYuanze+='<h3 style="color: #CC5D13">2、泡沫灭火</h3>'
chuzhiYuanze+='<span style="color: #FFFFFF">①登罐灭火最佳时间;着火时间冬季在</span>'
chuzhiYuanze+='<span style="color: #F95E5A">60 分钟</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">之内,夏季在 </span>'
chuzhiYuanze+='<span style="color: #F95E5A">40 分钟</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">之内;</br>②登罐灭火作业,必须根据现场风向和液位合理布设进攻阵地,推进灭火过程还需注意风向变化,适时调整左右推进速度;</br> </span>'
chuzhiYuanze+='<span style="color: #F95E5A">③严禁将移动炮、车载炮、高喷臂架炮的泡沫和冷却水直接打入罐体浮盘中央,</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">防止出现卡盘、沉盘。对着火罐的冷却要均匀,不能留有空白点,防止温差大导致罐体变形、塌陷;</br>④泡沫灭火时,</span>'
chuzhiYuanze+='<span style="color: #F95E5A">应选用同一种类、比例、倍数的泡沫,</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">必须保证喷射的泡沫打在一侧的罐壁上,流向液面形成覆盖层,严禁不同方向同时喷射泡沫。</br>⑤固定系统操作失误,到场水罐无可利用水源,应再采取冷油循环的基础上,控制灾情。再采取紧急调集远程供水。</span>'
chuzhiYuanze+='<h3 style="color: #CC5D13">3、沸溢喷溅</h3>'
chuzhiYuanze+='<span style="color: #FFFFFF">①由于处置方法、处置程序错误或排水不及时,重质油品通常在起火</span>'
chuzhiYuanze+='<span style="color: #F95E5A">3-6小时</span>'
chuzhiYuanze+='<span style="color: #FFFFFF">后罐内出现水垫层,随着油温传导水垫层气化出现油品沸溢,喷射时间一般晚于沸溢时间,常常先发生沸溢,间隔一段时间,再发生喷溅。现场指挥员要科学把握进攻时机,运用好浮盘中央排水和罐内紧急排水两种方法,加强储罐定时积水排放;</br>'
chuzhiYuanze+='②一旦发生沸溢、喷溅征兆时,如罐体颤动、发出嘶撕声、浓黑的烟变白变淡、火焰变高耀眼、油面蠕动涌涨现象明显等,应立即发生撤离信号,指挥部应事先统一撤离信号、撤离的路径方式和集结区。</span>'
}
mianban.innerHTML=chuzhiYuanze
}
}

90
src/app/ui/plan-assistance/plan-assistance.component.html

@ -1,11 +1,95 @@
<div class="content">
<div class="left">
<div class="header leftHeader">到场力量</div>
<div class="list">
<div class="tableDiv">
<div class="tableRows" *ngFor="let item of allCarsData" (click)='selectCar(item)' [ngClass]="{selectIcon: canvasData.selectCar.Id == item.Id}">
<div style="flex: 60%;display: flex;flex-direction: column;justify-content: center;align-items: center;">
<p style="flex: 60%;font-size: 16px;font-weight: 550;" class="contentText">{{item.Name}}</p>
<p style="flex: 40%" class="contentText">{{item.FireTeamName}}</p>
</div>
<div style="flex: 40%; line-height: 50px;text-align: center;color: #37f76D;" *ngIf="item.ReachTime < 1">已到场</div>
<div style="flex: 40%; line-height: 50px;text-align: center;color: #fff;" *ngIf="item.ReachTime > 0">
<label>{{item.ReachTime}}分钟</label>
</div>
</div>
</div>
</div>
</div>
<!-- canvas -->
<div class="center">
<app-working-area #workingArea></app-working-area>
<div class="center" id="center">
<div class="header" style="position: relative;">
<div class="title">总平面图</div>
<div class="draw">
<label title="开始绘制" (click)='plot(0)'></label>
<label title="开始绘制" (click)='plot(1)'></label>
</div>
<div style="float: right;width: 66px;height: 100%;line-height: 40px;text-align: center;position: relative;">
<mat-icon style="color: #fff;font-size: 32px;width: 32px;height: 32px;" (click)='toggleSay()'>volume_up</mat-icon>
<div class="rightSpeak" *ngIf="rightSayIsShow">
<div style="flex: 1;">
<div class="iconButton" style="background-color: #fe9400;">冷却</div>
<div class="iconButton" style="background-color: #f95e5a;">登罐</div>
<div class="iconButton" style="background-color: #0676ee;">注入泡沫</div>
</div>
<div style="width: 100%;height: 34px;line-height: 34px;display: flex;">
<mat-icon>settings_voice</mat-icon>
<label class="sayBgc">按住说话</label>
<mat-icon>search</mat-icon>
</div>
</div>
</div>
</div>
<div class="canvas">
<!-- 底部车辆信息 -->
<div class="bottomWork" *ngIf="bottomIsShow">
<div style="flex: 30%;line-height: 30px;width: 120px;color: #fff;text-align: center;">
<label>车辆属性 <mat-icon (click)="closeBottom()">highlight_off</mat-icon></label>
</div>
<div style="flex: 70%;display: flex;">
<div style="flex: 90%;">
<div class="publicRow" style="box-sizing: border-box;border-bottom: 1px solid #30bbec;color: #f7ae4a; font-weight: 550;">
<p>载水量</p>
<p>载泡沫</p>
<p>载人数</p>
<p>吨位</p>
<p>执行任务</p>
<p>连接车辆</p>
<p>水源占用</p>
</div>
<div class="publicRow" style="color: #fff;font-size: 12px;">
<p>{{canvasData.selectCar.WaterYield}}</p>
<p>{{canvasData.selectCar.Foam}}</p>
<p>{{canvasData.selectCar.PeopleNum}}</p>
<p>{{canvasData.selectCar.Tonnage}}</p>
<p>
<input type="text" class="taskInput" [(ngModel)]="canvasData.selectCar.Assignment">
</p>
<p>{{canvasData.selectCar.LinkCar}}</p>
<p>{{canvasData.selectCar.WaterOccupy}}</p>
</div>
</div>
<div style="flex: 10%;text-align: center;line-height: 70px;">
<button mat-button>发送</button>
</div>
</div>
</div>
<!-- 底部车辆信息 -->
<!-- 右侧楼层区域 -->
<div class="showRightStorey" *ngIf="!rightIsShow" title="打开楼层/区域"><mat-icon (click)='openRight()'>keyboard_arrow_left</mat-icon></div>
<div class="rightStorey" [ngClass]="{closeRight: !rightIsShow,openRight: rightIsShow}">
<div style="flex: 10%;">
<label><mat-icon (click)='closeRight()' title="关闭楼层/区域">keyboard_arrow_right</mat-icon> 楼层/区域</label>
</div>
<div style="flex: 90%;border-top: 1px solid #30bbec;padding: 1px 0;">
<div style="font-size: 14px;width: 100%;height: 35px;line-height: 35px;background-color: rgba(7,89,155,0.7);"><label>厂区总平面图</label></div>
</div>
</div>
<!-- 右侧楼层区域 -->
<app-working-area #workingArea></app-working-area>
</div>
</div>
<!-- canvas -->
</div>

218
src/app/ui/plan-assistance/plan-assistance.component.scss

@ -7,14 +7,230 @@
display: flex;
}
//左右侧 header
.header {
width: 100%;
height: 40px;
min-height: 40px;
}
.leftHeader {
line-height: 40px;
text-align: center;
font-size: 20px;
font-weight: 550;
color: #F7bA2A;
cursor: pointer;
}
.title {
display: inline-block;
margin: 1px 0;
width: 120px;
height: 38px;
line-height: 38px;
background: url('../../../assets/images/标签正常.png');
-moz-background-size:100% 100%;
background-size:100% 100%;
font-size: 20px;
color: #fff;
padding-left: 25px;
cursor: pointer;
}
//左侧菜单
.left {
width: 300px;
height: 100%;
background-color: #000;
min-width: 250px;
box-sizing: border-box;
padding: 1px;
display: flex;
flex-direction: column;
.list {
flex: 1;
overflow: hidden;
.tableDiv {
height: 100%;
overflow-y: auto;
border-left: 1px solid #30bbec;
border-top: 1px solid #30bbec;
}
}
//每一行
.tableRows {
height: 50px;
overflow: hidden;
display: flex;
margin: 13px 0;
.contentText {
font-size: 12px;
color: #fff;
cursor: pointer;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
}
}
//选中状态
.selectIcon {
background-color: rgba(13, 139, 241, 0.7);
}
//右侧工作区
.center {
flex: 1;
box-sizing: border-box;
display: flex;
flex-direction: column;
.canvas {
flex: 1;
position: relative;
}
}
.mat-icon { vertical-align: middle; cursor: pointer; }
//下方 车辆信息 UI
.bottomWork {
width: 800px;
height: 100px;
position: absolute;
bottom: 5px;
left: 50%;
margin-left: -400px;
z-index: 10;
display: flex;
flex-direction: column;
>div{ background-color:rgba(2, 44, 73, 0.9); }
button { width: 50px; height: 40px; background-color: #67c23a; color: #fff; }
//table表格
.publicRow {
height: 50%;
display: flex;
align-items: center;
justify-content: center;
p { flex: 1; text-align: center; line-height: 35px; }
}
.taskInput {
width: 100px;
height: 24px;
padding-left: 5px;
outline: none;
border: none;
background-color:rgba(255,255,255,0);
background: url('../../../assets/images/输入框.png') no-repeat;
background-size: 100% 100%;
color: #fff;
}
}
//右侧 楼层UI
.rightStorey {
width: 100px;
height: 250px;
position: absolute;
right: 2px;
top: 50%;
margin-top: -125px;
z-index: 10;
display: flex;
flex-direction: column;
background-color:rgba(2, 44, 73, 0.9);
color: #fff;
font-weight: 300;
>div {text-align: center; line-height: 25px;}
}
.showRightStorey {
position: absolute;
right: 0;
top: 50%;
margin-top: -13px;
z-index: 10;
width: 26px;
height: 26px;
line-height: 26px;
text-align: center;
background-color:rgba(2, 44, 73, 0.9);
color: #fff;
}
//打开关闭右侧 楼层
.openRight {
margin-right: 0px;
transition: margin-right 0.5s;
}
.closeRight {
margin-right: -300px;
transition: margin-right 0.5s;
}
//右侧语音 UI
.rightSpeak {
position: absolute;
top: 40px;
left: -275px;
width: 310px;
height: 320px;
z-index: 11;
box-sizing: border-box;
padding: 3px;
border: 1px solid #30bbec;
background-color:rgba(2, 44, 73, 0.9);
color: #fff;
display: flex;
flex-direction: column;
.mat-icon {
font-size: 28px;
width: 28px;
height: 28px;
margin: 3px 10px;
}
.sayBgc {
flex: 1;
box-sizing: border-box;
background: url('../../../assets/images/输入框.png');
background-size: 100% 100%;
color: #30bbec;
}
.iconButton {
margin: 10px;
border-radius: 18px;
width: 70px;
height: 30px;
text-align: center;
line-height: 30px;
display: inline-block;
font-size: 13px;
color: white;
cursor: pointer;
}
}
//右侧 绘制工具
.draw {
display: inline-block;
position: absolute;
width: 80px;
height: 38px;
top: 1px;
left: 50%;
margin-left: -40px;
padding-top: 6px;
label {
display: inline-block;
width: 24px;
height: 24px;
margin: 0 5px;
border-radius: 50%;
cursor: pointer;
}
:first-child {
background: url('../../../assets/images/route.png') no-repeat center center;
background-size: 16px 16px;
background-color: #fff;
}
:last-child {
background: url('../../../assets/images/direction.png') no-repeat center center;
background-size: 16px 16px;
background-color: #fff;
}
}

765
src/app/ui/plan-assistance/plan-assistance.component.ts

File diff suppressed because it is too large Load Diff

14
src/app/ui/similar-plans/similar-plans.component.html

@ -1 +1,13 @@
<p>similar-plans works!</p>
<div class="leisiTable">
<table>
<thead >
<td style="width:40%;">单位名称</td>
<td style="width:10%;">始建于</td>
<td style="width:10%;">着火物</td>
<td style="width:10%;">点火位置</td>
<td style="width:10%;">相近度</td>
<td style="width:20%;">详情</td>
</thead>
<tbody id="shujubody"></tbody>
</table>
</div>

19
src/app/ui/similar-plans/similar-plans.component.scss

@ -0,0 +1,19 @@
.leisiTable{
border:1px solid #0E79A9;
height: 95%;
width: 100%;
background-color: #05385E;
margin-top: 50px;
table{
width: 100%;
height: 100%;
thead{
td{
color:#F7BA2A;
height: 50px;
text-align:center;
border-bottom: 1px solid #0E79A9;
}
}
}
}

38
src/app/ui/similar-plans/similar-plans.component.ts

@ -10,6 +10,44 @@ export class SimilarPlansComponent implements OnInit {
constructor() { }
ngOnInit(): void {
this.tableData()
}
leisiYuan=[
{danweiName:"广西钦州志诚化工有限公司",year:"XXXX年",zhoahuo:"XXX",weizhi:"2#储罐",xiangjin:"80%"},
{danweiName:"南宁交能石化有限责任公司",year:"",zhoahuo:"XXX",weizhi:"3#储罐",xiangjin:"75%"},
{danweiName:"广西藤县通轩立信化学有限公司",year:"",zhoahuo:"XXX",weizhi:"1#储罐",xiangjin:"70%"},
{danweiName:"广西田东锦盛化工科技有限公司",year:"",zhoahuo:"XXXXXX",weizhi:"12#储罐",xiangjin:"60%"},
{danweiName:"梧州市联溢化工有限公司",year:"",zhoahuo:"XXX",weizhi:"5#储罐",xiangjin:"50%"},
{danweiName:"田东石油化工钦州港油品储运库",year:"",zhoahuo:"XXX",weizhi:"4-1#储罐",xiangjin:"40%"},
{danweiName:"中国石油进德油库",year:"",zhoahuo:"XXX",weizhi:"3#储罐",xiangjin:"45%"},
{danweiName:"广西华鑫化工有限公司",year:"",zhoahuo:"XXX",weizhi:"11#储罐",xiangjin:"42%"},
{danweiName:"广西中油能源有限公司",year:"",zhoahuo:"XXX",weizhi:"6#储罐",xiangjin:"39%"},
{danweiName:"广西钦州澄星化工科技有限公司",year:"",zhoahuo:"XXX",weizhi:"5-2#储罐",xiangjin:"35%"},
{danweiName:"中油广西田东石油化工总厂有限公司",year:"",zhoahuo:"XXX",weizhi:"3-1#储罐",xiangjin:"35%"}
]
tableData(){
var res=''
for(var i=0;i<this.leisiYuan.length;i++){
res+='<tr style="color:#FFFFFF">'
res+='<td style="text-align:center;">'+this.leisiYuan[i].danweiName+'</td>'
res+='<td style="text-align:center;">'+"" +'</td>'
res+='<td style="text-align:center;">'+""+'</td>'
res+='<td style="text-align:center;">'+this.leisiYuan[i].weizhi+'</td>'
if(parseFloat(this.leisiYuan[i].xiangjin)<parseFloat('50%')){
res+='<td style="text-align:center;">'+this.leisiYuan[i].xiangjin+'</td>'
}
else if(parseFloat(this.leisiYuan[i].xiangjin)<=parseFloat('60%')&&parseFloat(this.leisiYuan[i].xiangjin)>=parseFloat('50%')){
res+='<td style="text-align:center;color:#3BA9F2">'+this.leisiYuan[i].xiangjin+'</td>'
}
else{
res+='<td style="text-align:center;color:#28BC69">'+this.leisiYuan[i].xiangjin+'</td>'
}
res+='<td style="text-align:center;"><a href="" style="color:#CC5D13">查看详情</a></td></tr>'
}
res+='</tbody>'
var shuju=document.getElementById('shujubody')
shuju.innerHTML=res
}
}

338
src/app/working-area/working-area.component.ts

@ -71,6 +71,14 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
*
*/
public paintPoints: PIXI.Point[] = [];
/**
* 线
*/
public paintingPipeline: Pipeline = null;
/**
*
*/
public paintingArrows: Arrows = null;
/**
*
*/
@ -148,11 +156,11 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
// 删除 选中的数据
if (item.assetData.IsFromBuilding) {
// console.log(this.canvasData.originaleveryStoreyData.data[item.assetData.Id]);
delete this.canvasData.originalcompanyBuildingData.data[item.assetData.Id];
delete this.canvasData.originalcompanyBuildingData?.data[item.assetData.Id];
// console.log(this.canvasData.originalcompanyBuildingData.data[item.assetData.Id]);
} else {
// console.log(this.canvasData.originaleveryStoreyData.data[item.assetData.Id]);
delete this.canvasData.originaleveryStoreyData.data[item.assetData.Id];
delete this.canvasData.originaleveryStoreyData?.data[item.assetData.Id];
// console.log(this.canvasData.originaleveryStoreyData.data[item.assetData.Id]);
}
// console.log(this.backgroundImage.getChildByName(item.assetData.Id));
@ -240,19 +248,27 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
// this.createEnterPaintEndButton();
// this.backgroundImage.addChild(this.paintingLine);
this.on('select', obj => {
if (obj instanceof MultipointIcon) {
obj.setPointVisiable(true);
} else if (obj instanceof PolygonIcon) {
obj.setPointVisiable(true);
if (this.allowEdit) {
if (obj instanceof MultipointIcon) {
obj.setPointVisiable(true);
} else if (obj instanceof PolygonIcon) {
obj.setPointVisiable(true);
} else {
obj.filters = [this.outlineFilterGreen];
}
} else {
obj.filters = [this.outlineFilterGreen];
}
});
this.on('deselect', obj => {
if (obj instanceof MultipointIcon) {
obj.setPointVisiable(false);
} else if (obj instanceof PolygonIcon) {
obj.setPointVisiable(false);
if (this.allowEdit) {
if (obj instanceof MultipointIcon) {
obj.setPointVisiable(false);
} else if (obj instanceof PolygonIcon) {
obj.setPointVisiable(false);
} else {
obj.filters = [];
}
} else {
obj.filters = [];
}
@ -297,6 +313,10 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
this.rectToolGraphics.endFill();
this.rectToolGraphics.closePath();
}
if (this.paintingArrows !== null) {
this.paintingArrows.data.pointB = new PIXI.Point(this.circleShadow.position.x, this.circleShadow.position.y);
this.paintingArrows.refresh();
}
});
}
/**
@ -407,7 +427,6 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
const single = new SinglePointIcon(element, this);
});
this.setNameVisible(false, GameMode.BasicInformation);
this.allowEdit = true;
const tempData = {
@ -419,6 +438,8 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
FillMode: 0,
FireElementId: 0,
FixedSize: false,
CanConnection: true,
ConnectionObjs: [],
Height: 45,
Width: 45,
Id: '5f67f92238f13cd2048cae9d',
@ -463,6 +484,8 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
Enabled: true,
FillMode: 0,
FireElementId: 0,
CanConnection: true,
ConnectionObjs: [],
FixedSize: false,
Height: 45,
Width: 45,
@ -500,9 +523,9 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
tempCar2.setParent(this.app.stage);
tempCar2.position.set(25, 50);
this.cancelPaint();
this.paintMode = PaintMode.connection;
this.previewSinglePointIcon.texture = PIXI.Texture.from('./assets/images/水罐消防车.png');
// 开始绘制管线
this.beginPaintPipeline();
// this.beginPaintingArrows();
}
/**
@ -712,8 +735,30 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
// }
// this.paintingIcon = new PolygonIcon(this.paintPoints, this);
break;
case PaintMode.connection:
case PaintMode.Pipeline:
if (this.paintingPipeline !== null) {
this.currentClickPoint.position = new PIXI.Point(this.circleShadow.x, this.circleShadow.y);
this.paintPoints.push(new PIXI.Point(this.circleShadow.x, this.circleShadow.y));
this.paintingPipeline.assetData.MultiPoint = JSON.parse(JSON.stringify(this.paintPoints));
this.paintingPipeline.refresh();
}
// this.emit('backgroundScale', this.backgroundImage.scale.x);
break;
case PaintMode.Arrows:
if (this.paintingArrows === null) {
const data = {
name: 'string',
point: new PIXI.Point(this.circleShadow.x, this.circleShadow.y),
pointA: new PIXI.Point(this.circleShadow.x, this.circleShadow.y),
pointB: new PIXI.Point(this.circleShadow.x, this.circleShadow.y),
source: 'assets/images/进攻方向.png',
};
this.paintingArrows = new Arrows(data, this);
} else {
this.paintingArrows.ready = true;
this.paintingArrows = null;
this.beginPaintPipeline();
}
break;
}
} else if (!event.currentTarget.dragging && this.selection.isMultiselection === true) {
@ -899,6 +944,25 @@ export class WorkingAreaComponent extends EventEmitter implements OnInit, AfterV
this.previewSinglePointIcon.texture = PIXI.Texture.from(this.canvasData.selectTemplateData.imageUrl);
this.circleShadow.visible = true;
}
/**
* 线
*/
private beginPaintPipeline(): void {
this.paintMode = PaintMode.Pipeline;
}
public paintingPipelineFinish(): void {
if (this.paintMode === PaintMode.Pipeline) {
this.paintMode = PaintMode.endPaint;
this.paintPoints.splice(0, this.paintPoints.length);
this.paintingPipeline = null;
}
this.beginPaintingArrows();
}
public beginPaintingArrows(): void {
this.paintMode = PaintMode.Arrows;
}
/**
*
*/
@ -1041,9 +1105,9 @@ enum PaintMode {
singlePointIcon,
lineIcon,
polygonIcon,
beginPainting,
endPaint,
connection
Pipeline,
Arrows
}
/**
*
@ -1071,7 +1135,11 @@ export class SinglePointIcon extends PIXI.Container {
+ this.assetData.PropertyInfos?.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style);
private image = PIXI.Sprite.from(this.assetData.ImageUrl);
// 是否可以被链接
canConnection: boolean;
canConnection = false;
// 链接对象
connectionObjs: any[] = [];
// 链接的管线
pipelines: any[] = [];
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
@ -1080,6 +1148,8 @@ export class SinglePointIcon extends PIXI.Container {
this.y = this.assetData.Point.y;
this.name = this.assetData.Id;
this.canConnection = this.assetData.CanConnection === undefined ? false : this.assetData.CanConnection;
this.image.angle = this.assetData.Angle;
this.image.x = 0;
@ -1095,7 +1165,33 @@ export class SinglePointIcon extends PIXI.Container {
console.log(this.assetData);
event.stopPropagation();
this.workingArea.selection.selectOne(this);
if (this.workingArea.allowEdit || this.assetData.GameMode === 2) {
if (this.canConnection && this.parent === this.workingArea.backgroundImage) {
if (this.workingArea.paintMode === PaintMode.Pipeline) {
if (this.workingArea.paintingPipeline === null) {
this.workingArea.previewLineSegment.visible = true;
this.workingArea.currentClickPoint.position =
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y);
this.workingArea.paintPoints.push(new PIXI.Point(this.position.x, this.position.y));
const tempData = {
Id: ObjectID.default.generate(),
MultiPoint: JSON.parse(JSON.stringify(this.workingArea.paintPoints)),
Point: new PIXI.Point(0, 0),
Name: '管线',
};
this.workingArea.paintingPipeline = new Pipeline(tempData, this.workingArea);
} else {
this.workingArea.previewLineSegment.visible = false;
this.workingArea.currentClickPoint.position =
new PIXI.Point(this.workingArea.circleShadow.x, this.workingArea.circleShadow.y);
this.workingArea.paintPoints.push(new PIXI.Point(this.position.x, this.position.y));
this.workingArea.paintingPipeline.assetData.MultiPoint = JSON.parse(JSON.stringify(this.workingArea.paintPoints));
this.workingArea.paintingPipeline.refresh();
this.workingArea.paintingPipelineFinish();
}
}
}
// 如果链接对象不为空,禁止移动
if ((this.workingArea.allowEdit || this.assetData.GameMode === 2) && this.connectionObjs.length === 0) {
event.currentTarget.parent.data = event.data;
event.currentTarget.parent.alpha = 0.5;
event.currentTarget.parent.dragging = true;
@ -1653,11 +1749,91 @@ export class PolygonIcon extends PIXI.Container {
export class Car extends SinglePointIcon {
}
export class Conection extends PIXI.Container {
/**
* 线
*/
export class Pipeline extends PIXI.Graphics {
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.name = this.assetData.Id;
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.workingArea.backgroundImage.addChild(this);
// 画线图标
this.refresh();
this.interactive = true;
this.on('mousedown', event => {
console.log(this.assetData);
event.stopPropagation();
this.workingArea.selection.selectOne(this);
});
}
/**
*
*/
public refresh() {
this.clear();
this.lineStyle(5, 0x0000ff, 1);
for (let i = 0, count = this.assetData.MultiPoint.length; i < count; i++) {
const pointA = this.assetData.MultiPoint[i];
if (i === 0) {
this.moveTo(pointA.x, pointA.y);
} else {
this.lineTo(pointA.x, pointA.y);
}
}
if (this.assetData.MultiPoint.length >= 2) {
const pointA = this.assetData.MultiPoint[0];
const pointB = this.assetData.MultiPoint[this.assetData.MultiPoint.length - 1];
// const angle = Math.atan2((pointB.y - pointA.y), (pointB.x - pointA.x)) * (5 / Math.PI);
this.beginFill(0x0000ff);
// this.drawStar(pointB.x, pointB.y, 3, 5, 0, angle);
this.drawCircle(pointA.x, pointA.y, 5);
this.drawCircle(pointB.x, pointB.y, 5);
this.endFill();
}
}
}
/**
*
* 2
*/
export class Arrows extends PIXI.Container {
public data: any;
public icon: PIXI.TilingSprite;
public ready = false;
constructor(assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.workingArea.backgroundImage.addChild(this);
this.data = assetData;
// 画线图标
this.icon = new PIXI.TilingSprite(PIXI.Texture.from(this.data.source), 0, 68);
this.addChild(this.icon);
this.refresh();
this.interactive = true;
this.on('mousedown', event => {
if (!this.ready) { return; }
event.stopPropagation();
this.workingArea.selection.selectOne(this);
});
}
/**
*
*/
public refresh() {
const angle = Math.atan2((this.data.pointB.y - this.data.pointA.y), (this.data.pointB.x - this.data.pointA.x)) * (180 / Math.PI);
const a = this.data.pointB.x - this.data.pointA.x;
const b = this.data.pointB.y - this.data.pointA.y;
const distance = Math.sqrt(a * a + b * b);
this.icon.width = distance;
this.icon.height = 68;
this.icon.anchor.set(0, 0.5);
this.icon.x = this.data.pointA.x;
this.icon.y = this.data.pointA.y;
this.icon.angle = angle;
}
}
/**
*
*/
@ -1798,117 +1974,3 @@ export class PropertyInfo {
*/
public PropertyValue: string;
}
/**
* demo图标
*/
export class DemoIcon extends PIXI.Container {
style = new PIXI.TextStyle({
fontFamily: 'Arial',
fontSize: 18,
fontStyle: 'normal',
fontWeight: 'bold',
fill: ['#000000'],
stroke: '#ffffff',
strokeThickness: 3,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 3,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 1,
wordWrap: false,
wordWrapWidth: 100,
});
private text = new PIXI.Text(this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue, this.style);
private image = PIXI.Sprite.from(this.assetData.ImageUrl);
constructor(public assetData: any, private workingArea: WorkingAreaComponent) {
super();
this.workingArea.backgroundImage.addChild(this);
this.x = this.assetData.Point.x;
this.y = this.assetData.Point.y;
this.name = this.assetData.Id;
this.image.angle = this.assetData.Angle;
this.image.x = 0;
this.image.y = 0;
this.image.width = this.assetData.Width;
this.image.height = this.assetData.Height;
this.image.alpha = 1;
this.image.anchor.set(0.5);
this.image.interactive = true;
this.image
.on('mousedown', event => {
event.stopPropagation();
this.workingArea.selection.selectOne(this);
if (this.workingArea.allowEdit) {
event.currentTarget.parent.data = event.data;
event.currentTarget.parent.alpha = 0.5;
event.currentTarget.parent.dragging = true;
}
})
.on('mouseup', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mouseupoutside', event => {
if (event.currentTarget.parent.dragging) {
event.currentTarget.parent.alpha = 1;
event.currentTarget.parent.dragging = false;
event.currentTarget.parent.data = null;
}
})
.on('mousemove', event => {
if (event.currentTarget.parent.dragging) {
const newPosition = event.currentTarget.parent.data.getLocalPosition(event.currentTarget.parent.parent);
event.currentTarget.parent.x = newPosition.x;
event.currentTarget.parent.y = newPosition.y;
this.assetData.Point = new PIXI.Point(this.x, this.y);
this.workingArea.canvasData.isChange = true;
}
})
.on('rightclick', event => {
})
.on('mouseover', event => {
});
this.workingArea.on('backgroundScale', data => {
if (this.assetData.FixedSize) {
const scale = 1 / data;
this.scale.set(scale);
}
});
this.text.x = this.image.x;
this.text.y = this.image.y - this.image.height / 2;
this.text.anchor.set(0.5, 1);
this.addChild(this.text);
this.addChild(this.image);
}
// 设置名称
public setNameVisible(value: boolean, mode: GameMode) {
if (this.assetData.GameMode === mode) {
this.text.visible = value;
}
}
// 刷新
public refresh() {
this.image.width = this.assetData.Width;
this.image.height = this.assetData.Height;
this.image.angle = this.assetData.Angle;
this.text.text = this.assetData.Name
+ '\r\n'
+ this.assetData.PropertyInfos.find(item => item.PropertyName === '名称/编号')?.PropertyValue;
this.text.x = this.image.x;
this.text.y = this.image.y - this.image.height / 2;
}
}

BIN
src/assets/images/direction.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/assets/images/route.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src/assets/images/进攻方向.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

2
src/index.html

@ -2,7 +2,7 @@
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>实战指挥预案</title>
<title>智能实战指挥平台</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">

Loading…
Cancel
Save