Compare commits

...

13 Commits

  1. 20733
      package-lock.json
  2. 2
      package.json
  3. 7
      proxy.config.json
  4. 63
      src/app/app-routing.module.ts
  5. 15
      src/app/pages/gis-home/card-list/card-list.component.html
  6. 54
      src/app/pages/gis-home/card-list/card-list.component.scss
  7. 20
      src/app/pages/gis-home/card-list/card-list.component.ts
  8. 4
      src/app/pages/gis-home/card-title/card-title.component.html
  9. 29
      src/app/pages/gis-home/card-title/card-title.component.scss
  10. 14
      src/app/pages/gis-home/card-title/card-title.component.ts
  11. 67
      src/app/pages/gis-home/gis-home.component.html
  12. 156
      src/app/pages/gis-home/gis-home.component.scss
  13. 1401
      src/app/pages/gis-home/gis-home.component.ts
  14. 6
      src/app/pages/gis-home/unit-title/unit-title.component.html
  15. 36
      src/app/pages/gis-home/unit-title/unit-title.component.scss
  16. 48
      src/app/pages/gis-home/unit-title/unit-title.component.ts
  17. 21
      src/app/pages/home/home.component.html
  18. 145
      src/app/pages/home/home.component.ts
  19. 8
      src/app/pages/login/login.component.html
  20. 386
      src/app/pages/login/login.component.ts
  21. 6
      src/app/pages/pages.module.ts
  22. 1229
      src/app/pages/records/criminal-records-admin/criminal-records-admin.component.ts
  23. 111
      src/app/pages/records/records-nav/records-nav.component.ts
  24. 12
      src/app/pages/today-warning-admin/today-warning-admin.component.html
  25. 38
      src/app/pages/today-warning-admin/today-warning-admin.component.scss
  26. 79
      src/app/pages/today-warning/get-out-of-line-details/get-out-of-line-details.component.ts
  27. 4
      src/app/system-management/organization/organization.component.html
  28. 51
      src/app/system-management/organization/organization.component.ts
  29. BIN
      src/assets/gismap/cardbg.png
  30. BIN
      src/assets/gismap/cardtitle.png
  31. BIN
      src/assets/gismap/gis/1.png
  32. BIN
      src/assets/gismap/gis/2.png
  33. BIN
      src/assets/gismap/gis/3.png
  34. BIN
      src/assets/gismap/gis/4.png
  35. BIN
      src/assets/gismap/gis/marker.png
  36. BIN
      src/assets/gismap/icon/1.png
  37. BIN
      src/assets/gismap/icon/2.png
  38. BIN
      src/assets/gismap/icon/3.png
  39. BIN
      src/assets/gismap/icon/4.png
  40. BIN
      src/assets/gismap/listtitle.png
  41. 8
      src/index.html
  42. 125
      src/styles.scss
  43. 228
      yarn.lock

20733
package-lock.json generated

File diff suppressed because it is too large Load Diff

2
package.json

@ -3,7 +3,7 @@
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.config.json --open --port 1119",
"start": "ng serve --proxy-config proxy.config.json --open --port 1119 --host 192.168.1.82",
"build": "node --max_old_space_size=5048 ./node_modules/@angular/cli/bin/ng build --configuration production",
"test": "ng test",
"lint": "ng lint",

7
proxy.config.json

@ -1,14 +1,11 @@
{
"/api": {
"target": "http://121.36.37.70:8906/",
"测试1": "http://121.36.37.70:8906/",
"测试2": "https://znaq.sinochemoilmarketing.com/",
"测试3": "https://gas.anxincloud.cn/",
"target": "http://121.36.37.70:8225/",
"secure": false,
"changeOrigin": true
},
"/signalr": {
"target": "http://121.36.37.70:8906/",
"target": "http://121.36.37.70:8225/",
"secure": false,
"ws": true,
"logLevel": "debug"

63
src/app/app-routing.module.ts

@ -1,35 +1,50 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { RegisterComponent } from './pages/register/register.component';
import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { LoginComponent } from "./pages/login/login.component";
import { RegisterComponent } from "./pages/register/register.component";
//路由守卫
import { AuthGuard } from './auth.guard'
import { HomeComponent } from './pages/home/home.component';
import { NavigationComponent } from './system-management/navigation/navigation.component';
import { HomePageNologinComponent } from './pages/home-page-nologin/home-page-nologin.component';
import { AuthGuard } from "./auth.guard";
import { HomeComponent } from "./pages/home/home.component";
import { NavigationComponent } from "./system-management/navigation/navigation.component";
import { HomePageNologinComponent } from "./pages/home-page-nologin/home-page-nologin.component";
import { GisHomeComponent } from "./pages/gis-home/gis-home.component";
const routes: Routes = [
{ path: '', redirectTo: 'login', pathMatch: 'full' },
{ path: 'login', component: LoginComponent }, //登录页
{ path: 'register', component: RegisterComponent }, //注册页
// { path: 'homepagenologin', component: HomePageNologinComponent }, //注册
{ path: "", redirectTo: "login", pathMatch: "full" },
{ path: "login", component: LoginComponent }, //登录页
{ path: "register", component: RegisterComponent }, //注册页
{ path: "gishome", component: GisHomeComponent }, //地图首
{
path: '', component: HomeComponent, canActivate: [AuthGuard], children: [
{ path: '', loadChildren: () => import('./pages/pages.module').then(m => m.PagesModule) }
]
path: "",
component: HomeComponent,
canActivate: [AuthGuard],
children: [
{
path: "",
loadChildren: () =>
import("./pages/pages.module").then((m) => m.PagesModule),
},
],
}, //首页
{
path: '', component: NavigationComponent, canActivate: [AuthGuard], children: [
{ path: 'system', loadChildren: () => import('./system-management/system-management.module').then(m => m.SystemManagementModule) }
]
}//系统管理
path: "",
component: NavigationComponent,
canActivate: [AuthGuard],
children: [
{
path: "system",
loadChildren: () =>
import("./system-management/system-management.module").then(
(m) => m.SystemManagementModule
),
},
],
}, //系统管理
];
@NgModule({
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
exports: [RouterModule]
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: "legacy" })],
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}

15
src/app/pages/gis-home/card-list/card-list.component.html

@ -0,0 +1,15 @@
<div class="box" cdkDrag>
<div class="title" cdkDragHandle>
<span>
{{title}}
</span>
<span class="close" (click)="close()">
<i nz-icon nzType="close" nzTheme="outline"></i>
</span>
</div>
<div class="content">
<ul>
<li *ngFor="let item of data">{{item}}</li>
</ul>
</div>
</div>

54
src/app/pages/gis-home/card-list/card-list.component.scss

@ -0,0 +1,54 @@
.box {
width: 280px;
font-size: 16px;
border: 1px solid #558DB1;
}
.title {
height: 32px;
line-height: 32px;
background-image: url(../../../../assets/gismap/listtitle.png);
background-size: 100% 100%;
background-repeat: no-repeat;
color: #fff;
box-sizing: border-box;
padding-left: 16px;
padding-right: 10px;
display: flex;
justify-content: space-between;
cursor: default;
.close{
cursor: pointer;
}
}
.content {
max-height: 250px;
overflow-y: auto;
ul{
margin-bottom: 0;
}
li {
height: 38px;
line-height: 38px;
padding-left: 16px;
padding-right: 10px;
color: #f7faff;
font-size: 15px;
cursor: pointer;
}
li:nth-child(odd) {
background: linear-gradient(
90deg,
RGBA(17, 50, 83, 1),
RGBA(17, 50, 83, 0.8)
);
}
li:nth-child(even) {
background: linear-gradient(
90deg,
RGBA(38, 56, 73, 1),
RGBA(38, 56, 73, 0.8)
);
border-top: 1px solid #3e4f60;
border-bottom: 1px solid #3e4f60;
}
}

20
src/app/pages/gis-home/card-list/card-list.component.ts

@ -0,0 +1,20 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
@Component({
selector: "app-card-list",
templateUrl: "./card-list.component.html",
styleUrls: ["./card-list.component.scss"],
})
export class CardListComponent implements OnInit {
@Input() title;
@Input() data;
@Output() childEvent = new EventEmitter<any>();
constructor() {}
ngOnInit(): void {}
close() {
this.childEvent.emit("closeCardList");
}
}

4
src/app/pages/gis-home/card-title/card-title.component.html

@ -0,0 +1,4 @@
<div class="box">
<span class="title">{{title}}</span>
<span class="subtitle">{{subtitle}}</span>
</div>

29
src/app/pages/gis-home/card-title/card-title.component.scss

@ -0,0 +1,29 @@
.box {
width: 100%;
height: 52px;
background-image: url(../../../../assets/gismap/cardtitle.png);
background-repeat: no-repeat;
background-size: 100% 100%;
position: absolute;
top: -6px;
left: 0px;
display: flex;
align-items: center;
.title {
font-size: 20px;
margin-left: 60px;
margin-top: 10px;
color: #fff;
font-family: titlefont;
// background: linear-gradient(to bottom, #fff, #88c3ec);
// -webkit-background-clip: text;
// -webkit-text-fill-color: transparent;
}
.subtitle {
font-size: 12px;
color: rgba(185, 233, 255, 0.4);
font-family: titlefont;
margin-left: 6px;
margin-top: 16px;
}
}

14
src/app/pages/gis-home/card-title/card-title.component.ts

@ -0,0 +1,14 @@
import { Component, Input, OnInit } from "@angular/core";
@Component({
selector: "app-card-title",
templateUrl: "./card-title.component.html",
styleUrls: ["./card-title.component.scss"],
})
export class CardTitleComponent implements OnInit {
@Input() title: string;
@Input() subtitle: string;
constructor() {}
ngOnInit(): void {}
}

67
src/app/pages/gis-home/gis-home.component.html

@ -0,0 +1,67 @@
<div class="box">
<div id="mapDiv"></div>
<div class="mask" style="pointer-events: none;"></div>
<div class="leftBox">
<div class="left1 cardItem"
(click)="urlTo('http://121.36.37.70:8201/planManagement/entryPlan?singleSignOn=true')">
<app-card-title [title]="'预案统计'" [subtitle]="'Plan statistics'"></app-card-title>
<app-unit-title [num]="21250" (childEvent)="handleChildData($event)"></app-unit-title>
<div class="content">
<div id="echartleft1"></div>
</div>
</div>
<div class="left2 cardItem" (click)="aHref($event,'ax://startup')">
<app-card-title [title]="'演练统计'" [subtitle]="'Exercise statistics'"></app-card-title>
<app-unit-title [num]="126"></app-unit-title>
<div class="content">
<div id="echartleft2"></div>
</div>
</div>
<div class="left3 cardItem" (click)="aHref($event,'ax2://startup')">
<app-card-title [title]="'风险管控平台统计'" [subtitle]="'Risk management'"></app-card-title>
<app-unit-title [num]="33"></app-unit-title>
<div class="content">
<div id="echartleft3"></div>
</div>
</div>
</div>
<div class="rightBox">
<div class="right1 cardItem" (click)="urlTo('http://121.36.37.70:8906/homepage?singleSignOn=true')">
<app-card-title [title]="'接入类型'" [subtitle]="'Intervention type'"></app-card-title>
<div class="content">
<div class="accessList">
<div class="accessitem" *ngFor="let item of accessList">
<div class="img">
<img [src]="item.img" alt="">
</div>
<div class="namebox">
<span class="name">{{item.name}}</span>
<span class="value" [ngStyle]="{'color': item.color}">{{item.value}}</span>
</div>
</div>
</div>
</div>
</div>
<div class="right2 cardItem" (click)="urlTo('http://121.36.37.70:8906/todaywarning?singleSignOn=true')">
<app-card-title [title]="'预警统计'" [subtitle]="'Warning statistics'"></app-card-title>
<div class="content">
<div id="echartright1"></div>
</div>
</div>
<div class="right3 cardItem"
(click)="urlTo('http://121.36.37.70:8906/records_nav/oliunloadinglist?singleSignOn=true')">
<app-card-title [title]="'卸油事件'" [subtitle]="'Oil unloading event'"></app-card-title>
<div class="content">
<div id="echartright2"></div>
<div id="echartright3"></div>
</div>
</div>
</div>
<div class="unitList" [hidden]="!isConnectedUnit">
<app-card-list [title]="'已接入单位'" [data]="unitList1" (childEvent)="handleChildData($event)"></app-card-list>
</div>
<div class="secretkey" (dblclick)="secretkeyTo()"></div>
</div>

156
src/app/pages/gis-home/gis-home.component.scss

@ -0,0 +1,156 @@
.box {
width: 100%;
height: 100%;
position: relative;
}
.mask {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 500;
// background: radial-gradient(
// rgba(255, 255, 255, 0) 0%,
// rgba(6, 24, 50, 0.6) 50%,
// rgb(5, 26, 56) 100%
// );
background: radial-gradient(
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 0),
rgba(6, 24, 50, 0.6),
rgba(6, 24, 50, 1)
);
}
#mapDiv {
width: 100%;
height: 100%;
}
.leftBox,
.rightBox {
width: 430px;
height: 100%;
position: absolute;
top: 0;
z-index: 500;
display: flex;
flex-direction: column;
justify-content: space-between;
box-sizing: border-box;
padding-top: 20px;
padding-bottom: 10px;
}
.leftBox {
left: 20px;
.left1 {
height: 38%;
}
.left2 {
height: 29%;
}
.left3 {
height: 29%;
}
}
.rightBox {
right: 20px;
.right1 {
height: 25%;
}
.right2 {
height: 34%;
}
.right3 {
height: 38%;
}
}
.cardItem {
background-image: url(../../../assets/gismap/cardbg.png);
background-repeat: no-repeat;
background-size: 100% 100%;
position: relative;
box-sizing: border-box;
padding-top: 50px;
display: flex;
flex-direction: column;
.content {
flex: 1;
position: relative;
}
}
.accessList {
display: flex;
flex-wrap: wrap;
align-items: center;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 12px 35px 12px 12px;
.accessitem {
width: 50%;
display: flex;
align-items: center;
.img {
margin-left: 20%;
margin-right: 12px;
}
.namebox {
display: flex;
flex-direction: column;
justify-content: center;
.name {
font-size: 16px;
// font-family: Alibaba PuHuiTi;
font-weight: 500;
color: #ffffff;
}
.value {
font-size: 20px;
font-family: DINPro;
font-weight: bold;
color: #479ffe;
}
}
}
}
#echartleft1,
#echartleft2,
#echartleft3,
#echartright1 {
width: 100%;
height: 100%;
}
#echartright2 {
width: 100%;
height: 60%;
}
#echartright3 {
width: 100%;
height: 45%;
position: absolute;
left: 0;
bottom: 0;
}
.unitList {
position: absolute;
left: 24%;
top: 2%;
z-index: 500;
}
.secretkey {
position: absolute;
right: 0;
bottom: 0;
width: 5px;
height: 5px;
cursor: pointer;
z-index: 999;
}

1401
src/app/pages/gis-home/gis-home.component.ts

File diff suppressed because it is too large Load Diff

6
src/app/pages/gis-home/unit-title/unit-title.component.html

@ -0,0 +1,6 @@
<div class="box">
<div class="numbox">
截至{{time}} , 已接入单位数 : <div class="num" *ngFor="let item of numArr">{{item}}</div>
</div>
<!-- <button class="btn" (click)="select($event)">选择</button> -->
</div>

36
src/app/pages/gis-home/unit-title/unit-title.component.scss

@ -0,0 +1,36 @@
.box {
color: #fff;
display: flex;
align-items: center;
font-size: 13px;
margin-top: 3px;
margin-left: 30px;
}
.numbox {
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-right: 12px;
.num {
width: 22px;
height: 22px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid rgba(129, 197, 200, 0.6);
font-family: DS-Digital;
font-weight: bold;
color: #ef9c00;
margin: 0 2px;
}
}
.btn {
width: 50px;
height: 24px;
border: 1px solid #46bbf1;
background: linear-gradient(0deg, #4ad0ff 0%, #2d3d5b 100%);
border-radius: 3px;
cursor: pointer;
}

48
src/app/pages/gis-home/unit-title/unit-title.component.ts

@ -0,0 +1,48 @@
import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
@Component({
selector: "app-unit-title",
templateUrl: "./unit-title.component.html",
styleUrls: ["./unit-title.component.scss"],
})
export class UnitTitleComponent implements OnInit {
@Input() num: number;
@Output() childEvent = new EventEmitter<any>();
constructor() {}
time: string;
ngOnInit(): void {
console.log(this.num);
this.getTime();
this.transformationNum(this.num);
}
getTime() {
let today = new Date();
let year = today.getFullYear();
let month = today.getMonth() + 1; // 月份是从0开始的,所以要加1
let day = today.getDate();
this.time = year + "/" + month + "/" + day;
}
numArr = [];
transformationNum(num) {
let str = String(num);
switch (str.length) {
case 1:
this.numArr = ["0", "0", str];
break;
case 2:
this.numArr = ["0", str[0], str[1]];
break;
default:
this.numArr = str.split("");
}
}
select(event) {
event.stopPropagation();
this.childEvent.emit("openCardList");
}
}

21
src/app/pages/home/home.component.html

@ -1,9 +1,9 @@
<div class="box">
<div class="menu">
<div class="boxleft">
<!-- <div class="boxleft">
<img *ngIf="isProd" src="../../../assets/images/logo2.png" alt="">
</div>
<div class="libox" *ngIf="!isGasStationNav">
</div> -->
<!-- <div class="libox" *ngIf="!isGasStationNav">
<li *ngFor="let item of menuList1" (click)="routerChange(item)"
[ngClass]="{'router-link-active': item.name == selectedItem}">
{{item.name}}
@ -21,8 +21,13 @@
{{item.name}}
</li>
</ng-template>
</div> -->
<div class="libox">
<li *ngFor="let item of menubeijing" (click)="routerChange(item)"
[ngClass]="{'router-link-active': item.name == selectedItem}">
{{item.name}}
</li>
</div>
<!-- 登录信息按钮 -->
<div class="boxright">
@ -66,13 +71,13 @@
<li *ngIf="isGasStation" nz-menu-item (click)="navChange('/oliStationInfo')">基本信息</li>
<li *ngIf="isGasStation" nz-menu-item (click)="navChange('/equipmentInfo')">器材信息</li>
<li nz-menu-item (click)="changePassword()">修改密码</li>
<li *ngIf="xitongguanli" nz-menu-item (click)="navChange2()">系统管理</li>
<li nz-menu-item (click)="navChange2()">系统管理</li>
<li nz-menu-item (click)="signOut()">退出系统</li>
</ul>
</nz-dropdown-menu>
<span style="margin: 0 12px;" *ngIf="isGasStationBack">|</span>
<img style="cursor: pointer;" *ngIf="isGasStationBack" src="../../../assets/images/goback.png" alt=""
(click)="goback()">
<!-- <span style="margin: 0 12px;" *ngIf="isGasStationBack">|</span> -->
<!-- <img style="cursor: pointer;" *ngIf="isGasStationBack" src="../../../assets/images/goback.png" alt=""
(click)="goback()"> -->
</div>
</div>

145
src/app/pages/home/home.component.ts

@ -41,16 +41,13 @@ export class HomeComponent implements OnInit {
private listRefreshService: listRefreshService,
private http: HttpClient,
private router: Router,
private navChangeService: NavChangeService,
public token: CacheTokenService,
private message: NzMessageService,
private notificationService: NzNotificationService,
private modal: NzModalService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
private selectedMenu: SelectedMenu,
private location: Location,
private patternService: PatternService
private location: Location
) {
const { password } = MyValidators;
@ -93,6 +90,14 @@ export class HomeComponent implements OnInit {
{ name: "资产类证照管理", url: "/system/fileOfLicense" },
{ name: "菜单管理", url: "/system/menu" },
];
menubeijing = [
{ name: "首页", url: "/homepage" },
// { name: "数字油站", url: "/plan" },
{ name: "今日预警", url: "/todaywarning" },
{ name: "预警记录", url: "/records_nav" },
// { name: "证照管理", url: "/audit" },
];
xitongguanli = false;
userMenu = [];
tap = [];
@ -100,13 +105,13 @@ export class HomeComponent implements OnInit {
menuList2 = [];
selectedItem;
routerChange(item) {
if (JSON.parse(sessionStorage.getItem("isGasStation"))) {
let a = JSON.parse(sessionStorage.getItem("3dSceneData"));
if (!a.hasBuildingInfo && item.url == "/plan/petrolStation") {
this.message.info("当前油站未开通!");
return;
}
}
// if (JSON.parse(sessionStorage.getItem("isGasStation"))) {
// let a = JSON.parse(sessionStorage.getItem("3dSceneData"));
// if (!a.hasBuildingInfo && item.url == "/plan/petrolStation") {
// this.message.info("当前油站未开通!");
// return;
// }
// }
if (item.name == this.selectedItem) {
return;
@ -115,39 +120,9 @@ export class HomeComponent implements OnInit {
this.selectedItem = item.name;
this.router.navigate([item.url]);
}
isProd: boolean;
ngOnInit(): void {
this.isProd = this.patternService.isProd;
this.location.subscribe((event) => {
if (event.url == "/homepage") {
sessionStorage.setItem("selectedMenu", "首页");
this.selectedItem = "首页";
} else if (event.url == "/plan" || event.url == "/plan/petrolStation") {
sessionStorage.setItem("selectedMenu", "数字油站");
this.selectedItem = "数字油站";
} else if (
event.url == "/todaywarning" ||
event.url == "/todaywarning/petrolStation"
) {
sessionStorage.setItem("selectedMenu", "今日预警");
this.selectedItem = "今日预警";
} else if (event.url.indexOf("/records_nav") != -1) {
if (event.url == "/records_nav") {
this.router.navigate(["/records_nav/all"]);
} else if (event.url == "/records_nav/petrolStation") {
this.router.navigate(["/records_nav/petrolStation/all"]);
}
sessionStorage.setItem("selectedMenu", "预警记录");
this.selectedItem = "预警记录";
} else if (
event.url == "/license" ||
event.url == "/license/petrolStation"
) {
sessionStorage.setItem("selectedMenu", "证照管理");
this.selectedItem = "证照管理";
}
});
ngOnInit(): void {
this.initSelectedItem(this.router);
let a = sessionStorage.getItem("userdata");
this.userMenu = JSON.parse(a).menus;
for (let index = 0; index < this.userMenu.length; index++) {
@ -159,33 +134,6 @@ export class HomeComponent implements OnInit {
}
this.isGasStation = JSON.parse(sessionStorage.getItem("isGasStation"));
//初始化登陆 如果是油站用户
if (this.isGasStation) {
this.isGasStationNav = true;
for (let index = 0; index < this.menu2.length; index++) {
for (let k = 0; k < this.tap.length; k++) {
if (this.tap[k] == this.menu2[index].name) {
this.menuList1.push(this.menu2[index]);
}
}
}
} else {
//初始化登陆 如果是管理者用户
this.isGasStationNav = false;
this.isGasStationBack = false;
for (let index = 0; index < this.menu1.length; index++) {
for (let k = 0; k < this.tap.length; k++) {
if (this.tap[k] == this.menu1[index].name) {
this.menuList1.push(this.menu1[index]);
}
}
}
for (let index = 0; index < this.tap.length; index++) {
if (this.tap[index] == "系统管理") {
this.xitongguanli = true;
}
}
}
this.router.events
.pipe(filter((event) => event instanceof NavigationEnd))
@ -243,6 +191,36 @@ export class HomeComponent implements OnInit {
this.getWarningSwitch();
}
initSelectedItem(event) {
if (event.url == "/homepage") {
sessionStorage.setItem("selectedMenu", "首页");
this.selectedItem = "首页";
} else if (event.url == "/plan" || event.url == "/plan/petrolStation") {
sessionStorage.setItem("selectedMenu", "数字油站");
this.selectedItem = "数字油站";
} else if (
event.url == "/todaywarning" ||
event.url == "/todaywarning/petrolStation"
) {
sessionStorage.setItem("selectedMenu", "今日预警");
this.selectedItem = "今日预警";
} else if (event.url.indexOf("/records_nav") != -1) {
if (event.url == "/records_nav") {
this.router.navigate(["/records_nav/all"]);
} else if (event.url == "/records_nav/petrolStation") {
this.router.navigate(["/records_nav/petrolStation/all"]);
}
sessionStorage.setItem("selectedMenu", "预警记录");
this.selectedItem = "预警记录";
} else if (
event.url == "/license" ||
event.url == "/license/petrolStation"
) {
sessionStorage.setItem("selectedMenu", "证照管理");
this.selectedItem = "证照管理";
}
}
isWarningVoice = true; //预警声音
isWarningWindow = true; //预警弹窗
/**
@ -671,19 +649,20 @@ export class HomeComponent implements OnInit {
}
}
navChange2() {
for (let index = 0; index < this.menu3.length; index++) {
for (let k = 0; k < this.tap.length; k++) {
if (this.tap[k] == this.menu3[index].name) {
this.menuList2.push(this.menu3[index]);
}
}
}
if (this.menuList2.length == 0) {
this.message.create("warning", "未分配系统管理菜单");
return;
} else {
window.open(this.menuList2[0].url);
}
// for (let index = 0; index < this.menu3.length; index++) {
// for (let k = 0; k < this.tap.length; k++) {
// if (this.tap[k] == this.menu3[index].name) {
// this.menuList2.push(this.menu3[index]);
// }
// }
// }
// if (this.menuList2.length == 0) {
// this.message.create("warning", "未分配系统管理菜单");
// return;
// } else {
// window.open(this.menuList2[0].url);
// }
window.open("/system/organization");
}
goback() {
this.router.navigate(["/plan"]);

8
src/app/pages/login/login.component.html

@ -1,7 +1,7 @@
<div class="login" id="login">
<div class="card">
<h1 class="cardheader">欢迎登录</h1>
<h1 class="cardheader">加油站智能安全管理系统</h1>
<h1 class="cardheader">智能安全管理系统</h1>
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()">
<nz-form-item>
@ -38,12 +38,12 @@
<button [nzLoading]="isLoading" nz-button class="login-form-button login-form-margin"
[nzType]="'primary'">登录</button>
</form>
<p *ngIf="isProd" class="company">中化石油销售有限公司 北京安信科创软件有限公司 版权所有</p>
<p *ngIf="isProd" class="company">北京安信科创软件有限公司 版权所有</p>
</div>
<div class="name">
<!-- <div class="name">
<img *ngIf="isProd" src="../../../assets/images/logo2.png" alt="">
</div>
</div> -->
</div>

386
src/app/pages/login/login.component.ts

@ -1,29 +1,45 @@
import { Component, OnInit, ViewContainerRef } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Router, ActivatedRoute } from '@angular/router'
import { CacheTokenService } from '../../service/cache-token.service'//引入服务
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd/message';
import { Base64 } from 'js-base64';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { SelectedMenu } from 'src/app/service/selectedMenu.service';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ForgetComponent } from './forget/forget.component';
import { PatternService } from 'src/app/service/pattern.service';
import { Component, OnInit, ViewContainerRef } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Router, ActivatedRoute } from "@angular/router";
import { CacheTokenService } from "../../service/cache-token.service"; //引入服务
import {
AbstractControl,
FormBuilder,
FormGroup,
Validators,
} from "@angular/forms";
import { NzMessageService } from "ng-zorro-antd/message";
import { Base64 } from "js-base64";
import { NzNotificationService } from "ng-zorro-antd/notification";
import { NzSafeAny } from "ng-zorro-antd/core/types";
import { SelectedMenu } from "src/app/service/selectedMenu.service";
import { NzModalService } from "ng-zorro-antd/modal";
import { ForgetComponent } from "./forget/forget.component";
import { PatternService } from "src/app/service/pattern.service";
// import { THIS_EXPR } from '@angular/compiler/src/output/output_ast';
declare var abp: any
declare var abp: any;
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
selector: "app-login",
templateUrl: "./login.component.html",
styleUrls: ["./login.component.scss"],
})
export class LoginComponent implements OnInit {
validateForm!: FormGroup;
passwordValidateForm!: FormGroup;
constructor(private http: HttpClient, private router: Router, private route: ActivatedRoute, public token: CacheTokenService, private fb: FormBuilder, private message: NzMessageService, private notificationService: NzNotificationService, private selectedMenu: SelectedMenu, private modal: NzModalService, private viewContainerRef: ViewContainerRef, private patternService: PatternService) {
constructor(
private http: HttpClient,
private router: Router,
private route: ActivatedRoute,
public token: CacheTokenService,
private fb: FormBuilder,
private message: NzMessageService,
private notificationService: NzNotificationService,
private selectedMenu: SelectedMenu,
private modal: NzModalService,
private viewContainerRef: ViewContainerRef,
private patternService: PatternService
) {
const { password } = MyValidators;
this.validateForm = this.fb.group({
userName: [null, [Validators.required]],
@ -34,224 +50,256 @@ export class LoginComponent implements OnInit {
this.passwordValidateForm = this.fb.group({
oldpassword: [null, [Validators.required]],
newpassword: [null, [Validators.required, password]],
affirmpassword: [null, [Validators.required, password]]
affirmpassword: [null, [Validators.required, password]],
});
}
isProd: boolean
isProd: boolean;
ngOnInit() {
this.isProd = this.patternService.isProd
this.isProd = this.patternService.isProd;
//如果本地储存了账号密码信息,那就回显在输入框
let account = localStorage.getItem('account')
let password = localStorage.getItem('password')
let account = localStorage.getItem("account");
let password = localStorage.getItem("password");
if (account && password) {
this.validateForm.patchValue({
userName: Base64.decode(localStorage.getItem('account')),
password: Base64.decode(localStorage.getItem('password'))
userName: Base64.decode(localStorage.getItem("account")),
password: Base64.decode(localStorage.getItem("password")),
});
this.remember = true //这一步是回显后让勾选框为选中状态
this.remember = true; //这一步是回显后让勾选框为选中状态
}
//自动登录
if (localStorage.getItem('isautologin') == 'true') {
this.submitForm()
this.autologin = true //这一步是回显后让勾选框为选中状态
if (localStorage.getItem("isautologin") == "true") {
this.submitForm();
this.autologin = true; //这一步是回显后让勾选框为选中状态
}
}
errmsg: string = ''; //错误信息
errmsg: string = ""; //错误信息
//跳转注册页面
toRegister() {
this.router.navigate(['/register'])
this.router.navigate(["/register"]);
}
//记住密码
rememberInfo() {
// 判断用户是否勾选记住密码,如果勾选,在本地储存中储存登录信息
if (this.remember) {
localStorage.setItem("account", Base64.encode(this.validateForm.value.userName))
localStorage.setItem("password", Base64.encode(this.validateForm.value.password))
localStorage.setItem(
"account",
Base64.encode(this.validateForm.value.userName)
);
localStorage.setItem(
"password",
Base64.encode(this.validateForm.value.password)
);
}
}
//自动登录
autoLogin() {
if (this.autologin) {
localStorage.setItem("isautologin", 'true')
localStorage.setItem("isautologin", "true");
}
}
remember: any//记住密码
autologin: any//自动登录
remember: any; //记住密码
autologin: any; //自动登录
isLoading = false;
messages
encryptedAccessToken
messages;
encryptedAccessToken;
menu1 = [
{ name: '首页', url: '/homepage' },
{ name: '数字油站', url: '/plan' },
{ name: '今日预警', url: '/todaywarning' },
{ name: '预警记录', url: '/records_nav' },
{ name: '证照管理', url: '/audit' },
]
{ name: "首页", url: "/homepage" },
{ name: "数字油站", url: "/plan" },
{ name: "今日预警", url: "/todaywarning" },
{ name: "预警记录", url: "/records_nav" },
{ name: "证照管理", url: "/audit" },
];
menu2 = [
{ name: '数字油站', url: '/plan/petrolStation' },
{ name: '今日预警', url: '/todaywarning/petrolStation' },
{ name: '预警记录', url: '/records_nav/petrolStation' },
{ name: '证照管理', url: '/license/petrolStation' },
]
init3D
{ name: "数字油站", url: "/plan/petrolStation" },
{ name: "今日预警", url: "/todaywarning/petrolStation" },
{ name: "预警记录", url: "/records_nav/petrolStation" },
{ name: "证照管理", url: "/license/petrolStation" },
];
init3D;
async getGasStationBaseInfo() {
await new Promise((resolve, reject) => {
let params = { organizationUnitId: (JSON.parse(sessionStorage.getItem('userdataOfgasstation'))).organization.id }
this.http.get('/api/services/app/GasStation/Get', { params: params }).subscribe((data: any) => {
resolve(data.result)
let params = {
organizationUnitId: JSON.parse(
sessionStorage.getItem("userdataOfgasstation")
).organization.id,
};
this.http
.get("/api/services/app/GasStation/Get", { params: params })
.subscribe((data: any) => {
resolve(data.result);
sessionStorage.setItem("3dSceneData", JSON.stringify(data.result))
this.init3D = data.result.hasBuildingInfo
})
})
sessionStorage.setItem("3dSceneData", JSON.stringify(data.result));
this.init3D = data.result.hasBuildingInfo;
});
});
}
submitForm(): void {
if (!this.remember) {
localStorage.removeItem("account")
localStorage.removeItem("password")
localStorage.removeItem("account");
localStorage.removeItem("password");
}
if (!this.autologin) {
localStorage.removeItem("isautologin")
localStorage.removeItem("isautologin");
}
for (const i in this.validateForm.controls) {
this.validateForm.controls[i].markAsDirty();
this.validateForm.controls[i].updateValueAndValidity();
}
if (!this.validateForm.valid) {
this.message.create('error', `请输入账号密码`);
return
this.message.create("error", `请输入账号密码`);
return;
}
this.isLoading = true;
this.http.post('/api/TokenAuth/Authenticate', {
userNameOrEmailAddress: this.validateForm.value.userName,
password: this.validateForm.value.password
}).subscribe(
(data: any) => {
sessionStorage.setItem("token", data.result.accessToken);
sessionStorage.setItem("encryptedAccessToken", data.result.encryptedAccessToken);
this.http.get('/api/services/app/Session/GetCurrentLoginInformations').subscribe(async (data: any) => {
console.log('GetCurrentLoginInformations', data.result)
if (data.result.user.menus.length == 0) {
this.message.create('error', `当前用户未分配菜单`);
this.isLoading = false
return
}
this.http
.post("/api/TokenAuth/Authenticate", {
userNameOrEmailAddress: this.validateForm.value.userName,
password: this.validateForm.value.password,
})
.subscribe(
(data: any) => {
sessionStorage.setItem("token", data.result.accessToken);
sessionStorage.setItem(
"encryptedAccessToken",
data.result.encryptedAccessToken
);
this.http
.get("/api/services/app/Session/GetCurrentLoginInformations")
.subscribe(
async (data: any) => {
console.log("GetCurrentLoginInformations", data.result);
// if (data.result.user.menus.length == 0) {
// this.message.create('error', `当前用户未分配菜单`);
// this.isLoading = false
// return
// }
sessionStorage.setItem('userdata', JSON.stringify(data.result.user))
sessionStorage.setItem('userdataOfgasstation', JSON.stringify(data.result.user))
sessionStorage.setItem('isDefaultPassword', JSON.stringify(data.result.user.isDefaultPassword))
sessionStorage.setItem('isPasswordExpired', JSON.stringify(data.result.user.isPasswordExpired))
this.isLoading = false;
if (!data.result.user.organization) {
this.message.create('error', `当前用户没有组织机构信息`);
return
}
if (data.result.user.organization.isGasStation) {
await this.getGasStationBaseInfo()
if (data.result.user.menus[0].name == "数字油站" && data.result.user.menus.length == 1 && !this.init3D) {
this.message.create('error', `当前用户油站未开通3D且仅分配油站菜单`);
return
}
}
//记住密码
this.rememberInfo()
//自动登录
this.autoLogin()
sessionStorage.setItem(
"userdata",
JSON.stringify(data.result.user)
);
sessionStorage.setItem(
"userdataOfgasstation",
JSON.stringify(data.result.user)
);
sessionStorage.setItem(
"isDefaultPassword",
JSON.stringify(data.result.user.isDefaultPassword)
);
sessionStorage.setItem(
"isPasswordExpired",
JSON.stringify(data.result.user.isPasswordExpired)
);
this.isLoading = false;
// if (!data.result.user.organization) {
// this.message.create('error', `当前用户没有组织机构信息`);
// return
// }
// if (data.result.user.organization.isGasStation) {
// await this.getGasStationBaseInfo()
// if (data.result.user.menus[0].name == "数字油站" && data.result.user.menus.length == 1 && !this.init3D) {
// this.message.create('error', `当前用户油站未开通3D且仅分配油站菜单`);
// return
// }
// }
//记住密码
this.rememberInfo();
//自动登录
this.autoLogin();
if (data.result.user.organization.isGasStation) {
sessionStorage.setItem("isGasStation", 'true');
let a = sessionStorage.getItem('userdataOfgasstation')
let menuList = this.returnLastMenus(a, this.menu2)
let isTrue = menuList.find((item) => {
return item.name == "今日预警"
});
if (isTrue) {
this.router.navigate(['/todaywarning/petrolStation'])
sessionStorage.setItem('selectedMenu', '今日预警')
} else if (data.result.user.menus[0].name == "数字油站" && !this.init3D) {
this.router.navigate([menuList[1].url])
sessionStorage.setItem('selectedMenu', menuList[1].name)
} else if (menuList.length == 0) {
return this.message.create('warning', `当前用户未分配菜单`);
} else {
this.router.navigate([menuList[0].url])
sessionStorage.setItem('selectedMenu', menuList[0].name)
}
} else {
sessionStorage.setItem("isGasStation", 'false');
let a = sessionStorage.getItem('userdata')
let menuList = this.returnLastMenus(a, this.menu1)
let isTrue = menuList.find((item) => {
return item.name == "首页"
});
if (menuList.length == 0) {
// if (data.result.user.organization.isGasStation) {
// sessionStorage.setItem("isGasStation", 'true');
// let a = sessionStorage.getItem('userdataOfgasstation')
// let menuList = this.returnLastMenus(a, this.menu2)
// let isTrue = menuList.find((item) => {
// return item.name == "今日预警"
// });
// if (isTrue) {
// this.router.navigate(['/todaywarning/petrolStation'])
// sessionStorage.setItem('selectedMenu', '今日预警')
// } else if (data.result.user.menus[0].name == "数字油站" && !this.init3D) {
// this.router.navigate([menuList[1].url])
// sessionStorage.setItem('selectedMenu', menuList[1].name)
// } else if (menuList.length == 0) {
// return this.message.create('warning', `当前用户未分配菜单`);
// } else {
// this.router.navigate([menuList[0].url])
// sessionStorage.setItem('selectedMenu', menuList[0].name)
// }
// } else {
// sessionStorage.setItem("isGasStation", 'false');
// let a = sessionStorage.getItem('userdata')
// let menuList = this.returnLastMenus(a, this.menu1)
// let isTrue = menuList.find((item) => {
// return item.name == "首页"
// });
// if (menuList.length == 0) {
return this.message.create('warning', `当前用户未分配菜单`);
// return this.message.create('warning', `当前用户未分配菜单`);
}
if (isTrue) {
this.router.navigate(['/homepage'])
sessionStorage.setItem('selectedMenu', '首页')
} else {
this.router.navigate([menuList[0].url])
sessionStorage.setItem('selectedMenu', menuList[0].name)
}
//
// }
// if (isTrue) {
// this.router.navigate(['/homepage'])
// sessionStorage.setItem('selectedMenu', '首页')
// } else {
// this.router.navigate([menuList[0].url])
// sessionStorage.setItem('selectedMenu', menuList[0].name)
// }
// //
}
this.message.create('success', `登录成功`);
}, err => {
// }
this.router.navigate(["/gishome"]);
this.message.create("success", `登录成功`);
},
(err) => {
this.isLoading = false;
}
);
},
(err) => {
this.isLoading = false;
})
},
(err) => {
this.isLoading = false;
// this.message.create('error', err.error.error.details);
}
)
// this.message.create('error', err.error.error.details);
}
);
}
returnLastMenus(data, originalMenus) {
let userMenu = JSON.parse(data).menus
let tap = []
let menuList = []
let userMenu = JSON.parse(data).menus;
let tap = [];
let menuList = [];
for (let index = 0; index < userMenu.length; index++) {
let a = userMenu[index].name
tap.push(a)
let a = userMenu[index].name;
tap.push(a);
}
for (let index = 0; index < originalMenus.length; index++) {
for (let k = 0; k < tap.length; k++) {
if (tap[k] == originalMenus[index].name) {
menuList.push(originalMenus[index])
menuList.push(originalMenus[index]);
}
}
}
return menuList
return menuList;
}
forget() {
// this.message.create('warning', `请联系管理员`);
this.modal.create({
nzTitle: '忘记密码',
nzTitle: "忘记密码",
nzContent: ForgetComponent,
nzViewContainerRef: this.viewContainerRef,
nzWidth: 288,
nzComponentParams: {},
nzFooter: null
nzFooter: null,
});
}
}
export type MyErrorsOptions = { 'zh-cn': string; en: string } & Record<string, NzSafeAny>;
export type MyErrorsOptions = { "zh-cn": string; en: string } & Record<
string,
NzSafeAny
>;
export type MyValidationErrors = Record<string, MyErrorsOptions>;
export class MyValidators extends Validators {
static password(control: AbstractControl): MyValidationErrors | null {
@ -261,14 +309,24 @@ export class MyValidators extends Validators {
return null;
}
return isPassword(value) ? null : { mobile: { 'zh-cn': `长度至少 8 位,必须包含大写字母、小写字母、数字、符号四种中的三种`, en: `Password phone number is not valid` } };
return isPassword(value)
? null
: {
mobile: {
"zh-cn": `长度至少 8 位,必须包含大写字母、小写字母、数字、符号四种中的三种`,
en: `Password phone number is not valid`,
},
};
}
}
function isEmptyInputValue(value: NzSafeAny): boolean {
return value == null || value.length === 0;
}
function isPassword(value: string): boolean {
return typeof value === 'string' && /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]{8,99}$/.test(value);
return (
typeof value === "string" &&
/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]{8,99}$/.test(
value
)
);
}

6
src/app/pages/pages.module.ts

@ -94,10 +94,14 @@ import { HomePageNologinComponent } from './home-page-nologin/home-page-nologin.
import { DownImageComponent } from './down-image/down-image.component';
import { ImgLookComponent } from './audit/img-look/img-look.component';
import { AnxinImgLookComponent } from './oil-unloading-process/anxin-img-look/anxin-img-look.component';
import { GisHomeComponent } from './gis-home/gis-home.component';
import { CardTitleComponent } from './gis-home/card-title/card-title.component';
import { UnitTitleComponent } from './gis-home/unit-title/unit-title.component';
import { CardListComponent } from './gis-home/card-list/card-list.component';
@NgModule({
declarations: [LoginComponent, RegisterComponent, HomeComponent, PlanComponent, TodayWarningComponent, CriminalRecordsComponent,
TodayWarningAdminComponent, CriminalRecordsAdminComponent, LeftDomainComponent, EquipmentInfoComponent, OilStationInfoComponent,
AddequipmentComponent, EditequipmentComponent, PlanAdminComponent, GetOutOfLineDetailsComponent, DispositionComponent, OilUnloadingProcessComponent, HomePageComponent, OilUnloadingProcessListComponent, ChangePasswordComponent, FacilitySortPipe, WarningStatisticsListComponent, DisposeequipmentComponent, NavBarComponent, InformComponent, UpdateCategoryComponent, FileCategoryComponent, HistoriesComponent, EditUpdateCategoryComponent, DetailsUpdateCategoryComponent, EditFileCategoryComponent, DetailsFileCategoryComponent, PdfWordLookComponent, OilStationListComponent, UpdateLicenseListComponent, FileLicenseListComponent, AuditNavComponent, AuditIngComponent, AuditRecordComponent, AuditInformTimeComponent, AuditDisposeComponent, EditInformTimeComponent, AuditDetailsInformTimeComponent, auditStatusPipe, GasBaseInfoComponent, notificationContent, licenseViolationType, handleState, AnnualInspectionComponent, EditAnnualInspectionComponent, RecordsNavComponent, UserDetailsComponent, AppealDetailsComponent, fileName, SystemModelComponent, ForgetComponent, HomePageNologinComponent, DownImageComponent, ImgLookComponent, AnxinImgLookComponent],
AddequipmentComponent, EditequipmentComponent, PlanAdminComponent, GetOutOfLineDetailsComponent, DispositionComponent, OilUnloadingProcessComponent, HomePageComponent, OilUnloadingProcessListComponent, ChangePasswordComponent, FacilitySortPipe, WarningStatisticsListComponent, DisposeequipmentComponent, NavBarComponent, InformComponent, UpdateCategoryComponent, FileCategoryComponent, HistoriesComponent, EditUpdateCategoryComponent, DetailsUpdateCategoryComponent, EditFileCategoryComponent, DetailsFileCategoryComponent, PdfWordLookComponent, OilStationListComponent, UpdateLicenseListComponent, FileLicenseListComponent, AuditNavComponent, AuditIngComponent, AuditRecordComponent, AuditInformTimeComponent, AuditDisposeComponent, EditInformTimeComponent, AuditDetailsInformTimeComponent, auditStatusPipe, GasBaseInfoComponent, notificationContent, licenseViolationType, handleState, AnnualInspectionComponent, EditAnnualInspectionComponent, RecordsNavComponent, UserDetailsComponent, AppealDetailsComponent, fileName, SystemModelComponent, ForgetComponent, HomePageNologinComponent, DownImageComponent, ImgLookComponent, AnxinImgLookComponent, GisHomeComponent, CardTitleComponent, UnitTitleComponent, CardListComponent],
imports: [

1229
src/app/pages/records/criminal-records-admin/criminal-records-admin.component.ts

File diff suppressed because it is too large Load Diff

111
src/app/pages/records/records-nav/records-nav.component.ts

@ -1,80 +1,73 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { IsShowEchartsService } from 'src/app/service/isShowEcharts.service';
import {Location} from "@angular/common";
import { Component, OnInit } from "@angular/core";
import { Router } from "@angular/router";
import { IsShowEchartsService } from "src/app/service/isShowEcharts.service";
import { Location } from "@angular/common";
@Component({
selector: 'app-records-nav',
templateUrl: './records-nav.component.html',
styleUrls: ['./records-nav.component.scss']
selector: "app-records-nav",
templateUrl: "./records-nav.component.html",
styleUrls: ["./records-nav.component.scss"],
})
export class RecordsNavComponent implements OnInit {
constructor(
private router: Router,
private isShowEcharts: IsShowEchartsService,
private location: Location
) {}
constructor(private router: Router, private isShowEcharts: IsShowEchartsService,private location: Location) { }
isEcharts = true
menuList = ['预警类型统计', '卸油统计', '证照预警统计']
tap=[]
userMenu = []
menu=[]
selectedMenu
isEcharts = true;
menuList = ["预警类型统计", "卸油统计", "证照预警统计"];
tap = [];
userMenu = [];
menu = ["预警类型统计", "卸油统计"];
selectedMenu;
ngOnInit(): void {
let a= sessionStorage.getItem('userdata')
this.userMenu=JSON.parse(a).menus
console.log(this.userMenu);
for (let index = 0; index < this.userMenu.length; index++) {
let a=this.userMenu[index].name
this.tap.push(a)
console.log(this.router);
if (this.router.url.indexOf("oliunloadinglist") !== -1) {
this.selectedMenu = "卸油统计";
}
console.log(this.tap);
if (this.userMenu.length==0) {
this.menu=this.menuList
}else{
for (let index = 0; index < this.menuList.length; index++) {
for (let k = 0; k < this.tap.length; k++) {
if (this.tap[k]==this.menuList[index]) {
this.menu.push(this.tap[k])
console.log( this.menu);
}
}
}
if (this.router.url === "/records_nav") {
this.selectedMenu = this.menu[0];
}
this.selectedMenu = this.menu[0]
this.routerChange()
this.routerChange();
}
selectMenu(item) {
if (this.selectedMenu == item) {
return
return;
}
this.isEcharts = true
this.selectedMenu = item
this.routerChange()
this.isEcharts = true;
this.selectedMenu = item;
this.routerChange();
}
routerChange() {
if (sessionStorage.getItem('isGasStation') == 'false') {
if (this.selectedMenu == '预警类型统计') {
this.router.navigate(['/records_nav/all'])
} else if (this.selectedMenu == '卸油统计') {
this.router.navigate(['/records_nav/oliunloadinglist'])
} else if (this.selectedMenu == '证照预警统计') {
this.router.navigate(['/records_nav/warningstatisticslist'])
console.log("this.selectedMenu", this.selectedMenu);
if (this.selectedMenu == "预警类型统计") {
this.router.navigate(["/records_nav/all"]);
} else if (this.selectedMenu == "卸油统计") {
this.router.navigate(["/records_nav/oliunloadinglist"]);
} else if (this.selectedMenu == "证照预警统计") {
this.router.navigate(["/records_nav/warningstatisticslist"]);
}
return;
if (sessionStorage.getItem("isGasStation") == "false") {
if (this.selectedMenu == "预警类型统计") {
this.router.navigate(["/records_nav/all"]);
} else if (this.selectedMenu == "卸油统计") {
this.router.navigate(["/records_nav/oliunloadinglist"]);
} else if (this.selectedMenu == "证照预警统计") {
this.router.navigate(["/records_nav/warningstatisticslist"]);
}
} else {
if (this.selectedMenu == '预警类型统计') {
this.router.navigate(['/records_nav/petrolStation/all'])
} else if (this.selectedMenu == '卸油统计') {
this.router.navigate(['/records_nav/petrolStation/oliunloadinglist'])
} else if (this.selectedMenu == '证照预警统计') {
this.router.navigate(['/records_nav/petrolStation/warningstatisticslist'])
if (this.selectedMenu == "预警类型统计") {
this.router.navigate(["/records_nav/petrolStation/all"]);
} else if (this.selectedMenu == "卸油统计") {
this.router.navigate(["/records_nav/petrolStation/oliunloadinglist"]);
} else if (this.selectedMenu == "证照预警统计") {
this.router.navigate([
"/records_nav/petrolStation/warningstatisticslist",
]);
}
}
}
}

12
src/app/pages/today-warning-admin/today-warning-admin.component.html

@ -61,12 +61,12 @@
<nz-form-control>
<nz-select [nzMaxTagCount]="1" nzMode="multitagsple" nzAllowClear id="area" formControlName="area"
nzPlaceHolder="预警区域">
<nz-option nzValue="出入口" nzLabel="出入口"></nz-option>
<!-- <nz-option nzValue="出入口" nzLabel="出入口"></nz-option>
<nz-option nzValue="加油区" nzLabel="加油区"></nz-option>
<nz-option nzValue="油罐区" nzLabel="油罐区"></nz-option>
<nz-option nzValue="便利店" nzLabel="便利店"></nz-option>
<nz-option nzValue="便利店" nzLabel="便利店"></nz-option> -->
<nz-option nzValue="办公区" nzLabel="办公区"></nz-option>
<nz-option nzValue="其他区域" nzLabel="其他区域"></nz-option>
<!-- <nz-option nzValue="其他区域" nzLabel="其他区域"></nz-option> -->
</nz-select>
</nz-form-control>
</nz-form-item>
@ -158,12 +158,12 @@
<div nz-col nzSpan="1" *ngIf="isMisinformation">
申诉状态
</div>
<div nz-col nzSpan="1">
<div nz-col nzSpan="1" style="min-width: 65px;">
操作
</div>
</div>
<div nz-row class="listitem" *ngFor="let item of list">
<div nz-row class="listitem listitembody" *ngFor="let item of list">
<div nz-col nzSpan="2" class="imgbox">
<span *ngIf="item.violation.violationType == '卸油作业检查'">
<img src="../../../assets/images/warning2.png">
@ -231,7 +231,7 @@
'申诉撤销' : item.appealStatus == 5 ? '申诉完成' : null}}
</span>
</div>
<div nz-col nzSpan="1" style="min-width: 64px;">
<div nz-col nzSpan="1" style="min-width: 65px;">
<button nz-button (click)="look(item)">查看</button>
</div>
</div>

38
src/app/pages/today-warning-admin/today-warning-admin.component.scss

@ -7,7 +7,7 @@
.title {
box-sizing: border-box;
padding: 0 20PX;
padding: 0 20px;
width: 100%;
height: 48px;
margin: 16px 0;
@ -28,7 +28,7 @@
.today {
font-size: 18px;
font-family: titlefont;
color: #D0EAFF;
color: #d0eaff;
margin-left: 8px;
margin-right: 16px;
}
@ -39,8 +39,6 @@
color: white;
font-weight: 600;
}
}
.search {
@ -83,7 +81,6 @@
nz-select {
color: rgba(145, 204, 255, 0.95);
;
}
nz-tree-select {
@ -107,11 +104,16 @@
width: 100%;
height: 78px;
display: flex;
flex-wrap: nowrap;
align-items: center;
border: 1px solid rgba(54, 162, 255, 0.478);
color: #91CCFF;
color: #91ccff;
margin-bottom: 12px;
background: linear-gradient(180deg, rgba(3, 0, 0, 0) 0%, rgba(0, 46, 91, 0.68) 100%);
background: linear-gradient(
180deg,
rgba(3, 0, 0, 0) 0%,
rgba(0, 46, 91, 0.68) 100%
);
box-sizing: border-box;
white-space: nowrap;
@ -127,7 +129,7 @@
font-size: 15px;
background-color: #013064;
border: 1px solid #4c8ac8;
color: #91CCFF;
color: #91ccff;
}
}
@ -154,11 +156,11 @@
}
.propsm1 {
background: #2399FF;
background: #2399ff;
}
.propsm2 {
background: #FF9963;
background: #ff9963;
}
}
@ -167,11 +169,9 @@
line-height: 40px;
background: rgba(35, 153, 255, 0.22);
border: 1px solid rgba(35, 217, 255, 0.4);
color: #23D9FF;
color: #23d9ff;
}
}
}
// 适配125%
@ -179,7 +179,7 @@
.warningbox {
.title {
box-sizing: border-box;
padding: 0 16PX;
padding: 0 16px;
height: 42px;
margin: 12px 0;
position: relative;
@ -202,8 +202,6 @@
.num {
font-size: 18px;
}
}
.search {
@ -220,8 +218,6 @@
}
}
.listbox {
flex: 1;
overflow-y: auto;
@ -251,7 +247,7 @@
.warningbox {
.title {
box-sizing: border-box;
padding: 0 12PX;
padding: 0 12px;
height: 38px;
margin: 6px 0;
position: relative;
@ -274,8 +270,6 @@
.num {
font-size: 16px;
}
}
.search {
@ -292,8 +286,6 @@
}
}
.listbox {
flex: 1;
overflow-y: auto;

79
src/app/pages/today-warning/get-out-of-line-details/get-out-of-line-details.component.ts

@ -49,26 +49,33 @@ export class GetOutOfLineDetailsComponent implements OnInit {
currentCoordinate = []; //当前需要标绘坐标点信息
legendList: any = [];
typeArr = [
{ id: 0, name: "工装", color: "#91CCFF" },
{ id: 2, name: "便装", color: "#46DFFF" },
{ id: 2, name: "抽烟", color: "#36A2FF" },
{ id: 3, name: "打电话", color: "#FF6181" },
{ id: 4, name: "隔离锥", color: "#000000" },
{ id: 5, name: "手持灭火器", color: "#ffffff" },
{ id: 6, name: "推车灭火器", color: "#B4C3FF" },
{ id: 7, name: "静电接地", color: "#FF9963" },
{ id: 8, name: "输油管(连接)", color: "#5A9CFF" },
{ id: 9, name: "输油管连接车", color: "#4BFFD4" },
{ id: 10, name: "输油管连接卸油口", color: "red" },
{ id: 11, name: "卸油口盖子", color: "green" },
{ id: 12, name: "卸油车", color: "yellow" },
{ id: 13, name: "私家车", color: "black" },
{ id: 14, name: "断开的卸油管", color: "blue" },
{ id: 15, name: "烟雾预警", color: "#B4C3FF" },
{ id: 16, name: "火灾报警", color: "red" },
{ id: 17, name: "延长工装", color: "blue" },
{ id: 18, name: "江苏工装", color: "blue" },
{ id: 19, name: "经理工装", color: "yellow" },
// { id: 0, name: "工装", color: "#91CCFF" },
// { id: 2, name: "便装", color: "#46DFFF" },
// { id: 2, name: "抽烟", color: "#36A2FF" },
// { id: 3, name: "打电话", color: "#FF6181" },
// { id: 4, name: "隔离锥", color: "#000000" },
// { id: 5, name: "手持灭火器", color: "#ffffff" },
// { id: 6, name: "推车灭火器", color: "#B4C3FF" },
// { id: 7, name: "静电接地", color: "#FF9963" },
// { id: 8, name: "输油管(连接)", color: "#5A9CFF" },
// { id: 9, name: "输油管连接车", color: "#4BFFD4" },
// { id: 10, name: "输油管连接卸油口", color: "red" },
// { id: 11, name: "卸油口盖子", color: "green" },
// { id: 12, name: "卸油车", color: "yellow" },
// { id: 13, name: "私家车", color: "black" },
// { id: 14, name: "断开的卸油管", color: "blue" },
// { id: 15, name: "烟雾预警", color: "#B4C3FF" },
// { id: 16, name: "火灾报警", color: "red" },
// { id: 17, name: "延长工装", color: "blue" },
// { id: 18, name: "江苏工装", color: "blue" },
// { id: 19, name: "经理工装", color: "yellow" },
{ id: 0, name: "安全帽", color: "yellow" },
{ id: 1, name: "清醒人", color: "blue" },
{ id: 2, name: "睡觉人", color: "blue" },
{ id: 3, name: "抽烟", color: "red" },
{ id: 4, name: "打电话", color: "pink" },
{ id: 5, name: "灭火器", color: "green" },
{ id: 6, name: "隔离锥", color: "gray" },
];
userName; //登录账号的用户名
isShowAxOtherRegion; //控制哪些用户可以看到ax全部
@ -276,18 +283,26 @@ export class GetOutOfLineDetailsComponent implements OnInit {
this.ctx.fillStyle = this.typeArr[item.id].color;
this.ctx.font = "16px Verdana";
let name = "";
// ⛑ 戴了
// 👨🦲 没戴
if (this.isShowAxOtherRegion) {
name = this.typeArr[item.id].name + item.scores;
if (this.typeArr[item.id].name.indexOf("人") !== -1) {
let icon;
item.helmet_person ? (icon = "⛑") : (icon = "👨🦲");
name = icon + this.typeArr[item.id].name + item.scores;
} else {
name = this.typeArr[item.id].name + item.scores;
}
} else {
name = this.typeArr[item.id].name;
if (this.typeArr[item.id].name.indexOf("人") !== -1) {
let icon;
item.helmet_person ? (icon = "⛑") : (icon = "👨🦲");
name = icon + this.typeArr[item.id].name;
} else {
name = this.typeArr[item.id].name;
}
}
this.ctx.fillText(
name,
startPoint[0],
startPoint[1] < 20 || item.id === 2 || item.id === 3
? endPoint[1] + 18
: startPoint[1] - 5
);
this.ctx.fillText(name, startPoint[0], startPoint[1] - 5);
} else {
if (item.error) {
this.ctx.strokeStyle = this.typeArr[item.id].color;
@ -302,6 +317,12 @@ export class GetOutOfLineDetailsComponent implements OnInit {
this.ctx.fillRect(startPoint[0], startPoint[1], 10, 10);
this.ctx.fillStyle = this.typeArr[item.id].color;
this.ctx.font = "16px Verdana";
if (this.typeArr[item.id].name.indexOf("人") !== -1) {
let icon;
item.helmet_person ? (icon = "⛑") : (icon = "👨🦲");
this.ctx.fillText(icon, startPoint[0], startPoint[1] - 5);
}
}
}
});

4
src/app/system-management/organization/organization.component.html

@ -28,10 +28,8 @@
<div class="nodebox">
<span class="name">
{{ node.title }}
<span *ngIf="!node.origin.isGasStation">({{node.origin.products? node.origin.products.stationsCount :
0}})</span>
</span>
<span class="operation" *ngIf="level === 1">
<span class="operation">
<span (click)="addOr(node)" *ngIf="!node.origin.isGasStation">新增</span>
<span (click)="waring(node)" *ngIf="node.origin.isGasStation">配置预警事件</span>
<span (click)="editOr(node)">编辑</span>

51
src/app/system-management/organization/organization.component.ts

@ -38,11 +38,11 @@ export class OrganizationComponent implements OnInit {
private viewContainerRef: ViewContainerRef
) {}
level: number; //当前登录账号的组织机构等级
// level: number; //当前登录账号的组织机构等级
ngOnInit(): void {
this.level = JSON.parse(
sessionStorage.getItem("userdata")
).organization.level;
// this.level = JSON.parse(
// sessionStorage.getItem("userdata")
// ).organization.level;
this.validateForm = this.fb.group({
search: [null],
});
@ -62,7 +62,7 @@ export class OrganizationComponent implements OnInit {
totalCount: string;
allOrList: any;
organization: any;
isLoading = false;
getAllOrganization() {
this.isLoading = true;
@ -80,44 +80,13 @@ export class OrganizationComponent implements OnInit {
params: params,
})
.subscribe((data: any) => {
this.organization = data.result.items;
this.getStationsNum(data.result.items);
this.totalCount = data.result.totalCount;
});
}
//获得组织机构下有多少油站
stationsList;
getStationsNum(e) {
let OrganizationUnitId =
sessionStorage.getItem("isGasStation") == "true"
? JSON.parse(sessionStorage.getItem("userdataOfgasstation"))
.organization.id
: JSON.parse(sessionStorage.getItem("userdata")).organization.id;
this.http
.get(
"/api/services/app/GasStation/GetCountsByOrganizations?IsContainsChildren=true"
)
.subscribe((data: any) => {
this.stationsList = data.result;
const arrs = e.map((item) => {
const data = this.stationsList.find(
(i) => item.id == i.organizationId
);
return {
...item,
products: data ? data : false,
};
console.log(data.result.items);
data.result.items.forEach((element) => {
element.title = element.displayName;
element.key = element.id;
});
for (let index = 0; index < arrs.length; index++) {
if (arrs[index].id == OrganizationUnitId) {
arrs[index].parentId = null;
}
arrs[index].title = arrs[index].displayName;
arrs[index].key = arrs[index].id;
arrs[index].selectable = false;
}
this.nodes = [...this.toTree.toTree(arrs)];
this.nodes = [...this.toTree.toTree(data.result.items)];
this.defaultExpandedKeys.length == 0
? (this.defaultExpandedKeys = [this.nodes[0].id])
: (this.defaultExpandedKeys = [...this.defaultExpandedKeys]);

BIN
src/assets/gismap/cardbg.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
src/assets/gismap/cardtitle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
src/assets/gismap/gis/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 416 B

BIN
src/assets/gismap/gis/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

BIN
src/assets/gismap/gis/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

BIN
src/assets/gismap/gis/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

BIN
src/assets/gismap/gis/marker.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/assets/gismap/icon/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
src/assets/gismap/icon/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
src/assets/gismap/icon/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
src/assets/gismap/icon/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

BIN
src/assets/gismap/listtitle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

8
src/index.html

@ -1,16 +1,20 @@
<!doctype html>
<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">
</head>
<body>
<app-root></app-root>
<div id="viewerjs" style="display:none"></div>
</body>
<script src="./assets/js/abp.js"></script>
<script src="./assets/js/echarts-tooltip-carousel.js"></script>
</html>
<script type="text/javascript" src="http://api.tianditu.gov.cn/api?v=4.0&tk=3027d4c8ed89bd8a185a9b73dbf3dcad"></script>
</html>

125
src/styles.scss

@ -104,8 +104,8 @@ h1 {
//三维场景
.dropDown {
border: 1px solid #23D9FF;
background: linear-gradient(180deg, #000D21 0%, #006E85 100%);
border: 1px solid #23d9ff;
background: linear-gradient(180deg, #000d21 0%, #006e85 100%);
li:hover {
background-color: transparent;
@ -121,8 +121,8 @@ h1 {
}
.dropDownPlan {
background: linear-gradient(360deg, #000D21 0%, rgba(0, 59, 110, 0.8) 100%);
box-shadow: 0px 0px 6px #2399FF;
background: linear-gradient(360deg, #000d21 0%, rgba(0, 59, 110, 0.8) 100%);
box-shadow: 0px 0px 6px #2399ff;
li {
color: #fff;
@ -131,10 +131,9 @@ h1 {
//任务弹窗
.taskDialog {
.ant-modal-header,
.ant-modal-content {
background: radial-gradient(circle, #004988 0%, #00122D 100%);
background: radial-gradient(circle, #004988 0%, #00122d 100%);
}
.ant-modal-header,
@ -143,26 +142,26 @@ h1 {
}
.ant-modal-title,
.ant-form-item-label>label,
.ant-form-item-label > label,
.ant-input {
color: #C4E2FC;
color: #c4e2fc;
}
.ant-modal-footer .ant-btn:first-child {
color: #C4E2FC;
background: #000D21;
border: 1px solid #C4E2FC;
color: #c4e2fc;
background: #000d21;
border: 1px solid #c4e2fc;
}
.ant-modal-footer .ant-btn:last-child {
color: #C4E2FC;
color: #c4e2fc;
background: rgba(0, 129, 255, 0.6);
border: 1px solid #36A2FF;
border: 1px solid #36a2ff;
}
.ant-input {
background: rgba(145, 204, 255, 0.41);
border: 1px solid #91CCFF;
border: 1px solid #91ccff;
}
textarea {
@ -181,7 +180,11 @@ h1 {
.ant-modal-body,
.ant-modal-content {
height: 100%;
background: radial-gradient(closest-side at 50% 55%, #004988 0%, #00122D 100%);
background: radial-gradient(
closest-side at 50% 55%,
#004988 0%,
#00122d 100%
);
}
}
@ -214,7 +217,6 @@ h1 {
//bbl 内置color
#threeDimensional {
//可展开面板
#disposalPlan {
font-size: 15px;
@ -223,7 +225,7 @@ h1 {
width: 100%;
height: 35px;
line-height: 35px;
color: #23D9FF;
color: #23d9ff;
padding: 0px;
background: rgba(35, 153, 255, 0.41);
border: 1px solid rgba(35, 217, 255, 0.4);
@ -235,12 +237,12 @@ h1 {
.ant-collapse-content {
background-color: transparent;
width: 100%
width: 100%;
}
}
.ant-tree {
color: #C4E2FC;
color: #c4e2fc;
}
//tree
@ -257,7 +259,8 @@ h1 {
//tree
.ant-select-disabled.ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
.ant-select-disabled.ant-select-single:not(.ant-select-customize-input)
.ant-select-selector {
color: #fff;
}
@ -296,9 +299,9 @@ h1 {
padding-left: 5px;
height: 30px;
line-height: 28px;
background: linear-gradient(360deg, #000D21 0%, rgba(0, 59, 110, 0.8) 100%);
background: linear-gradient(360deg, #000d21 0%, rgba(0, 59, 110, 0.8) 100%);
border: 1px solid rgba(35, 217, 255, 0.4);
color: #23D9FF;
color: #23d9ff;
.ant-collapse-arrow {
left: 5px;
@ -314,13 +317,13 @@ h1 {
//步骤条
//滚动条样式
//滚动条样式
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-thumb {
background-image: linear-gradient(#2495f8, #1c73c2, #02233f, );
background-image: linear-gradient(#2495f8, #1c73c2, #02233f);
}
::-webkit-scrollbar-track {
@ -366,7 +369,7 @@ ul {
}
.btn {
color: #36A2FF;
color: #36a2ff;
span {
cursor: pointer;
@ -380,7 +383,6 @@ ul {
margin-right: 40px;
}
}
}
.spin {
@ -395,3 +397,74 @@ ul {
left: 0;
top: 0;
}
.markerInfoWin {
position: absolute;
z-index: 999;
display: flex;
overflow: hidden;
border-radius: 4px;
div {
display: flex;
justify-content: center;
align-items: center;
color: #fff;
}
.icon {
width: 38px;
height: 36px;
}
.icon1 {
background: linear-gradient(
90deg,
RGBA(102, 131, 188, 1),
RGBA(102, 131, 188, 0.8)
);
}
.icon2 {
background: linear-gradient(
90deg,
RGBA(98, 52, 136, 1),
RGBA(98, 52, 136, 0.8)
);
}
.icon3 {
background: linear-gradient(
90deg,
RGBA(39, 126, 81, 1),
RGBA(39, 126, 81, 0.8)
);
}
.icon4 {
background: linear-gradient(
90deg,
RGBA(122, 67, 49, 1),
RGBA(122, 67, 49, 0.8)
);
}
.num {
height: 36px;
// width: 40px;
box-sizing: border-box;
padding: 0 13px;
font-size: 16px;
background: RGBA(44, 60, 103, 0.9);
}
}
.markerTotal {
color: #00f6ff;
border: 1px solid #43b0d5;
background: rgba(67, 86, 91, 0.8);
position: absolute;
left: 50%;
z-index: 100;
top: 50%;
font-size: 15px;
line-height: 25px;
box-sizing: border-box;
padding: 0px 5px;
border-radius: 3px;
}
.tdt-marker-pane {
z-index: 399 !important;
}

228
yarn.lock

@ -3117,7 +3117,7 @@
"resolved" "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz"
"version" "7.0.11"
"@types/long@*", "@types/long@^4.0.0", "@types/long@^4.0.1":
"@types/long@*", "@types/long@^4.0.1":
"integrity" "sha1-RZxl+hhn2v5qjzIsTFFpVmPMVek="
"resolved" "https://registry.npm.taobao.org/@types/long/download/@types/long-4.0.1.tgz"
"version" "4.0.1"
@ -3132,12 +3132,12 @@
"resolved" "https://registry.npm.taobao.org/@types/node/download/@types/node-12.12.26.tgz?cache=0&sync_timestamp=1580843161457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-12.12.26.tgz"
"version" "12.12.26"
"@types/node@^10.1.0":
"integrity" "sha1-tsYOvy+15CKf3XUf+d364PXzFUE="
"resolved" "https://registry.npm.taobao.org/@types/node/download/@types/node-10.17.14.tgz?cache=0&sync_timestamp=1580843161457&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-10.17.14.tgz"
"version" "10.17.14"
"@types/node@>=12.12.47":
"integrity" "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ=="
"resolved" "https://registry.npmmirror.com/@types/node/-/node-17.0.21.tgz"
"version" "17.0.21"
"@types/node@>=12.12.47", "@types/node@>=13.7.0":
"@types/node@>=13.7.0":
"integrity" "sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ=="
"resolved" "https://registry.npmmirror.com/@types/node/-/node-17.0.21.tgz"
"version" "17.0.21"
@ -3471,7 +3471,7 @@
dependencies:
"fast-deep-equal" "^3.1.3"
"ajv@^6.12.4", "ajv@^6.12.5", "ajv@^6.5.5", "ajv@^6.9.1":
"ajv@^6.12.4":
"integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz"
"version" "6.12.6"
@ -3481,27 +3481,27 @@
"json-schema-traverse" "^0.4.1"
"uri-js" "^4.2.2"
"ajv@^8.0.0":
"integrity" "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz"
"version" "8.11.0"
"ajv@^6.12.5":
"integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz"
"version" "6.12.6"
dependencies:
"fast-deep-equal" "^3.1.1"
"json-schema-traverse" "^1.0.0"
"require-from-string" "^2.0.2"
"fast-json-stable-stringify" "^2.0.0"
"json-schema-traverse" "^0.4.1"
"uri-js" "^4.2.2"
"ajv@^8.8.0", "ajv@^8.8.2":
"integrity" "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-8.11.0.tgz"
"version" "8.11.0"
"ajv@^6.5.5":
"integrity" "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz"
"version" "6.12.6"
dependencies:
"fast-deep-equal" "^3.1.1"
"json-schema-traverse" "^1.0.0"
"require-from-string" "^2.0.2"
"fast-json-stable-stringify" "^2.0.0"
"json-schema-traverse" "^0.4.1"
"uri-js" "^4.2.2"
"ajv@8.9.0":
"ajv@^6.9.1", "ajv@^8.0.0", "ajv@^8.8.0", "ajv@^8.8.2", "ajv@8.9.0":
"integrity" "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ=="
"resolved" "https://registry.npmmirror.com/ajv/-/ajv-8.9.0.tgz"
"version" "8.9.0"
@ -3958,7 +3958,7 @@
"bson-objectid@^1.3.1":
"integrity" "sha512-eQBNQXsisEAXlwiSy8zRNZdW2xDBJaEVkTPbodYR9hGxxtE548Qq7ilYOd8WAQ86xF7NRUdiWSQ1pa/TkKiE2A=="
"resolved" "https://registry.npmjs.org/bson-objectid/-/bson-objectid-1.3.1.tgz"
"resolved" "https://registry.npmmirror.com/bson-objectid/-/bson-objectid-1.3.1.tgz"
"version" "1.3.1"
"buffer-from@^1.0.0", "buffer-from@^1.1.0":
@ -4104,7 +4104,18 @@
dependencies:
"esm" "^3.2.25"
"chalk@^1.1.1", "chalk@^1.1.3":
"chalk@^1.1.1":
"integrity" "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="
"resolved" "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1573282918610&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz"
"version" "1.1.3"
dependencies:
"ansi-styles" "^2.2.1"
"escape-string-regexp" "^1.0.2"
"has-ansi" "^2.0.0"
"strip-ansi" "^3.0.0"
"supports-color" "^2.0.0"
"chalk@^1.1.3":
"integrity" "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg="
"resolved" "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz?cache=0&sync_timestamp=1573282918610&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchalk%2Fdownload%2Fchalk-1.1.3.tgz"
"version" "1.1.3"
@ -4786,7 +4797,12 @@
"resolved" "https://registry.npm.taobao.org/density-clustering/download/density-clustering-1.3.0.tgz"
"version" "1.3.0"
"depd@^1.1.2", "depd@~1.1.2":
"depd@^1.1.2":
"integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
"resolved" "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz"
"version" "1.1.2"
"depd@~1.1.2":
"integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
"resolved" "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz"
"version" "1.1.2"
@ -5338,14 +5354,7 @@
dependencies:
"reusify" "^1.0.4"
"faye-websocket@^0.11.3":
"integrity" "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g=="
"resolved" "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.4.tgz"
"version" "0.11.4"
dependencies:
"websocket-driver" ">=0.5.1"
"faye-websocket@0.11.3":
"faye-websocket@^0.11.3", "faye-websocket@0.11.3":
"integrity" "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA=="
"resolved" "https://registry.npmmirror.com/faye-websocket/-/faye-websocket-0.11.3.tgz"
"version" "0.11.3"
@ -5590,7 +5599,7 @@
dependencies:
"assert-plus" "^1.0.0"
"glob-parent@^5.1.2":
"glob-parent@^5.1.2", "glob-parent@~5.1.2":
"integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="
"resolved" "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
"version" "5.1.2"
@ -5604,13 +5613,6 @@
dependencies:
"is-glob" "^4.0.3"
"glob-parent@~5.1.2":
"integrity" "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="
"resolved" "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz"
"version" "5.1.2"
dependencies:
"is-glob" "^4.0.1"
"glob-to-regexp@^0.4.1":
"integrity" "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
"resolved" "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
@ -5881,15 +5883,7 @@
"agent-base" "^4.3.0"
"debug" "^3.1.0"
"https-proxy-agent@^5.0.0":
"integrity" "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA=="
"resolved" "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz"
"version" "5.0.0"
dependencies:
"agent-base" "6"
"debug" "4"
"https-proxy-agent@5.0.0":
"https-proxy-agent@^5.0.0", "https-proxy-agent@5.0.0":
"integrity" "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA=="
"resolved" "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz"
"version" "5.0.0"
@ -6855,13 +6849,6 @@
dependencies:
"brace-expansion" "^1.1.7"
"minimatch@^3.1.1":
"integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
"resolved" "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz"
"version" "3.1.2"
dependencies:
"brace-expansion" "^1.1.7"
"minimatch@^5.0.1":
"integrity" "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg=="
"resolved" "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.0.tgz"
@ -6947,19 +6934,35 @@
"minipass" "^3.0.0"
"yallist" "^4.0.0"
"mkdirp@^0.5.1", "mkdirp@^0.5.3", "mkdirp@^0.5.5", "mkdirp@^0.5.6":
"mkdirp@^0.5.1":
"integrity" "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz"
"version" "0.5.6"
dependencies:
"minimist" "^1.2.6"
"mkdirp@^1.0.3":
"integrity" "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz"
"version" "1.0.4"
"mkdirp@^0.5.3":
"integrity" "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz"
"version" "0.5.6"
dependencies:
"minimist" "^1.2.6"
"mkdirp@^0.5.5":
"integrity" "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz"
"version" "0.5.6"
dependencies:
"minimist" "^1.2.6"
"mkdirp@^0.5.6":
"integrity" "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz"
"version" "0.5.6"
dependencies:
"minimist" "^1.2.6"
"mkdirp@^1.0.4":
"mkdirp@^1.0.3", "mkdirp@^1.0.4":
"integrity" "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
"resolved" "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz"
"version" "1.0.4"
@ -7903,7 +7906,7 @@
"glob" "^7.0.5"
"yargs" "^3.10.0"
"protobufjs@^6.10.0":
"protobufjs@^6.10.0", "protobufjs@^6.8.6":
"integrity" "sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw=="
"resolved" "https://registry.npmmirror.com/protobufjs/-/protobufjs-6.11.2.tgz"
"version" "6.11.2"
@ -7922,25 +7925,6 @@
"@types/node" ">=13.7.0"
"long" "^4.0.0"
"protobufjs@^6.8.6":
"integrity" "sha1-yLTxKC/XqQ5vWxCe0RyEr4KQjnw="
"resolved" "https://registry.npm.taobao.org/protobufjs/download/protobufjs-6.8.8.tgz"
"version" "6.8.8"
dependencies:
"@protobufjs/aspromise" "^1.1.2"
"@protobufjs/base64" "^1.1.2"
"@protobufjs/codegen" "^2.0.4"
"@protobufjs/eventemitter" "^1.1.0"
"@protobufjs/fetch" "^1.1.0"
"@protobufjs/float" "^1.0.2"
"@protobufjs/inquire" "^1.1.0"
"@protobufjs/path" "^1.1.2"
"@protobufjs/pool" "^1.1.0"
"@protobufjs/utf8" "^1.1.0"
"@types/long" "^4.0.0"
"@types/node" "^10.1.0"
"long" "^4.0.0"
"protractor@^7.0.0", "protractor@~7.0.0":
"integrity" "sha512-UqkFjivi4GcvUQYzqGYNe0mLzfn5jiLmO8w9nMhQoJRLhy2grJonpga2IWhI6yJO30LibWXJJtA4MOIZD2GgZw=="
"resolved" "https://registry.npmmirror.com/protractor/-/protractor-7.0.0.tgz"
@ -8027,11 +8011,6 @@
"resolved" "https://registry.npm.taobao.org/quickselect/download/quickselect-1.1.1.tgz"
"version" "1.1.1"
"quickselect@^2.0.0":
"integrity" "sha1-8ZaApIal7vtYEwPgI+mPqvJd0Bg="
"resolved" "https://registry.npm.taobao.org/quickselect/download/quickselect-2.0.0.tgz"
"version" "2.0.0"
"randombytes@^2.1.0":
"integrity" "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="
"resolved" "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz"
@ -8054,14 +8033,7 @@
"iconv-lite" "0.4.24"
"unpipe" "1.0.0"
"rbush@*":
"integrity" "sha1-X6+op5s7mv3+UAhAOnIMwd6ILs8="
"resolved" "https://registry.npm.taobao.org/rbush/download/rbush-3.0.1.tgz"
"version" "3.0.1"
dependencies:
"quickselect" "^2.0.0"
"rbush@^2.0.1":
"rbush@*", "rbush@^2.0.1":
"integrity" "sha1-u2AFwnMbe6HVqaA1dykn0WphRgU="
"resolved" "https://registry.npm.taobao.org/rbush/download/rbush-2.0.2.tgz"
"version" "2.0.2"
@ -8083,7 +8055,7 @@
"json-parse-even-better-errors" "^2.3.0"
"npm-normalize-package-bin" "^1.0.1"
"readable-stream@^2.0.1", "readable-stream@~2.3.6":
"readable-stream@^2.0.1":
"integrity" "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c="
"resolved" "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz"
"version" "2.3.7"
@ -8096,7 +8068,7 @@
"string_decoder" "~1.1.1"
"util-deprecate" "~1.0.1"
"readable-stream@^3.0.6":
"readable-stream@^3.0.6", "readable-stream@^3.4.0", "readable-stream@^3.6.0":
"integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="
"resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz"
"version" "3.6.0"
@ -8105,23 +8077,18 @@
"string_decoder" "^1.1.1"
"util-deprecate" "^1.0.1"
"readable-stream@^3.4.0":
"integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="
"resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz"
"version" "3.6.0"
dependencies:
"inherits" "^2.0.3"
"string_decoder" "^1.1.1"
"util-deprecate" "^1.0.1"
"readable-stream@^3.6.0":
"integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA=="
"resolved" "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.0.tgz"
"version" "3.6.0"
"readable-stream@~2.3.6":
"integrity" "sha1-Hsoc9xGu+BTAT2IlKjamL2yyO1c="
"resolved" "https://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.7.tgz"
"version" "2.3.7"
dependencies:
"inherits" "^2.0.3"
"string_decoder" "^1.1.1"
"util-deprecate" "^1.0.1"
"core-util-is" "~1.0.0"
"inherits" "~2.0.3"
"isarray" "~1.0.0"
"process-nextick-args" "~2.0.0"
"safe-buffer" "~5.1.1"
"string_decoder" "~1.1.1"
"util-deprecate" "~1.0.1"
"readdirp@~3.6.0":
"integrity" "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="
@ -8326,7 +8293,28 @@
"resolved" "https://registry.npmmirror.com/rfdc/-/rfdc-1.3.0.tgz"
"version" "1.3.0"
"rimraf@^2.2.8", "rimraf@^2.5.2", "rimraf@^2.5.4", "rimraf@^2.6.3":
"rimraf@^2.2.8":
"integrity" "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w="
"resolved" "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz"
"version" "2.7.1"
dependencies:
"glob" "^7.1.3"
"rimraf@^2.5.2":
"integrity" "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w="
"resolved" "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz"
"version" "2.7.1"
dependencies:
"glob" "^7.1.3"
"rimraf@^2.5.4":
"integrity" "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w="
"resolved" "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz"
"version" "2.7.1"
dependencies:
"glob" "^7.1.3"
"rimraf@^2.6.3":
"integrity" "sha1-NXl/E6f9rcVmFCwp1PB8ytSD4+w="
"resolved" "https://registry.npm.taobao.org/rimraf/download/rimraf-2.7.1.tgz"
"version" "2.7.1"
@ -8953,13 +8941,6 @@
dependencies:
"ansi-regex" "^5.0.1"
"strip-ansi@^6.0.1":
"integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="
"resolved" "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz"
"version" "6.0.1"
dependencies:
"ansi-regex" "^5.0.1"
"strip-ansi@^7.0.0":
"integrity" "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw=="
"resolved" "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.0.1.tgz"
@ -9403,12 +9384,7 @@
"resolved" "https://registry.npm.taobao.org/uuid/download/uuid-3.3.3.tgz"
"version" "3.3.3"
"uuid@^8.3.2":
"integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
"resolved" "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz"
"version" "8.3.2"
"uuid@8.3.2":
"uuid@^8.3.2", "uuid@8.3.2":
"integrity" "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
"resolved" "https://registry.npmmirror.com/uuid/-/uuid-8.3.2.tgz"
"version" "8.3.2"

Loading…
Cancel
Save