diff options
Diffstat (limited to 'usecaseui-portal/src/app/ccvpn-creation')
4 files changed, 1081 insertions, 0 deletions
diff --git a/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.css b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.css new file mode 100644 index 00000000..35fdbef5 --- /dev/null +++ b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.css @@ -0,0 +1,195 @@ +/* + Copyright (C) 2018 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +.title { + font: 700 18px/18px "思源黑体"; + color: #4c5e70; + margin-bottom: 18px; +} +hr { + border: none; + height: 2px; + background-color: #dce1e7; + margin-bottom: 10px; +} +.model { + background-color: #fff; + height: 90%; + overflow-y: auto; +} +.model .back { + position: absolute; + top: 10px; + right: 20px; +} +.model .creation { + position: relative; + width: 60%; + height: 100%; + overflow-y: auto; + border-radius: 5px; + padding: 15px; +} +.model .creation h3.title { + height: 20px; + font: 700 20px/20px "Arial"; + color: #666; +} +.model .creation h3 { + height: 20px; + font: 700 16px/20px "Arial"; + margin: 5px 0px; + color: #000; +} +.model .creation .submit { + position: absolute; + top: 10px; + right: 20px; +} +/* SOTN VPN */ +.model .creation .sotnvpn ul li { + display: inline-block; + height: 35px; + width: 49.5%; +} +.model .creation .sotnvpn ul li span { + display: inline-block; + width: 110px; + font: 700 14px "Arial"; + color: #3fa8eb; + vertical-align: middle; +} +.model .creation .sotnvpn ul li input { + width: 165px; +} +/* Site List */ +/* addsite model */ +.model .sitemodel { + position: absolute; + z-index: 10; + left: 10px; + top: 60px; + background-color: #fff; + box-shadow: 0px 0px 20px #000; + width: 60%; + max-height: 90%; + border-radius: 5px; + overflow-y: auto; +} +.model .sitemodel h3 { + height: 30px; + font: 700 16px/30px "Arial"; + border-bottom: 1px solid #aaa; + padding-left: 10px; +} +.model .sitemodel h4 { + height: 30px; + font: 700 16px/30px "Arial"; + padding-left: 10px; + background-color: #ddd; +} +.model .sitemodel .inputs { + padding: 10px 20px 0; +} +.model .sitemodel .inputs ul li { + display: inline-block; + height: 35px; + width: 49.5%; +} +.model .sitemodel .inputs ul li span { + display: inline-block; + width: 110px; + font: 700 14px "Arial"; + color: #3fa8eb; + vertical-align: middle; +} +.model .sitemodel .inputs input { + width: 165px; +} +.model .sitemodel .action { + float: left; + padding: 10px; +} + +.model nz-table tbody td i.anticon:hover { + color: #3fa8eb; + cursor: pointer; +} + +/* site table */ +.model .site nz-table tbody td i.anticon:hover { + color: #3fa8eb; + cursor: pointer; +} +/* WAN Port */ + +/* Site Group List */ +.model .sitegroup .sitegroupmodal { + position: absolute; + z-index: 10; + left: 200px; + top: 300px; + background-color: #fff; + box-shadow: 0px 0px 20px #000; + width: 330px; + border-radius: 5px; +} +.model .sitegroup .sitegroupmodal h3 { + height: 30px; + font: 700 16px/30px "Arial"; + border-bottom: 1px solid #aaa; + padding-left: 10px; +} +.model .sitegroup .sitegroupmodal .inputs { + padding: 10px 20px 0; +} +.model .sitegroup .sitegroupmodal span { + display: inline-block; + width: 100px; + margin-bottom: 10px; +} +.model .sitegroup .sitegroupmodal .inputs input { + width: 165px; +} +.model .sitegroup .sitegroupmodal .action { + float: right; + padding: 10px; +} + + +/* 图 */ +.model .chart { + width: 40%; + padding: 10px; + height: 100%; + border-left: 10px solid #f3f3f3; +} +.model .chart #createChart { + width: 100%; + height: 80%; + margin-top: 20px; + position: relative; +} +.model .chart #createChart .siteNameP { + position: fixed; + border: 5px; + padding: 3px 5px; + color: #fff; + background: #999; + box-shadow: 0px 0px 20px #000; + max-width: 100px; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.html b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.html new file mode 100644 index 00000000..15486238 --- /dev/null +++ b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.html @@ -0,0 +1,313 @@ +<!-- + Copyright (C) 2018 CMCC, Inc. and others. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<h3 class="title"> Services List </h3> +<hr> +<div class="model"> + <!-- 创建数据 --> + <button class="back" nz-button (click)="goback()"><span><i class="anticon anticon-rollback"></i></span></button> + <div class="creation fl"> + <h3 class="title">{{createParams.commonParams.templateType}} Instance Creation</h3> + <div class="sotnvpn clearfix"> + <h3>SOTN VPN Info</h3> + <ul> + <li><span>Name:</span> <input nz-input [(ngModel)]="sotnInfo.name"></li> + <li><span>Description:</span> <input nz-input [(ngModel)]="sotnInfo.description"></li> + <li><span>Start Time:</span> + <nz-date-picker [(ngModel)]="sotnInfo.startTime" + (ngModelChange)="startTimeChange($event)" + nzPlaceHolder="start time" + nzShowTime> + </nz-date-picker> + </li> + <li><span>End Time:</span> + <nz-date-picker [(ngModel)]="sotnInfo.endTime" + (ngModelChange)="endTimeChange($event)" + nzPlaceHolder="end time" + nzShowTime> + </nz-date-picker> + </li> + <li><span>COS:</span> + <nz-select style="width: 165px;" [(ngModel)]="sotnInfo.COS" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="premium" nzLabel="premium"></nz-option> + <nz-option nzValue="standard" nzLabel="standard"></nz-option> + </nz-select> + </li> + <li><span>Reroute Enabled:</span> <nz-switch [(ngModel)]="sotnInfo.reroute"></nz-switch> </li> + <li><span>Service Level Specification:</span> <input nz-input [(ngModel)]="sotnInfo.SLS"></li> + <li><span>Dual Link:</span> + <nz-select style="width: 165px;" [(ngModel)]="sotnInfo.dualLink" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="no_protection" nzLabel="no_protection"></nz-option> + <nz-option nzValue="static_1+1" nzLabel="static_1+1"></nz-option> + <nz-option nzValue="permanent_1+1" nzLabel="permanent_1+1"></nz-option> + </nz-select> + </li> + <li><span>CIR:</span> <input nz-input [(ngModel)]="sotnInfo.CIR"></li> + <li><span>EIR:</span> <input nz-input [(ngModel)]="sotnInfo.EIR"></li> + <li><span>CBS:</span> <input nz-input [(ngModel)]="sotnInfo.CBS"></li> + <li><span>EBS:</span> <input nz-input [(ngModel)]="sotnInfo.EBS"></li> + <li><span>Color Aware:</span> <nz-switch [(ngModel)]="sotnInfo.colorAware"></nz-switch> </li> + <li><span>Coupling Flag:</span> <nz-switch [(ngModel)]="sotnInfo.couplingFlag"></nz-switch> </li> + </ul> + </div> + + <div class="site"> + <h3>Site List</h3> + <button nz-button (click)="addSite()">Add Site</button> + <nz-table #siteTable [nzData]="siteTableData" + [nzShowPagination]="false" + nzSize="small"> + <thead> + <tr> + <th nzWidth="10%"> NO. </th> + <th nzWidth="15%"> Name </th> + <th nzWidth="15%"> Description </th> + <th nzWidth="15%"> Post Code </th> + <th nzWidth="15%"> Address </th> + <th nzWidth="15%"> VLAN </th> + <th nzWidth="15%"> Action </th> + </tr> + </thead> + <tbody> + <!-- <ng-template ngFor let-data [ngForOf]="siteTable.data" let-i="index"> --> + <tr *ngFor="let item of siteTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.baseData.name}}</td> + <td>{{item.baseData.description}}</td> + <td>{{item.baseData.postcode}}</td> + <td>{{item.baseData.address}}</td> + <td>{{item.baseData.vlan}}</td> + <td> + <span class="action" (click)="editSite(i+1)"><i class="anticon anticon-edit"></i></span> + <span class="action" (click)="deleteSite(i+1)"><i class="anticon anticon-delete"></i></span> + </td> + </tr> + <!-- </ng-template> --> + </tbody> + </nz-table> + </div> + + <div class="sitegroup" *ngIf="createParams.commonParams.templateType == 'CCVPN'"> + <h3>Site_Group List</h3> + <button nz-button (click)="addSiteGroup()">Add Group</button> + <div class="sitegroupmodal" *ngIf="siteGroupModelShow"> + <h3>Site_Group</h3> + <div class="inputs"> + <span>Group Name:</span> <input nz-input [(ngModel)]="siteGroupModelData.name"> <br> + <span>Topology:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteGroupModelData.topology" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="full-mesh" nzLabel="full-mesh"></nz-option> + <nz-option nzValue="hub-spoke" nzLabel="hub-spoke"></nz-option> + </nz-select> + <nz-table #groupModalTable [nzData]="siteGroupModalTableData" [nzLoading]="loading" [nzShowPagination]="false" nzSize="small"> + <thead> + <tr> + <th nzShowCheckbox [(nzChecked)]="allChecked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="groupModal_checkAll($event)"></th> + <th> Site Name</th> + <th> Role</th> + </tr> + </thead> + <tbody> + <tr *ngFor="let item of groupModalTable.data; let i = index;"> + <td nzShowCheckbox [nzDisabled]="item.disabled" [(nzChecked)]="item.checked" (nzCheckedChange)="refreshStatus($event)"></td> + <td>{{ item.siteName }}</td> + <td> + <nz-select style="width: 80px;" [(ngModel)]="item.role" + nzAllowClear nzPlaceHolder="Choose" + [nzDisabled]="siteGroupModelData.topology != 'hub-spoke'"> + <nz-option nzValue="hub" nzLabel="hub"></nz-option> + <nz-option nzValue="spoke" nzLabel="spoke"></nz-option> + </nz-select> + </td> + </tr> + </tbody> + </nz-table> + </div> + <div class="action"> + <button nz-button nzType="primary" (click)="addsitegroup_OK()">OK</button> + <button nz-button nzType="primary" (click)="addsitegroup_cancel()">Cancel</button> + </div> + </div> + <nz-table #siteGroupTable [nzData]="siteGroupTableData" + [nzLoading]="loading" + [nzShowPagination]="false" + nzSize="small"> + <thead> + <tr> + <th nzWidth="10%"> NO. </th> + <th nzWidth="20%"> Group Name </th> + <th nzWidth="20%"> Topology </th> + <th nzWidth="20%"> Sites </th> + <th nzWidth="15%"> Role </th> + <th nzWidth="15%"> Action </th> + </tr> + </thead> + <tbody> + <!-- <ng-template ngFor let-data [ngForOf]="siteGroupTable.data" let-i="index"> --> + <tr *ngFor="let item of siteGroupTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.name}}</td> + <td>{{item.topology}}</td> + <td>{{item.sites}}</td> + <td>{{item.role}}</td> + <td> + <span class="action" (click)="editGroupSite(i+1)"><i class="anticon anticon-edit"></i></span> + <span class="action" (click)="deleteGroupSite(i+1)"><i class="anticon anticon-delete"></i></span> + </td> + </tr> + <!-- </ng-template> --> + </tbody> + </nz-table> + </div> + + <button class="submit" nz-button [nzType]="'primary'" (click)="submit()"><span>Create</span></button> + </div> + <!-- site模态框 --> + <div class="sitemodel" *ngIf="siteModelShow"> + <h3>Site_Enterprise Service</h3> + <div class="inputs"> + <ul> + <li><span>Name:</span> <input nz-input [(ngModel)]="siteBaseData.name"></li> + <li><span>Description:</span> <input nz-input [(ngModel)]="siteBaseData.description"></li> + <li *ngIf="createParams.commonParams.templateType == 'CCVPN'"><span>Type:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteBaseData.type" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="single-gateway" nzLabel="single-gateway"></nz-option> + <nz-option nzValue="dual-gateway" nzLabel="dual-gateway"></nz-option> + </nz-select> + </li> + <li *ngIf="createParams.commonParams.templateType == 'CCVPN'"><span>Role:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteBaseData.role" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="dsvpn-hub" nzLabel="dsvpn-hub"></nz-option> + <nz-option nzValue="sd-wan-edge" nzLabel="sd-wan-edge"></nz-option> + </nz-select> + </li> + <li><span>PostCode:</span> <input nz-input [(ngModel)]="siteBaseData.postcode"></li> + <li><span>VLAN:</span> <input nz-input [(ngModel)]="siteBaseData.vlan"></li> + <li><span>Address:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteBaseData.address" nzAllowClear nzPlaceHolder="Choose"> + <nz-option *ngFor="let item of siteModeAddress" nzValue="{{item}}" nzLabel="{{item}}"></nz-option> + </nz-select> + </li> + </ul> + </div> + <div *ngIf="createParams.commonParams.templateType == 'CCVPN'"> + <h4>CPE</h4> + <div class="inputs"> + <ul> + <li><span>Name:</span> <input nz-input [(ngModel)]="siteCpeData.device_name"></li> + <li><span>Version:</span> <input nz-input [(ngModel)]="siteCpeData.device_version"></li> + <li><span>ESN:</span> <input nz-input [(ngModel)]="siteCpeData.device_esn"></li> + <li><span>Class:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteCpeData.device_class" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="VNF" nzLabel="VNF"></nz-option> + <nz-option nzValue="PNF" nzLabel="PNF"></nz-option> + </nz-select> + </li> + <li><span>System IP:</span> <input nz-input [(ngModel)]="siteCpeData.device_systemIp"></li> + <li><span>Vendor:</span> <input nz-input [(ngModel)]="siteCpeData.device_vendor"></li> + <li><span>Type:</span> <input nz-input [(ngModel)]="siteCpeData.device_type"></li> + </ul> + </div> + <h4>WAN Port</h4> + <div> + <nz-table #siteModalTable [nzData]="siteWanData" + [nzLoading]="loading" + [nzShowPagination]="false" + nzSize="small"> + <thead> + <tr> + <th nzWidth="10%"> NO. </th> + <th nzWidth="15%"> Name </th> + <th nzWidth="15%"> Description </th> + <th nzWidth="15%"> PortType </th> + <th nzWidth="18%"> PortNumber </th> + <th nzWidth="17%"> IPAddress </th> + <th nzWidth="10%"> Action </th> + </tr> + </thead> + <tbody> + <!-- <ng-template ngFor let-data [ngForOf]="siteModalTable.data" let-i="index"> --> + <tr *ngFor="let item of siteModalTable.data; let i = index; "> + <td>{{i+1}}</td> + <td>{{item.sitewanport_name}}</td> + <td>{{item.sitewanport_description}}</td> + <td>{{item.sitewanport_portType}}</td> + <td>{{item.sitewanport_portNumber}}</td> + <td>{{item.sitewanport_ipAddress}}</td> + <td> + <span class="action" (click)="editWanPort(i+1)"><i class="anticon anticon-edit"></i></span> + </td> + </tr> + <!-- </ng-template> --> + </tbody> + </nz-table> + </div> + <nz-modal [(nzVisible)]="wanPortModal" nzWidth="400" nzTitle="WAN Port Edit" (nzOnCancel)="wanPortModal_Cancel()" (nzOnOk)="wanPortModal_Ok()"> + <ul class="wanPortModalList"> + <li><span>Name:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_name"></li> + <!-- <li><span>Device Name:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_deviceName"></li> --> + <li><span>Description:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_description"></li> + <li><span>Port Type:</span> + <nz-select style="width: 165px;" [(ngModel)]="siteWanParams.sitewanport_portType" nzAllowClear nzPlaceHolder="Choose"> + <nz-option nzValue="GE" nzLabel="GE"></nz-option> + <nz-option nzValue="FE" nzLabel="FE"></nz-option> + <nz-option nzValue="XGE" nzLabel="XGE"></nz-option> + <nz-option nzValue="LTE" nzLabel="LTE"></nz-option> + <nz-option nzValue="xDSL(ATM)" nzLabel="xDSL(ATM)"></nz-option> + <nz-option nzValue="xSDL(PTM)" nzLabel="xSDL(PTM)"></nz-option> + </nz-select> + </li> + <li><span>Port Number:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_portNumber"></li> + <li><span>Ip Address:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_ipAddress"></li> + <li><span>Provider IP Address:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_providerIpAddress"></li> + <li><span>Transport Nerwork:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_transportNetworkName"></li> + <li><span>Input Bandwidth:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_inputBandwidth"></li> + <li><span>Output Bandwidth:</span> <input nz-input [(ngModel)]="siteWanParams.sitewanport_outputBandwidth"></li> + </ul> + </nz-modal> + </div> + + <div class="action"> + <button nz-button nzType="primary" (click)="addsite_OK()">OK</button> + <button nz-button nzType="primary" (click)="addsite_cancel()">Cancel</button> + </div> + </div> + <!-- 图 --> + <div class="chart fr"> + Create Service + {{createParams.commonParams.templateType}} + <div id="createChart"> + <svg width="100%" height="100%"> + <line *ngFor="let item of lines" x1=50% y1="45%" [attr.x2]="item.x2" y2="72%" style="stroke:#3fa8eb;stroke-width:2"/> + <image xlink:href="./assets/images/cloud-site.png" + x="25%" y="30%" width="50%"/> + <!-- <text dx="42%" dy="45%" style="font:700 18px 'Arial';fill:#666">{{createParams.commonParams.templateType}}</text> --> + <text dx="42%" dy="45%" style="font:700 18px 'Arial';fill:#666"></text> + <g *ngFor="let item of siteImage" + (mouseover)="showSite($event,item)" + (mousemove)="moveSite($event,item)" + (mouseout)="hideSite($event)"> + <image + xlink:href="./assets/images/site.png" + [attr.x]="item.x" y="65%" width="80px"/> + <text [attr.dx]="item.x + 25" dy="72%" style="font:700 16px 'Arial';fill:#666">{{ item.name }}</text> + </g> + + </svg> + <!-- <p class="siteNameP" [ngStyle]="siteNameStyle">{{ siteName }}</p> --> + </div> + </div> + +</div> diff --git a/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.spec.ts b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.spec.ts new file mode 100644 index 00000000..922bd9ea --- /dev/null +++ b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CcvpnCreationComponent } from './ccvpn-creation.component'; + +describe('CcvpnCreationComponent', () => { + let component: CcvpnCreationComponent; + let fixture: ComponentFixture<CcvpnCreationComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CcvpnCreationComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CcvpnCreationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.ts b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.ts new file mode 100644 index 00000000..ffc354c7 --- /dev/null +++ b/usecaseui-portal/src/app/ccvpn-creation/ccvpn-creation.component.ts @@ -0,0 +1,548 @@ +import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; +import { MyhttpService } from '../myhttp.service'; + +@Component({ + selector: 'app-ccvpn-creation', + templateUrl: './ccvpn-creation.component.html', + styleUrls: ['./ccvpn-creation.component.css'] +}) +export class CcvpnCreationComponent implements OnInit { + + constructor(private myhttp:MyhttpService) { } + + ngOnInit() { + this.getSiteAddressList(); + this.getTemParameters(); + } + + @Input() createParams; + @Input() namesTranslate; //输入项参数名字转换 + @Output() closeCreate = new EventEmitter(); + + templateParameters = {}; + getTemParameters(){ //获取模板参数 + let chosedtemplates = Object.values(this.createParams.templates); + // console.log(this.createParams); + console.log(chosedtemplates); //模板id数组 + let types = ["sotnvpn","site","sdwanvpn"]; + chosedtemplates.forEach((item,index)=>{ + this.myhttp.getTemplateParameters(types[index],item) + .subscribe((data)=>{ + if(index === 0){ + this.templateParameters["sotnvpn"] = data; + this.sotnNames = data.inputs.map((item)=>{return item.name}); //云的真实名字 + }else if(index === 1){ + this.templateParameters["site"] = data; + let wanportnames = {}; + this.siteNames = data.inputs.map((item)=>{return item.name}); //site中所有真实名字,没有分组,放在一起了 + this.siteNames.forEach((item)=>{ + if(item.includes("_device_")){ + this.siteCpeNames.push(item); + }else if(item.includes("_sitewanport_")){ + let firstName = item.split("_")[0]; + wanportnames[firstName]?wanportnames[firstName].push(item):wanportnames[firstName]=[item]; + }else { + this.siteBaseNames.push(item); + } + }) + this.siteWanNames = Object.values(wanportnames); + this.siteWanNames.forEach((item)=>{ + this.siteWanData.push(this.siteWanParams); //根据wanport组添加表格中 + }) + // console.log(this.sotnNames) + // console.log(this.siteNames) + // console.log(this.siteBaseNames) + // console.log(this.siteCpeNames) + // console.log(this.siteWanNames) + // console.log(this.siteWanData) + }else if(index === 2){ + this.templateParameters["sdwan"] = data; + this.siteGroupNames = data.inputs.map((item)=>{return item.name}); //sdwanvpn真实名字 + // console.log(this.siteGroupNames); + } + + },(err)=>{ + + }) + }) + + } + // SOTN VPN Info 输入参数 + sotnInfo = { + name:null,description:null, + startTime:null,endTime:null, + COS:"premium",reroute:false, + SLS:null,dualLink:false, + CIR:null,EIR:null, + CBS:null,EBS:null, + colorAware:false,couplingFlag:false + } + sotnNames = [] //真实名字 + + startTimeChange(event){ + console.log(event) + } + endTimeChange(event){ + console.log(event) + } + + + // Site List + siteTableData = [ + + ] + siteModeAddress = [];//site地址,筛选框数据,本地配置文件 + siteNames = [];//site中所有真实名字,未分组,模拟真实请求情况; + + siteBaseData = { //模态框数据,输入参数,绑定数据 + name:null, + description:null, + type:null, + role:null, + postcode:null, + address:null, + vlan:null, + sotnVpnName:null, //SOTN VPN Info中name + controlPoint:null, //site group里面site的Role设置为spoke时,传递site group里面Role设置为hub的site name;否则传递空白 + groupRole:null, //site group的role + groupName:null, //site group的name + emails:null,// 不显示传空 + latitude:null,// + longitude:null,// + clientSignal:null// + }; + siteBaseNames = [] //真实名字 + // cpe 编辑 + siteCpeData = { + device_name:null, + device_version:null, + device_esn:null, + device_class:null, + device_systemIp:null, + device_vendor:null, + device_type:null + }; + siteCpeNames = [] //真实名字 + // Wan Port 编辑 + siteWanData = []; //wan port 表格绑定数据 + siteWanParams = { //每一行数据详细参数,模态框 + sitewanport_name:null, + sitewanport_deviceName:null, + sitewanport_description:null, + sitewanport_portType:null, + sitewanport_portNumber:null, + sitewanport_ipAddress:null, + sitewanport_providerIpAddress:null, + sitewanport_transportNetworkName:null, + sitewanport_inputBandwidth:null, + sitewanport_outputBandwidth:null + }; + siteWanNames = [] //真实名字 + wanPortModal = false; //模态框显示隐藏 + wanPortEditNum = 0;//编辑哪行 + editWanPort(num){ + this.wanPortModal = true; + this.wanPortEditNum = num; + this.siteWanParams = Object.assign({},this.siteWanData[num-1]); + } + wanPortModal_Ok(){ + let inputsData = Object.assign({},this.siteWanParams); //新建对象,断开原引用,因为后面要清空模态框 + inputsData.sitewanport_deviceName = this.siteCpeData.device_name; + this.siteWanData[this.wanPortEditNum-1] = inputsData; + this.siteWanData = [...this.siteWanData]; //表格刷新 + Object.keys(this.siteWanParams).forEach((item)=>{ //清空模态框 + this.siteWanParams[item] = null; + }) + this.wanPortModal = false; + console.log(this.siteWanData) + } + wanPortModal_Cancel(){ + this.wanPortModal = false; + } + + + // 获取site地址,手动文件 + getSiteAddressList(){ + this.myhttp.getSiteAddress() + .subscribe((data)=>{ + console.log(data); + this.siteModeAddress = data.map((item)=>{ return item.location}); + },(err)=>{ + console.log(err); + }) + } + siteModelShow = false; + addSite(){ + this.siteModelShow = true; + this.isEdit = 0; + } + // addsite模态框按钮 + isEdit = 0; //编辑序号,No值,0表示增加 + addsite_OK(){ + this.siteBaseData.sotnVpnName = this.sotnInfo.name; + // let inputsData = Object.assign({},this.siteBaseData,this.siteCpeData,this.siteWanData); //新建对象,断开原引用,因为后面要清空模态框 + let inputs = {}; + inputs["baseData"] = Object.assign({},this.siteBaseData); + inputs["cpeData"] = Object.assign({},this.siteCpeData); + inputs["wanportData"] = this.siteWanData.map((item)=>{ + return Object.assign({},item); + }) + console.log(inputs); + if(this.isEdit){ + // 编辑状态不增加 + this.siteTableData[this.isEdit-1] = inputs; + this.siteTableData = [...this.siteTableData]; //表格刷新 + this.siteGroupTableData.forEach((item)=>{ //site修改名字后,更新组中sites值 + if(item.sites.split(";").filter((d)=>{return d!=""}).includes(this.lastSiteName)){ + item.sites = item.sites.replace(this.lastSiteName,this.siteBaseData.name); + } + }) + }else{ + // this.siteTableData.push(inputs);//使用 push 或者 splice 修改 nzData 失效 当加上[nzFrontPagination]="false" 时,生效 + this.siteTableData = [...this.siteTableData,inputs]; + } + + Object.keys(this.siteBaseData).forEach((item)=>{ //清空模态框 + this.siteBaseData[item] = null; + }) + Object.keys(this.siteCpeData).forEach((item)=>{ //清空模态框 + this.siteCpeData[item] = null; + }) + this.siteWanData.forEach((item)=>{ + Object.keys(item).forEach((item2)=>{ + item[item2] = null; + }) + }) + // console.log(this.siteTableData); + this.lastSiteName = null; + this.drawImage(this.siteTableData); + this.siteModelShow = false; + } + addsite_cancel(){ + Object.keys(this.siteBaseData).forEach((item)=>{ //清空模态框 + this.siteBaseData[item] = null; + }) + Object.keys(this.siteCpeData).forEach((item)=>{ //清空模态框 + this.siteCpeData[item] = null; + }) + this.siteWanData.forEach((item)=>{ + Object.keys(item).forEach((item2)=>{ + item[item2] = null; + }) + }) + this.lastSiteName = null; + this.siteModelShow = false; + } + lastSiteName = null; //当site修改之后,若修改了名字,则需要更新group中sites的名字 + editSite(num){ //编辑修改选中site信息 + this.siteModelShow = true; + this.isEdit=num; + this.siteBaseData = Object.assign({},this.siteTableData[num-1].baseData); + this.siteCpeData = Object.assign({},this.siteTableData[num-1].cpeData); + this.siteWanData = this.siteTableData[num-1].wanportData.map((item)=>{return Object.assign({},item)}); + this.lastSiteName = this.siteBaseData.name; + } + deleteSite(num){ + let deleteSiteName = this.siteTableData[num-1].baseData.name; //删除的site中name + let groupSites = []; + this.siteGroupTableData.forEach((item)=>{ groupSites.push(...item.sites.split(";").filter((d)=>{return d!=""})) }); + if(groupSites.includes(deleteSiteName)){ + alert("this site has in grouplist;can't delete!") + return false; + } + this.siteTableData = this.siteTableData.filter((d,i) => i !== num-1); + // this.siteTableData.splice(num-1,1); //模板中加上[nzFrontPagination]="false" 时,生效 + this.drawImage(this.siteTableData); + + // let groupIndex = this.siteGroupTableData.findIndex((item)=>{return item.sites.split(";").includes(deleteSiteName)}); + // console.log(groupIndex) + // this.deleteGroupSite(groupIndex + 1); //删除时首行编号为1 + } + + // site节点图形描绘 + lines=[]; + siteImage=[]; + drawImage(sitelist){ + let cx = 200; + let cy = 200; + let r = 180; + let startAngle = -210 * (Math.PI/180); + let step = sitelist.length > 1 ? 120/(sitelist.length-1) * (Math.PI/180) : 1; + + this.lines = sitelist.map((item,index)=>{ + let x = cx + Math.cos(startAngle - step*index)*r; + let y = cy + Math.sin(startAngle - step*index)*r; + return {img:"line",site:item.baseData.name,x1:cx,y1:cy,x2:x,y2:y} + }) + this.siteImage = this.lines.map((item)=>{ + return {img:"site",name:item.site,x:item.x2 - 40,y:item.y2 - 40} + }) + } + + siteName=null; + siteNameStyle = { + 'display':'none', + 'left':'0', + 'top':'0' + } + showSite($event,item){ + this.siteName = item.name; + this.siteNameStyle.display = 'block'; + } + moveSite($event,item){ + this.siteNameStyle.left = $event.clientX + "px"; + this.siteNameStyle.top = $event.clientY - 35 + "px"; + } + hideSite($event){ + this.siteNameStyle.display = 'none'; + } + // siteGroup List + siteGroupTableData = [ + + ] + siteGroupModelData = { + name:null, + topology:null, + sites:null, + role:null + } + siteGroupModelShow = false; + siteGroupModalTableData = [];// ==> siteTableData? + siteGroupNames=[]; //sdwanvpn真实名字 + + // 勾选框 + allChecked = false; + indeterminate = false; + groupModal_checkAll(value){ + this.siteGroupModalTableData.forEach(data => { + if (!data.disabled) { + data.checked = value; + } + }); + this.refreshStatus(); + } + refreshStatus(){ + const allChecked = this.siteGroupModalTableData.filter(item => !item.disabled).every(item => item.checked === true); + const allUnChecked = this.siteGroupModalTableData.filter(item => !item.disabled).every(item => !item.checked); + this.allChecked = allChecked; + this.indeterminate = (!allChecked) && (!allUnChecked); + } + + addSiteGroup(){ + this.isGroupEdit = 0; + this.siteGroupModelShow = true; + let checkedSite = this.siteGroupTableData.map((item)=>{return item.sites}).join(";").split(";").filter((d)=>{return d!=""});//循环组中是否已经选用了某个site,若存在 则新组不可选 + // console.log(checkedSite); + this.siteTableData.forEach((item,index)=>{ + if(checkedSite.includes(item.baseData.name)){ + this.siteGroupModalTableData.push({siteName:item.baseData.name,role:null,checked:false,disabled:true}) + }else { + this.siteGroupModalTableData.push({siteName:item.baseData.name,role:null,checked:false,disabled:false}) + } + }) + } + // addsiteGroup模态框按钮 + addsitegroup_OK(){ //将模态框中的值赋给表中对应项--->将选中的site中的groupRole、groupName、controlPoint更新---> + //拷贝数据判断是增加或编辑,更新表中数据---> 清除模态框中数据,便于下次添加,关闭模态框 + console.log(this.siteGroupModalTableData); + this.siteGroupModelData.sites=""; //置空组成员名字,写成""方便+= ,若为null +=时会转成 "null" + this.siteGroupModelData.role=""; // + let site_controlPoint = this.siteGroupModalTableData.map((item)=>{ if(item.checked&&item.role=="hub"){ return item.siteName}}).filter((item)=>{return item!=undefined}); + // console.log(site_controlPoint); + this.siteGroupModalTableData.forEach((item,index)=>{ //模态框中site顺序和 表中site顺序一致 + if(item.checked){ + this.siteGroupModelData.sites += item.siteName+";"; + this.siteGroupModelData.role += item.role+";"; + this.siteTableData[index].baseData.groupRole = item.role; //site group的role + this.siteTableData[index].baseData.groupName = this.siteGroupModelData.name; //site group的name + if(item.role == "spoke"){ + this.siteTableData[index].baseData.controlPoint = site_controlPoint.join(); //site group里面site的Role设置为spoke时,传递site group里面Role设置为hub的site name;否则传递空白 + } + } + }) + + let inputsData = {}; + Object.assign(inputsData,this.siteGroupModelData); + if(this.isGroupEdit){ + // 编辑状态不增加 + this.siteGroupTableData[this.isGroupEdit-1] = inputsData; + this.siteGroupTableData = [...this.siteGroupTableData]; //表格刷新 + }else{ + // this.siteTableData.push(inputsData);//使用 push 或者 splice 修改 nzData 失效 + this.siteGroupTableData = [...this.siteGroupTableData,inputsData]; + } + + Object.keys(this.siteGroupModelData).forEach((item)=>{ + this.siteGroupModelData[item] = null; + }) + this.siteGroupModalTableData = []; + this.siteGroupModelShow = false; + } + addsitegroup_cancel(){ + this.siteGroupModalTableData = []; + this.siteGroupModelShow = false; + } + isGroupEdit = 0; //编辑序号,No值,0表示增加 + editGroupSite(num){ //将当前编辑的行数据填入模态框--->获取当前编辑项sites名--->判断更新模态框中site项状态 + this.siteGroupModelShow = true; + this.isGroupEdit=num; + this.siteGroupModelData = Object.assign({},this.siteGroupTableData[num-1]); + console.log(this.siteGroupModelData) + let editSites = this.siteGroupTableData[num-1].sites.split(";").filter((item)=>{return item!=""}); //获取组中的site名 + // console.log(editSites); + let checkedSite = this.siteGroupTableData.map((item)=>{return item.sites}).join(";").split(";").filter((d)=>{return d!=""});//循环组中是否已经选用了某个site,若存在 则新组不可选 + // console.log(checkedSite); + this.siteTableData.forEach((item,index)=>{ + if(editSites.includes(item.baseData.name)){//先将编辑组中的site 中这三个值还原,否则减少某个site时 不会更新不选中的 + item.baseData.groupRole = null; //site group的role + item.baseData.groupName = null; //site group的name + item.baseData.controlPoint = null; + this.siteGroupModalTableData.push({siteName:item.baseData.name,role:item.baseData.groupRole,checked:true,disabled:false}) + }else + if(checkedSite.includes(item.baseData.name)){ + this.siteGroupModalTableData.push({siteName:item.baseData.name,role:null,checked:false,disabled:true}) + }else { + this.siteGroupModalTableData.push({siteName:item.baseData.name,role:null,checked:false,disabled:false}) + } + }) + + } + deleteGroupSite(num){ + let deleteSiteGroupsites = this.siteGroupTableData[num-1].sites.split(";").filter((item)=>{return item!=""}); //删除的site中name + this.siteGroupTableData = this.siteGroupTableData.filter((d,i) => i !== num-1); + this.siteTableData.forEach((item,index)=>{ + if(deleteSiteGroupsites.includes(item.baseData.name)){ + item.baseData.groupRole = null; //site group的role + item.baseData.groupName = null; //site group的name + item.baseData.controlPoint = null; + } + }) + } + + + + // 提交创建数据 + submit(){ + let globalCustomerId = this.createParams.commonParams.customer.id; + let globalServiceType = this.createParams.commonParams.serviceType; + let sotnInputs = {}; + // 由于请求模板不一样,所以外层需要循环请求回来的真实名字,内层循环本地参数,将当前值赋给真实名字 + this.sotnNames.forEach((name)=>{ + for(let key in this.sotnInfo){ + let nameParts = this.namesTranslate.sotnNameTranslate[key].split("_"); + if(name.startsWith(nameParts[0])&&name.endsWith(nameParts[1])){ + sotnInputs[name] = this.sotnInfo[key]; + break; + } + } + }) + console.log(sotnInputs); + let vpnbody = { + service:{ + name:this.sotnInfo.name, + description:this.sotnInfo.description, + serviceInvariantUuid:this.templateParameters["sotnvpn"].invariantUUID, //template.invariantUUID, //serviceDefId + serviceUuid:this.templateParameters["sotnvpn"].uuid, //template.uuid, // uuid ?? templateId + globalSubscriberId:globalCustomerId, //customer.id + serviceType:globalServiceType, //serviceType.value + parameters:{ + locationConstraints:[], + resources:[], + requestInputs:sotnInputs + } + } + } + + let sitebody = this.siteTableData.map((site)=>{ + let siteInputs = {}; + this.siteBaseNames.forEach((basename)=>{ + for(let key in site.baseData){ + let namePart = this.namesTranslate.siteNameTranslate.baseNames[key]; + if(basename.endsWith(namePart)){ + siteInputs[basename] = site.baseData[key]; + break; + } + } + }) + this.siteCpeNames.forEach((cpename)=>{ + for(let key in site.cpeData){ + let namePart = this.namesTranslate.siteNameTranslate.cpeNames[key]; + if(cpename.endsWith(namePart)){ + siteInputs[cpename] = site.cpeData[key]; + break; + } + } + }) + this.siteWanNames.forEach((item,index)=>{ + item.forEach((wanportname)=>{ + for(let key in site.wanportData[index]){ + let namePart = this.namesTranslate.siteNameTranslate.wanportNames[key]; + if(wanportname.endsWith(namePart)){ + siteInputs[wanportname] = site.wanportData[index][key]; + break; + } + } + }) + }) + + return { + service:{ + name:site.baseData.name, + description:site.baseData.description, + serviceInvariantUuid:this.templateParameters["site"].invariantUUID, + serviceUuid:this.templateParameters["site"].uuid, + globalSubscriberId:globalCustomerId, + serviceType:globalServiceType, + parameters:{ + locationConstraints:[], + resources:[], + requestInputs:siteInputs + } + } + } + }); + console.log(sitebody); + + let groupbody = this.siteGroupTableData.map((item)=>{ + let siteGroupInputs = {}; + this.siteGroupNames.forEach((name)=>{ + for(let key in item){ + let nameParts = this.namesTranslate.siteGroupNameTranslate[key].split("_"); + if(name.startsWith(nameParts[0])&&name.endsWith(nameParts[1])){ + siteGroupInputs[name] = item[key]; + break; + } + } + }) + return { + service:{ + name:item.name, + description:item.topology, + serviceInvariantUuid:this.templateParameters["sdwan"].invariantUUID, + serviceUuid:this.templateParameters["sdwan"].uuid, + globalSubscriberId:globalCustomerId, + serviceType:globalServiceType, + parameters:{ + locationConstraints:[], + resources:[], + requestInputs:siteGroupInputs + } + } + } + }) + console.log(groupbody); + + let createObj = { + vpnbody:vpnbody, + sitebody:sitebody, + groupbody:groupbody + } + + this.closeCreate.emit(createObj); + + } + + goback(){ + this.closeCreate.emit(); + } +} |