邵佳豪
3 years ago
commit
4e36bb60e3
125 changed files with 14535 additions and 0 deletions
@ -0,0 +1,16 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below. |
||||
# For additional information regarding the format and rule options, please see: |
||||
# https://github.com/browserslist/browserslist#queries |
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see: |
||||
# https://angular.io/guide/browser-support |
||||
|
||||
# You can see what browsers were selected by your queries by running: |
||||
# npx browserslist |
||||
|
||||
last 1 Chrome version |
||||
last 1 Firefox version |
||||
last 2 Edge major versions |
||||
last 2 Safari major versions |
||||
last 2 iOS major versions |
||||
Firefox ESR |
@ -0,0 +1,16 @@
|
||||
# Editor configuration, see https://editorconfig.org |
||||
root = true |
||||
|
||||
[*] |
||||
charset = utf-8 |
||||
indent_style = space |
||||
indent_size = 2 |
||||
insert_final_newline = true |
||||
trim_trailing_whitespace = true |
||||
|
||||
[*.ts] |
||||
quote_type = single |
||||
|
||||
[*.md] |
||||
max_line_length = off |
||||
trim_trailing_whitespace = false |
@ -0,0 +1,42 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files. |
||||
|
||||
# Compiled output |
||||
/dist |
||||
/tmp |
||||
/out-tsc |
||||
/bazel-out |
||||
|
||||
# Node |
||||
/node_modules |
||||
npm-debug.log |
||||
yarn-error.log |
||||
|
||||
# IDEs and editors |
||||
.idea/ |
||||
.project |
||||
.classpath |
||||
.c9/ |
||||
*.launch |
||||
.settings/ |
||||
*.sublime-workspace |
||||
|
||||
# Visual Studio Code |
||||
.vscode/* |
||||
!.vscode/settings.json |
||||
!.vscode/tasks.json |
||||
!.vscode/launch.json |
||||
!.vscode/extensions.json |
||||
.history/* |
||||
|
||||
# Miscellaneous |
||||
/.angular/cache |
||||
.sass-cache/ |
||||
/connect.lock |
||||
/coverage |
||||
/libpeerconnection.log |
||||
testem.log |
||||
/typings |
||||
|
||||
# System files |
||||
.DS_Store |
||||
Thumbs.db |
@ -0,0 +1,4 @@
|
||||
{ |
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 |
||||
"recommendations": ["angular.ng-template"] |
||||
} |
@ -0,0 +1,20 @@
|
||||
{ |
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 |
||||
"version": "0.2.0", |
||||
"configurations": [ |
||||
{ |
||||
"name": "ng serve", |
||||
"type": "pwa-chrome", |
||||
"request": "launch", |
||||
"preLaunchTask": "npm: start", |
||||
"url": "http://localhost:4200/" |
||||
}, |
||||
{ |
||||
"name": "ng test", |
||||
"type": "chrome", |
||||
"request": "launch", |
||||
"preLaunchTask": "npm: test", |
||||
"url": "http://localhost:9876/debug.html" |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,42 @@
|
||||
{ |
||||
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 |
||||
"version": "2.0.0", |
||||
"tasks": [ |
||||
{ |
||||
"type": "npm", |
||||
"script": "start", |
||||
"isBackground": true, |
||||
"problemMatcher": { |
||||
"owner": "typescript", |
||||
"pattern": "$tsc", |
||||
"background": { |
||||
"activeOnStart": true, |
||||
"beginsPattern": { |
||||
"regexp": "(.*?)" |
||||
}, |
||||
"endsPattern": { |
||||
"regexp": "bundle generation complete" |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "npm", |
||||
"script": "test", |
||||
"isBackground": true, |
||||
"problemMatcher": { |
||||
"owner": "typescript", |
||||
"pattern": "$tsc", |
||||
"background": { |
||||
"activeOnStart": true, |
||||
"beginsPattern": { |
||||
"regexp": "(.*?)" |
||||
}, |
||||
"endsPattern": { |
||||
"regexp": "bundle generation complete" |
||||
} |
||||
} |
||||
} |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,117 @@
|
||||
{ |
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json", |
||||
"version": 1, |
||||
"newProjectRoot": "projects", |
||||
"projects": { |
||||
"EdgeHostMaintenance": { |
||||
"projectType": "application", |
||||
"schematics": { |
||||
"@schematics/angular:component": { |
||||
"style": "scss" |
||||
}, |
||||
"@schematics/angular:application": { |
||||
"strict": true |
||||
} |
||||
}, |
||||
"root": "", |
||||
"sourceRoot": "src", |
||||
"prefix": "app", |
||||
"architect": { |
||||
"build": { |
||||
"builder": "@angular-devkit/build-angular:browser", |
||||
"options": { |
||||
"outputPath": "dist/edge-host-maintenance", |
||||
"index": "src/index.html", |
||||
"main": "src/main.ts", |
||||
"polyfills": "src/polyfills.ts", |
||||
"tsConfig": "tsconfig.app.json", |
||||
"inlineStyleLanguage": "scss", |
||||
"assets": [ |
||||
"src/favicon.ico", |
||||
"src/assets", |
||||
{ |
||||
"glob": "**/*", |
||||
"input": "./node_modules/@ant-design/icons-angular/src/inline-svg/", |
||||
"output": "/assets/" |
||||
} |
||||
], |
||||
"styles": [ |
||||
"src/styles.scss", |
||||
"node_modules/ng-zorro-antd/ng-zorro-antd.min.css" |
||||
], |
||||
"scripts": [] |
||||
}, |
||||
"configurations": { |
||||
"production": { |
||||
"budgets": [ |
||||
{ |
||||
"type": "initial", |
||||
"maximumWarning": "5mb", |
||||
"maximumError": "5mb" |
||||
}, |
||||
{ |
||||
"type": "anyComponentStyle", |
||||
"maximumWarning": "2kb", |
||||
"maximumError": "4kb" |
||||
} |
||||
], |
||||
"fileReplacements": [ |
||||
{ |
||||
"replace": "src/environments/environment.ts", |
||||
"with": "src/environments/environment.prod.ts" |
||||
} |
||||
], |
||||
"outputHashing": "all" |
||||
}, |
||||
"development": { |
||||
"buildOptimizer": false, |
||||
"optimization": false, |
||||
"vendorChunk": true, |
||||
"extractLicenses": false, |
||||
"sourceMap": true, |
||||
"namedChunks": true |
||||
} |
||||
}, |
||||
"defaultConfiguration": "production" |
||||
}, |
||||
"serve": { |
||||
"builder": "@angular-devkit/build-angular:dev-server", |
||||
"configurations": { |
||||
"production": { |
||||
"browserTarget": "EdgeHostMaintenance:build:production" |
||||
}, |
||||
"development": { |
||||
"browserTarget": "EdgeHostMaintenance:build:development" |
||||
} |
||||
}, |
||||
"defaultConfiguration": "development" |
||||
}, |
||||
"extract-i18n": { |
||||
"builder": "@angular-devkit/build-angular:extract-i18n", |
||||
"options": { |
||||
"browserTarget": "EdgeHostMaintenance:build" |
||||
} |
||||
}, |
||||
"test": { |
||||
"builder": "@angular-devkit/build-angular:karma", |
||||
"options": { |
||||
"main": "src/test.ts", |
||||
"polyfills": "src/polyfills.ts", |
||||
"tsConfig": "tsconfig.spec.json", |
||||
"karmaConfig": "karma.conf.js", |
||||
"inlineStyleLanguage": "scss", |
||||
"assets": [ |
||||
"src/favicon.ico", |
||||
"src/assets" |
||||
], |
||||
"styles": [ |
||||
"src/styles.scss" |
||||
], |
||||
"scripts": [] |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
"defaultProject": "EdgeHostMaintenance" |
||||
} |
@ -0,0 +1,44 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) { |
||||
config.set({ |
||||
basePath: '', |
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'], |
||||
plugins: [ |
||||
require('karma-jasmine'), |
||||
require('karma-chrome-launcher'), |
||||
require('karma-jasmine-html-reporter'), |
||||
require('karma-coverage'), |
||||
require('@angular-devkit/build-angular/plugins/karma') |
||||
], |
||||
client: { |
||||
jasmine: { |
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
// for example, you can disable the random execution with `random: false`
|
||||
// or set a specific seed with `seed: 4321`
|
||||
}, |
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
}, |
||||
jasmineHtmlReporter: { |
||||
suppressAll: true // removes the duplicated traces
|
||||
}, |
||||
coverageReporter: { |
||||
dir: require('path').join(__dirname, './coverage/edge-host-maintenance'), |
||||
subdir: '.', |
||||
reporters: [ |
||||
{ type: 'html' }, |
||||
{ type: 'text-summary' } |
||||
] |
||||
}, |
||||
reporters: ['progress', 'kjhtml'], |
||||
port: 9876, |
||||
colors: true, |
||||
logLevel: config.LOG_INFO, |
||||
autoWatch: true, |
||||
browsers: ['Chrome'], |
||||
singleRun: false, |
||||
restartOnFileChange: true |
||||
}); |
||||
}; |
@ -0,0 +1,42 @@
|
||||
{ |
||||
"name": "edge-host-maintenance", |
||||
"version": "0.0.0", |
||||
"scripts": { |
||||
"ng": "ng", |
||||
"start": "ng serve --proxy-config proxy.config.json --open --port 4000 ", |
||||
"build": "ng build", |
||||
"watch": "ng build --watch --configuration development", |
||||
"test": "ng test" |
||||
}, |
||||
"private": true, |
||||
"dependencies": { |
||||
"@angular/animations": "~13.1.0", |
||||
"@angular/common": "~13.1.0", |
||||
"@angular/compiler": "~13.1.0", |
||||
"@angular/core": "~13.1.0", |
||||
"@angular/forms": "~13.1.0", |
||||
"@angular/platform-browser": "~13.1.0", |
||||
"@angular/platform-browser-dynamic": "~13.1.0", |
||||
"@angular/router": "~13.1.0", |
||||
"js-base64": "^3.7.2", |
||||
"ng-zorro-antd": "^13.0.1", |
||||
"ngx-cookie-service": "^13.1.2", |
||||
"rxjs": "~7.4.0", |
||||
"tslib": "^2.3.0", |
||||
"zone.js": "~0.11.4" |
||||
}, |
||||
"devDependencies": { |
||||
"@angular-devkit/build-angular": "~13.1.4", |
||||
"@angular/cli": "~13.1.4", |
||||
"@angular/compiler-cli": "~13.1.0", |
||||
"@types/jasmine": "~3.10.0", |
||||
"@types/node": "^12.11.1", |
||||
"jasmine-core": "~3.10.0", |
||||
"karma": "~6.3.0", |
||||
"karma-chrome-launcher": "~3.1.0", |
||||
"karma-coverage": "~2.1.0", |
||||
"karma-jasmine": "~4.0.0", |
||||
"karma-jasmine-html-reporter": "~1.7.0", |
||||
"typescript": "~4.5.2" |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
{ |
||||
"/api": { |
||||
"target": "http://39.106.78.171:8920", |
||||
"secure": false, |
||||
"changeOrigin": true |
||||
}, |
||||
"/signalr": { |
||||
"target": "http://39.106.78.171:8920", |
||||
"secure": false, |
||||
"ws": true, |
||||
"logLevel": "debug" |
||||
} |
||||
} |
@ -0,0 +1,58 @@
|
||||
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; |
||||
|
||||
export class CustomReuseStrategy implements RouteReuseStrategy { |
||||
|
||||
public static handlers: { [key: string]: DetachedRouteHandle } = {}; |
||||
|
||||
/** 删除缓存路由快照的方法 */ |
||||
public static deleteRouteSnapshot(path: string): void { |
||||
const name = path.replace(/\//g, '_'); |
||||
if (CustomReuseStrategy.handlers[name]) { |
||||
delete CustomReuseStrategy.handlers[name]; |
||||
} |
||||
} |
||||
|
||||
/** 表示对所有路由允许复用 如果你有路由不想利用可以在这加一些业务逻辑判断 */ |
||||
shouldDetach(route: ActivatedRouteSnapshot): boolean { |
||||
console.log('shouldDetach======>', route); |
||||
return true; |
||||
} |
||||
|
||||
/** 当路由离开时会触发。按path作为key存储路由快照&组件当前实例对象 */ |
||||
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { |
||||
console.log('store======>', route, handle); |
||||
if(route.routeConfig.path == 'host'){ |
||||
CustomReuseStrategy.handlers[this.getRouteUrl(route)] = handle; |
||||
} |
||||
} |
||||
|
||||
/** 若 path 在缓存中有的都认为允许还原路由 */ |
||||
shouldAttach(route: ActivatedRouteSnapshot): boolean { |
||||
// console.debug('shouldAttach======>', route);
|
||||
return !!CustomReuseStrategy.handlers[this.getRouteUrl(route)]; |
||||
} |
||||
|
||||
/** 从缓存中获取快照,若无则返回nul */ |
||||
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle { |
||||
// console.debug('retrieve======>', route);
|
||||
if (!CustomReuseStrategy.handlers[this.getRouteUrl(route)]) { |
||||
return null; |
||||
} |
||||
|
||||
return CustomReuseStrategy.handlers[this.getRouteUrl(route)]; |
||||
} |
||||
|
||||
/** 进入路由触发,判断是否同一路由 */ |
||||
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { |
||||
// console.debug('shouldReuseRoute======>', future, curr);
|
||||
return future.routeConfig === curr.routeConfig && |
||||
JSON.stringify(future.params) === JSON.stringify(curr.params); |
||||
} |
||||
|
||||
/** 使用route的path作为快照的key */ |
||||
getRouteUrl(route: ActivatedRouteSnapshot) { |
||||
const path = route['_routerState'].url.replace(/\//g, '_'); |
||||
return path; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core'; |
||||
import { RouterModule, Routes } from '@angular/router'; |
||||
import { AuthGuard } from './auth.guard'; |
||||
import { LoginComponent } from './pages/login/login.component'; |
||||
import { NavigationComponent } from './system-management/navigation/navigation.component'; |
||||
|
||||
const routes: Routes = [ |
||||
{ path: '', redirectTo: '/login', pathMatch: 'full' }, |
||||
{ path: 'login', component: LoginComponent, }, |
||||
{ |
||||
path: '', component: NavigationComponent, canActivate: [AuthGuard], children: [ |
||||
{ path: 'system', loadChildren: () => import('./system-management/system-management.module').then(m => m.SystemManagementModule) } |
||||
] |
||||
}//系统管理
|
||||
]; |
||||
|
||||
@NgModule({ |
||||
imports: [RouterModule.forRoot(routes)], |
||||
exports: [RouterModule] |
||||
}) |
||||
export class AppRoutingModule { } |
@ -0,0 +1,17 @@
|
||||
import { Component } from '@angular/core'; |
||||
import { CacheTokenService } from './service/cache-token.service'; |
||||
|
||||
@Component({ |
||||
selector: 'app-root', |
||||
templateUrl: './app.component.html', |
||||
styleUrls: ['./app.component.scss'] |
||||
}) |
||||
export class AppComponent { |
||||
constructor(public token: CacheTokenService) { } |
||||
ngOnInit() { |
||||
if (sessionStorage.getItem('token') && !this.token.timer) { |
||||
//调用服务中的function刷新token
|
||||
this.token.startUp()
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
|
||||
import { BrowserModule } from '@angular/platform-browser'; |
||||
import { NgModule } from '@angular/core'; |
||||
import { AppRoutingModule } from './app-routing.module'; |
||||
import { AppComponent } from './app.component'; |
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; |
||||
import { PagesModule } from './pages/pages.module'; |
||||
import { FormsModule } from '@angular/forms'; |
||||
import { HttpClientModule } from '@angular/common/http'; |
||||
import { httpInterceptorProviders } from './http-interceptors/index' |
||||
import { CacheTokenService } from './service/cache-token.service' |
||||
import { NzNotificationModule } from 'ng-zorro-antd/notification'; |
||||
import { NzMessageModule } from 'ng-zorro-antd/message'; |
||||
import { TreeService } from './service/tree.service'; |
||||
import { RouteReuseStrategy } from '@angular/router'; |
||||
import { CustomReuseStrategy } from './CustomReuseStrategy'; |
||||
import { ConfigFormDataService } from './service/configFormData.service'; |
||||
@NgModule({ |
||||
declarations: [ |
||||
AppComponent |
||||
], |
||||
imports: [ |
||||
BrowserModule, |
||||
AppRoutingModule, |
||||
BrowserAnimationsModule, |
||||
PagesModule, |
||||
FormsModule, |
||||
HttpClientModule, |
||||
NzNotificationModule, |
||||
NzMessageModule |
||||
], |
||||
providers: [httpInterceptorProviders, CacheTokenService, TreeService, ConfigFormDataService, |
||||
{ provide: RouteReuseStrategy, useClass: CustomReuseStrategy }], |
||||
bootstrap: [AppComponent] |
||||
}) |
||||
export class AppModule { } |
@ -0,0 +1,36 @@
|
||||
import { Component, OnInit, Inject } from '@angular/core'; |
||||
import { Injectable } from '@angular/core'; |
||||
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router'; |
||||
|
||||
@Injectable({ |
||||
providedIn: 'root' |
||||
}) |
||||
export class AuthGuard implements CanActivate { |
||||
|
||||
constructor(private router: Router) { |
||||
|
||||
} |
||||
|
||||
// 路由守卫
|
||||
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { |
||||
// console.log('路由守卫',next.data)
|
||||
// if(next.data.permission == 'xxxx'){
|
||||
// return true;
|
||||
// }
|
||||
return this.checkLogin(); |
||||
} |
||||
|
||||
checkLogin(): boolean { |
||||
// console.log('xxxxxxxxxxxx')
|
||||
// 判断本地有没有token
|
||||
const token = sessionStorage.getItem('token'); |
||||
|
||||
// 如果有token,允许访问
|
||||
if (token) { return true; } |
||||
|
||||
//如果没有token,跳转登录页
|
||||
this.router.navigate(['/login']); |
||||
|
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,91 @@
|
||||
import { Injectable } from '@angular/core'; |
||||
import { |
||||
HttpClient, HttpInterceptor, HttpHandler, HttpRequest, |
||||
HttpErrorResponse |
||||
} from '@angular/common/http'; |
||||
import { throwError } from 'rxjs' |
||||
import { catchError } from 'rxjs/operators'; |
||||
import { Router } from '@angular/router' |
||||
import { CacheTokenService } from '../service/cache-token.service' |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
//baseurl
|
||||
// const baseurl = 'http://39.106.78.171:8008';
|
||||
|
||||
@Injectable() |
||||
export class BaseInterceptor implements HttpInterceptor { |
||||
|
||||
constructor(private router: Router, public token: CacheTokenService, private message: NzMessageService) { } |
||||
|
||||
intercept(req: any, next: HttpHandler) { |
||||
|
||||
let params = req.params; |
||||
for (const key of req.params.keys()) { |
||||
if (params.get(key) === undefined || params.get(key) === null) { |
||||
params = params.delete(key, undefined); |
||||
} |
||||
} |
||||
req = req.clone({ params }); |
||||
// debugger
|
||||
// console.log('xxxxxx',req)
|
||||
let newReq = req.clone({ |
||||
url: req.hadBaseurl ? `${req.url}` : `${req.url}`, |
||||
}); |
||||
if (!req.cancelToken) { |
||||
/*获取token*/ |
||||
let token = sessionStorage.getItem('token') |
||||
/*此处设置额外请求头,token令牌*/ |
||||
newReq.headers = |
||||
newReq.headers.set('Authorization', `Bearer ${token}`) |
||||
} |
||||
|
||||
// 携带请求头发送下一次请求
|
||||
return next.handle(newReq) |
||||
.pipe( |
||||
//箭头函数,注意this指向
|
||||
catchError((err) => this.handleError(err)) |
||||
) |
||||
} |
||||
|
||||
// 捕获错误
|
||||
//401 token过期 403没权限!!! 400参数错误 404未找到 614刷新令牌过期!!!
|
||||
|
||||
private handleError(error: HttpErrorResponse) { |
||||
console.log('http错误', error) |
||||
// 用户认证失败返回登录页
|
||||
if (error.status === 401) { |
||||
this.token.delete() |
||||
sessionStorage.clear() |
||||
localStorage.removeItem("isautologin") |
||||
this.message.create('error', `用户认证信息过期,请重新登录!`); |
||||
this.router.navigate(['/login']) |
||||
return |
||||
} |
||||
if (error.status === 403) { |
||||
this.message.create('error', `对不起,您无此权限!`); |
||||
return |
||||
} |
||||
if (error.status === 400) { |
||||
this.message.create('error', error.error); |
||||
return |
||||
} |
||||
if (error.status === 503) { |
||||
this.message.create('error', error.error.detail); |
||||
return |
||||
} |
||||
if (error.error instanceof ErrorEvent) { |
||||
// 发生客户端或网络错误。相应处理。
|
||||
console.error('An error occurred:', error.error.message); |
||||
} else { |
||||
// 服务端返回http状态码
|
||||
// 服务端返回错误信息
|
||||
console.error( |
||||
`状态码${error.status}, ` + |
||||
`错误内容:${error.error}`); |
||||
this.message.create('error', error.error); |
||||
} |
||||
// 返回带有面向用户的错误信息
|
||||
return throwError(() => { |
||||
new Error('error') |
||||
}); |
||||
}; |
||||
} |
@ -0,0 +1,9 @@
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http'; |
||||
|
||||
import { BaseInterceptor } from './base-interceptor'; |
||||
|
||||
/** Http interceptor providers in outside-in order */ |
||||
export const httpInterceptorProviders = [ |
||||
{ provide: HTTP_INTERCEPTORS, useClass: BaseInterceptor, multi: true }, |
||||
|
||||
]; |
@ -0,0 +1,46 @@
|
||||
<div class="login" id="login"> |
||||
<div class="card"> |
||||
<h1 class="cardheader">欢迎登录</h1> |
||||
<h1 class="cardheader">济南管理系统</h1> |
||||
|
||||
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()"> |
||||
<nz-form-item> |
||||
<nz-form-control nzErrorTip="请输入账号!"> |
||||
<nz-input-group nzPrefixIcon="user"> |
||||
<input required nz-input type="text" formControlName="userName" placeholder="请输入账号"/> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-control nzErrorTip="请输入密码!"> |
||||
<nz-input-group nzPrefixIcon="lock"> |
||||
<input required nz-input type="password" formControlName="password" placeholder="请输入密码"/> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<div class="hint"> |
||||
<nz-form-item style="margin-bottom: 0;"> |
||||
<nz-form-control> |
||||
<label nz-checkbox formControlName="remember" [(ngModel)]="remember">记住密码</label> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<span class="forget" (click)="forget()">忘记密码?</span> |
||||
</div> |
||||
<nz-form-item style="margin-bottom: 0;"> |
||||
<nz-form-control> |
||||
<label class="autologin" formControlName="autologin" nz-checkbox [(ngModel)]="autologin">自动登录</label> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<button [nzLoading]="isLoading" nz-button class="login-form-button login-form-margin" |
||||
[nzType]="'primary'">登录</button> |
||||
</form> |
||||
<p class="company">北京安信科创软件有限公司 版权所有</p> |
||||
</div> |
||||
|
||||
|
||||
<div class="name"> |
||||
</div> |
||||
|
||||
</div> |
@ -0,0 +1,93 @@
|
||||
.login { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: url('../../../assets/images/bgImg.png'); |
||||
background-size: 100% 100%; |
||||
position: relative; |
||||
} |
||||
|
||||
.card { |
||||
position: absolute; |
||||
top: 50%; |
||||
left: 50%; |
||||
transform: translate(-50%,-50%); |
||||
background-color: rgba(0, 13, 33, 0.24); |
||||
border-radius: 16px; |
||||
width: 468px; |
||||
height: 548px; |
||||
box-sizing: border-box; |
||||
padding: 79px 45px 42px 45px; |
||||
color: rgba(255, 255, 255, 1); |
||||
} |
||||
|
||||
.cardheader { |
||||
font-size: 22px; |
||||
color: rgba(255, 255, 255, 1); |
||||
} |
||||
.cardheader:nth-child(2) { |
||||
margin-bottom: 40px; |
||||
} |
||||
|
||||
label { |
||||
color: #fff; |
||||
} |
||||
|
||||
.hint { |
||||
display: flex; |
||||
justify-content: space-between; |
||||
margin-bottom: 6px; |
||||
align-items: center; |
||||
.forget { |
||||
cursor: pointer; |
||||
color: #2399FF; |
||||
} |
||||
} |
||||
|
||||
.autologin { |
||||
margin-bottom: 40px; |
||||
} |
||||
|
||||
button { |
||||
width: 100%; |
||||
height: 42px; |
||||
font-size: 16px; |
||||
border-radius: 4px; |
||||
} |
||||
|
||||
p { |
||||
text-align: center; |
||||
} |
||||
|
||||
.role { |
||||
color: #2399FF; |
||||
margin-top: 38px; |
||||
font-size: 15px; |
||||
} |
||||
|
||||
.company { |
||||
color: #666262; |
||||
margin-top: 25px; |
||||
font-size: 14px; |
||||
} |
||||
|
||||
.name { |
||||
position: absolute; |
||||
left:40px; |
||||
top:40px; |
||||
|
||||
img { |
||||
// margin-bottom: 32px; |
||||
width: 254px; |
||||
height: 56px; |
||||
} |
||||
|
||||
h1 { |
||||
font-size: 63px; |
||||
color: #feffff; |
||||
font-weight: 600; |
||||
|
||||
text-shadow: 0px 2px 8px #2399FF; |
||||
letter-spacing: 5px; |
||||
margin-bottom: 0px; |
||||
} |
||||
} |
@ -0,0 +1,128 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { HttpClient } from '@angular/common/http' |
||||
import { Router, ActivatedRoute } from '@angular/router' |
||||
import { CacheTokenService } from '../../service/cache-token.service'//引入服务
|
||||
import { 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'; |
||||
|
||||
@Component({ |
||||
selector: 'app-login', |
||||
templateUrl: './login.component.html', |
||||
styleUrls: ['./login.component.scss'], |
||||
|
||||
}) |
||||
export class LoginComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private http: HttpClient, private router: Router, public token: CacheTokenService, private fb: FormBuilder, private message: NzMessageService) { } |
||||
|
||||
ngOnInit() { |
||||
this.validateForm = this.fb.group({ |
||||
userName: [null, [Validators.required]], |
||||
password: [null, [Validators.required]], |
||||
remember: [null], |
||||
autologin: [null], |
||||
}); |
||||
//如果本地储存了账号密码信息,那就回显在输入框
|
||||
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')) |
||||
}); |
||||
this.remember = true //这一步是回显后让勾选框为选中状态
|
||||
} |
||||
//自动登录
|
||||
if (localStorage.getItem('isautologin') == 'true') { |
||||
this.submitForm() |
||||
this.autologin = true //这一步是回显后让勾选框为选中状态
|
||||
} |
||||
|
||||
} |
||||
|
||||
errmsg: string = ''; //错误信息
|
||||
|
||||
|
||||
|
||||
// //跳转注册页面
|
||||
// toRegister() {
|
||||
// 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)) |
||||
} |
||||
} |
||||
//自动登录
|
||||
autoLogin() { |
||||
if (this.autologin) { |
||||
localStorage.setItem("isautologin", 'true') |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
remember: any//记住密码
|
||||
autologin: any//自动登录
|
||||
isLoading = false; |
||||
messages: any |
||||
encryptedAccessToken: any |
||||
submitForm(): void { |
||||
|
||||
if (!this.remember) { |
||||
localStorage.removeItem("account") |
||||
localStorage.removeItem("password") |
||||
} |
||||
if (!this.autologin) { |
||||
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.isLoading = true; |
||||
this.http.post('/api/Accounts/SignIn', { |
||||
username: this.validateForm.value.userName, |
||||
password: this.validateForm.value.password |
||||
}).subscribe({ |
||||
next: (data: any) => { |
||||
// this.isLoading = false;
|
||||
console.log('登录信息', data) |
||||
this.rememberInfo() |
||||
this.autoLogin() |
||||
sessionStorage.setItem("token", data.token); |
||||
sessionStorage.setItem("refreshToken", data.refreshToken); |
||||
this.router.navigate(['/system/organization']) |
||||
this.message.create('success', `登录成功`); |
||||
|
||||
//调用服务中的function刷新token
|
||||
this.token.startUp() |
||||
}, |
||||
error: (err) => { |
||||
this.isLoading = false; |
||||
console.log(err) |
||||
} |
||||
} |
||||
|
||||
) |
||||
} |
||||
|
||||
forget() { |
||||
this.message.create('warning', `请联系管理员`); |
||||
} |
||||
} |
@ -0,0 +1,44 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; |
||||
import { CommonModule } from '@angular/common'; |
||||
import { A11yModule } from '@angular/cdk/a11y'; |
||||
import { DragDropModule } from '@angular/cdk/drag-drop'; |
||||
import { PortalModule } from '@angular/cdk/portal'; |
||||
import { ScrollingModule } from '@angular/cdk/scrolling'; |
||||
import { CdkStepperModule } from '@angular/cdk/stepper'; |
||||
import { CdkTableModule } from '@angular/cdk/table'; |
||||
import { CdkTreeModule } from '@angular/cdk/tree'; |
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; |
||||
import { RouterModule } from '@angular/router'; |
||||
import { NzFormModule } from 'ng-zorro-antd/form'; |
||||
import { NzButtonModule } from 'ng-zorro-antd/button'; |
||||
import { NzInputModule } from 'ng-zorro-antd/input'; |
||||
import { NzSelectModule } from 'ng-zorro-antd/select'; |
||||
import { LoginComponent } from './login/login.component'; |
||||
import { NzMessageModule } from 'ng-zorro-antd/message'; |
||||
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; |
||||
@NgModule({ |
||||
declarations: [ |
||||
LoginComponent |
||||
], |
||||
imports: [ |
||||
CommonModule, |
||||
A11yModule, |
||||
DragDropModule, |
||||
PortalModule, |
||||
ScrollingModule, |
||||
CdkStepperModule, |
||||
CdkTableModule, |
||||
CdkTreeModule, |
||||
FormsModule, |
||||
ReactiveFormsModule, |
||||
RouterModule, |
||||
NzFormModule, |
||||
NzButtonModule, |
||||
NzInputModule, |
||||
NzSelectModule, |
||||
NzMessageModule, |
||||
NzCheckboxModule |
||||
], |
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA] |
||||
}) |
||||
export class PagesModule { } |
@ -0,0 +1,16 @@
|
||||
import { NgModule } from '@angular/core'; |
||||
import { Routes, RouterModule } from '@angular/router'; |
||||
|
||||
|
||||
|
||||
const routes: Routes = [ |
||||
|
||||
]; |
||||
|
||||
|
||||
|
||||
@NgModule({ |
||||
imports: [RouterModule.forChild(routes)], |
||||
exports: [RouterModule] |
||||
}) |
||||
export class pagesRoutingModule { } |
@ -0,0 +1,17 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'; |
||||
/* |
||||
* Raise the value exponentially |
||||
* Takes an exponent argument that defaults to 1. |
||||
* Usage: |
||||
* value | exponentialStrength:exponent |
||||
* Example: |
||||
* {{ 2 | exponentialStrength:10 }} |
||||
* formats to: 1024 |
||||
*/ |
||||
@Pipe({ name: 'cameraType' }) |
||||
export class cameraType implements PipeTransform { |
||||
transform(value: number): string { |
||||
let arr = ['进出口', '加油区', '卸油区', '便利店'] |
||||
return arr[value] |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
import { Injectable } from '@angular/core'; |
||||
import { HttpClient } from '@angular/common/http' |
||||
|
||||
@Injectable({ |
||||
providedIn: 'root' |
||||
}) |
||||
export class CacheTokenService { |
||||
|
||||
constructor(private http: HttpClient) { } |
||||
|
||||
public timer: number | undefined; |
||||
|
||||
//刷新token令牌定时器
|
||||
startUp = (): void => { |
||||
window.clearInterval(this.timer) |
||||
this.timer = window.setInterval(() => { |
||||
var token = sessionStorage.getItem("token"); |
||||
var refreshToken = sessionStorage.getItem("refreshToken"); |
||||
this.http.post('/api/Accounts/RefreshToken', { |
||||
token: token, |
||||
refreshToken: refreshToken |
||||
}).subscribe((data: any) => { |
||||
|
||||
console.log('定时刷新token成功',data) |
||||
sessionStorage.setItem("token", data.token); |
||||
sessionStorage.setItem("refreshToken", data.refreshToken); |
||||
}) |
||||
}, 18 * 60 * 1000) |
||||
console.log('启动定时刷新token') |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//删除定时器
|
||||
delete = (): void => { |
||||
window.clearInterval(this.timer) |
||||
} |
||||
|
||||
createTime = (time: string) => { |
||||
var newtime = time.substr(0, 4) + '年' + time.substr(5, 2) + '月' + time.substr(8, 2) + '日' + time.substr(11, 8) |
||||
} |
||||
|
||||
} |
@ -0,0 +1,10 @@
|
||||
import { Injectable } from '@angular/core'; |
||||
|
||||
@Injectable() |
||||
export class ConfigFormDataService { |
||||
tableData: any//摄像头列表数据
|
||||
config1: any//配置文件
|
||||
config2: any//配置文件
|
||||
config3: any//配置文件
|
||||
config4: any//配置文件
|
||||
} |
@ -0,0 +1,38 @@
|
||||
import { Injectable } from '@angular/core'; |
||||
|
||||
@Injectable() |
||||
export class TreeService { |
||||
|
||||
|
||||
toTree(olddata) { |
||||
let newdata = [] |
||||
function getparentNode(parentId) { |
||||
return olddata.find((item) => { |
||||
return item.id == parentId |
||||
}) |
||||
} |
||||
olddata.forEach(item => { |
||||
var parentNode = getparentNode(item.parentId); |
||||
if (parentNode) { |
||||
if (!parentNode.children) { |
||||
parentNode.children = [] |
||||
} |
||||
|
||||
// if (parentNode.children.length == 0) {
|
||||
// item.isTop = true;
|
||||
// } else {
|
||||
// item.isTop = false;
|
||||
// parentNode.children[parentNode.children.length -1].isBottom = false;
|
||||
// }
|
||||
// item.isBottom = true;
|
||||
|
||||
parentNode.children.push(item) |
||||
} else { |
||||
if (!item.parentId) {//如果parentId为null
|
||||
newdata.push(item) |
||||
} |
||||
} |
||||
}); |
||||
return newdata; |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="ip" placeholder="请输入ip" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,3 @@
|
||||
.ant-form-item{ |
||||
margin-bottom: 0; |
||||
} |
@ -0,0 +1,21 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
|
||||
@Component({ |
||||
selector: 'app-addhost', |
||||
templateUrl: './addhost.component.html', |
||||
styleUrls: ['./addhost.component.scss'] |
||||
}) |
||||
export class AddhostComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
ip: [null, [Validators.required]] |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,73 @@
|
||||
<div class="bigbox" id="hostbox"> |
||||
<div class="orbox"> |
||||
<div class="topbox"> |
||||
<div class="lefttop"> |
||||
<span>组织机构列表</span> |
||||
</div> |
||||
<div class="righttop"> |
||||
<nz-input-group nzPrefixIcon="search"> |
||||
<input type="text" nz-input placeholder="请输入机构名称" [(ngModel)]="searchValue" /> |
||||
</nz-input-group> |
||||
</div> |
||||
</div> |
||||
<div class="treeTitle"> |
||||
<span>组织机构</span> |
||||
</div> |
||||
<div class="treebox"> |
||||
<nz-tree [nzSearchValue]="searchValue" #nzTreeComponent [nzData]="nodes" [nzExpandAll]="nzExpandAll" |
||||
[nzExpandedKeys]="defaultExpandedKeys" [nzSelectedKeys]='nzSelectedKeys' (nzClick)="nzClick($event)" |
||||
[nzTreeTemplate]="nzTreeTemplate" [nzExpandedIcon]="multiExpandedIconTpl"> |
||||
</nz-tree> |
||||
<ng-template #nzTreeTemplate let-node let-origin="origin"> |
||||
<div class="nodebox"> |
||||
<span class="name">{{ node.title }}</span> |
||||
</div> |
||||
</ng-template> |
||||
<ng-template #multiExpandedIconTpl let-node let-origin="origin"> |
||||
<ng-container *ngIf="node.children.length == 0; else elseTemplate"> |
||||
|
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<i nz-icon [nzType]="node.isExpanded ? 'caret-down' : 'caret-right'" class="ant-tree-switcher-line-icon"></i> |
||||
</ng-template> |
||||
</ng-template> |
||||
</div> |
||||
|
||||
</div> |
||||
<div class="hostListbox"> |
||||
<div class="topbox"> |
||||
<div class="lefttop"> |
||||
<span>{{selectedOilStation ? selectedOilStation.displayName : '加油站'}} 边缘盒子列表 |
||||
<span class="yellowspan">(请从左侧选择加油站)</span> |
||||
</span> |
||||
</div> |
||||
<div class="righttop" *ngIf="selectedOilStation"> |
||||
<button nz-button nzType="primary" (click)="addHost()"><i nz-icon nzType="plus-circle" |
||||
nzTheme="outline"></i>新增边缘盒子</button> |
||||
</div> |
||||
</div> |
||||
<div class="tablebox"> |
||||
<nz-table #basicTable [nzData]="listOfData" [nzShowPagination]='false' [nzPageSize]='16' [nzLoading]="isLoading"> |
||||
<thead> |
||||
<tr> |
||||
<th>ip</th> |
||||
<th>配置状态</th> |
||||
<th>操作</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr *ngFor="let data of basicTable.data"> |
||||
<td>{{data.hostIPAddress}}</td> |
||||
<td>!配置状态!</td> |
||||
<td class="operation"> |
||||
<a (click)="edit(data)" style="margin-right: 12px;">编辑</a> |
||||
<a (click)="config(data)" style="margin-right: 12px;">配置</a> |
||||
<a (click)="download(data)" style="margin-right: 12px;">下载设备编号</a> |
||||
<a class="red" (click)="delete(data)">删除</a> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</nz-table> |
||||
</div> |
||||
</div> |
||||
</div> |
@ -0,0 +1,100 @@
|
||||
.bigbox { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
background: #fff; |
||||
box-sizing: border-box; |
||||
padding: 20px; |
||||
font-size: 15px; |
||||
} |
||||
|
||||
|
||||
.orbox { |
||||
width: 375px; |
||||
height: 100%; |
||||
overflow-y: auto; |
||||
|
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.topbox { |
||||
width: 100%; |
||||
height: 36px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.lefttop { |
||||
span { |
||||
color: #000D21; |
||||
margin-right: 16px; |
||||
} |
||||
|
||||
.yellowspan { |
||||
color: rgb(240, 176, 37); |
||||
} |
||||
} |
||||
|
||||
.righttop { |
||||
height: 36px; |
||||
display: flex; |
||||
|
||||
button { |
||||
margin-left: 16px; |
||||
} |
||||
|
||||
nz-input-group { |
||||
height: 32px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.treeTitle { |
||||
width: 100%; |
||||
height: 36px; |
||||
line-height: 36px; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
color: #000D21; |
||||
box-sizing: border-box; |
||||
padding-left: 30px; |
||||
padding-right: 180px; |
||||
background: rgba(145, 204, 255, 0.2); |
||||
border: 1px solid rgba(145, 204, 255, 0.2); |
||||
} |
||||
|
||||
.treebox { |
||||
flex: 1; |
||||
overflow-y: auto; |
||||
border: 1px solid rgba(145, 204, 255, 0.2); |
||||
border-top: 0px; |
||||
box-sizing: border-box; |
||||
padding: 10px 6px; |
||||
|
||||
tr { |
||||
|
||||
th, |
||||
td { |
||||
text-align: center !important; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.nodebox { |
||||
font-size: 15px; |
||||
} |
||||
|
||||
.hostListbox { |
||||
flex: 1; |
||||
margin-left: 26px; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.tablebox { |
||||
margin-top: 16px; |
||||
} |
||||
|
||||
.red:hover{ |
||||
color: red; |
||||
} |
@ -0,0 +1,204 @@
|
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { Component, OnInit, AfterViewInit, ViewChild, ViewContainerRef } from '@angular/core'; |
||||
import { TreeService } from 'src/app/service/tree.service'; |
||||
import { NzFormatEmitEvent, NzTreeComponent, NzTreeNodeOptions } from 'ng-zorro-antd/tree'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { AddhostComponent } from './addhost/addhost.component'; |
||||
import { EdithostComponent } from './edithost/edithost.component'; |
||||
import { Router } from '@angular/router'; |
||||
@Component({ |
||||
selector: 'app-analysis-of-the-host', |
||||
templateUrl: './analysis-of-the-host.component.html', |
||||
styleUrls: ['./analysis-of-the-host.component.scss'] |
||||
}) |
||||
export class AnalysisOfTheHostComponent implements OnInit { |
||||
|
||||
constructor(private router: Router, private fb: FormBuilder, private http: HttpClient, private toTree: TreeService, private modal: NzModalService, private message: NzMessageService, private viewContainerRef: ViewContainerRef) { } |
||||
ngOnInit(): void { |
||||
this.getAllOrganization() |
||||
} |
||||
|
||||
|
||||
//获取所有组织机构
|
||||
searchValue = ''; |
||||
nzExpandAll = false; |
||||
totalCount: string |
||||
|
||||
getAllOrganization() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
PageSize: 9999 |
||||
} |
||||
this.http.get('/api/Organizations', { |
||||
params: params |
||||
}).subscribe((data: any) => { |
||||
this.totalCount = data.totalCount |
||||
data.items.forEach(element => { |
||||
element.key = element.id |
||||
element.title = element.name |
||||
element.selectable = false |
||||
}); |
||||
this.nodes = [...this.toTree.toTree(data.items)] |
||||
this.defaultExpandedKeys = [this.nodes[0].id] |
||||
this.defaultExpandedKeys = [...this.defaultExpandedKeys] |
||||
}) |
||||
} |
||||
|
||||
|
||||
@ViewChild('nzTreeComponent', { static: false }) nzTreeComponent!: NzTreeComponent; |
||||
|
||||
defaultExpandedKeys = []; |
||||
|
||||
nodes: any[] = [] |
||||
nzSelectedKeys: any[] = [] |
||||
selectedOilStation: any |
||||
nzClick(event: NzFormatEmitEvent): void { |
||||
if (event.node.origin['isGasStation']) {//如果点击的是加油站才生效
|
||||
this.nzSelectedKeys[0] = event.node.origin.id |
||||
this.nzSelectedKeys = [...this.nzSelectedKeys] |
||||
this.selectedOilStation = event.node.origin |
||||
console.log(this.selectedOilStation) |
||||
this.getHost() |
||||
} else { |
||||
this.message.info('只有加油站才可以增加主机'); |
||||
} |
||||
} |
||||
|
||||
//获得加油站的主机
|
||||
listOfData: any[] = []; |
||||
isLoading = false |
||||
getHost() { |
||||
this.isLoading = true |
||||
this.http.get('/api/EdgeDevices', { |
||||
params: { |
||||
ContainsChildren: true, |
||||
OrganizationId: this.selectedOilStation.id, |
||||
PageSize: 999 |
||||
} |
||||
}).subscribe((data: any) => { |
||||
console.log('主机列表', data.items) |
||||
this.isLoading = false |
||||
this.listOfData = data.items |
||||
}) |
||||
} |
||||
|
||||
|
||||
ngAfterViewInit(): void { |
||||
|
||||
} |
||||
|
||||
//新增边缘盒子
|
||||
addHost() { |
||||
console.log(this.selectedOilStation) |
||||
const modal = this.modal.create({ |
||||
nzTitle: '新增边缘盒子', |
||||
nzContent: AddhostComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise(resolve => { |
||||
console.log('表单信息', instance.validateForm) |
||||
let body = { |
||||
hostIPAddress: instance.validateForm.value.ip, |
||||
OrganizationId: this.selectedOilStation.id |
||||
} |
||||
this.http.post('/api/EdgeDevices', body).subscribe(data => { |
||||
resolve(data) |
||||
this.message.create('success', '创建成功!'); |
||||
this.getHost() |
||||
return true |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
|
||||
edit(data) { |
||||
console.log(data) |
||||
const modal = this.modal.create({ |
||||
nzTitle: '编辑边缘盒子', |
||||
nzContent: EdithostComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: { |
||||
ip: data.hostIPAddress |
||||
}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise(resolve => { |
||||
console.log('表单信息', instance.validateForm) |
||||
data.hostIPAddress = instance.validateForm.value.ip, |
||||
this.http.put(`/api/EdgeDevices/${data.id}`, data).subscribe(data => { |
||||
resolve(data) |
||||
this.message.create('success', '修改成功!'); |
||||
this.getHost() |
||||
return true |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
|
||||
delete(item) { |
||||
console.log(item) |
||||
this.modal.confirm({ |
||||
nzTitle: `确定要删除${item.name}这个主机吗?`, |
||||
nzOkText: '确定', |
||||
nzOkType: 'primary', |
||||
nzOnOk: () => { |
||||
this.http.delete(`/api/EdgeDevices/${item.id}`).subscribe(data => { |
||||
this.message.create('success', '删除成功!'); |
||||
this.getHost() |
||||
}) |
||||
}, |
||||
nzCancelText: '取消' |
||||
}); |
||||
} |
||||
|
||||
config(data) { |
||||
this.router.navigate([`/system/host/camera`], { queryParams: { 'hostId': data.id, 'orId': this.selectedOilStation.id } }) |
||||
} |
||||
|
||||
|
||||
download(data) { |
||||
console.log(data) |
||||
let params = { |
||||
edgeDeviceId: data.id |
||||
} |
||||
const httpOptions = { |
||||
responseType: 'blob' as 'json', |
||||
params: params |
||||
}; |
||||
this.http.get(`/api/EdgeDevices/IdentityDigest/File`, httpOptions).subscribe({ |
||||
next: (data: any) => { |
||||
console.log('文件',data) |
||||
// 文件名中有中文 则对文件名进行转码
|
||||
const link = document.createElement('a'); |
||||
const blob = new Blob([data], { type: 'application/octet-stream' }); |
||||
link.setAttribute('href', window.URL.createObjectURL(blob)); |
||||
link.setAttribute('download', `.deviceid`); |
||||
link.style.visibility = 'hidden'; |
||||
document.body.appendChild(link); |
||||
link.click(); |
||||
document.body.removeChild(link); |
||||
}, |
||||
error: (err) => { |
||||
console.log(err) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,11 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input [(ngModel)]="ip" nz-input type="text" formControlName="ip" placeholder="请输入ip" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,23 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
|
||||
@Component({ |
||||
selector: 'app-edithost', |
||||
templateUrl: './edithost.component.html', |
||||
styleUrls: ['./edithost.component.scss'] |
||||
}) |
||||
export class EdithostComponent implements OnInit { |
||||
|
||||
@Input() ip: any |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
ip: [null, [Validators.required]] |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,182 @@
|
||||
<div class="box"> |
||||
<div class="topbox"> |
||||
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()"> |
||||
<nz-form-item class="searchParams"> |
||||
<nz-form-control> |
||||
<nz-tree-select [nzAllowClear]="false" [nzDropdownClassName]="'maxHeightTreeSelect'" nzShowSearch |
||||
formControlName="organization" [nzNodes]="nodes" nzPlaceHolder="请选择所属机构" [(ngModel)]="defaultOrId" |
||||
[nzExpandedIcon]="multiExpandedIconTpl"> |
||||
</nz-tree-select> |
||||
<ng-template #multiExpandedIconTpl let-node let-origin="origin"> |
||||
<ng-container *ngIf="node.children.length == 0; else elseTemplate"> |
||||
|
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<i nz-icon [nzType]="node.isExpanded ? 'caret-down' : 'caret-right'" |
||||
class="ant-tree-switcher-line-icon"></i> |
||||
</ng-template> |
||||
</ng-template> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item> |
||||
<!-- <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="state">设备状态</nz-form-label> --> |
||||
<nz-form-control> |
||||
<nz-select formControlName="state" nzPlaceHolder="请选择设备状态"> |
||||
<nz-option [nzValue]="0" nzLabel="离线"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="在线"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button nzType="primary" type="submit" class="submit"><i nz-icon [nzType]="'search'"></i>查询</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button type="button" class="reset" (click)="resetForm($event)"><i nz-icon |
||||
[nzType]="'sync'"></i>重置</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<!-- <button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'UpdateStates'" (click)="sendRequest('UpdateStates')"> |
||||
更新识别程序服务状态 |
||||
</button> --> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'UpdateApps'" (click)="sendRequest('UpdateApps')"> |
||||
更新识别程序 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'primary'" (click)="sendRequest('UpdateImages')"> |
||||
更新镜像 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'primary'" (click)="sendRequest('UpdateModels')"> |
||||
更新模型 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'primary'" (click)="sendRequest('UpdateMonitors')"> |
||||
更新监控程序 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'file'" (click)="file()"> |
||||
更新监控程序配置文件 |
||||
</button> |
||||
</form> |
||||
|
||||
</div> |
||||
<nz-table #basicTable nzShowSizeChanger [nzData]="listOfData" [nzLoading]="isLoading" |
||||
(nzCurrentPageDataChange)="onCurrentPageDataChange($event)" [nzShowPagination]='false' [nzPageSize]='10'> |
||||
<thead> |
||||
<tr> |
||||
<th [nzChecked]="checked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="onAllChecked($event)"></th> |
||||
<th>ip地址</th> |
||||
<th>所属油站</th> |
||||
<th>设备状态</th> |
||||
<th>识别程序更新状态</th> |
||||
<!-- <th>识别程序更新状态开始时间</th> |
||||
<th>识别程序更新状态结束时间</th> --> |
||||
<th>镜像更新状态</th> |
||||
<!-- <th>镜像更新状态开始时间</th> |
||||
<th>镜像更新状态结束时间</th> --> |
||||
|
||||
<th>模型更新状态</th> |
||||
|
||||
<th>监控程序更新状态</th> |
||||
<!-- <th>监控程序更新状态开始时间</th> |
||||
<th>监控程序更新状态结束时间</th> --> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr *ngFor="let data of basicTable.data"> |
||||
<td [nzChecked]="setOfCheckedId.has(data.id)" [nzDisabled]="data.disabled" |
||||
(nzCheckedChange)="onItemChecked(data.id, $event)"></td> |
||||
<td>{{ data.hostIPAddress }}</td> |
||||
<td>{{ data.gasStationName }}</td> |
||||
<td> |
||||
<ng-container *ngIf="data.hubConnectionState == 'Disconnected'; else elseTemplate"> |
||||
<span style="color: red;">离线</span> |
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<span style="color: rgb(52, 204, 52);">在线</span> |
||||
</ng-template> |
||||
|
||||
</td> |
||||
<!-- 识别程序 --> |
||||
<td> |
||||
<p> |
||||
<span *ngIf="data.appUpdatingState == 'Never'">未更新</span> |
||||
<span *ngIf="data.appUpdatingState == 'Updating'">更新中</span> |
||||
<span *ngIf="data.appUpdatingState == 'Updated'">已更新</span> |
||||
</p> |
||||
<p> |
||||
开始时间:{{data.appUpdatingStartedTime ? (data.appUpdatingStartedTime | date:"yyyy-MM-dd HH:mm:ss") :'/'}} |
||||
|
||||
</p> |
||||
<p> |
||||
结束时间:{{data.appUpdatingFinishedTime ? (data.appUpdatingFinishedTime | date:"yyyy-MM-dd HH:mm:ss") :'/'}} |
||||
</p> |
||||
</td> |
||||
<!-- 镜像 --> |
||||
<td> |
||||
<p> |
||||
<span *ngIf="data.imageUpdatingState == 'Never'">未更新</span> |
||||
<span *ngIf="data.imageUpdatingState == 'Updating'">更新中</span> |
||||
<span *ngIf="data.imageUpdatingState == 'Updated'">已更新</span> |
||||
</p> |
||||
<p> |
||||
{{data.imageUpdatingStartedTime ? (data.imageUpdatingStartedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
<p> |
||||
{{data.imageUpdatingFinishedTime ? (data.imageUpdatingFinishedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
</td> |
||||
<!-- 模型 --> |
||||
<td> |
||||
<p> |
||||
<span *ngIf="data.modelsUpdatingState == 'Never'">未更新</span> |
||||
<span *ngIf="data.modelsUpdatingState == 'Updating'">更新中</span> |
||||
<span *ngIf="data.modelsUpdatingState == 'Updated'">已更新</span> |
||||
</p> |
||||
<p> |
||||
{{data.modelsUpdatingStartedTime ? (data.modelsUpdatingStartedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
<p> |
||||
{{data.modelsUpdatingFinishedTime ? (data.modelsUpdatingFinishedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
</td> |
||||
<!-- 监控程序 --> |
||||
<td> |
||||
<p> |
||||
<span *ngIf="data.monitorUpdatingState == 'Never'">未更新</span> |
||||
<span *ngIf="data.monitorUpdatingState == 'Updating'">更新中</span> |
||||
<span *ngIf="data.monitorUpdatingState == 'Updated'">已更新</span> |
||||
<span *ngIf="data.monitorUpdatingState == 'UpdatingTimeout'">更新超时</span> |
||||
</p> |
||||
<p> |
||||
{{data.monitorUpdatingStartedTime ? (data.monitorUpdatingStartedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
<p> |
||||
{{data.monitorUpdatingFinishedTime ? (data.monitorUpdatingFinishedTime | date:"yyyy-MM-dd HH:mm:ss") : |
||||
'/'}} |
||||
</p> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</nz-table> |
||||
<div class="pagination"> |
||||
<nz-pagination [nzHideOnSinglePage]="false" [nzPageIndex]="1" [nzTotal]="num" [nzPageSize]="10" |
||||
[nzShowTotal]="totalTemplate" nzShowQuickJumper (nzPageIndexChange)="pageChange($event)"> |
||||
</nz-pagination> |
||||
<ng-template #totalTemplate let-total> 10条/页,共{{num}}条 </ng-template> |
||||
</div> |
||||
</div> |
@ -0,0 +1,17 @@
|
||||
.topbox { |
||||
form { |
||||
display: flex; |
||||
|
||||
nz-form-item { |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
button { |
||||
margin-right: 6px; |
||||
} |
||||
} |
||||
|
||||
.searchParams { |
||||
width: 250px; |
||||
} |
||||
} |
@ -0,0 +1,270 @@
|
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { TreeService } from 'src/app/service/tree.service'; |
||||
import { FileComponent } from './file/file.component'; |
||||
import { ModelComponent } from './model/model.component'; |
||||
@Component({ |
||||
selector: 'app-condition-monitoring', |
||||
templateUrl: './condition-monitoring.component.html', |
||||
styleUrls: ['./condition-monitoring.component.scss'] |
||||
}) |
||||
export class ConditionMonitoringComponent implements OnInit { |
||||
|
||||
constructor(private http: HttpClient, private fb: FormBuilder, private toTree: TreeService, private message: NzMessageService, private modal: NzModalService, private viewContainerRef: ViewContainerRef) { } |
||||
validateForm!: FormGroup; |
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
organization: [null], |
||||
state: [null] |
||||
}); |
||||
this.getAllOrganization() |
||||
|
||||
} |
||||
//获取所有组织机构
|
||||
nodes: any = [] |
||||
defaultOrId: string |
||||
defaultExpandedKeys = []; |
||||
getAllOrganization() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
pageSize: 9999 |
||||
} |
||||
this.http.get('/api/Organizations', { |
||||
params: params |
||||
}).subscribe((data: any) => { |
||||
console.log('组织机构列表', data) |
||||
data.items.forEach(element => { |
||||
element.key = element.id |
||||
element.title = element.name |
||||
// element.selectable = false
|
||||
}); |
||||
this.nodes = [...this.toTree.toTree(data.items)] |
||||
this.defaultOrId = this.nodes[0].id |
||||
this.validateForm.value.organization = this.defaultOrId |
||||
this.getConditionMonitoring() |
||||
}) |
||||
} |
||||
|
||||
submitForm(): void { |
||||
for (const i in this.validateForm.controls) { |
||||
this.validateForm.controls[i].markAsDirty(); |
||||
this.validateForm.controls[i].updateValueAndValidity(); |
||||
} |
||||
this.getConditionMonitoring() |
||||
} |
||||
resetForm(e: MouseEvent): void { |
||||
e.preventDefault(); |
||||
this.validateForm.reset(); |
||||
for (const key in this.validateForm.controls) { |
||||
this.validateForm.controls[key].markAsPristine(); |
||||
this.validateForm.controls[key].updateValueAndValidity(); |
||||
} |
||||
this.validateForm.patchValue({ |
||||
organization: this.nodes[0].id, |
||||
}); |
||||
this.PageNumber = 1 |
||||
this.getConditionMonitoring() |
||||
} |
||||
listOfData: any |
||||
num: string |
||||
PageNumber: number = 1 |
||||
isLoading = false |
||||
//获取盒子状态
|
||||
getConditionMonitoring() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
OrganizationId: this.defaultOrId, |
||||
PageNumber: this.PageNumber, |
||||
PageSize: 10, |
||||
HubConnectionState: this.validateForm.value.state |
||||
} |
||||
this.isLoading = true |
||||
this.http.get('/api/EdgeDevices/Statuses', { params: params }).subscribe( |
||||
(data: any) => { |
||||
console.log(data) |
||||
this.isLoading = false |
||||
this.listOfData = data.items |
||||
this.num = data.totalCount |
||||
}, err => { |
||||
|
||||
} |
||||
) |
||||
} |
||||
pageChange($event) { |
||||
this.PageNumber = $event |
||||
this.getConditionMonitoring() |
||||
} |
||||
|
||||
|
||||
checked = false; |
||||
loading |
||||
indeterminate = false; |
||||
listOfCurrentPageData: readonly any[] = []; |
||||
setOfCheckedId = new Set<number>(); |
||||
updateCheckedSet(id: number, checked: boolean): void { |
||||
if (checked) { |
||||
this.setOfCheckedId.add(id); |
||||
} else { |
||||
this.setOfCheckedId.delete(id); |
||||
} |
||||
} |
||||
|
||||
onCurrentPageDataChange(listOfCurrentPageData: readonly any[]): void { |
||||
this.listOfCurrentPageData = listOfCurrentPageData; |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
refreshCheckedStatus(): void { |
||||
const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled); |
||||
this.checked = listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id)); |
||||
this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked; |
||||
} |
||||
|
||||
onItemChecked(id: number, checked: boolean): void { |
||||
this.updateCheckedSet(id, checked); |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
onAllChecked(checked: boolean): void { |
||||
this.listOfCurrentPageData |
||||
.filter(({ disabled }) => !disabled) |
||||
.forEach(({ id }) => this.updateCheckedSet(id, checked)); |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
sendRequest(type): void { |
||||
|
||||
const requestData = this.listOfData.filter(data => this.setOfCheckedId.has(data.id)); |
||||
|
||||
let strArr = [] |
||||
requestData.forEach(element => { |
||||
strArr.push(element.id) |
||||
}); |
||||
let body |
||||
if (type != 'UpdateModels') { |
||||
this.loading = type; |
||||
body = { |
||||
edgeDeviceIds: strArr |
||||
} |
||||
this.http.patch('/api/EdgeDevices/Commands', body, { params: { command: type } }).subscribe({ |
||||
next: (data: any) => { |
||||
this.message.create('success', '通知边缘盒子成功,请过一段时间手动刷新尝试!'); |
||||
console.log(data) |
||||
if (data.failedItems.length != 0) { |
||||
data.failedItems.forEach(element => { |
||||
this.message.create('info', element.detail); |
||||
}); |
||||
} |
||||
this.setOfCheckedId.clear(); |
||||
this.refreshCheckedStatus(); |
||||
this.loading = null; |
||||
this.getConditionMonitoring() |
||||
}, |
||||
error: (err) => { |
||||
this.loading = null; |
||||
} |
||||
}) |
||||
} else { |
||||
const modal = this.modal.create({ |
||||
nzTitle: '选择更新模型类型', |
||||
nzContent: ModelComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
// console.log(instance.validateForm.value.type)
|
||||
if (instance.validateForm.valid) { |
||||
body = { |
||||
edgeDeviceIds: strArr, |
||||
modelNames: instance.validateForm.value.type |
||||
} |
||||
await new Promise(resolve => { |
||||
this.http.patch('/api/EdgeDevices/Commands', body, { params: { command: type } }).subscribe({ |
||||
next: (data: any) => { |
||||
resolve(data) |
||||
this.message.create('success', '通知边缘盒子成功,请过一段时间手动刷新尝试!'); |
||||
if (data.failedItems.length != 0) { |
||||
data.failedItems.forEach(element => { |
||||
this.message.create('info', element.detail); |
||||
}); |
||||
} |
||||
this.setOfCheckedId.clear(); |
||||
this.refreshCheckedStatus(); |
||||
this.loading = null; |
||||
this.getConditionMonitoring() |
||||
return true |
||||
}, |
||||
error: (err) => { |
||||
resolve(err) |
||||
this.loading = null; |
||||
return false |
||||
} |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
|
||||
} |
||||
|
||||
file() { |
||||
const requestData = this.listOfData.filter(data => this.setOfCheckedId.has(data.id)); |
||||
let strArr = [] |
||||
requestData.forEach(element => { |
||||
strArr.push(element.id) |
||||
}); |
||||
const modal = this.modal.create({ |
||||
nzTitle: '配置文件', |
||||
nzContent: FileComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 500, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
let body = { |
||||
edgeDeviceIds: strArr, |
||||
scheme: instance.validateForm.value.scheme, |
||||
host: instance.validateForm.value.host, |
||||
port: instance.validateForm.value.port, |
||||
maxRetries: instance.validateForm.value.maxRetries |
||||
} |
||||
await new Promise(resolve => { |
||||
this.loading = 'file' |
||||
this.http.patch('/api/EdgeDevices/Commands/PushMonitorSettingsJson', body).subscribe({ |
||||
next: (data: any) => { |
||||
this.message.create('success', '通知边缘盒子成功,请过一段时间手动刷新尝试!'); |
||||
// console.log(data)
|
||||
if (data.failedItems.length != 0) { |
||||
data.failedItems.forEach(element => { |
||||
this.message.create('info', element.detail); |
||||
}); |
||||
} |
||||
this.setOfCheckedId.clear(); |
||||
this.refreshCheckedStatus(); |
||||
|
||||
this.getConditionMonitoring() |
||||
this.loading = null; |
||||
}, |
||||
error: (err) => { |
||||
this.loading = null; |
||||
} |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,36 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm" class="formbox"> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="scheme">协议</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="scheme" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="host">主机/ip</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="host" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="port">端口</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input type="number" nz-input formControlName="port" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="maxRetries">最大重试次数</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input type="number" nz-input formControlName="maxRetries" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,27 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
|
||||
@Component({ |
||||
selector: 'app-file', |
||||
templateUrl: './file.component.html', |
||||
styleUrls: ['./file.component.scss'] |
||||
}) |
||||
export class FileComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
scheme: [null, [Validators.required]], |
||||
host: [null, [Validators.required]], |
||||
port: [null, [Validators.required]], |
||||
maxRetries: [null, [Validators.required]] |
||||
}); |
||||
} |
||||
destroyModal(): void { |
||||
this.modal.destroy({ data: 'this the result data' }); |
||||
} |
||||
} |
@ -0,0 +1,18 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<nz-select nzMode="multiple" formControlName="type" nzPlaceHolder="请选择类型"> |
||||
<nz-option [nzValue]="'peoplenet'" nzLabel="peoplenet"></nz-option> |
||||
<nz-option [nzValue]="'trafficcam'" nzLabel="trafficcam"></nz-option> |
||||
<nz-option [nzValue]="'actionnet'" nzLabel="actionnet"></nz-option> |
||||
<nz-option [nzValue]="'idnet'" nzLabel="idnet"></nz-option> |
||||
<nz-option [nzValue]="'oilnet'" nzLabel="oilnet"></nz-option> |
||||
<nz-option [nzValue]="'smoking_calling_net'" nzLabel="smoking_calling_net"></nz-option> |
||||
<nz-option [nzValue]="'connet'" nzLabel="connet"></nz-option> |
||||
<nz-option [nzValue]="'fire_smoke_net'" nzLabel="fire_smoke_net"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,24 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
@Component({ |
||||
selector: 'app-model', |
||||
templateUrl: './model.component.html', |
||||
styleUrls: ['./model.component.scss'] |
||||
}) |
||||
export class ModelComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
type: [null, [Validators.required]], |
||||
}); |
||||
} |
||||
destroyModal(): void { |
||||
this.modal.destroy({ data: 'this the result data' }); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,15 @@
|
||||
<div class="box"> |
||||
<nz-page-header class="site-page-header" (nzBack)="goback()" nzBackIcon nzSubtitle="返回上一页"></nz-page-header> |
||||
<div class="content"> |
||||
<nz-tabset> |
||||
<nz-tab nzTitle="config_nvdsanalytics.txt"><textarea name="config1" id="config1" [(ngModel)]="config1"></textarea> |
||||
</nz-tab> |
||||
<nz-tab nzTitle="config.yaml"> <textarea name="config2" id="config2" [(ngModel)]="config2"></textarea></nz-tab> |
||||
<nz-tab nzTitle="producer.yaml"> <textarea name="config3" id="config3" [(ngModel)]="config3"></textarea></nz-tab> |
||||
<!-- <nz-tab nzTitle="source.yaml"> <textarea name="config4" id="config4" [(ngModel)]="config4"></textarea></nz-tab> --> |
||||
</nz-tabset> |
||||
</div> |
||||
<div class="btnbox"> |
||||
<button nz-button nzType="primary" (click)="putConfig()">下发算法配置</button> |
||||
</div> |
||||
</div> |
@ -0,0 +1,29 @@
|
||||
.box { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #fff; |
||||
font-size: 15px; |
||||
color: black; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
flex-direction: column; |
||||
overflow-y: auto; |
||||
} |
||||
.content{ |
||||
flex: 1; |
||||
box-sizing: border-box; |
||||
padding: 0 12px; |
||||
nz-tabset{ |
||||
height: 100%; |
||||
} |
||||
textarea{ |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
} |
||||
.btnbox{ |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
height: 52px; |
||||
} |
@ -0,0 +1,76 @@
|
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { ActivatedRoute } from '@angular/router'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { ConfigFormDataService } from 'src/app/service/configFormData.service'; |
||||
|
||||
@Component({ |
||||
selector: 'app-config-form', |
||||
templateUrl: './config-form.component.html', |
||||
styleUrls: ['./config-form.component.scss'] |
||||
}) |
||||
export class ConfigFormComponent implements OnInit { |
||||
|
||||
constructor(public configFormData: ConfigFormDataService, private http: HttpClient, private route: ActivatedRoute, private message: NzMessageService) { } |
||||
config1: string |
||||
config2: string |
||||
config3: string |
||||
// config4: string
|
||||
hostId//主机id
|
||||
orId//加油站id
|
||||
ngOnInit(): void { |
||||
this.hostId = this.route.snapshot.queryParams.hostId |
||||
this.orId = this.route.snapshot.queryParams.orId |
||||
this.config1 = sessionStorage.getItem('config1') |
||||
this.config2 = sessionStorage.getItem('config2') |
||||
this.config3 = sessionStorage.getItem('config3') |
||||
// this.config4 = sessionStorage.getItem('config4')
|
||||
} |
||||
goback() { |
||||
history.go(-1) |
||||
} |
||||
putConfig() { |
||||
let body = { |
||||
configFiles: [ |
||||
{ name: 'config_nvdsanalytics.txt', content: this.config1 }, |
||||
{ name: 'config.yaml', content: this.config2 }, |
||||
{ name: 'producer.yaml', content: this.config3 }, |
||||
// { name: 'source.yaml', content: this.config4 }
|
||||
] |
||||
} |
||||
this.http.put(`/api/EdgeDevices/${this.hostId}`, body).subscribe({ |
||||
next: (data) => { |
||||
this.message.create('success', `文件保存成功`); |
||||
let promiseArr = [] |
||||
body.configFiles.forEach(element => { |
||||
let params = { |
||||
edgeDeviceId: this.hostId, |
||||
fileName: element.name |
||||
} |
||||
promiseArr.push( |
||||
new Promise((resolve, reject) => { |
||||
this.http.put('/api/EdgeDevices/Commands/PushFile', '', { params: params }).subscribe({ |
||||
next: (data) => { |
||||
resolve('成功了') |
||||
}, |
||||
error: err => { |
||||
reject('失败了') |
||||
} |
||||
}) |
||||
}) |
||||
) |
||||
}); |
||||
Promise.all(promiseArr).then((result) => { |
||||
this.message.create('success', `发送文件名成功`); |
||||
}).catch((error) => { |
||||
// this.message.create('error', `发送文件名失败`);
|
||||
console.log('发送文件名失败', error) |
||||
}) |
||||
}, |
||||
error: (err) => { |
||||
this.message.create('error', `文件保存失败`); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
} |
@ -0,0 +1,75 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="name">名称</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="name" placeholder="请输入名称" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="user">用户名</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="user" placeholder="请输入用户名" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="password">密码</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="password" placeholder="请输入密码" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="uri">地址</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="uri" placeholder="请输入地址" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="type">类型</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-select formControlName="type" nzPlaceHolder="请选择类型"> |
||||
<nz-option [nzValue]="0" nzLabel="进出口"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="加油区"></nz-option> |
||||
<nz-option [nzValue]="2" nzLabel="卸油区"></nz-option> |
||||
<nz-option [nzValue]="3" nzLabel="便利店"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<!-- <nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="type">序号</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-select formControlName="order" nzPlaceHolder="请选择序号"> |
||||
<nz-option [nzValue]="0" nzLabel="0"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="1"></nz-option> |
||||
<nz-option [nzValue]="2" nzLabel="2"></nz-option> |
||||
<nz-option [nzValue]="3" nzLabel="3"></nz-option> |
||||
<nz-option [nzValue]="4" nzLabel="4"></nz-option> |
||||
<nz-option [nzValue]="5" nzLabel="5"></nz-option> |
||||
<nz-option [nzValue]="6" nzLabel="6"></nz-option> |
||||
<nz-option [nzValue]="7" nzLabel="7"></nz-option> |
||||
<nz-option [nzValue]="8" nzLabel="8"></nz-option> |
||||
<nz-option [nzValue]="9" nzLabel="9"></nz-option> |
||||
<nz-option [nzValue]="10" nzLabel="10"></nz-option> |
||||
<nz-option [nzValue]="11" nzLabel="11"></nz-option> |
||||
<nz-option [nzValue]="12" nzLabel="12"></nz-option> |
||||
<nz-option [nzValue]="13" nzLabel="13"></nz-option> |
||||
<nz-option [nzValue]="14" nzLabel="14"></nz-option> |
||||
<nz-option [nzValue]="15" nzLabel="15"></nz-option> |
||||
<nz-option [nzValue]="16" nzLabel="16"></nz-option> |
||||
<nz-option [nzValue]="17" nzLabel="17"></nz-option> |
||||
<nz-option [nzValue]="18" nzLabel="18"></nz-option> |
||||
<nz-option [nzValue]="19" nzLabel="19"></nz-option> |
||||
<nz-option [nzValue]="20" nzLabel="20"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> --> |
||||
</form> |
||||
</div> |
@ -0,0 +1,50 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { NzSafeAny } from 'ng-zorro-antd/core/types'; |
||||
@Component({ |
||||
selector: 'app-addcamera', |
||||
templateUrl: './addcamera.component.html', |
||||
styleUrls: ['./addcamera.component.scss'] |
||||
}) |
||||
export class AddcameraComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
const { namevalidate } = MyValidators; |
||||
this.validateForm = this.fb.group({ |
||||
name: [null, [Validators.required, namevalidate]], |
||||
user: [null, [Validators.required]], |
||||
password: [null, [Validators.required]], |
||||
uri: [null, [Validators.required]], |
||||
type: [null, [Validators.required]], |
||||
// order: [null, [Validators.required]],
|
||||
}); |
||||
} |
||||
|
||||
|
||||
} |
||||
export type MyErrorsOptions = { 'zh-cn': string; en: string } & Record<string, NzSafeAny>; |
||||
export type MyValidationErrors = Record<string, MyErrorsOptions>; |
||||
export class MyValidators extends Validators { |
||||
static namevalidate(control: AbstractControl): MyValidationErrors | null { |
||||
const value = control.value; |
||||
|
||||
if (isEmptyInputValue(value)) { |
||||
return null; |
||||
} |
||||
|
||||
return isPassword(value) ? null : { mobile: { 'zh-cn': `名称只能是汉字、大小写英文、数字,不能使用特殊字符`, en: `not valid` } }; |
||||
} |
||||
|
||||
} |
||||
|
||||
function isEmptyInputValue(value: NzSafeAny): boolean { |
||||
return value == null || value.length === 0; |
||||
} |
||||
function isPassword(value: string): boolean { |
||||
return typeof value === 'string' && /^[\u4E00-\u9FA5A-Za-z0-9]+$/.test(value); |
||||
} |
@ -0,0 +1,75 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="name">名称</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="name" placeholder="请输入名称" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="user">用户名</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="user" placeholder="请输入用户名" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="password">密码</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="password" placeholder="请输入密码" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="uri">地址</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="uri" placeholder="请输入地址" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="type">类型</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-select formControlName="type" nzPlaceHolder="请选择类型"> |
||||
<nz-option [nzValue]="0" nzLabel="进出口"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="加油区"></nz-option> |
||||
<nz-option [nzValue]="2" nzLabel="卸油区"></nz-option> |
||||
<nz-option [nzValue]="3" nzLabel="便利店"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<nz-form-item> |
||||
<nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="type">序号</nz-form-label> |
||||
<nz-form-control> |
||||
<nz-select formControlName="order" nzPlaceHolder="请选择序号"> |
||||
<nz-option [nzValue]="0" nzLabel="0"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="1"></nz-option> |
||||
<nz-option [nzValue]="2" nzLabel="2"></nz-option> |
||||
<nz-option [nzValue]="3" nzLabel="3"></nz-option> |
||||
<nz-option [nzValue]="4" nzLabel="4"></nz-option> |
||||
<nz-option [nzValue]="5" nzLabel="5"></nz-option> |
||||
<nz-option [nzValue]="6" nzLabel="6"></nz-option> |
||||
<nz-option [nzValue]="7" nzLabel="7"></nz-option> |
||||
<nz-option [nzValue]="8" nzLabel="8"></nz-option> |
||||
<nz-option [nzValue]="9" nzLabel="9"></nz-option> |
||||
<nz-option [nzValue]="10" nzLabel="10"></nz-option> |
||||
<nz-option [nzValue]="11" nzLabel="11"></nz-option> |
||||
<nz-option [nzValue]="12" nzLabel="12"></nz-option> |
||||
<nz-option [nzValue]="13" nzLabel="13"></nz-option> |
||||
<nz-option [nzValue]="14" nzLabel="14"></nz-option> |
||||
<nz-option [nzValue]="15" nzLabel="15"></nz-option> |
||||
<nz-option [nzValue]="16" nzLabel="16"></nz-option> |
||||
<nz-option [nzValue]="17" nzLabel="17"></nz-option> |
||||
<nz-option [nzValue]="18" nzLabel="18"></nz-option> |
||||
<nz-option [nzValue]="19" nzLabel="19"></nz-option> |
||||
<nz-option [nzValue]="20" nzLabel="20"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,32 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { MyValidators } from '../addcamera/addcamera.component'; |
||||
|
||||
@Component({ |
||||
selector: 'app-editcamera', |
||||
templateUrl: './editcamera.component.html', |
||||
styleUrls: ['./editcamera.component.scss'] |
||||
}) |
||||
export class EditcameraComponent implements OnInit { |
||||
|
||||
@Input() data: any |
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
const { namevalidate } = MyValidators; |
||||
let datacopy = JSON.parse(JSON.stringify(this.data)) |
||||
console.log('编辑数据', datacopy) |
||||
this.validateForm = this.fb.group({ |
||||
name: [datacopy.name, [Validators.required,namevalidate]], |
||||
user: [datacopy.user, [Validators.required]], |
||||
password: [datacopy.password, [Validators.required]], |
||||
uri: [datacopy.uri, [Validators.required]], |
||||
type: [datacopy.type, [Validators.required]], |
||||
order: [datacopy.order, [Validators.required]] |
||||
}); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,66 @@
|
||||
<div class="box"> |
||||
<div class="leftbox"> |
||||
<nz-page-header class="site-page-header" (nzBack)="goback()" nzBackIcon nzSubtitle="返回上一页"></nz-page-header> |
||||
<div class="cameraList"> |
||||
<div class="title"> |
||||
<span>摄像头列表</span> |
||||
<button nz-button nzType="primary" (click)="addCamera()">新增摄像头</button> |
||||
</div> |
||||
<nz-table #basicTable [nzData]="listOfData" [nzShowPagination]="false" [nzLoading]="isLoading"> |
||||
<thead> |
||||
<tr> |
||||
<th>序号</th> |
||||
<th>名称</th> |
||||
<th>用户名</th> |
||||
<th>密码</th> |
||||
<th>地址</th> |
||||
<th>类型</th> |
||||
<th>标注情况</th> |
||||
<th>状态</th> |
||||
<th>操作</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr *ngFor="let item of basicTable.data"> |
||||
<td>{{ item.order }}</td> |
||||
<td>{{ item.name }}</td> |
||||
<td>{{ item.user }}</td> |
||||
<td>{{ item.password }}</td> |
||||
<td>{{ item.uri }}</td> |
||||
<td>{{ item.type | cameraType}}</td> |
||||
<td> |
||||
<ng-container *ngIf="item.type == 1; else elseTemplate"> |
||||
不需要标注 |
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
{{item.dimensionedPoints ? '已标注' : '未标注'}} |
||||
</ng-template> |
||||
</td> |
||||
<td>{{ item.isEnabled ? '已启用' : '已禁用'}}</td> |
||||
<td> |
||||
<span class="blue" style="margin-right: 12px;" (click)="editCamera(item)">编辑</span> |
||||
<span class="blue" style="margin-right: 12px;" [ngClass]="{'forbid': item.type == 1}" |
||||
(click)="label(item)">标注</span> |
||||
<ng-container *ngIf="item.isEnabled; else elseTemplate2"> |
||||
<span class="red" style="margin-right: 12px;" (click)="forbidden(item)">禁用</span> |
||||
</ng-container> |
||||
<ng-template #elseTemplate2> |
||||
<span class="blue" style="margin-right: 12px;color: rgb(26, 173, 26);" (click)="forbidden(item)">启用</span> |
||||
</ng-template> |
||||
<span class="red" (click)="deleteCamera(item)">删除</span> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</nz-table> |
||||
<div class="footer"> |
||||
<button nz-button nzType="primary" (click)="sourceYaml()">下发source.yaml配置</button> |
||||
</div> |
||||
<div class="footer"> |
||||
<button [disabled]="isSourceYaml === false" nz-button nzType="primary" (click)="connect()">下发算法配置</button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="rightbox"> |
||||
|
||||
</div> |
||||
</div> |
@ -0,0 +1,43 @@
|
||||
.box { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
background: #fff; |
||||
font-size: 15px; |
||||
color: black; |
||||
} |
||||
|
||||
.leftbox { |
||||
width: 100%; |
||||
height: 100%; |
||||
border-right: 1px solid #F2F2F2; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
.cameraList { |
||||
flex: 1; |
||||
padding: 0 20px; |
||||
|
||||
.title { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
margin-bottom: 12px; |
||||
} |
||||
.footer{ |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
margin: 12px 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.rightbox { |
||||
flex: 1; |
||||
box-sizing: border-box; |
||||
padding: 20px; |
||||
} |
||||
|
@ -0,0 +1,593 @@
|
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core'; |
||||
import { ActivatedRoute, Route, Router } from '@angular/router'; |
||||
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; |
||||
import { NzFormTooltipIcon } from 'ng-zorro-antd/form'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { AddcameraComponent } from './addcamera/addcamera.component'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { HttpClient, HttpErrorResponse, HttpResponse } from '@angular/common/http'; |
||||
import { EditcameraComponent } from './editcamera/editcamera.component'; |
||||
import { catchError, tap } from 'rxjs/operators'; |
||||
import { ConfigFormDataService } from 'src/app/service/configFormData.service'; |
||||
import { SendFileComponent } from './send-file/send-file.component'; |
||||
import { ImageLabel2Component } from '../image-label2/image-label2.component'; |
||||
interface Camera { |
||||
name: string; |
||||
user: string; |
||||
password: string; |
||||
uri: string; |
||||
type: number; |
||||
order: number; |
||||
dimensionedPoints: string, |
||||
isEnabled: boolean |
||||
} |
||||
|
||||
@Component({ |
||||
selector: 'app-host-config', |
||||
templateUrl: './host-config.component.html', |
||||
styleUrls: ['./host-config.component.scss'] |
||||
}) |
||||
|
||||
export class HostConfigComponent implements OnInit { |
||||
|
||||
|
||||
constructor(private router: Router, private route: ActivatedRoute, private fb: FormBuilder, private modal: NzModalService, private message: NzMessageService, private viewContainerRef: ViewContainerRef, private http: HttpClient, public configFormData: ConfigFormDataService,) { } |
||||
|
||||
hostId//主机id
|
||||
orId//加油站id
|
||||
ngOnInit(): void { |
||||
this.hostId = this.route.snapshot.queryParams.hostId |
||||
this.orId = this.route.snapshot.queryParams.orId |
||||
this.getCamera() |
||||
|
||||
this.http.get(`/api/EdgeDevices/${this.hostId}`).subscribe( |
||||
{ |
||||
next: ((data: any) => { |
||||
console.log(data) |
||||
// let isExist = data.configFiles.find((item, index, arr) => {
|
||||
// if (item.name == 'source.yaml') {
|
||||
// console.log("存在", index)
|
||||
// return item
|
||||
// }
|
||||
// })
|
||||
if (data.configFiles && data.configFiles.length != 0) { |
||||
this.isSourceYaml = true |
||||
} else { |
||||
this.isSourceYaml = false |
||||
} |
||||
}), |
||||
error: (err) => { |
||||
// this.message.create('error', '请先下发source.yaml配置');
|
||||
} |
||||
} |
||||
|
||||
|
||||
) |
||||
} |
||||
listOfData: Camera[] = []; |
||||
goback() { |
||||
history.go(-1) |
||||
} |
||||
//摄像头
|
||||
isLoading = false |
||||
getCamera() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
EdgeDeviceId: this.hostId |
||||
} |
||||
this.isLoading = true |
||||
this.http.get('/api/Cameras', { params: params }).subscribe((data: any) => { |
||||
data.items.forEach(element => { |
||||
element.dimensionedPointsObj = JSON.parse(element.dimensionedPoints) |
||||
}); |
||||
this.listOfData = data.items |
||||
this.isLoading = false |
||||
console.log('摄像头列表', data.items) |
||||
}) |
||||
} |
||||
addCamera() { |
||||
const modal = this.modal.create({ |
||||
nzTitle: '新增加油站摄像头', |
||||
nzContent: AddcameraComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 388, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise((resolve, rejects) => { |
||||
console.log('表单信息', instance.validateForm) |
||||
let body = { |
||||
name: instance.validateForm.value.name, |
||||
user: instance.validateForm.value.user, |
||||
password: instance.validateForm.value.password, |
||||
uri: instance.validateForm.value.uri, |
||||
type: instance.validateForm.value.type, |
||||
organizationId: this.orId, |
||||
edgeDeviceId: this.hostId, |
||||
// order: instance.validateForm.value.order,
|
||||
} |
||||
this.http.post('/api/Cameras', body).subscribe({ |
||||
next: data => { |
||||
resolve(data) |
||||
this.message.create('success', '创建成功!'); |
||||
this.getCamera() |
||||
this.isSourceYaml = false |
||||
return true |
||||
}, |
||||
error: (err) => { |
||||
rejects(err) |
||||
return false |
||||
} |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
editCamera(data) { |
||||
console.log(data) |
||||
const modal = this.modal.create({ |
||||
nzTitle: '编辑加油站摄像头', |
||||
nzContent: EditcameraComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 388, |
||||
nzComponentParams: { |
||||
data: data |
||||
}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise(resolve => { |
||||
console.log('表单信息', instance.validateForm) |
||||
let body = { |
||||
name: instance.validateForm.value.name, |
||||
user: instance.validateForm.value.user, |
||||
password: instance.validateForm.value.password, |
||||
uri: instance.validateForm.value.uri, |
||||
type: instance.validateForm.value.type, |
||||
organizationId: this.orId, |
||||
edgeDeviceId: this.hostId, |
||||
order: instance.validateForm.value.order, |
||||
} |
||||
this.http.put(`/api/Cameras/${data.id}`, body).subscribe(data => { |
||||
resolve(data) |
||||
this.message.create('success', '编辑成功!'); |
||||
this.getCamera() |
||||
this.isSourceYaml = false |
||||
return true |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
deleteCamera(item) { |
||||
console.log(item) |
||||
this.modal.confirm({ |
||||
nzTitle: `确定要删除${item.name}这个摄像头吗?`, |
||||
nzOkText: '确定', |
||||
nzOkType: 'default', |
||||
nzOnOk: () => { |
||||
this.http.delete(`/api/Cameras/${item.id}`).subscribe(data => { |
||||
this.message.create('success', '删除成功!'); |
||||
this.getCamera() |
||||
this.isSourceYaml = false |
||||
}) |
||||
}, |
||||
nzCancelText: '取消' |
||||
}); |
||||
} |
||||
|
||||
|
||||
isSourceYaml: boolean |
||||
|
||||
label(item) { |
||||
|
||||
this.http.get(`/api/EdgeDevices/${this.hostId}`).subscribe( |
||||
{ |
||||
next: ((data: any) => { |
||||
if (data.configFiles) { |
||||
this.isSourceYaml = true |
||||
const element = document.documentElement |
||||
if (element.requestFullscreen) { //进入全屏
|
||||
element.requestFullscreen(); |
||||
} |
||||
const modal = this.modal.create({ |
||||
nzContent: ImageLabel2Component, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 1920, |
||||
nzClosable: false, |
||||
nzFooter: null, |
||||
nzWrapClassName: 'canvasContentBox', |
||||
nzBodyStyle: { |
||||
'border-radius': '0px', |
||||
'padding': '0px', |
||||
'margin': '0px', |
||||
}, |
||||
nzComponentParams: { |
||||
data: item.id |
||||
}, |
||||
nzOnOk: async () => { |
||||
|
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
|
||||
modal.afterClose.subscribe(result => { |
||||
this.ngOnInit() |
||||
}); |
||||
//this.router.navigate(['/system/host/camera/imageLabel'], { queryParams: { id: item.id } })
|
||||
} else { |
||||
this.isSourceYaml = false |
||||
this.message.create('error', '请先下发source.yaml配置'); |
||||
} |
||||
}), |
||||
error: (err) => { |
||||
// this.message.create('error', '请先下发source.yaml配置');
|
||||
} |
||||
} |
||||
|
||||
|
||||
) |
||||
|
||||
|
||||
} |
||||
|
||||
connect() { |
||||
|
||||
// let isAllLabel = this.listOfData.find((item: any) => {
|
||||
// if (item.type != 1 && !item.dimensionedPoints) {
|
||||
// console.log('存在摄像头未标注的情况')
|
||||
// return item
|
||||
// }
|
||||
// })
|
||||
// if (isAllLabel) {
|
||||
// this.message.create('error', '存在摄像头未标注的情况');
|
||||
// return
|
||||
// }
|
||||
// let ids = []
|
||||
// this.listOfData.forEach((item: any) => {
|
||||
// ids.push(item.id)
|
||||
// })
|
||||
// this.http.get('/api/Cameras/Statuses', {
|
||||
// params: { ids: ids }
|
||||
// }).subscribe({
|
||||
// next: (data) => {
|
||||
// console.log('连接状态', data)
|
||||
|
||||
// },
|
||||
// error: (err) => {
|
||||
// console.log('连接失败', err)
|
||||
// }
|
||||
// })
|
||||
this.disposalData() |
||||
this.router.navigate(['/system/host/camera/configForm'], { queryParams: { 'hostId': this.hostId, 'orId': this.orId } }) |
||||
} |
||||
|
||||
forbidden(item) { |
||||
console.log(item) |
||||
let body = { |
||||
isEnabled: !item.isEnabled, |
||||
} |
||||
this.http.put(`/api/Cameras/${item.id}`, body).subscribe(data => { |
||||
this.message.create('success', '修改成功!'); |
||||
this.getCamera() |
||||
}) |
||||
} |
||||
sourceYaml() { |
||||
let copyListOfData = JSON.parse(JSON.stringify(this.listOfData)) |
||||
copyListOfData = copyListOfData.filter((item, i) => { |
||||
return item.isEnabled; |
||||
}) |
||||
let config4 = `video_rate: 5
|
||||
inference_buffer_second: 6 |
||||
sources:` |
||||
copyListOfData.forEach((item: any, index) => { |
||||
config4 += ` |
||||
- name: '${item.name}' |
||||
user: '${item.user}' |
||||
password: '${item.password}' |
||||
uri: '${item.uri}' |
||||
type: ${item.type} |
||||
` |
||||
}) |
||||
const modal = this.modal.create({ |
||||
nzTitle: '下发source.yaml配置', |
||||
nzContent: SendFileComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 1000, |
||||
nzBodyStyle: { |
||||
'border-radius': '0px', |
||||
'padding': '7px', |
||||
}, |
||||
nzComponentParams: { |
||||
data: config4 |
||||
}, |
||||
nzOnOk: async () => { |
||||
|
||||
await new Promise(resolve => { |
||||
console.log('表单信息', instance.validateForm) |
||||
let body = { |
||||
configFiles: [ |
||||
{ name: 'source.yaml', content: instance.datacopy } |
||||
] |
||||
} |
||||
this.http.put(`/api/EdgeDevices/${this.hostId}`, body).subscribe({ |
||||
next: (data) => { |
||||
this.message.create('success', `文件保存成功`); |
||||
resolve('成功了') |
||||
this.isSourceYaml = true |
||||
let params = { |
||||
edgeDeviceId: this.hostId, |
||||
fileName: 'source.yaml' |
||||
} |
||||
this.http.put('/api/EdgeDevices/Commands/PushFile', '', { params: params }).subscribe({ |
||||
next: (data) => { |
||||
this.message.create('success', `发送文件名成功`); |
||||
}, |
||||
error: err => { |
||||
// this.message.create('error', `发送文件名失败`);
|
||||
// reject('失败了')
|
||||
} |
||||
}) |
||||
}, |
||||
error: (err) => { |
||||
// this.message.create('error', `文件保存失败`);
|
||||
} |
||||
}) |
||||
|
||||
}) |
||||
|
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
//整理配置文件数据
|
||||
disposalData() { |
||||
|
||||
let copyListOfData = JSON.parse(JSON.stringify(this.listOfData)) |
||||
copyListOfData = copyListOfData.filter((item, i) => { |
||||
return item.isEnabled; |
||||
}) |
||||
|
||||
console.log(copyListOfData) |
||||
|
||||
let config1 = `[property]
|
||||
enable=1 |
||||
#Width height used for configuration to which below configs are configured |
||||
config-width=1980 |
||||
config-height=1080 |
||||
#osd-mode 0: Dont display any lines, rois and text |
||||
# 1: Display only lines, rois and static text i.e. labels |
||||
# 2: Display all info from 1 plus information about counts |
||||
osd-mode=2 |
||||
#Set OSD font size that has to be displayed |
||||
display-font-size=12 |
||||
` |
||||
let config2 = '' |
||||
let config3 = `test_action: true
|
||||
logging_interval : 600 |
||||
` |
||||
let xieyouqu = [] |
||||
let order |
||||
copyListOfData.forEach((item: any, index) => { |
||||
if (item.type == 2) { |
||||
xieyouqu.push(item) |
||||
order = item.order |
||||
} |
||||
|
||||
if (item.type == 0 && item.dimensionedPointsObj && item.dimensionedPointsObj.polygon.length != 0) { |
||||
let str = '' |
||||
item.dimensionedPointsObj ? item.dimensionedPointsObj.polygon.forEach(element => { |
||||
str += element.x + ';' |
||||
str += element.y + ';' |
||||
}) : 0; |
||||
str = str.substring(0, str.lastIndexOf(';')) |
||||
console.log('进出口多边形', str) |
||||
config1 += ` |
||||
## Per stream configuration |
||||
[roi-filtering-stream-${item.order}] |
||||
#shoushiyuan-out202 |
||||
#enable or disable following feature |
||||
enable=1 |
||||
#ROI to filter select objects, and remove from meta data |
||||
roi-RF=${str} |
||||
#remove objects in the ROI |
||||
inverse-roi=0 |
||||
class-id=-1 |
||||
` |
||||
} |
||||
if ((item.type == 2 || item.type == 3) && item.dimensionedPointsObj && item.dimensionedPointsObj.arrow.length != 0) { |
||||
let arrowArr = item.dimensionedPointsObj.arrow |
||||
let str = arrowArr[1].startX + ';' + arrowArr[1].startY + ';' + arrowArr[1].endX + ';' + arrowArr[1].endY + ';' + arrowArr[0].startX + ';' + arrowArr[0].startY + ';' + arrowArr[0].endX + ';' + arrowArr[0].endY |
||||
config1 += ` |
||||
[line-crossing-stream-${item.order}] |
||||
enable=1 |
||||
#Label;direction;lc |
||||
line-crossing-Entry=${str} |
||||
# line-crossing-Exit=789;672;1084;900;851;773;1203;732 |
||||
class-id=0 |
||||
#extended when 0- only counts crossing on the configured Line |
||||
# 1- assumes extended Line crossing counts all the crossing |
||||
extended=0 |
||||
#LC modes supported: |
||||
#loose : counts all crossing without strong adherence to direction |
||||
#balanced: Strict direction adherence expected compared to mode=loose |
||||
#strict : Strict direction adherence expected compared to mode=balanced |
||||
mode=strict |
||||
` |
||||
} |
||||
}) |
||||
//新增东南西北参数
|
||||
copyListOfData.forEach(element => { |
||||
if (element.type == 2 || element.type == 3) {//卸油区
|
||||
let obj = element.dimensionedPointsObj |
||||
let str1 = '' |
||||
if (obj && obj.arrow && obj.arrow.length == 2) { |
||||
str1 = `${obj.arrow[1].startX};${obj.arrow[1].startY};${obj.arrow[1].endX};${obj.arrow[1].endY}` |
||||
} |
||||
let str2 = '' |
||||
if (obj && obj.arrowOfWest && obj.arrowOfWest.length == 2) { |
||||
str2 = `${obj.arrowOfWest[1].startX};${obj.arrowOfWest[1].startY};${obj.arrowOfWest[1].endX};${obj.arrowOfWest[1].endY}` |
||||
} |
||||
if (str1 || str2) { |
||||
let arr = [ |
||||
{ name: 'South', value: str1 }, |
||||
{ name: 'West', value: str2 } |
||||
] |
||||
let newstr = '' |
||||
arr.forEach(item => { |
||||
if (item.value) { |
||||
newstr += `direction-${item.name}=${item.value} |
||||
` |
||||
} |
||||
}); |
||||
config1 += ` |
||||
[direction-detection-stream-${element.order}] |
||||
enable=1 |
||||
#Label;direction; |
||||
${newstr}class-id=0 |
||||
` |
||||
} |
||||
} |
||||
|
||||
}); |
||||
let xieyouguan = ''; |
||||
let jingdian = ''; |
||||
if (xieyouqu.length != 0 && xieyouqu[0].dimensionedPointsObj && xieyouqu[0].dimensionedPointsObj.rectangle.length != 0) { |
||||
xieyouqu[0].dimensionedPointsObj.rectangle.forEach(element => { |
||||
if (element.oilUnloadingArea) { |
||||
xieyouguan = element.x + ',' + element.y + ',' + element.width + ',' + element.height |
||||
} else { |
||||
jingdian = element.x + ',' + element.y + ',' + element.width + ',' + element.height |
||||
} |
||||
}) |
||||
} else { |
||||
xieyouguan = '0,0,0,0' |
||||
jingdian = '0,0,0,0' |
||||
} |
||||
|
||||
(order != undefined) ? null : order = copyListOfData[copyListOfData.length - 1].order + 1 |
||||
console.log('泄油管区域', xieyouguan) |
||||
console.log('静电接地', jingdian) |
||||
config2 = `# The all in one config file.
|
||||
# RTSP sources |
||||
# type |
||||
# 0 ViolateArea.ENTRANCE, |
||||
# 1 ViolateArea.GAS_AREA, |
||||
# 2 ViolateArea.FUEL_AREA, |
||||
# 3 ViolateArea.MART, |
||||
# don't change the key name. |
||||
|
||||
debug: false #when the debug is on, osd. |
||||
video_record: 3 #time to record into the .ts video |
||||
|
||||
sources: |
||||
config: 'config/source.yaml' |
||||
|
||||
tracker: |
||||
config: 'config/dstest_tracker_config.txt' |
||||
|
||||
analytics: |
||||
config: 'config/config_nvdsanalytics.txt' |
||||
|
||||
peoplenet: |
||||
enable: true |
||||
apply_on: -1 |
||||
interval: 1 |
||||
batch_size: 16 |
||||
topk: 5 |
||||
roi-top-offset: 0 |
||||
roi-bottom-offset: 0 |
||||
detected-min-w: 20
|
||||
detected-min-h: 200 |
||||
|
||||
trafficcam: |
||||
enable: true |
||||
apply_on: 0 |
||||
interval: 1 |
||||
batch_size: 16 |
||||
topk: 5 |
||||
roi-top-offset: 0 |
||||
roi-bottom-offset: 0 |
||||
detected-min-w: 100
|
||||
detected-min-h: 100 |
||||
|
||||
actionnet: |
||||
enable: false |
||||
apply_on: 1 |
||||
# roi: |
||||
# - 'fuel_island-4': |
||||
# - [200, 0, 450, 500] |
||||
# - 'fuel_island-5': |
||||
# - [930, 93, 940, 987] |
||||
# - 'fuel_island-6': |
||||
# - [1174, 151, 746, 929] |
||||
# - 'fuel_island-7': |
||||
# - [1450, 300, 460, 650] |
||||
interval: 1 |
||||
batch_size: 32 |
||||
|
||||
idnet: |
||||
enable: true |
||||
apply_on: -1 |
||||
interval: 1 |
||||
batch_size: 32 |
||||
|
||||
oilnet: |
||||
enable: true |
||||
apply_on: 2 |
||||
interval: 1 |
||||
batch_size: 16
|
||||
roi-top-offset: 0 |
||||
roi-bottom-offset: 0 |
||||
detected-min-w: 20
|
||||
detected-min-h: 20 |
||||
|
||||
fire_smoke_net: |
||||
enable: true |
||||
apply_on: -1 |
||||
interval: 1 |
||||
batch_size: 16 |
||||
|
||||
smoking_calling_net: |
||||
enable: true |
||||
apply_on: -1 |
||||
interval: 1 |
||||
batch_size: 32 |
||||
|
||||
connet: |
||||
enable: true |
||||
apply_on: 2 |
||||
roi: |
||||
- 'oil_tube-${order}': |
||||
- [${xieyouguan}] |
||||
- 'grounder-${order}': |
||||
- [${jingdian}] |
||||
interval: 1 |
||||
batch_size: 2 |
||||
|
||||
#new field for rule threshold |
||||
rule_threshold: |
||||
object_occurence_interval_second: 3 |
||||
object_disappear_interval_second: 10 |
||||
on_car_parking_interval_second: 1800 |
||||
on_fire_smoke_interval_second: 5 |
||||
threshold_relying_sitting: 0.4 #rolling mean confidence |
||||
threshold_smoking_calling: 0.3 #rolling mean confidence |
||||
threshold_connecting: 0.667 #rolling mean confidence |
||||
threshold_identity: 0.5 #only to filter out people net error |
||||
` |
||||
|
||||
sessionStorage.setItem('config1', config1) |
||||
sessionStorage.setItem('config2', config2) |
||||
sessionStorage.setItem('config3', config3) |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
<div class="box"> |
||||
<div class="content"> |
||||
<textarea name="config" id="config" [(ngModel)]="datacopy"></textarea> |
||||
</div> |
||||
</div> |
@ -0,0 +1,20 @@
|
||||
.box { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #fff; |
||||
font-size: 15px; |
||||
color: black; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
flex-direction: column; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.content { |
||||
flex: 1; |
||||
box-sizing: border-box; |
||||
textarea { |
||||
width: 100%; |
||||
height: 400px; |
||||
} |
||||
} |
@ -0,0 +1,23 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
@Component({ |
||||
selector: 'app-send-file', |
||||
templateUrl: './send-file.component.html', |
||||
styleUrls: ['./send-file.component.scss'] |
||||
}) |
||||
export class SendFileComponent implements OnInit { |
||||
|
||||
@Input() data: any |
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
datacopy |
||||
ngOnInit(): void { |
||||
this.datacopy = JSON.parse(JSON.stringify(this.data)) |
||||
console.log(this.datacopy) |
||||
} |
||||
putConfig() { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
<div class="box" id="canvasBox"> |
||||
<div class="btnbox"> |
||||
<button nz-button [ngClass]="{selectBtn: markType}" (click)="markType = true;">标注监控区域</button> |
||||
<button nz-button [ngClass]="{selectBtn: !markType}" (click)="markType = false;">标注禁止区域</button> |
||||
<button nz-button nzType="primary" nzDanger (click)="clearCanvas()">清空</button> |
||||
</div> |
||||
<div class="imgbox" [style]="heightCount()"> |
||||
<div class="content"> |
||||
<div class="center" id="canvasCenter"><canvas id="canvas" [width]="canvasWidth" [height]="canvasHeight"></canvas></div> |
||||
</div> |
||||
</div> |
||||
</div> |
@ -0,0 +1,26 @@
|
||||
.box { |
||||
width: 100%; |
||||
height: 100%; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.btnbox { |
||||
margin-bottom: 5px; |
||||
button { |
||||
margin-right: 15px; |
||||
} |
||||
} |
||||
.selectBtn { background-color: #1890ff; color: #fff; } |
||||
|
||||
.imgbox { |
||||
width: 100%; |
||||
height:500px; |
||||
overflow: hidden; |
||||
canvas{ overflow: hidden; } |
||||
.content,.center{ |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; |
||||
} |
||||
} |
@ -0,0 +1,216 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
|
||||
@Component({ |
||||
selector: 'app-image-label', |
||||
templateUrl: './image-label.component.html', |
||||
styleUrls: ['./image-label.component.scss'] |
||||
}) |
||||
export class ImageLabelComponent implements OnInit { |
||||
|
||||
constructor() { } |
||||
|
||||
imgItem: any; |
||||
canvasWidth: number = 0; |
||||
canvasHeight: number = 0; |
||||
copyCanvas: any; |
||||
markType: boolean = true; //标注type
|
||||
|
||||
ngOnInit(): void { |
||||
|
||||
} |
||||
|
||||
ngAfterContentInit(): void { |
||||
this.initBackgroundImg() |
||||
} |
||||
|
||||
//初始化背景图
|
||||
initBackgroundImg() { |
||||
let canvas = document.getElementById('canvas') as any; |
||||
canvas.oncontextmenu = () =>{ return false; }; |
||||
let that = this |
||||
let ctx |
||||
// 检测canvas支持性
|
||||
if (canvas.getContext) { |
||||
ctx = canvas.getContext('2d'); // 返回一个对象,该对象提供了用在画布上绘图的方法和属性
|
||||
} else { |
||||
document.write("你的浏览器不支持canvas,请升级你的浏览器!"); |
||||
return; |
||||
} |
||||
|
||||
// 读取可视区域 宽高
|
||||
let center = (document.getElementById('canvasCenter') as any).getBoundingClientRect(); |
||||
|
||||
// 图片加载完后,将其显示在canvas中
|
||||
var img = new Image(); |
||||
img.src = that.imgItem.url? that.imgItem.url : "../../../assets/images/bgImg.png"; |
||||
img.onload = () => { |
||||
// 等比例缩放图片
|
||||
var scale = 1; |
||||
if (img.width > center.width || img.height > center.height) { |
||||
if (img.width > img.height) { |
||||
scale = center.width / img.width; |
||||
}else { |
||||
scale = center.height / img.height; |
||||
} |
||||
} |
||||
that.canvasWidth = img.width * scale; |
||||
that.canvasHeight = img.height * scale; // 计算等比缩小后图片
|
||||
window.setTimeout(()=>{ // 加载图片
|
||||
ctx.drawImage(img, 0, 0, that.canvasWidth, that.canvasHeight); |
||||
this.copyCanvas = ctx.getImageData(0, 0, that.canvasWidth, that.canvasHeight) |
||||
that.initCanvasEvent(canvas) |
||||
}, 0) |
||||
} |
||||
} |
||||
|
||||
//线段的点的集合
|
||||
points = []; |
||||
points2 = []; |
||||
//可拖动圆圈的点的集合
|
||||
circles = []; |
||||
circles2 = []; |
||||
//整体移动点位
|
||||
allpoints = []; |
||||
allpoints2 = []; |
||||
isDragging = false |
||||
//是否在绘制区域内
|
||||
isInOut = false |
||||
//记录鼠标点击位置
|
||||
downx = 0 |
||||
downy = 0 |
||||
|
||||
//清空画布
|
||||
clearCanvas() { |
||||
this.points = []; |
||||
this.points2 = []; |
||||
this.circles = []; |
||||
this.circles2 = []; |
||||
this.allpoints = []; |
||||
this.allpoints2 = []; |
||||
let canvas = document.getElementById('canvas') as any; |
||||
let context = canvas.getContext('2d'); |
||||
context.clearRect(0, 0, canvas.width, canvas.height); |
||||
|
||||
this.copyCanvas?context.putImageData(this.copyCanvas, 0, 0) : null; |
||||
} |
||||
|
||||
//初始化 canvas画布 点击事件
|
||||
initCanvasEvent(canvas) { |
||||
let context = canvas.getContext('2d'); |
||||
let html = document.documentElement |
||||
let boxDiv = document.getElementsByClassName("canvasDialog")[0] |
||||
canvas.onmousedown = (e)=>{ |
||||
var clickX = e.pageX - canvas.offsetLeft - ((html.clientWidth - boxDiv.clientWidth) / 2); |
||||
var clickY = e.pageY - canvas.offsetTop - ((html.clientHeight - boxDiv.clientHeight) / 2); |
||||
this.downx = clickX |
||||
this.downy = clickY |
||||
if (this.isInt(clickX, clickY)) { |
||||
this.isInOut = true |
||||
return |
||||
} else { |
||||
this.isInOut = false |
||||
} |
||||
|
||||
let index |
||||
let beforeCircles = this.markType? this.circles: this.circles2 |
||||
//判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
|
||||
for (var i = 0; i < beforeCircles.length; i++) { |
||||
let circle = beforeCircles[i]; |
||||
//使用勾股定理计算这个点与圆心之间的距离
|
||||
var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)); |
||||
|
||||
// 如果是其他的点,则设置可以拖动
|
||||
if (distanceFromCenter <= circle.radius) { |
||||
// 清除之前选择的圆圈
|
||||
index = i; |
||||
this.isDragging = true; |
||||
//停止搜索
|
||||
return; |
||||
} |
||||
} |
||||
//如果点击新的位置,则进入下面的代码,绘制点
|
||||
//context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
//遍历数组画圆
|
||||
var circle = { |
||||
x: clickX, |
||||
y: clickY, |
||||
radius: 10, |
||||
color: "blue", |
||||
isSelected: false, //拖拽点的标记
|
||||
}; |
||||
if (this.markType) { |
||||
this.circles.push(circle); |
||||
this.allpoints = JSON.parse(JSON.stringify(this.circles)) |
||||
this.circles[0].color = "green"; |
||||
} else { |
||||
this.circles2.push(circle); |
||||
this.allpoints2 = JSON.parse(JSON.stringify(this.circles2)) |
||||
this.circles2[0].color = "red"; |
||||
} |
||||
for (var i = 0; i < beforeCircles.length; i++) { |
||||
let circle = beforeCircles[i]; |
||||
// 绘制圆圈
|
||||
context.globalAlpha = 0.85; |
||||
context.beginPath(); |
||||
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2); |
||||
context.fillStyle = circle.color; |
||||
context.strokeStyle = "black"; |
||||
context.fill(); |
||||
context.stroke(); |
||||
} |
||||
// 画线
|
||||
var point = { |
||||
x: clickX, |
||||
y: clickY, |
||||
}; |
||||
this.markType? this.points.push(point) : this.points2.push(point) |
||||
context.beginPath(); |
||||
context.lineWidth = 3; |
||||
//从起始点开始绘制
|
||||
let beforePoint = this.markType? this.points: this.points2 |
||||
context.moveTo(beforePoint[0].x, beforePoint[0].y); |
||||
for (var i = 0; i < beforePoint.length; i++) { |
||||
context.lineTo(beforePoint[i].x, beforePoint[i].y); |
||||
} |
||||
context.closePath() |
||||
context.fillStyle = "rgb(2,100,30)"; |
||||
context.fill(); |
||||
context.strokeStyle = "#9d4dca"; |
||||
context.stroke(); |
||||
} |
||||
} |
||||
|
||||
//判断点位是否在图形区域内
|
||||
isInt(x, y) { |
||||
if (this.markType && !this.points[2]) { |
||||
return |
||||
} |
||||
if (!this.markType && !this.points2[2]) { |
||||
return |
||||
} |
||||
var pt = { |
||||
x: x, |
||||
y: y |
||||
} |
||||
var poly = this.markType? this.points : this.points2; |
||||
return this.PointInPoly(pt, poly) |
||||
} |
||||
|
||||
//射线法判断点位
|
||||
PointInPoly(pt, poly) { |
||||
for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) |
||||
((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) |
||||
&& (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) |
||||
&& (c = !c); |
||||
return c; |
||||
} |
||||
|
||||
//cneter height
|
||||
heightCount() { |
||||
let style: any = {} |
||||
let height = document.documentElement.clientHeight |
||||
style.height = (height - 180) + 'px'; |
||||
return style |
||||
} |
||||
|
||||
} |
@ -0,0 +1,37 @@
|
||||
<div class="canvasBox"> |
||||
<!-- <nz-page-header class="site-page-header" (nzBack)="goback()" nzBackIcon nzSubtitle="返回上一页"></nz-page-header> --> |
||||
<div class="btnbox"> |
||||
<label class="leftTitle" *ngIf="markType === 0">进出口</label> |
||||
<label class="leftTitle" *ngIf="markType === 2">卸油区</label> |
||||
<label class="leftTitle" *ngIf="markType === 3">便利店</label> |
||||
<button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: isDrawArrow && !arrowDirection}" |
||||
(click)="isDrawArrow = true;arrowDirection=null">箭头方向标绘1</button> |
||||
<!-- <button nz-button *ngIf="markType === 2" |
||||
[ngClass]="{selectBtn:(isDrawArrow && arrowDirection=='South')}" |
||||
(click)="isDrawArrow = true;arrowDirection='South'">South</button> --> |
||||
<button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: (isDrawArrow && arrowDirection=='West')}" |
||||
(click)="isDrawArrow = true;arrowDirection='West'">箭头方向标绘2</button> |
||||
<!-- <button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: (isDrawArrow && arrowDirection=='East')}" |
||||
(click)="isDrawArrow = true;arrowDirection='East'">East</button> |
||||
<button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: (isDrawArrow && arrowDirection=='North')}" |
||||
(click)="isDrawArrow = true;arrowDirection='North'">North</button> --> |
||||
<button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: !isDrawArrow && oilUnloadingArea}" |
||||
(click)="isDrawArrow = false; oilUnloadingArea = true;">泄油管区域</button> |
||||
<button nz-button *ngIf="markType === 2" [ngClass]="{selectBtn: !isDrawArrow && !oilUnloadingArea}" |
||||
(click)="isDrawArrow = false; oilUnloadingArea = false;">静电接地仪</button> |
||||
<button nz-button nzType="primary" (click)="anewgetImg()">重新捕获摄像头图片</button> |
||||
<button nz-button nzType="primary" (click)="save()">保存</button> |
||||
<button nz-button nzType="primary" nzDanger nz-popconfirm nzPopconfirmTitle="您确定要清空吗?" |
||||
(nzOnConfirm)="clearCanvas()">清空</button> |
||||
<label *ngIf="camerasData" class="rightTitle">原始分辨率: {{camerasData.originalWeight}} × |
||||
{{camerasData.originalHeight}}</label> |
||||
|
||||
<!-- <label *ngIf="markType === 2 && !isDrawArrow" class="rightTitle">当前矩形框高度为:{{rectangleHeight}}px,请确保低于420px</label> --> |
||||
</div> |
||||
<div class="imgbox"> |
||||
<div class="content"> |
||||
<div class="center" id="canvasCenter"><canvas id="canvas" [width]="canvasWidth" [height]="canvasHeight"></canvas> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
@ -0,0 +1,38 @@
|
||||
.canvasBox { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #fff; |
||||
font-size: 15px; |
||||
color: black; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
flex-direction: column; |
||||
overflow: hidden; |
||||
.imgbox{ flex: 1; overflow: hidden; } |
||||
canvas{ overflow: hidden; display: block; } |
||||
.content,.center{ |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; |
||||
} |
||||
} |
||||
|
||||
.btnbox { |
||||
display: flex; |
||||
position: fixed; |
||||
left: 1%; |
||||
top: 1%; |
||||
z-index: 10; |
||||
button { |
||||
margin-right: 6px; |
||||
} |
||||
.leftTitle{ line-height: 32px; margin-right: 10px; color: #fff; } |
||||
.rightTitle{ line-height: 32px; margin-left: 10px; color: #fff; } |
||||
} |
||||
|
||||
.imgbox, |
||||
.btnbox { |
||||
box-sizing: border-box; |
||||
padding: 0; |
||||
} |
||||
.selectBtn { background-color: #1890ff; color: #fff; } |
@ -0,0 +1,647 @@
|
||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http'; |
||||
import { Component, Input, OnInit } from '@angular/core'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
|
||||
@Component({ |
||||
selector: 'app-image-label2', |
||||
templateUrl: './image-label2.component.html', |
||||
styleUrls: ['./image-label2.component.scss'] |
||||
}) |
||||
export class ImageLabel2Component implements OnInit { |
||||
|
||||
constructor(private http: HttpClient, private message: NzMessageService, private modal: NzModalService) { } |
||||
|
||||
@Input() data: any; //传递id
|
||||
camerasData: any; //摄像头Data
|
||||
imgItem: any; //图片 URL
|
||||
canvasWidth: number = 0; |
||||
canvasHeight: number = 0; |
||||
copyCanvas: any; //拷贝 canvas底图
|
||||
|
||||
//返回上一步路由
|
||||
goback() { |
||||
history.go(-1) |
||||
} |
||||
|
||||
ngOnInit(): void { |
||||
|
||||
} |
||||
|
||||
ngAfterContentInit(): void { |
||||
this.getImgMarkData().then((res: any) => { |
||||
this.imgItem = window.URL.createObjectURL(res) |
||||
window.setTimeout(() => { |
||||
this.initBackgroundImg() |
||||
}, 0) |
||||
}).catch(err => { |
||||
this.message.create('error', '获取图片失败!'); |
||||
}) |
||||
} |
||||
|
||||
anewgetImg() { |
||||
let params = { |
||||
cameraId: this.data |
||||
} |
||||
this.http.put('/api/Cameras/Commands/CaptureImages', '', { params: params }).subscribe( |
||||
{ |
||||
next: (value: Object) => { |
||||
this.message.create('success', '向边缘设备发送请求成功,请过一段时间手动刷新页面!'); |
||||
}, |
||||
error: (error: HttpErrorResponse) => { |
||||
|
||||
}, |
||||
complete: () => { |
||||
|
||||
} |
||||
} |
||||
) |
||||
} |
||||
|
||||
//获取 摄像头图片/标注点位
|
||||
getImgMarkData() { |
||||
let that = this |
||||
return new Promise((resolve, reject) => { |
||||
that.http.get(`/api/Cameras/${that.data}`).subscribe((info: any) => { |
||||
info.dimensionedPoints ? info.dimensionedPoints = JSON.parse(info.dimensionedPoints) : null; |
||||
that.camerasData = info; |
||||
that.markType = info.type; |
||||
console.log(that.camerasData, "摄像头数据") |
||||
const httpOptions = { |
||||
responseType: 'blob' as 'json', |
||||
params: { cameraId: that.data } |
||||
}; |
||||
that.http.get(`/api/Cameras/Images`, httpOptions).subscribe({ |
||||
next: (data) => { |
||||
resolve(data) |
||||
}, |
||||
error: (err) => { |
||||
reject('error') |
||||
}, |
||||
}) //get
|
||||
}) //get
|
||||
}) |
||||
} |
||||
|
||||
//保存
|
||||
save() { |
||||
if (!this.camerasData.dimensionedPoints) { |
||||
this.camerasData.dimensionedPoints = { |
||||
polygon: [], |
||||
arrow: [], |
||||
arrowOfSouth: [], |
||||
arrowOfWest: [], |
||||
arrowOfEast: [], |
||||
arrowOfNorth: [], |
||||
rectangle: [], |
||||
} |
||||
} |
||||
if (this.markType === 0) { |
||||
if (!this.points.length) { |
||||
this.message.create('warning', '绘制完整后可保存!'); |
||||
return |
||||
} |
||||
this.camerasData.dimensionedPoints.polygon = this.points |
||||
} else if (this.markType === 2) { |
||||
if (this.arrowPoints.length != 2 || this.oblongPoints.length != 2 || !this.oblongPoints.find(item => { return item.oilUnloadingArea }) || !this.oblongPoints.find(item => { return !item.oilUnloadingArea })) { |
||||
this.message.create('warning', '绘制完整后可保存!'); |
||||
return |
||||
} |
||||
this.camerasData.dimensionedPoints.arrow = this.arrowPoints |
||||
|
||||
this.camerasData.dimensionedPoints.arrowOfSouth = this.arrowPointsOfSouth |
||||
this.camerasData.dimensionedPoints.arrowOfWest = this.arrowPointsOfWest |
||||
this.camerasData.dimensionedPoints.arrowOfEast = this.arrowPointsOfEast |
||||
this.camerasData.dimensionedPoints.arrowOfNorth = this.arrowPointsOfNorth |
||||
|
||||
this.camerasData.dimensionedPoints.rectangle = this.oblongPoints |
||||
} else if (this.markType === 3) { |
||||
if (this.arrowPoints.length != 2) { |
||||
this.message.create('warning', '绘制完整后可保存!'); |
||||
return |
||||
} |
||||
this.camerasData.dimensionedPoints.arrow = this.arrowPoints |
||||
this.camerasData.dimensionedPoints.arrowOfSouth = this.arrowPointsOfSouth |
||||
} |
||||
let paramsData = JSON.parse(JSON.stringify(this.camerasData)) |
||||
paramsData.dimensionedPoints = JSON.stringify(paramsData.dimensionedPoints) |
||||
console.log('标点结果', this.camerasData.dimensionedPoints) |
||||
this.http.put(`/api/Cameras/${this.camerasData.id}/DimensionedPoints`, paramsData).subscribe(data => { |
||||
this.message.create('success', '保存成功!'); |
||||
const isFullScreen = document.fullscreenElement |
||||
if (document.exitFullscreen && isFullScreen) { //关闭全屏
|
||||
document.exitFullscreen() |
||||
} |
||||
this.modal.closeAll(); |
||||
}) |
||||
} |
||||
|
||||
//初始化背景图
|
||||
initBackgroundImg() { |
||||
let canvas = document.getElementById('canvas') as any; |
||||
canvas.oncontextmenu = () => { return false; }; |
||||
let that = this |
||||
let ctx |
||||
// 检测canvas支持性
|
||||
if (canvas.getContext) { |
||||
ctx = canvas.getContext('2d'); // 返回一个对象,该对象提供了用在画布上绘图的方法和属性
|
||||
} else { |
||||
document.write("你的浏览器不支持canvas,请升级你的浏览器!"); |
||||
return; |
||||
} |
||||
|
||||
// 读取可视区域 宽高
|
||||
let center = document.getElementById('canvasCenter') as any; |
||||
|
||||
// 图片加载完后,将其显示在canvas中
|
||||
var img = new Image(); |
||||
img.src = that.imgItem ? that.imgItem : "../../../assets/images/bgImg.png"; |
||||
img.onload = () => { |
||||
// 等比例缩放图片
|
||||
// var scale = 1;
|
||||
// if (img.width > center.clientWidth || img.height > center.clientHeight) {
|
||||
// let scaleOne = center.clientWidth / img.width;
|
||||
// let scaleTwo = center.clientHeight / img.height;
|
||||
// if (img.width * scaleOne <= center.clientWidth && img.height * scaleOne <= center.clientHeight) {
|
||||
// scale = scaleOne;
|
||||
// } else if (img.width * scaleTwo <= center.clientWidth && img.height * scaleTwo <= center.clientHeight) {
|
||||
// scale = scaleTwo;
|
||||
// } else {
|
||||
// scale = 0.3;
|
||||
// }
|
||||
// }
|
||||
// that.canvasWidth = img.width * scale;
|
||||
// that.canvasHeight = img.height * scale; // 计算等比缩小后图片
|
||||
that.canvasWidth = img.width; |
||||
that.canvasHeight = img.height; |
||||
console.log(img.width + "*" + img.height) |
||||
window.setTimeout(() => { // 加载图片
|
||||
ctx.drawImage(img, 0, 0, that.canvasWidth, that.canvasHeight); |
||||
this.copyCanvas = ctx.getImageData(0, 0, that.canvasWidth, that.canvasHeight) |
||||
that.initCanvasEvent(canvas) //监听canvas事件
|
||||
that.initMark(canvas, ctx) //初始化标绘图形
|
||||
}, 0) |
||||
} |
||||
} |
||||
|
||||
//初始化标绘图形
|
||||
initMark(canvas, context) { |
||||
if (!this.camerasData.dimensionedPoints) { |
||||
return |
||||
} |
||||
if (this.markType === 0) { |
||||
this.camerasData.dimensionedPoints.polygon.forEach(element => { |
||||
this.drawPolygon(element.x, element.y, canvas, context); //绘制多边形
|
||||
}); |
||||
} else if (this.markType === 2) { |
||||
this.arrowPoints = this.camerasData.dimensionedPoints.arrow |
||||
if (this.camerasData.dimensionedPoints.arrowOfSouth && this.camerasData.dimensionedPoints.arrowOfSouth.length != 0) { |
||||
this.arrowPointsOfSouth = this.camerasData.dimensionedPoints.arrowOfSouth |
||||
} |
||||
if (this.camerasData.dimensionedPoints.arrowOfWest && this.camerasData.dimensionedPoints.arrowOfWest.length != 0) { |
||||
this.arrowPointsOfWest = this.camerasData.dimensionedPoints.arrowOfWest |
||||
} |
||||
if (this.camerasData.dimensionedPoints.arrowOfEast && this.camerasData.dimensionedPoints.arrowOfEast.length != 0) { |
||||
this.arrowPointsOfEast = this.camerasData.dimensionedPoints.arrowOfEast |
||||
} |
||||
if (this.camerasData.dimensionedPoints.arrowOfNorth && this.camerasData.dimensionedPoints.arrowOfNorth.length != 0) { |
||||
this.arrowPointsOfNorth = this.camerasData.dimensionedPoints.arrowOfNorth |
||||
} |
||||
this.oblongPoints = this.camerasData.dimensionedPoints.rectangle |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else if (this.markType === 3) { |
||||
this.arrowPoints = this.camerasData.dimensionedPoints.arrow |
||||
if (this.camerasData.dimensionedPoints.arrowOfSouth && this.camerasData.dimensionedPoints.arrowOfSouth.length != 0) { |
||||
this.arrowPointsOfSouth = this.camerasData.dimensionedPoints.arrowOfSouth |
||||
} |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth] |
||||
this.drawLine(arr, context) |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
markType: number = 0; //0=进出口,2=卸油区,3=便利店,
|
||||
isDrawArrow: boolean = true; //绘制type 箭头/矩形
|
||||
arrowDirection = null |
||||
oilUnloadingArea: boolean = true; //卸油区type 泄油管区域/静电接地仪
|
||||
//记录鼠标点击位置
|
||||
downx = 0; |
||||
downy = 0; |
||||
|
||||
//清空画布
|
||||
clearCanvas() { |
||||
// 清空标绘箭头
|
||||
this.arrowPoints = []; |
||||
this.arrowPointsOfSouth = []; //南 箭头的点的集合
|
||||
this.arrowPointsOfWest = []; //西 箭头的点的集合
|
||||
this.arrowPointsOfEast = []; //东 箭头的点的集合
|
||||
this.arrowPointsOfNorth = []; //北 箭头的点的集合
|
||||
// 清空标绘箭头
|
||||
// 清空标绘矩形
|
||||
this.oblongPoints = []; |
||||
// 清空标绘矩形
|
||||
// 清空标绘多边形
|
||||
this.points = []; |
||||
this.circles = []; |
||||
this.allpoints = []; |
||||
// 清空标绘多边形
|
||||
let canvas = document.getElementById('canvas') as any; |
||||
let context = canvas.getContext('2d'); |
||||
|
||||
context.clearRect(0, 0, canvas.width, canvas.height); |
||||
this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null; |
||||
} |
||||
|
||||
//初始化 canvas画布 监听事件
|
||||
|
||||
initCanvasEvent(canvas) { |
||||
let context = canvas.getContext('2d'); |
||||
canvas.onmousedown = (e) => { //鼠标按下事件
|
||||
var clickX = e.pageX - canvas.offsetLeft; |
||||
var clickY = e.pageY - canvas.offsetTop; |
||||
this.downx = clickX |
||||
this.downy = clickY |
||||
|
||||
if (this.markType === 0) { //进出口
|
||||
this.drawPolygon(clickX, clickY, canvas, context); //绘制多边形
|
||||
} else if (this.markType === 2 || this.markType === 3) { //卸油区/便利店
|
||||
//开始绘制
|
||||
context.beginPath(); |
||||
context.moveTo(clickX, clickY); |
||||
context.strokeStyle = "green"; |
||||
context.lineWidth = 3; |
||||
canvas.onmousemove = (ev) => { //鼠标移动事件
|
||||
var moveX = ev.pageX - canvas.offsetLeft; |
||||
var moveY = ev.pageY - canvas.offsetTop; |
||||
if (this.isDrawArrow && !this.arrowDirection) { //绘制 箭头
|
||||
if (this.arrowPoints.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
context.lineTo(moveX, moveY); |
||||
context.stroke(); |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'South') { |
||||
if (this.arrowPointsOfSouth.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
context.lineTo(moveX, moveY); |
||||
context.stroke(); |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'West') { |
||||
if (this.arrowPointsOfWest.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
context.lineTo(moveX, moveY); |
||||
context.stroke(); |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'East') { |
||||
if (this.arrowPointsOfEast.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
context.lineTo(moveX, moveY); |
||||
context.stroke(); |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'North') { |
||||
if (this.arrowPointsOfNorth.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
context.lineTo(moveX, moveY); |
||||
context.stroke(); |
||||
} else { //绘制 矩形
|
||||
if (this.oblongPoints.length === 2) { //限制数量
|
||||
return |
||||
} |
||||
this.drawOblong(this.oblongPoints, context) |
||||
context.strokeStyle = this.oilUnloadingArea ? "green" : "red"; |
||||
let element = this.getOblongInfo(this.downx, this.downy, moveX, moveY) |
||||
context.strokeRect(element.x, element.y, element.width, element.height); |
||||
context.font = '22px Arial'; |
||||
context.fillText('高度:' + element.height, element.x + 3, element.y + 22); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
canvas.onmouseup = (e) => { //鼠标松开事件
|
||||
canvas.onmousemove = (ev) => { //鼠标移动事件
|
||||
return false; |
||||
} |
||||
if (this.markType != 2 && this.markType != 3) { |
||||
return |
||||
} |
||||
var upX = e.pageX - canvas.offsetLeft; |
||||
var upY = e.pageY - canvas.offsetTop; |
||||
if (this.isDrawArrow && !this.arrowDirection) { //绘制 箭头
|
||||
if (this.arrowPoints.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = { |
||||
startX: this.downx, |
||||
startY: this.downy, |
||||
endX: upX, |
||||
endY: upY, |
||||
} |
||||
this.arrowPoints.push(point); |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'South') { |
||||
if (this.arrowPointsOfSouth.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = { |
||||
startX: this.downx, |
||||
startY: this.downy, |
||||
endX: upX, |
||||
endY: upY, |
||||
} |
||||
this.arrowPointsOfSouth.push(point); |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'West') { |
||||
if (this.arrowPointsOfWest.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = { |
||||
startX: this.downx, |
||||
startY: this.downy, |
||||
endX: upX, |
||||
endY: upY, |
||||
} |
||||
this.arrowPointsOfWest.push(point); |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'East') { |
||||
console.log('East') |
||||
if (this.arrowPointsOfEast.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = { |
||||
startX: this.downx, |
||||
startY: this.downy, |
||||
endX: upX, |
||||
endY: upY, |
||||
} |
||||
this.arrowPointsOfEast.push(point); |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else if (this.isDrawArrow && this.arrowDirection == 'North') { |
||||
console.log('North') |
||||
if (this.arrowPointsOfNorth.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = { |
||||
startX: this.downx, |
||||
startY: this.downy, |
||||
endX: upX, |
||||
endY: upY, |
||||
} |
||||
this.arrowPointsOfNorth.push(point); |
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context) |
||||
} else { //绘制 矩形
|
||||
if (this.oblongPoints.length === 2) { //限制数量
|
||||
this.message.create('warning', '绘制数量已达上限!'); |
||||
return |
||||
} |
||||
let point = this.getOblongInfo(this.downx, this.downy, upX, upY) |
||||
this.oblongPoints.push(point) |
||||
this.drawOblong(this.oblongPoints, context) |
||||
} |
||||
}; |
||||
|
||||
} |
||||
|
||||
arrowPoints = []; //箭头的点的集合
|
||||
|
||||
arrowPointsOfSouth = []; //南 箭头的点的集合
|
||||
arrowPointsOfWest = []; //西 箭头的点的集合
|
||||
arrowPointsOfEast = []; //东 箭头的点的集合
|
||||
arrowPointsOfNorth = []; //北 箭头的点的集合
|
||||
|
||||
|
||||
|
||||
//canvas 绘制直线
|
||||
drawLine(pointsList, context, isRepeat: boolean = false) { |
||||
context.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
||||
this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null; |
||||
if (this.markType === 2 && !isRepeat) { //同时绘制 矩形
|
||||
this.oblongPoints.forEach(element => { |
||||
context.strokeStyle = element.oilUnloadingArea ? "green" : "red"; |
||||
context.lineWidth = 3; |
||||
context.strokeRect(element.x, element.y, element.width, element.height); |
||||
context.font = '22px Arial'; |
||||
context.fillText('高度:' + element.height, element.x + 3, element.y + 22); |
||||
}); |
||||
} |
||||
// console.log(789, pointsList)
|
||||
pointsList.forEach(element => { |
||||
if (element.length != 0) { |
||||
element.forEach((item, index) => { |
||||
if ((index + 1) % 2 === 0) { |
||||
this.drawArrow(item.startX, item.startY, item.endX, item.endY, 30, 10, 3, 'green', context) |
||||
} else { |
||||
context.beginPath(); |
||||
context.moveTo(item.startX, item.startY); |
||||
context.strokeStyle = "green"; |
||||
context.lineWidth = 3; |
||||
context.lineTo(item.endX, item.endY); |
||||
context.stroke(); |
||||
} |
||||
}) |
||||
} |
||||
|
||||
}); |
||||
|
||||
|
||||
} |
||||
|
||||
//canvas 绘制箭头
|
||||
drawArrow(fromX, fromY, toX, toY, theta, headlen, width, color, ctx) { |
||||
// fromX, fromY:起点坐标(也可以换成p1,只不过它是一个数组)
|
||||
// toX, toY:终点坐标 (也可以换成p2,只不过它是一个数组)
|
||||
// theta:三角斜边一直线夹角
|
||||
// headlen:三角斜边长度
|
||||
// width:箭头线宽度
|
||||
// color:箭头颜色
|
||||
|
||||
theta = typeof (theta) != 'undefined' ? theta : 30; |
||||
headlen = typeof (theta) != 'undefined' ? headlen : 10; |
||||
width = typeof (width) != 'undefined' ? width : 1; |
||||
color = typeof (color) != 'undefined' ? color : '#000'; |
||||
|
||||
// 计算各角度和对应的P2,P3坐标
|
||||
var angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI, |
||||
angle1 = (angle + theta) * Math.PI / 180, |
||||
angle2 = (angle - theta) * Math.PI / 180, |
||||
topX = headlen * Math.cos(angle1), |
||||
topY = headlen * Math.sin(angle1), |
||||
botX = headlen * Math.cos(angle2), |
||||
botY = headlen * Math.sin(angle2); |
||||
ctx.save(); |
||||
ctx.beginPath(); |
||||
|
||||
var arrowX = fromX - topX, |
||||
arrowY = fromY - topY; |
||||
|
||||
ctx.moveTo(arrowX, arrowY); |
||||
ctx.moveTo(fromX, fromY); |
||||
ctx.lineTo(toX, toY); |
||||
arrowX = toX + topX; |
||||
arrowY = toY + topY; |
||||
ctx.moveTo(arrowX, arrowY); |
||||
ctx.lineTo(toX, toY); |
||||
arrowX = toX + botX; |
||||
arrowY = toY + botY; |
||||
ctx.lineTo(arrowX, arrowY); |
||||
ctx.strokeStyle = color; |
||||
ctx.lineWidth = width; |
||||
ctx.stroke(); |
||||
ctx.restore(); |
||||
} |
||||
|
||||
oblongPoints = []; //矩形的点的集合
|
||||
|
||||
//获取 矩形左上角点位/宽高
|
||||
getOblongInfo(startX, startY, endX, endY) { |
||||
let point = { |
||||
x: 0, |
||||
y: 0, |
||||
width: 0, |
||||
height: 0, |
||||
oilUnloadingArea: this.oilUnloadingArea, |
||||
} |
||||
if (startX > endX) { |
||||
point.x = endX |
||||
point.width = startX - endX |
||||
} else { |
||||
point.x = startX |
||||
point.width = endX - startX |
||||
} |
||||
if (startY > endY) { |
||||
point.y = endY |
||||
point.height = startY - endY |
||||
} else { |
||||
point.y = startY |
||||
point.height = endY - startY |
||||
} |
||||
return point |
||||
} |
||||
|
||||
//canvas 绘制矩形
|
||||
drawOblong(oblongList, context) { |
||||
context.clearRect(0, 0, this.canvasWidth, this.canvasHeight); |
||||
this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null; |
||||
if (this.markType === 2) { //同时绘制 直线箭头
|
||||
let arr = [this.arrowPoints, this.arrowPointsOfSouth, this.arrowPointsOfWest, this.arrowPointsOfEast, this.arrowPointsOfNorth] |
||||
this.drawLine(arr, context, true) |
||||
} |
||||
oblongList.forEach(element => { |
||||
context.strokeStyle = element.oilUnloadingArea ? "green" : "red"; |
||||
context.lineWidth = 3; |
||||
context.strokeRect(element.x, element.y, element.width, element.height); |
||||
context.font = '22px Arial'; |
||||
context.fillText('高度:' + element.height, element.x + 3, element.y + 22); |
||||
}); |
||||
} |
||||
|
||||
points = []; //线段的点的集合
|
||||
circles = []; //可拖动圆圈的点的集合
|
||||
allpoints = []; //整体移动点位
|
||||
isDragging = false; //是否可拖拽
|
||||
isInOut = false; //是否在绘制区域内
|
||||
|
||||
//canvas 绘制多边形
|
||||
drawPolygon(clickX, clickY, canvas, context) { |
||||
if (this.isInt(clickX, clickY)) { |
||||
this.isInOut = true |
||||
return |
||||
} else { |
||||
this.isInOut = false |
||||
} |
||||
|
||||
let index |
||||
//判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
|
||||
for (var i = 0; i < this.circles.length; i++) { |
||||
let circle = this.circles[i]; |
||||
//使用勾股定理计算这个点与圆心之间的距离
|
||||
var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)); |
||||
|
||||
// 如果是其他的点,则设置可以拖动
|
||||
if (distanceFromCenter <= circle.radius) { |
||||
// 清除之前选择的圆圈
|
||||
index = i; |
||||
this.isDragging = true; |
||||
//停止搜索
|
||||
return; |
||||
} |
||||
} |
||||
//如果点击新的位置,则进入下面的代码,绘制点
|
||||
context.clearRect(0, 0, canvas.width, canvas.height); |
||||
this.copyCanvas ? context.putImageData(this.copyCanvas, 0, 0) : null; |
||||
//遍历数组画圆
|
||||
var circle = { |
||||
x: clickX, |
||||
y: clickY, |
||||
radius: 5, |
||||
color: "white", |
||||
isSelected: false, //拖拽点的标记
|
||||
}; |
||||
this.circles.push(circle); |
||||
this.allpoints = JSON.parse(JSON.stringify(this.circles)) |
||||
this.circles[0].color = "white"; |
||||
for (var i = 0; i < this.circles.length; i++) { |
||||
let circle = this.circles[i]; |
||||
// 绘制圆圈
|
||||
context.globalAlpha = 0.85; |
||||
context.beginPath(); |
||||
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2); |
||||
context.fillStyle = circle.color; |
||||
context.strokeStyle = "red"; |
||||
context.fill(); |
||||
context.stroke(); |
||||
} |
||||
// 画线
|
||||
var point = { |
||||
x: clickX, |
||||
y: clickY, |
||||
}; |
||||
this.points.push(point) |
||||
context.beginPath(); |
||||
context.lineWidth = 3; |
||||
//从起始点开始绘制
|
||||
context.moveTo(this.points[0].x, this.points[0].y); |
||||
for (var i = 0; i < this.points.length; i++) { |
||||
context.lineTo(this.points[i].x, this.points[i].y); |
||||
} |
||||
context.closePath() |
||||
//ontext.fillStyle = "rgb(2,100,30)";
|
||||
//context.fill();
|
||||
context.strokeStyle = "green"; |
||||
context.stroke(); |
||||
} |
||||
|
||||
//判断点位是否在图形区域内
|
||||
isInt(x, y) { |
||||
if (!this.points[2]) { |
||||
return |
||||
} |
||||
var pt = { |
||||
x: x, |
||||
y: y |
||||
} |
||||
return this.PointInPoly(pt, this.points) |
||||
} |
||||
|
||||
//射线法判断点位
|
||||
PointInPoly(pt, poly) { |
||||
for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) |
||||
((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) |
||||
&& (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) |
||||
&& (c = !c); |
||||
return c; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,19 @@
|
||||
<div class="box"> |
||||
<nz-page-header class="site-page-header" (nzBack)="goback()" nzBackIcon nzSubtitle="返回上一页"></nz-page-header> |
||||
<div class="imgbox"> |
||||
<div class="imageItemBox" *ngFor="let item of imgList"> |
||||
<div class="imgbox"> |
||||
<img [src]="item.url" alt="" (click)="label(item)"> |
||||
</div> |
||||
<div class="coord"> |
||||
监控坐标点:<span>{{item.showCoord}}</span> |
||||
</div> |
||||
<div class="coord"> |
||||
禁止坐标点:<span>{{item.banCoord}}</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div class="footer"> |
||||
<button nz-button nzType="primary">提交</button> |
||||
</div> |
||||
</div> |
@ -0,0 +1,48 @@
|
||||
.box { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: #fff; |
||||
font-size: 15px; |
||||
color: black; |
||||
box-sizing: border-box; |
||||
display: flex; |
||||
flex-direction: column; |
||||
overflow-y: auto; |
||||
} |
||||
|
||||
.imgbox { |
||||
display: flex; |
||||
flex-wrap: wrap; |
||||
align-content: flex-start; |
||||
} |
||||
|
||||
.imageItemBox { |
||||
display: flex; |
||||
flex-direction: column; |
||||
width: 220px; |
||||
border: 1px solid #F2F2F2; |
||||
margin: 6px; |
||||
|
||||
.imgbox { |
||||
width: 100%; |
||||
height: 250px; |
||||
|
||||
img { |
||||
display: block; |
||||
width: 100%; |
||||
height: 100%; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
|
||||
.coord { |
||||
height: 25px; |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
} |
||||
.footer{ |
||||
margin: 6px 0; |
||||
display: flex; |
||||
justify-content: center; |
||||
} |
@ -0,0 +1,50 @@
|
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { ImageLabelComponent } from '../image-label/image-label.component'; |
||||
|
||||
@Component({ |
||||
selector: 'app-image-list', |
||||
templateUrl: './image-list.component.html', |
||||
styleUrls: ['./image-list.component.scss'] |
||||
}) |
||||
export class ImageListComponent implements OnInit { |
||||
|
||||
constructor(private modal: NzModalService, private viewContainerRef: ViewContainerRef) { } |
||||
imgList = [ |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/bgImg.png', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' }, |
||||
{ url: '../../../assets/images/test/dog.jpg', showCoord: '', banCoord: '' } |
||||
] |
||||
ngOnInit(): void { |
||||
} |
||||
goback() { |
||||
history.go(-1) |
||||
} |
||||
label(item) { |
||||
let width = document.documentElement.clientWidth |
||||
const modal = this.modal.create({ |
||||
nzContent: ImageLabelComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzComponentParams: { |
||||
imgItem: item, |
||||
}, |
||||
nzClassName: "canvasDialog", |
||||
nzWidth: width - 100, |
||||
nzCentered: true, |
||||
nzOnOk: () => new Promise(resolve => { |
||||
item.showCoord = '' |
||||
item.banCoord = '' |
||||
resolve(1) |
||||
}), |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
modal.afterOpen.subscribe(() => console.log('[afterOpen] emitted!')); |
||||
// Return a result when closed
|
||||
modal.afterClose.subscribe(result => console.log('[afterClose] The result is:', result)); |
||||
} |
||||
} |
@ -0,0 +1 @@
|
||||
<p>kafka works!</p> |
@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
|
||||
@Component({ |
||||
selector: 'app-kafka', |
||||
templateUrl: './kafka.component.html', |
||||
styleUrls: ['./kafka.component.scss'] |
||||
}) |
||||
export class KafkaComponent implements OnInit { |
||||
|
||||
constructor() { } |
||||
|
||||
ngOnInit(): void { |
||||
} |
||||
|
||||
} |
@ -0,0 +1,47 @@
|
||||
<!-- <p>系统管理页面</p> --> |
||||
<nz-layout> |
||||
<nz-sider [nzWidth]='300'> |
||||
<div class="logo"> |
||||
<img style="width: 154px;" src="../../../assets/images/logo2.png" alt=""> |
||||
</div> |
||||
<div class="headPortrait"> |
||||
<div class="photograph"> |
||||
<img src="../../../assets/images/userbig.png" alt=""> |
||||
</div> |
||||
<span>Administrator</span> |
||||
<span><img src="../../../assets/images/icon/admin.png" alt=""> 管理员</span> |
||||
</div> |
||||
<div class="nav"> |
||||
<ul> |
||||
<li [routerLink]="['/system/organization']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/organization.png" alt="">组织机构管理</li> |
||||
<li [routerLink]="['/system/host']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/host.png" alt="">边缘设备管理</li> |
||||
<li [routerLink]="['/system/conditionMonitoring']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/push.png" alt="">边缘设备更新</li> |
||||
<li [routerLink]="['/system/statusMonitoring']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/push.png" alt="">边缘设备监控</li> |
||||
<li [routerLink]="['/system/videoStreaming']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/push.png" alt="">视频流监控</li> |
||||
<!-- <li [routerLink]="['/system/kafka']" routerLinkActive="router-link-active"><img |
||||
src="../../../assets/images/icon/push.png" alt="">kafka检查</li> --> |
||||
</ul> |
||||
</div> |
||||
</nz-sider> |
||||
<nz-layout> |
||||
<nz-header> |
||||
<span>Hey,欢迎登录加油站边缘主机管理系统</span> |
||||
<a nz-dropdown [nzDropdownMenu]="menu" [nzTrigger]="'click'" [nzBackdrop]='false'> |
||||
<i nz-icon nzType="setting"></i> |
||||
</a> |
||||
<nz-dropdown-menu #menu="nzDropdownMenu"> |
||||
<ul nz-menu nzSelectable> |
||||
<li nz-menu-item (click)="signOut()">退出</li> |
||||
</ul> |
||||
</nz-dropdown-menu> |
||||
</nz-header> |
||||
<nz-content> |
||||
<router-outlet></router-outlet> |
||||
</nz-content> |
||||
</nz-layout> |
||||
</nz-layout> |
@ -0,0 +1,79 @@
|
||||
nz-layout { |
||||
width: 100%; |
||||
height: 100%; |
||||
color: #fff; |
||||
font-size: 16px !important; |
||||
} |
||||
|
||||
nz-sider { |
||||
background: #001B3B; |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
overflow-y: auto; |
||||
|
||||
.logo { |
||||
width: 100%; |
||||
display: flex; |
||||
justify-content: center; |
||||
margin-top: 40px; |
||||
} |
||||
|
||||
.headPortrait { |
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
margin-top: 46px; |
||||
margin-bottom: 46px; |
||||
.photograph { |
||||
// width: 140px; |
||||
// height: 140px; |
||||
// border: 4px solid #FFFFFF; |
||||
// opacity: 1; |
||||
// border-radius: 32px; |
||||
} |
||||
|
||||
span { |
||||
margin-top: 18px; |
||||
} |
||||
} |
||||
|
||||
.nav { |
||||
ul { |
||||
li { |
||||
width: 300px; |
||||
height: 40px; |
||||
cursor: pointer; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: left; |
||||
margin-bottom: 16px; |
||||
box-sizing: border-box; |
||||
padding-left: 26%; |
||||
|
||||
img { |
||||
margin-right: 8px; |
||||
} |
||||
} |
||||
|
||||
.router-link-active { |
||||
background: linear-gradient(90deg, rgba(0, 13, 33, 0) 0%, #2399FF 52%, rgba(0, 13, 33, 0) 100%); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
nz-header { |
||||
height: 56px; |
||||
background: #FFFFFF; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
padding: 0 16px; |
||||
} |
||||
|
||||
nz-content { |
||||
background: #F2F2F2; |
||||
box-sizing: border-box; |
||||
padding: 16px; |
||||
} |
@ -0,0 +1,20 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { Router } from '@angular/router'; |
||||
import { CacheTokenService } from 'src/app/service/cache-token.service'; |
||||
|
||||
@Component({ |
||||
selector: 'app-navigation', |
||||
templateUrl: './navigation.component.html', |
||||
styleUrls: ['./navigation.component.scss'] |
||||
}) |
||||
export class NavigationComponent implements OnInit { |
||||
|
||||
constructor(private router: Router, public token: CacheTokenService) { } |
||||
|
||||
ngOnInit(): void { |
||||
} |
||||
signOut() { |
||||
this.token.delete() |
||||
this.router.navigate(['/login']) |
||||
} |
||||
} |
@ -0,0 +1,23 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="name" placeholder="请输入名称" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<!-- <nz-form-item> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input nz-input type="text" formControlName="code" placeholder="请输入编码" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> --> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<label nz-checkbox formControlName="isGasStation">是否为加油站</label> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,26 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
@Component({ |
||||
selector: 'app-addor', |
||||
templateUrl: './addor.component.html', |
||||
styleUrls: ['./addor.component.scss'] |
||||
}) |
||||
export class AddorComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
name: [null, [Validators.required]], |
||||
// code: [null, [Validators.required]],
|
||||
isGasStation: [false] |
||||
}); |
||||
} |
||||
destroyModal(): void { |
||||
this.modal.destroy({ data: 'this the result data' }); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,23 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control nzErrorTip="请输入名称"> |
||||
<nz-input-group> |
||||
<input [(ngModel)]="datacopy.name" nz-input type="text" formControlName="name" placeholder="请输入名称" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
<!-- <nz-form-item> |
||||
<nz-form-control> |
||||
<nz-input-group> |
||||
<input [(ngModel)]="datacopy.code" nz-input type="text" formControlName="code" placeholder="请输入编码" /> |
||||
</nz-input-group> |
||||
</nz-form-control> |
||||
</nz-form-item> --> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<label [(ngModel)]="datacopy.isGasStation" nz-checkbox formControlName="isGasStation">是否为加油站</label> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,30 @@
|
||||
import { Component, OnInit, Input } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
@Component({ |
||||
selector: 'app-editor', |
||||
templateUrl: './editor.component.html', |
||||
styleUrls: ['./editor.component.scss'] |
||||
}) |
||||
export class EditorComponent implements OnInit { |
||||
|
||||
@Input() data?: any; |
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
datacopy:any |
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
name: [null, [Validators.required]], |
||||
// code: [null, [Validators.required]],
|
||||
isGasStation: [] |
||||
}); |
||||
this.datacopy = JSON.parse(JSON.stringify(this.data))
|
||||
} |
||||
destroyModal(): void { |
||||
this.modal.destroy({ data: 'this the result data' }); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,42 @@
|
||||
<div class="orbox" id="orbox"> |
||||
<div class="topbox"> |
||||
<div class="lefttop"> |
||||
<span>组织机构列表</span> |
||||
<span><img style="vertical-align: top;" src="../../../assets/images/icon/orgrey.png" alt=""> |
||||
{{totalCount}}个单位</span> |
||||
</div> |
||||
<div class="righttop"> |
||||
<nz-input-group nzPrefixIcon="search"> |
||||
<input type="text" nz-input placeholder="请输入单位" [(ngModel)]="searchValue" /> |
||||
</nz-input-group> |
||||
<button nz-button nzType="primary" (click)="addOr()"><i nz-icon nzType="plus-circle" |
||||
nzTheme="outline"></i>新增</button> |
||||
</div> |
||||
</div> |
||||
<div class="treeTitle"> |
||||
<span>组织机构</span> |
||||
<span>操作</span> |
||||
</div> |
||||
<nz-tree [nzHideUnMatched]='true' [nzSearchValue]="searchValue" #nzTreeComponent [nzData]="nodes" |
||||
[nzExpandAll]="nzExpandAll" [nzExpandedKeys]="defaultExpandedKeys" [nzTreeTemplate]="nzTreeTemplate" nzDraggable |
||||
nzBlockNode (nzOnDrop)="nzEvent($event)" [nzBeforeDrop]="beforeDrop" [nzExpandedIcon]="multiExpandedIconTpl"> |
||||
</nz-tree> |
||||
<ng-template #nzTreeTemplate let-node let-origin="origin"> |
||||
<div class="nodebox"> |
||||
<span class="name">{{ node.title }}</span> |
||||
<span class="operation"> |
||||
<span (click)="addOr(node)" *ngIf="!node.origin.isGasStation">新增</span> |
||||
<span (click)="editOr(node)">编辑</span> |
||||
<span (click)="deleteOr(node)">删除</span> |
||||
</span> |
||||
</div> |
||||
</ng-template> |
||||
<ng-template #multiExpandedIconTpl let-node let-origin="origin"> |
||||
<ng-container *ngIf="node.children.length == 0; else elseTemplate"> |
||||
|
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<i nz-icon [nzType]="node.isExpanded ? 'caret-down' : 'caret-right'" class="ant-tree-switcher-line-icon"></i> |
||||
</ng-template> |
||||
</ng-template> |
||||
</div> |
@ -0,0 +1,78 @@
|
||||
.orbox { |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow-y: auto; |
||||
background: #fff; |
||||
box-sizing: border-box; |
||||
padding: 20px; |
||||
font-size: 15px; |
||||
} |
||||
|
||||
.topbox { |
||||
width: 700px; |
||||
height: 36px; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: space-between; |
||||
|
||||
.lefttop { |
||||
span:nth-child(1) { |
||||
color: #000D21; |
||||
margin-right: 16px; |
||||
} |
||||
|
||||
span:nth-child(2) { |
||||
color: rgba(36, 36, 36, 0.24); |
||||
} |
||||
} |
||||
|
||||
.righttop { |
||||
height: 36px; |
||||
display: flex; |
||||
|
||||
button { |
||||
margin-left: 16px; |
||||
} |
||||
|
||||
nz-input-group { |
||||
height: 32px; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.treeTitle { |
||||
width: 100%; |
||||
height: 36px; |
||||
line-height: 36px; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
color: #000D21; |
||||
box-sizing: border-box; |
||||
padding-left: 30px; |
||||
padding-right: 140px; |
||||
background: rgba(145, 204, 255, 0.2); |
||||
margin: 12px 0; |
||||
} |
||||
|
||||
.nodebox { |
||||
font-size: 15px; |
||||
|
||||
} |
||||
|
||||
.operation { |
||||
position: absolute; |
||||
right: 0; |
||||
|
||||
span { |
||||
margin-left: 40px; |
||||
} |
||||
|
||||
span:nth-child(1), |
||||
span:nth-child(2) { |
||||
color: #2399FF; |
||||
} |
||||
|
||||
span:nth-child(3) { |
||||
color: rgba(0, 13, 33, 0.48); |
||||
} |
||||
} |
@ -0,0 +1,314 @@
|
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { Component, OnInit, AfterViewInit, ViewChild, ViewContainerRef } from '@angular/core'; |
||||
import { TreeService } from 'src/app/service/tree.service'; |
||||
import { NzFormatEmitEvent, NzTreeComponent, NzTreeNodeOptions } from 'ng-zorro-antd/tree'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { AddorComponent } from './addor/addor.component'; |
||||
import { EditorComponent } from './editor/editor.component'; |
||||
|
||||
import { NzFormatBeforeDropEvent } from 'ng-zorro-antd/tree'; |
||||
import { Observable, of } from 'rxjs'; |
||||
import { delay } from 'rxjs/operators'; |
||||
import { CustomReuseStrategy } from 'src/app/CustomReuseStrategy'; |
||||
@Component({ |
||||
selector: 'app-organization', |
||||
templateUrl: './organization.component.html', |
||||
styleUrls: ['./organization.component.scss'] |
||||
}) |
||||
export class OrganizationComponent implements OnInit { |
||||
validateForm!: FormGroup; |
||||
constructor(private fb: FormBuilder, private http: HttpClient, private toTree: TreeService, private modal: NzModalService, private message: NzMessageService, private viewContainerRef: ViewContainerRef) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
search: [null] |
||||
}); |
||||
this.getAllOrganization() |
||||
|
||||
this.deleteRouteSnapshot(); |
||||
} |
||||
deleteRouteSnapshot() { |
||||
CustomReuseStrategy.deleteRouteSnapshot('/system/host'); |
||||
} |
||||
//搜索框提交
|
||||
submitForm(): void { |
||||
for (const i in this.validateForm.controls) { |
||||
this.validateForm.controls[i].markAsDirty(); |
||||
this.validateForm.controls[i].updateValueAndValidity(); |
||||
} |
||||
} |
||||
|
||||
//获取所有组织机构
|
||||
searchValue = ''; |
||||
nzExpandAll = false; |
||||
totalCount: string |
||||
|
||||
allOrList: any |
||||
getAllOrganization() { |
||||
let OrganizationUnitId = '' |
||||
let params = { |
||||
// OrganizationUnitId: OrganizationUnitId,
|
||||
// IsContainsChildren: "true"
|
||||
ContainsChildren: true, |
||||
pageSize: 9999 |
||||
} |
||||
this.http.get('/api/Organizations', { |
||||
params: params |
||||
}).subscribe((data: any) => { |
||||
console.log('组织机构列表', data) |
||||
this.totalCount = data.totalCount |
||||
data.items.forEach(element => { |
||||
element.key = element.id |
||||
element.title = element.name |
||||
element.selectable = false |
||||
}); |
||||
this.allOrList = data.items |
||||
this.nodes = [...this.toTree.toTree(data.items)] |
||||
this.defaultExpandedKeys = [this.nodes[0].id] |
||||
this.defaultExpandedKeys = [...this.defaultExpandedKeys] |
||||
}) |
||||
} |
||||
|
||||
|
||||
@ViewChild('nzTreeComponent', { static: false }) nzTreeComponent!: NzTreeComponent; |
||||
|
||||
defaultExpandedKeys = []; |
||||
|
||||
nodes: any[] = [] |
||||
|
||||
|
||||
addOr(node?: any) { |
||||
console.log(node) |
||||
const modal = this.modal.create({ |
||||
nzTitle: node ? '新增组织机构' : '新增一级组织机构', |
||||
nzContent: AddorComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise(resolve => { |
||||
let body = { |
||||
name: instance.validateForm.value.name, |
||||
parentId: node ? Number(node.key) : null, |
||||
isGasStation: instance.validateForm.value.isGasStation |
||||
} |
||||
this.http.post('/api/Organizations', body).subscribe(data => { |
||||
resolve(data) |
||||
this.message.create('success', '创建成功!'); |
||||
this.nzTreeComponent.getExpandedNodeList().forEach((item) => { |
||||
this.defaultExpandedKeys.push(item.key) |
||||
}) |
||||
this.getAllOrganization() |
||||
return true |
||||
}, err => { |
||||
resolve(err) |
||||
this.message.create('warning', '创建失败'); |
||||
return false |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
|
||||
} |
||||
editOr(node) { |
||||
// console.log(node)
|
||||
const modal = this.modal.create({ |
||||
nzTitle: '编辑组织机构', |
||||
nzContent: EditorComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: { |
||||
data: node.origin, |
||||
}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
await new Promise(resolve => { |
||||
let body = { |
||||
name: instance.validateForm.value.name, |
||||
isGasStation: instance.validateForm.value.isGasStation, |
||||
parentId: node.origin.parentId |
||||
} |
||||
this.http.put(`/api/Organizations/${node.origin.id}`, body).subscribe(data => { |
||||
resolve(data) |
||||
this.message.create('success', '编辑成功!'); |
||||
this.nzTreeComponent.getExpandedNodeList().forEach((item) => { |
||||
this.defaultExpandedKeys.push(item.key) |
||||
}) |
||||
this.getAllOrganization() |
||||
return true |
||||
}, err => { |
||||
resolve(err) |
||||
this.message.create('warning', '编辑失败'); |
||||
return false |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
deleteOr(item) { |
||||
console.log(item) |
||||
if (item.origin.children && item.origin.children.length != 0) { |
||||
this.message.create('warning', '请先删除所有子节点'); |
||||
} else { |
||||
this.modal.confirm({ |
||||
nzTitle: `确定要删除${item.title}这个机构吗?`, |
||||
nzOkText: '确定', |
||||
nzOkType: 'primary', |
||||
nzOnOk: () => { |
||||
this.http.delete(`/api/Organizations/${item.origin.id}`).subscribe(data => { |
||||
this.nzTreeComponent.getExpandedNodeList().forEach((item) => { |
||||
this.defaultExpandedKeys.push(item.key) |
||||
}) |
||||
this.getAllOrganization() |
||||
this.message.create('success', '删除成功!'); |
||||
}) |
||||
}, |
||||
nzCancelText: '取消', |
||||
nzOnCancel: () => { |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
nzEvent(event: NzFormatEmitEvent): void { |
||||
console.log('event', event) |
||||
if (this.isDrag) { |
||||
let parentId |
||||
if (this.pos == 0) {//目标节点内部
|
||||
parentId = event.node.key |
||||
} else { |
||||
if (event.node.level == 0) { |
||||
parentId = null |
||||
} else { |
||||
parentId = event.node.origin.parentId |
||||
} |
||||
} |
||||
|
||||
let body = { |
||||
parentId: parentId, |
||||
name: event.dragNode.origin.name, |
||||
isGasStation: event.dragNode.origin.isGasStation |
||||
} |
||||
this.http.put(`/api/Organizations/${event.dragNode.origin.id}`, body).subscribe(data => { |
||||
this.message.create('success', '拖拽成功!'); |
||||
this.nzTreeComponent.getExpandedNodeList().forEach((item) => { |
||||
this.defaultExpandedKeys.push(item.key) |
||||
}) |
||||
this.getAllOrganization() |
||||
return true |
||||
}, err => { |
||||
this.message.create('warning', '拖拽失败'); |
||||
return false |
||||
}) |
||||
|
||||
|
||||
// console.log('this.allOrList', this.allOrList)
|
||||
// let orders = {}
|
||||
// let originalData = JSON.parse(JSON.stringify(this.allOrList || [])) //tree原始数据
|
||||
// let targetNodeData = []//拖动移入节点的数据,用于遍历求出放在该数组的第几位
|
||||
//找到需要重新排序的数组
|
||||
// if (this.pos == 0) {
|
||||
// originalData.forEach(item => {
|
||||
// if (item.parentId == event.node.key) {
|
||||
// targetNodeData.push(item)
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// if (event.node.origin.parentId) {//如果拖动目标为非一级节点
|
||||
// originalData.forEach(item => {
|
||||
// if (item.parentId == event.node.origin.parentId) {
|
||||
// targetNodeData.push(item)
|
||||
// }
|
||||
// })
|
||||
// } else {//如果拖动目标为一级节点
|
||||
// originalData.forEach(item => {
|
||||
// if (!item.parentId) {
|
||||
// targetNodeData.push(item)
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// let idArr = []
|
||||
// targetNodeData.forEach(i => {
|
||||
// idArr.push(i.id)
|
||||
// })
|
||||
// if (this.pos == 0 && event.node.origin.children.length == 1) {
|
||||
// // console.log("移入,没有兄弟")
|
||||
// let key = event.dragNode.key
|
||||
// orders[key] = 0
|
||||
// parentId = event.node.key
|
||||
// } else {
|
||||
|
||||
// let array = []
|
||||
// targetNodeData.forEach(item => {
|
||||
// if (item.id != event.dragNode.key) { //将拖动项先移除掉
|
||||
// array.push(item)
|
||||
// }
|
||||
// })
|
||||
// if (event.dragNode.isEnd[event.dragNode.isEnd.length - 1]) { //如果移入到最后一个
|
||||
// // console.log("最后")
|
||||
// array.push(event.dragNode.origin)
|
||||
// } else if (event.dragNode.isStart[event.dragNode.isStart.length - 1]) {//如果移入到第一个
|
||||
// // console.log("第一")
|
||||
// array.unshift(event.dragNode.origin)
|
||||
// } else {//如果移入中间位置
|
||||
// // console.log("中间")
|
||||
// array.splice(event.node.origin.order, 0, event.dragNode.origin)
|
||||
// }
|
||||
// array.forEach((item, key) => {
|
||||
// orders[item.id] = key
|
||||
// })
|
||||
// console.log("移入,多个兄弟",orders)
|
||||
// }
|
||||
|
||||
// let obj = {
|
||||
// id: event.dragNode.origin.id,
|
||||
// parentId: parentId,
|
||||
// orders: orders
|
||||
// }
|
||||
|
||||
// this.http.put("/api/DisposalNodes/Sort", obj).subscribe(data => {
|
||||
// const config = new MatSnackBarConfig();
|
||||
// config.verticalPosition = 'top';
|
||||
// config.duration = 3000
|
||||
// this.snackBar.open('排序成功', '确定', config)
|
||||
// this.refurbishTreeData()
|
||||
// })
|
||||
|
||||
|
||||
|
||||
} |
||||
} |
||||
isDrag //是否可以拖动
|
||||
pos//放置位置
|
||||
beforeDrop = (arg: NzFormatBeforeDropEvent) => { |
||||
console.log('arg', arg) |
||||
if (arg.node.level === 0) {//如果为数据节点则不允许拖到一级节点
|
||||
this.message.create('warning', '不允许拖拽到一级节点'); |
||||
this.isDrag = false |
||||
return of(false); |
||||
} else { |
||||
this.isDrag = true |
||||
this.pos = arg.pos |
||||
return of(true) |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,3 @@
|
||||
<div class="content"> |
||||
<div class="center" id="center"><canvas id="canvas" [width]="canvasWidth" [height]="canvasHeight"></canvas></div> |
||||
</div> |
@ -0,0 +1,7 @@
|
||||
.content{ |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.center{ width: 100%; height: 100%; } |
@ -0,0 +1,171 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
|
||||
@Component({ |
||||
selector: 'app-plotting-image', |
||||
templateUrl: './plotting-image.component.html', |
||||
styleUrls: ['./plotting-image.component.scss'] |
||||
}) |
||||
export class PlottingImageComponent implements OnInit { |
||||
|
||||
constructor() { } |
||||
|
||||
canvasWidth: number = 0; |
||||
canvasHeight: number = 0; |
||||
|
||||
ngOnInit(): void { |
||||
window.onload = () => { |
||||
this.initBackgroundImg() |
||||
} |
||||
} |
||||
|
||||
//初始化背景图
|
||||
initBackgroundImg() { |
||||
let canvas = document.getElementById('canvas') as any; |
||||
canvas.oncontextmenu = () =>{ return false; }; |
||||
let ctx |
||||
// 检测canvas支持性
|
||||
if (canvas.getContext) { |
||||
ctx = canvas.getContext('2d'); // 返回一个对象,该对象提供了用在画布上绘图的方法和属性
|
||||
} else { |
||||
document.write("你的浏览器不支持canvas,请升级你的浏览器!"); |
||||
return; |
||||
} |
||||
|
||||
// 读取可视区域 宽高
|
||||
let center = (document.getElementById('center') as any).getBoundingClientRect(); |
||||
|
||||
// 图片加载完后,将其显示在canvas中
|
||||
var img = new Image(); |
||||
img.src = "../../../assets/images/bgImg.png"; |
||||
img.onload = () => { |
||||
// 等比例缩放图片
|
||||
var scale = 1; |
||||
if (img.width > center.width || img.height > center.height) { |
||||
if (img.width > img.height) { |
||||
scale = center.width / img.width; |
||||
}else { |
||||
scale = center.height / img.height; |
||||
} |
||||
} |
||||
this.canvasWidth = img.width * scale; |
||||
this.canvasHeight = img.height * scale; // 计算等比缩小后图片
|
||||
window.setTimeout(()=>{ // 加载图片
|
||||
ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight); |
||||
this.initCanvasEvent(canvas) |
||||
}, 0) |
||||
} |
||||
} |
||||
|
||||
//线段的点的集合
|
||||
points = []; |
||||
//可拖动圆圈的点的集合
|
||||
circles = []; |
||||
//整体移动点位
|
||||
allpoints = [] |
||||
isDragging = false |
||||
//是否在绘制区域内
|
||||
isInOut = false |
||||
//记录鼠标点击位置
|
||||
downx = 0 |
||||
downy = 0 |
||||
|
||||
//初始化 canvas画布 点击事件
|
||||
initCanvasEvent(canvas) { |
||||
let context = canvas.getContext('2d'); |
||||
canvas.onmousedown = (e)=>{ |
||||
console.log(e.pageX,e.pageY) |
||||
var clickX = e.pageX - canvas.offsetLeft; |
||||
var clickY = e.pageY - canvas.offsetTop; |
||||
this.downx = clickX |
||||
this.downy = clickY |
||||
if (this.isInt(clickX, clickY)) { |
||||
this.isInOut = true |
||||
return |
||||
} else { |
||||
this.isInOut = false |
||||
} |
||||
|
||||
let index |
||||
//判断当前点击点是否在已经绘制的圆圈上,如果是执行相关操作,并return,不进入画线的代码
|
||||
for (var i = 0; i < this.circles.length; i++) { |
||||
let circle = this.circles[i]; |
||||
//使用勾股定理计算这个点与圆心之间的距离
|
||||
var distanceFromCenter = Math.sqrt(Math.pow(circle.x - clickX, 2) + Math.pow(circle.y - clickY, 2)); |
||||
|
||||
// 如果是其他的点,则设置可以拖动
|
||||
if (distanceFromCenter <= circle.radius) { |
||||
// 清除之前选择的圆圈
|
||||
index = i; |
||||
this.isDragging = true; |
||||
//停止搜索
|
||||
return; |
||||
} |
||||
} |
||||
//如果点击新的位置,则进入下面的代码,绘制点
|
||||
//context.clearRect(0, 0, canvas.width, canvas.height);
|
||||
//遍历数组画圆
|
||||
var circle = { |
||||
x: clickX, |
||||
y: clickY, |
||||
radius: 10, |
||||
color: "blue", |
||||
isSelected: false, //拖拽点的标记
|
||||
}; |
||||
this.circles.push(circle); |
||||
this.allpoints = JSON.parse(JSON.stringify(this.circles)) |
||||
this.circles[0].color = "green"; |
||||
for (var i = 0; i < this.circles.length; i++) { |
||||
let circle = this.circles[i]; |
||||
// 绘制圆圈
|
||||
context.globalAlpha = 0.85; |
||||
context.beginPath(); |
||||
context.arc(circle.x, circle.y, circle.radius, 0, Math.PI * 2); |
||||
context.fillStyle = circle.color; |
||||
context.strokeStyle = "black"; |
||||
context.fill(); |
||||
context.stroke(); |
||||
} |
||||
// 画线
|
||||
var point = { |
||||
x: clickX, |
||||
y: clickY, |
||||
}; |
||||
this.points.push(point); |
||||
context.beginPath(); |
||||
context.lineWidth = 3; |
||||
//从起始点开始绘制
|
||||
context.moveTo(this.points[0].x, this.points[0].y); |
||||
for (var i = 0; i < this.points.length; i++) { |
||||
context.lineTo(this.points[i].x, this.points[i].y); |
||||
} |
||||
context.closePath() |
||||
context.fillStyle = "rgb(2,100,30)"; |
||||
context.fill(); |
||||
context.strokeStyle = "#9d4dca"; |
||||
context.stroke(); |
||||
} |
||||
} |
||||
|
||||
//判断点位是否在图形区域内
|
||||
isInt(x, y) { |
||||
if (!this.points[2]) { |
||||
return |
||||
} |
||||
var pt = { |
||||
x: x, |
||||
y: y |
||||
} |
||||
var poly = this.points |
||||
return this.PointInPoly(pt, poly) |
||||
} |
||||
|
||||
//射线法判断点位
|
||||
PointInPoly(pt, poly) { |
||||
for (var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) |
||||
((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) |
||||
&& (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) |
||||
&& (c = !c); |
||||
return c; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,12 @@
|
||||
<div class="box"> |
||||
<form nz-form [formGroup]="validateForm"> |
||||
<nz-form-item> |
||||
<nz-form-control> |
||||
<nz-select nzMode="multiple" formControlName="script" nzPlaceHolder="请选择脚本"> |
||||
<nz-option [nzValue]="'restartContainer'" nzLabel="restartContainer"></nz-option> |
||||
<nz-option [nzValue]="'restartMonitor'" nzLabel="restartMonitor"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
</form> |
||||
</div> |
@ -0,0 +1,25 @@
|
||||
import { Component, OnInit } from '@angular/core'; |
||||
import { NzModalRef } from 'ng-zorro-antd/modal'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { HttpClient } from '@angular/common/http'; |
||||
|
||||
@Component({ |
||||
selector: 'app-script', |
||||
templateUrl: './script.component.html', |
||||
styleUrls: ['./script.component.scss'] |
||||
}) |
||||
export class ScriptComponent implements OnInit { |
||||
|
||||
validateForm!: FormGroup; |
||||
constructor(private modal: NzModalRef, private fb: FormBuilder, private http: HttpClient) { } |
||||
|
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
script: [null, [Validators.required]], |
||||
}); |
||||
} |
||||
destroyModal(): void { |
||||
this.modal.destroy({ data: 'this the result data' }); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,96 @@
|
||||
<div class="box"> |
||||
<div class="topbox"> |
||||
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()"> |
||||
<nz-form-item class="searchParams"> |
||||
<nz-form-control> |
||||
<nz-tree-select [nzAllowClear]="false" [nzDropdownClassName]="'maxHeightTreeSelect'" nzShowSearch |
||||
formControlName="organization" [nzNodes]="nodes" nzPlaceHolder="请选择所属机构" |
||||
[(ngModel)]="defaultOrId" [nzExpandedIcon]="multiExpandedIconTpl"> |
||||
</nz-tree-select> |
||||
<ng-template #multiExpandedIconTpl let-node let-origin="origin"> |
||||
<ng-container *ngIf="node.children.length == 0; else elseTemplate"> |
||||
|
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<i nz-icon [nzType]="node.isExpanded ? 'caret-down' : 'caret-right'" |
||||
class="ant-tree-switcher-line-icon"></i> |
||||
</ng-template> |
||||
</ng-template> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item> |
||||
<!-- <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="state">设备状态</nz-form-label> --> |
||||
<nz-form-control> |
||||
<nz-select formControlName="state" nzPlaceHolder="请选择设备状态"> |
||||
<nz-option [nzValue]="0" nzLabel="离线"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="在线"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button nzType="primary" type="submit" class="submit"><i nz-icon |
||||
[nzType]="'search'"></i>查询</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button type="button" class="reset" (click)="resetForm($event)"><i nz-icon |
||||
[nzType]="'sync'"></i>重置</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'RestartApps'" (click)="sendRequest('RestartApps')"> |
||||
重启识别程序 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'RestartMonitors'" (click)="sendRequest('RestartMonitors')"> |
||||
重启监控程序 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'RestartMonitors'" (click)="executeTheScript()"> |
||||
执行脚本 |
||||
</button> |
||||
</form> |
||||
|
||||
</div> |
||||
<nz-table #basicTable nzShowSizeChanger [nzData]="listOfData" [nzLoading]="isLoading" |
||||
(nzCurrentPageDataChange)="onCurrentPageDataChange($event)" [nzShowPagination]='false' [nzPageSize]='10'> |
||||
<thead> |
||||
<tr> |
||||
<th [nzChecked]="checked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="onAllChecked($event)"> |
||||
</th> |
||||
<th>ip地址</th> |
||||
<th>所属油站</th> |
||||
<th>设备状态</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr *ngFor="let data of basicTable.data"> |
||||
<td [nzChecked]="setOfCheckedId.has(data.id)" [nzDisabled]="data.disabled" |
||||
(nzCheckedChange)="onItemChecked(data.id, $event)"></td> |
||||
<td>{{ data.hostIPAddress }}</td> |
||||
<td>{{ data.gasStationName }}</td> |
||||
<td> |
||||
<ng-container *ngIf="data.hubConnectionState == 'Disconnected'; else elseTemplate"> |
||||
<span style="color: red;">离线</span> |
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<span style="color: rgb(52, 204, 52);">在线</span> |
||||
</ng-template> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</nz-table> |
||||
<div class="pagination"> |
||||
<nz-pagination [nzHideOnSinglePage]="false" [nzPageIndex]="1" [nzTotal]="num" [nzPageSize]="10" |
||||
[nzShowTotal]="totalTemplate" nzShowQuickJumper (nzPageIndexChange)="pageChange($event)"> |
||||
</nz-pagination> |
||||
<ng-template #totalTemplate let-total> 10条/页,共{{num}}条 </ng-template> |
||||
</div> |
||||
</div> |
@ -0,0 +1,17 @@
|
||||
.topbox { |
||||
form { |
||||
display: flex; |
||||
|
||||
nz-form-item { |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
button { |
||||
margin-right: 6px; |
||||
} |
||||
} |
||||
|
||||
.searchParams { |
||||
width: 250px; |
||||
} |
||||
} |
@ -0,0 +1,221 @@
|
||||
import { HttpClient } from '@angular/common/http'; |
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core'; |
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'; |
||||
import { NzMessageService } from 'ng-zorro-antd/message'; |
||||
import { NzModalService } from 'ng-zorro-antd/modal'; |
||||
import { TreeService } from 'src/app/service/tree.service'; |
||||
import { ScriptComponent } from './script/script.component'; |
||||
|
||||
@Component({ |
||||
selector: 'app-status-monitoring', |
||||
templateUrl: './status-monitoring.component.html', |
||||
styleUrls: ['./status-monitoring.component.scss'] |
||||
}) |
||||
export class StatusMonitoringComponent implements OnInit { |
||||
|
||||
constructor(private http: HttpClient, private fb: FormBuilder, private toTree: TreeService, private message: NzMessageService, private modal: NzModalService, private viewContainerRef: ViewContainerRef) { } |
||||
validateForm!: FormGroup; |
||||
ngOnInit(): void { |
||||
this.validateForm = this.fb.group({ |
||||
organization: [null], |
||||
state: [null] |
||||
}); |
||||
this.getAllOrganization() |
||||
|
||||
} |
||||
//获取所有组织机构
|
||||
nodes: any = [] |
||||
defaultOrId: string |
||||
defaultExpandedKeys = []; |
||||
getAllOrganization() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
pageSize: 9999 |
||||
} |
||||
this.http.get('/api/Organizations', { |
||||
params: params |
||||
}).subscribe((data: any) => { |
||||
console.log('组织机构列表', data) |
||||
data.items.forEach(element => { |
||||
element.key = element.id |
||||
element.title = element.name |
||||
// element.selectable = false
|
||||
}); |
||||
this.nodes = [...this.toTree.toTree(data.items)] |
||||
this.defaultOrId = this.nodes[0].id |
||||
this.validateForm.value.organization = this.defaultOrId |
||||
this.getConditionMonitoring() |
||||
}) |
||||
} |
||||
|
||||
submitForm(): void { |
||||
for (const i in this.validateForm.controls) { |
||||
this.validateForm.controls[i].markAsDirty(); |
||||
this.validateForm.controls[i].updateValueAndValidity(); |
||||
} |
||||
this.getConditionMonitoring() |
||||
} |
||||
resetForm(e: MouseEvent): void { |
||||
e.preventDefault(); |
||||
this.validateForm.reset(); |
||||
for (const key in this.validateForm.controls) { |
||||
this.validateForm.controls[key].markAsPristine(); |
||||
this.validateForm.controls[key].updateValueAndValidity(); |
||||
} |
||||
this.validateForm.patchValue({ |
||||
organization: this.nodes[0].id, |
||||
}); |
||||
this.PageNumber = 1 |
||||
this.getConditionMonitoring() |
||||
} |
||||
listOfData: any |
||||
num: string |
||||
PageNumber: number = 1 |
||||
isLoading = false |
||||
//获取盒子状态
|
||||
getConditionMonitoring() { |
||||
let params = { |
||||
ContainsChildren: true, |
||||
OrganizationId: this.defaultOrId, |
||||
PageNumber: this.PageNumber, |
||||
PageSize: 10, |
||||
HubConnectionState: this.validateForm.value.state |
||||
} |
||||
this.isLoading = true |
||||
this.http.get('/api/EdgeDevices/Statuses', { params: params }).subscribe( |
||||
(data: any) => { |
||||
console.log(data) |
||||
this.isLoading = false |
||||
this.listOfData = data.items |
||||
this.num = data.totalCount |
||||
}, err => { |
||||
|
||||
} |
||||
) |
||||
} |
||||
pageChange($event) { |
||||
this.PageNumber = $event |
||||
this.getConditionMonitoring() |
||||
} |
||||
|
||||
|
||||
checked = false; |
||||
loading |
||||
indeterminate = false; |
||||
listOfCurrentPageData: readonly any[] = []; |
||||
setOfCheckedId = new Set<number>(); |
||||
updateCheckedSet(id: number, checked: boolean): void { |
||||
if (checked) { |
||||
this.setOfCheckedId.add(id); |
||||
} else { |
||||
this.setOfCheckedId.delete(id); |
||||
} |
||||
} |
||||
|
||||
onCurrentPageDataChange(listOfCurrentPageData: readonly any[]): void { |
||||
this.listOfCurrentPageData = listOfCurrentPageData; |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
refreshCheckedStatus(): void { |
||||
const listOfEnabledData = this.listOfCurrentPageData.filter(({ disabled }) => !disabled); |
||||
this.checked = listOfEnabledData.every(({ id }) => this.setOfCheckedId.has(id)); |
||||
this.indeterminate = listOfEnabledData.some(({ id }) => this.setOfCheckedId.has(id)) && !this.checked; |
||||
} |
||||
|
||||
onItemChecked(id: number, checked: boolean): void { |
||||
this.updateCheckedSet(id, checked); |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
onAllChecked(checked: boolean): void { |
||||
this.listOfCurrentPageData |
||||
.filter(({ disabled }) => !disabled) |
||||
.forEach(({ id }) => this.updateCheckedSet(id, checked)); |
||||
this.refreshCheckedStatus(); |
||||
} |
||||
|
||||
sendRequest(type): void { |
||||
|
||||
const requestData = this.listOfData.filter(data => this.setOfCheckedId.has(data.id)); |
||||
|
||||
let strArr = [] |
||||
requestData.forEach(element => { |
||||
strArr.push(element.id) |
||||
}); |
||||
let body |
||||
this.loading = type; |
||||
body = { |
||||
edgeDeviceIds: strArr |
||||
} |
||||
this.http.patch('/api/EdgeDevices/Commands', body, { params: { command: type } }).subscribe({ |
||||
next: (data: any) => { |
||||
this.message.create('success', '通知边缘盒子成功,请过一段时间手动刷新尝试!'); |
||||
console.log(data) |
||||
if (data.failedItems.length != 0) { |
||||
data.failedItems.forEach(element => { |
||||
this.message.create('info', element.detail); |
||||
}); |
||||
} |
||||
this.setOfCheckedId.clear(); |
||||
this.refreshCheckedStatus(); |
||||
this.loading = null; |
||||
this.getConditionMonitoring() |
||||
}, |
||||
error: (err) => { |
||||
this.loading = null; |
||||
} |
||||
}) |
||||
|
||||
|
||||
} |
||||
|
||||
executeTheScript() { |
||||
const requestData = this.listOfData.filter(data => this.setOfCheckedId.has(data.id)); |
||||
let strArr = [] |
||||
requestData.forEach(element => { |
||||
strArr.push(element.id) |
||||
}); |
||||
const modal = this.modal.create({ |
||||
nzTitle: '选择执行脚本', |
||||
nzContent: ScriptComponent, |
||||
nzViewContainerRef: this.viewContainerRef, |
||||
nzWidth: 288, |
||||
nzComponentParams: {}, |
||||
nzOnOk: async () => { |
||||
if (instance.validateForm.valid) { |
||||
let body = { |
||||
edgeDeviceIds: strArr |
||||
} |
||||
await new Promise(resolve => { |
||||
this.http.patch('/api/EdgeDevices/Commands/ExecuteScript', body, { params: { name: instance.validateForm.value.script } }).subscribe({ |
||||
next: (data: any) => { |
||||
resolve(data) |
||||
this.message.create('success', '通知边缘盒子成功,请过一段时间手动刷新尝试!'); |
||||
// if (data.failedItems && data.failedItems.length != 0) {
|
||||
// data.failedItems.forEach(element => {
|
||||
// this.message.create('info', element.detail);
|
||||
// });
|
||||
// }
|
||||
this.setOfCheckedId.clear(); |
||||
this.refreshCheckedStatus(); |
||||
this.loading = null; |
||||
this.getConditionMonitoring() |
||||
return true |
||||
}, |
||||
error: (err) => { |
||||
resolve(err) |
||||
this.loading = null; |
||||
return false |
||||
} |
||||
}) |
||||
}) |
||||
} else { |
||||
this.message.create('warning', '请填写完整!'); |
||||
return false |
||||
} |
||||
} |
||||
}); |
||||
const instance = modal.getContentComponent(); |
||||
} |
||||
} |
@ -0,0 +1,34 @@
|
||||
import { Routes, RouterModule } from '@angular/router'; |
||||
import { NgModule } from '@angular/core'; |
||||
import { OrganizationComponent } from './organization/organization.component'; |
||||
import { AnalysisOfTheHostComponent } from './analysis-of-the-host/analysis-of-the-host.component'; |
||||
import { HostConfigComponent } from './host-config/host-config.component'; |
||||
import { ImageListComponent } from './image-list/image-list.component'; |
||||
import { PlottingImageComponent } from './plotting-image/plotting-image.component'; |
||||
import { ImageLabel2Component } from './image-label2/image-label2.component'; |
||||
import { ConfigFormComponent } from './config-form/config-form.component'; |
||||
import { ConditionMonitoringComponent } from './condition-monitoring/condition-monitoring.component'; |
||||
import { KafkaComponent } from './kafka/kafka.component'; |
||||
import { StatusMonitoringComponent } from './status-monitoring/status-monitoring.component'; |
||||
import { VideoStreamingComponent } from './video-streaming/video-streaming.component'; |
||||
|
||||
|
||||
const routes: Routes = [ |
||||
{ path: 'organization', component: OrganizationComponent }, |
||||
{ path: 'host', component: AnalysisOfTheHostComponent }, |
||||
{ path: 'host/camera', component: HostConfigComponent }, |
||||
{ path: 'host/camera/imageList', component: ImageListComponent }, |
||||
{ path: 'host/camera/imageLabel', component: ImageLabel2Component }, |
||||
{ path: 'host/camera/configForm', component: ConfigFormComponent }, |
||||
{ path: 'plottingImage', component: PlottingImageComponent }, |
||||
{ path: 'conditionMonitoring', component: ConditionMonitoringComponent }, |
||||
{ path: 'statusMonitoring', component: StatusMonitoringComponent }, |
||||
{ path: 'kafka', component: KafkaComponent }, |
||||
{ path: 'videoStreaming', component: VideoStreamingComponent } |
||||
]; |
||||
|
||||
@NgModule({ |
||||
imports: [RouterModule.forChild(routes)], |
||||
exports: [RouterModule] |
||||
}) |
||||
export class SystemRoutingModule { } |
@ -0,0 +1,76 @@
|
||||
import { NgModule } from '@angular/core'; |
||||
import { CommonModule } from '@angular/common'; |
||||
import { SystemRoutingModule } from './system-management-routing.module'; |
||||
import { OrganizationComponent } from './organization/organization.component'; |
||||
import { NavigationComponent } from './navigation/navigation.component'; |
||||
import { NzLayoutModule } from 'ng-zorro-antd/layout'; |
||||
import { NzIconModule } from 'ng-zorro-antd/icon'; |
||||
import { NzTableModule } from 'ng-zorro-antd/table'; |
||||
import { NzDropDownModule } from 'ng-zorro-antd/dropdown'; |
||||
import { NzPaginationModule } from 'ng-zorro-antd/pagination'; |
||||
import { NzInputModule } from 'ng-zorro-antd/input'; |
||||
import { NzButtonModule } from 'ng-zorro-antd/button'; |
||||
import { NzFormModule } from 'ng-zorro-antd/form'; |
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; |
||||
import { NzModalModule } from 'ng-zorro-antd/modal'; |
||||
import { NzSelectModule } from 'ng-zorro-antd/select'; |
||||
import { NzMessageModule } from 'ng-zorro-antd/message'; |
||||
import { NzTreeModule } from 'ng-zorro-antd/tree'; |
||||
import { NzSpinModule } from 'ng-zorro-antd/spin'; |
||||
import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select'; |
||||
import { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm'; |
||||
import { AddorComponent } from './organization/addor/addor.component'; |
||||
import { EditorComponent } from './organization/editor/editor.component'; |
||||
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox'; |
||||
import { AnalysisOfTheHostComponent } from './analysis-of-the-host/analysis-of-the-host.component'; |
||||
import { AddhostComponent } from './analysis-of-the-host/addhost/addhost.component'; |
||||
import { EdithostComponent } from './analysis-of-the-host/edithost/edithost.component'; |
||||
import { AddcameraComponent } from './host-config/addcamera/addcamera.component'; |
||||
import { EditcameraComponent } from './host-config/editcamera/editcamera.component'; |
||||
import { HostConfigComponent } from './host-config/host-config.component'; |
||||
import { NzPageHeaderModule } from 'ng-zorro-antd/page-header'; |
||||
import { PlottingImageComponent } from './plotting-image/plotting-image.component'; |
||||
import { cameraType } from '../pipe/cameraTypePipe'; |
||||
import { ImageListComponent } from './image-list/image-list.component'; |
||||
import { ImageLabelComponent } from './image-label/image-label.component'; |
||||
import { ImageLabel2Component } from './image-label2/image-label2.component'; |
||||
import { ConfigFormComponent } from './config-form/config-form.component'; |
||||
import { NzTabsModule } from 'ng-zorro-antd/tabs'; |
||||
import { ConditionMonitoringComponent } from './condition-monitoring/condition-monitoring.component'; |
||||
import { SendFileComponent } from './host-config/send-file/send-file.component'; |
||||
import { ModelComponent } from './condition-monitoring/model/model.component'; |
||||
import { KafkaComponent } from './kafka/kafka.component'; |
||||
import { StatusMonitoringComponent } from './status-monitoring/status-monitoring.component'; |
||||
import { FileComponent } from './condition-monitoring/file/file.component'; |
||||
import { ScriptComponent } from './status-monitoring/script/script.component'; |
||||
import { VideoStreamingComponent } from './video-streaming/video-streaming.component'; |
||||
@NgModule({ |
||||
declarations: [OrganizationComponent, NavigationComponent, AddorComponent, EditorComponent, AnalysisOfTheHostComponent, AddhostComponent, EdithostComponent, AddcameraComponent, EditcameraComponent, HostConfigComponent, ImageListComponent, ImageLabelComponent, PlottingImageComponent, cameraType, ImageLabel2Component, ConfigFormComponent, ConditionMonitoringComponent, SendFileComponent, ModelComponent, KafkaComponent, StatusMonitoringComponent, FileComponent, ScriptComponent, VideoStreamingComponent], |
||||
imports: [ |
||||
CommonModule, |
||||
SystemRoutingModule, |
||||
NzLayoutModule, |
||||
NzIconModule, |
||||
NzTableModule, |
||||
NzDropDownModule, |
||||
NzPaginationModule, |
||||
NzInputModule, |
||||
NzButtonModule, |
||||
NzFormModule, |
||||
FormsModule, |
||||
ReactiveFormsModule, |
||||
NzModalModule, |
||||
NzSelectModule, |
||||
NzMessageModule, |
||||
NzTreeModule, |
||||
NzSpinModule, |
||||
NzTreeSelectModule, |
||||
NzCheckboxModule, |
||||
NzPageHeaderModule, |
||||
NzTabsModule, |
||||
NzPopconfirmModule |
||||
], |
||||
entryComponents: [AddorComponent, EditorComponent, AddhostComponent, EdithostComponent, AddcameraComponent, EditcameraComponent, SendFileComponent, ModelComponent, FileComponent,ScriptComponent] |
||||
|
||||
}) |
||||
export class SystemManagementModule { } |
@ -0,0 +1,116 @@
|
||||
<div class="box"> |
||||
<div class="topbox"> |
||||
<form nz-form [formGroup]="validateForm" class="login-form" (ngSubmit)="submitForm()"> |
||||
<nz-form-item class="searchParams"> |
||||
<nz-form-control> |
||||
<nz-tree-select [nzAllowClear]="false" [nzDropdownClassName]="'maxHeightTreeSelect'" nzShowSearch |
||||
formControlName="organization" [nzNodes]="nodes" nzPlaceHolder="请选择所属机构" |
||||
[(ngModel)]="defaultOrId" [nzExpandedIcon]="multiExpandedIconTpl"> |
||||
</nz-tree-select> |
||||
<ng-template #multiExpandedIconTpl let-node let-origin="origin"> |
||||
<ng-container *ngIf="node.children.length == 0; else elseTemplate"> |
||||
|
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<i nz-icon [nzType]="node.isExpanded ? 'caret-down' : 'caret-right'" |
||||
class="ant-tree-switcher-line-icon"></i> |
||||
</ng-template> |
||||
</ng-template> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item> |
||||
<!-- <nz-form-label [nzSm]="6" [nzXs]="24" nzRequired nzFor="state">设备状态</nz-form-label> --> |
||||
<nz-form-control> |
||||
<nz-select formControlName="state" nzPlaceHolder="请选择设备状态"> |
||||
<nz-option [nzValue]="0" nzLabel="离线"></nz-option> |
||||
<nz-option [nzValue]="1" nzLabel="在线"></nz-option> |
||||
</nz-select> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button nzType="primary" type="submit" class="submit"><i nz-icon |
||||
[nzType]="'search'"></i>查询</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<nz-form-item class="btn"> |
||||
<nz-form-control> |
||||
<button nz-button type="button" class="reset" (click)="resetForm($event)"><i nz-icon |
||||
[nzType]="'sync'"></i>重置</button> |
||||
</nz-form-control> |
||||
</nz-form-item> |
||||
|
||||
<!-- <button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'RestartApps'" (click)="sendRequest('RestartApps')"> |
||||
重启识别程序 |
||||
</button> |
||||
<button nz-button nzType="primary" type="button" [disabled]="setOfCheckedId.size === 0" |
||||
[nzLoading]="loading == 'RestartMonitors'" (click)="sendRequest('RestartMonitors')"> |
||||
重启监控程序 |
||||
</button> --> |
||||
</form> |
||||
|
||||
</div> |
||||
<nz-table #basicTable nzShowSizeChanger [nzData]="listOfData" [nzLoading]="isLoading" |
||||
(nzCurrentPageDataChange)="onCurrentPageDataChange($event)" [nzShowPagination]='false' [nzPageSize]='10'> |
||||
<thead> |
||||
<tr> |
||||
<!-- <th [nzChecked]="checked" [nzIndeterminate]="indeterminate" (nzCheckedChange)="onAllChecked($event)"> |
||||
</th> --> |
||||
<!-- <th>IP</th> --> |
||||
<th>所属油站</th> |
||||
<th>设备状态</th> |
||||
<th>报告时间</th> |
||||
<th>报告内容</th> |
||||
<th>操作</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr *ngFor="let data of basicTable.data"> |
||||
<!-- <td [nzChecked]="setOfCheckedId.has(data.id)" [nzDisabled]="data.disabled" |
||||
(nzCheckedChange)="onItemChecked(data.id, $event)"></td> --> |
||||
<!-- <td>{{ data.hostIPAddress }}</td> --> |
||||
<td>{{ data.gasStationName }}</td> |
||||
<td> |
||||
<ng-container *ngIf="data.hubConnectionState == 'Disconnected'; else elseTemplate"> |
||||
<span style="color: red;">离线</span> |
||||
</ng-container> |
||||
<ng-template #elseTemplate> |
||||
<span style="color: rgb(52, 204, 52);">在线</span> |
||||
</ng-template> |
||||
</td> |
||||
<td> |
||||
<p> |
||||
开始时间:{{data.beginTime ? (data.beginTime | date:"yyyy-MM-dd HH:mm:ss") |
||||
:'/'}} |
||||
</p> |
||||
<p> |
||||
结束时间:{{data.endTime ? (data.endTime | date:"yyyy-MM-dd HH:mm:ss") :'/'}} |
||||
</p> |
||||
</td> |
||||
<td> |
||||
<span class="blue" (click)="showModal()">详情</span> |
||||
<nz-modal [(nzVisible)]="isVisible" nzTitle="详情" (nzOnCancel)="handleCancel()" |
||||
(nzOnOk)="handleOk()"> |
||||
<ng-container *nzModalContent> |
||||
{{data.detail}} |
||||
</ng-container> |
||||
</nz-modal> |
||||
</td> |
||||
<td> |
||||
<span class="blue" (click)="dispose(data)">处置</span> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
</nz-table> |
||||
<div class="pagination"> |
||||
<nz-pagination [nzHideOnSinglePage]="false" [nzPageIndex]="1" [nzTotal]="num" [nzPageSize]="10" |
||||
[nzShowTotal]="totalTemplate" nzShowQuickJumper (nzPageIndexChange)="pageChange($event)"> |
||||
</nz-pagination> |
||||
<ng-template #totalTemplate let-total> 10条/页,共{{num}}条 </ng-template> |
||||
</div> |
||||
</div> |
@ -0,0 +1,17 @@
|
||||
.topbox { |
||||
form { |
||||
display: flex; |
||||
|
||||
nz-form-item { |
||||
margin-right: 6px; |
||||
} |
||||
|
||||
button { |
||||
margin-right: 6px; |
||||
} |
||||
} |
||||
|
||||
.searchParams { |
||||
width: 250px; |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue