diff --git a/angular.json b/angular.json
index d8c500d..778e1bd 100644
--- a/angular.json
+++ b/angular.json
@@ -28,7 +28,12 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
- "src/assets"
+ "src/assets",
+ {
+ "glob": "**/*",
+ "input": "./node_modules/@ant-design/icons-angular/src/inline-svg/",
+ "output": "/assets/"
+ }
],
"styles": [
"src/styles.scss",
diff --git a/package-lock.json b/package-lock.json
index 151ef1e..f23b09d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,7 +16,9 @@
"@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"
@@ -2965,11 +2967,16 @@
"resolved": "https://registry.npmmirror.com/ajv/download/ajv-8.8.2.tgz",
"integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
@@ -6493,6 +6500,11 @@
"node": ">=10"
}
},
+ "node_modules/js-base64": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmmirror.com/js-base64/download/js-base64-3.7.2.tgz",
+ "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ=="
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz",
@@ -7485,6 +7497,18 @@
"@angular/router": "^13.0.1"
}
},
+ "node_modules/ngx-cookie-service": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmmirror.com/ngx-cookie-service/download/ngx-cookie-service-13.1.2.tgz",
+ "integrity": "sha512-CInzm1xjI51QA1gCJEnqfDFLnN7w/SzqM5+kGdpI+UiCeHKgYEXpKG1s7lFz4jbLDrL/jHKtrf92t7RGsm66Cg==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@angular/common": "^13.0.0",
+ "@angular/core": "^13.0.0"
+ }
+ },
"node_modules/nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/nice-napi/download/nice-napi-1.0.2.tgz",
@@ -9346,11 +9370,16 @@
"resolved": "https://registry.npmmirror.com/ajv/download/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/schema-utils/node_modules/ajv-keywords": {
@@ -10074,11 +10103,16 @@
"resolved": "https://registry.npmmirror.com/ajv/download/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
@@ -10671,11 +10705,16 @@
"resolved": "https://registry.npmmirror.com/ajv/download/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/webpack/node_modules/ajv-keywords": {
@@ -15805,6 +15844,11 @@
}
}
},
+ "js-base64": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmmirror.com/js-base64/download/js-base64-3.7.2.tgz",
+ "integrity": "sha512-NnRs6dsyqUXejqk/yv2aiXlAvOs56sLkX6nUdeaNezI5LFFLlsZjOThmwnrcwh5ZZRwZlCMnVAY3CvhIhoVEKQ=="
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.nlark.com/js-tokens/download/js-tokens-4.0.0.tgz",
@@ -16558,6 +16602,14 @@
"tslib": "^2.3.0"
}
},
+ "ngx-cookie-service": {
+ "version": "13.1.2",
+ "resolved": "https://registry.npmmirror.com/ngx-cookie-service/download/ngx-cookie-service-13.1.2.tgz",
+ "integrity": "sha512-CInzm1xjI51QA1gCJEnqfDFLnN7w/SzqM5+kGdpI+UiCeHKgYEXpKG1s7lFz4jbLDrL/jHKtrf92t7RGsm66Cg==",
+ "requires": {
+ "tslib": "^2.0.0"
+ }
+ },
"nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/nice-napi/download/nice-napi-1.0.2.tgz",
diff --git a/package.json b/package.json
index 38316ab..f67166b 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"version": "0.0.0",
"scripts": {
"ng": "ng",
- "start": "ng serve",
+ "start": "ng serve --proxy-config proxy.config.json --open --port 4000 ",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
@@ -18,7 +18,9 @@
"@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"
diff --git a/proxy.config.json b/proxy.config.json
new file mode 100644
index 0000000..b147575
--- /dev/null
+++ b/proxy.config.json
@@ -0,0 +1,13 @@
+{
+ "/api": {
+ "target": "http://39.106.78.171:8906",
+ "secure": false,
+ "changeOrigin": true
+ },
+ "/signalr": {
+ "target": "http://39.106.78.171:8906",
+ "secure": false,
+ "ws": true,
+ "logLevel": "debug"
+ }
+}
diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts
index 0d6d373..c46a6d8 100644
--- a/src/app/app-routing.module.ts
+++ b/src/app/app-routing.module.ts
@@ -1,17 +1,24 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
+import { AuthGuard } from './auth.guard';
import { HomeComponent } from './pages/home/home.component';
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:'home',component: HomeComponent,
+ path:'',component: HomeComponent,
children:[
{path:'home',loadChildren:() => import('./pages/pages.module').then(m => m.PagesModule)},
]
},
+ {
+ path: '', component: NavigationComponent, canActivate: [AuthGuard], children: [
+ { path: 'system', loadChildren: () => import('./system-management/system-management.module').then(m => m.SystemManagementModule) }
+ ]
+ }//系统管理
];
@NgModule({
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a16a5d5..7599eb2 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -1,14 +1,17 @@
-import { NgModule } from '@angular/core';
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 { CookieService } from 'ngx-cookie-service';//cookie插件
import { NzNotificationModule } from 'ng-zorro-antd/notification';
import { NzMessageModule } from 'ng-zorro-antd/message';
-
-import { AppComponent } from './app.component';
-
+import { TreeService } from './service/tree.service';
@NgModule({
declarations: [
AppComponent
@@ -17,12 +20,13 @@ import { AppComponent } from './app.component';
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
+ PagesModule,
FormsModule,
HttpClientModule,
NzNotificationModule,
NzMessageModule
],
- providers: [],
+ providers: [httpInterceptorProviders, CacheTokenService, TreeService, CookieService],
bootstrap: [AppComponent]
})
export class AppModule { }
diff --git a/src/app/auth.guard.ts b/src/app/auth.guard.ts
new file mode 100644
index 0000000..af4d216
--- /dev/null
+++ b/src/app/auth.guard.ts
@@ -0,0 +1,37 @@
+import { Component, OnInit, Inject } from '@angular/core';
+import { Injectable } from '@angular/core';
+import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
+import { CookieService } from 'ngx-cookie-service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthGuard implements CanActivate {
+
+ constructor(private router: Router,private cookieService: CookieService) {
+
+ }
+
+ // 路由守卫
+ 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 = this.cookieService.get("token") || sessionStorage.getItem('token');
+
+ // 如果有token,允许访问
+ if (token) { return true; }
+
+ //如果没有token,跳转登录页
+ this.router.navigate(['/login']);
+
+ return false;
+ }
+}
diff --git a/src/app/http-interceptors/base-interceptor.ts b/src/app/http-interceptors/base-interceptor.ts
new file mode 100644
index 0000000..7229f32
--- /dev/null
+++ b/src/app/http-interceptors/base-interceptor.ts
@@ -0,0 +1,87 @@
+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 { CookieService } from 'ngx-cookie-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 cookieService: CookieService, 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 = this.cookieService.get("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 || error.status === 614) {
+ this.token.delete()
+ sessionStorage.clear()
+ // window.localStorage.clear()
+ localStorage.removeItem("isautologin")
+ this.cookieService.set("token", '', new Date(new Date().getTime() + 1), '/')
+ this.cookieService.set("refreshToken", '', new Date(new Date().getTime() + 1), '/')
+ this.message.create('error', `用户认证信息过期,请重新登录!`);
+ this.router.navigate(['/login'])
+ }
+ if (error.status === 403) {
+ this.message.create('error', `对不起,您无此权限!`);
+ }
+ if (error.status === 400) {
+ this.message.create('error', `请核对您的输入信息或格式是否正确!`);
+ }
+
+ if (error.error instanceof ErrorEvent) {
+ // 发生客户端或网络错误。相应处理。
+ console.error('An error occurred:', error.error.message);
+ } else {
+ // 服务端返回http状态码
+ // 服务端返回错误信息
+ console.error(
+ `Backend returned code ${error.status}, ` +
+ `body was: ${error.error}`);
+ }
+ // 返回带有面向用户的错误信息
+ return throwError(
+ error);
+ };
+}
diff --git a/src/app/http-interceptors/index.ts b/src/app/http-interceptors/index.ts
new file mode 100644
index 0000000..3e35136
--- /dev/null
+++ b/src/app/http-interceptors/index.ts
@@ -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 },
+
+];
\ No newline at end of file
diff --git a/src/app/pages/login/login.component.html b/src/app/pages/login/login.component.html
index e400637..5c926e4 100644
--- a/src/app/pages/login/login.component.html
+++ b/src/app/pages/login/login.component.html
@@ -1,33 +1,46 @@
-
-
-
-
中化石油销售有限公司 北京安信科创软件有限公司 版权所有
+
+
+
+
+
+
+ 忘记密码?
+
+
+
+
+
+
+
+
+
+
北京安信科创软件有限公司 版权所有
-
-
+
\ No newline at end of file
diff --git a/src/app/pages/login/login.component.scss b/src/app/pages/login/login.component.scss
index dd123f9..3724d20 100644
--- a/src/app/pages/login/login.component.scss
+++ b/src/app/pages/login/login.component.scss
@@ -1,6 +1,7 @@
.login {
width: 100%;
height: 100%;
+ background: url('../../../assets/images/bgImg.png');
background-size: 100% 100%;
position: relative;
}
@@ -89,4 +90,4 @@ p {
letter-spacing: 5px;
margin-bottom: 0px;
}
-}
\ No newline at end of file
+}
diff --git a/src/app/pages/login/login.component.ts b/src/app/pages/login/login.component.ts
index f162d0f..71a6774 100644
--- a/src/app/pages/login/login.component.ts
+++ b/src/app/pages/login/login.component.ts
@@ -1,26 +1,122 @@
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 { CookieService } from 'ngx-cookie-service';//cookie插件
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']
+ styleUrls: ['./login.component.scss'],
+
})
export class LoginComponent implements OnInit {
- constructor() { }
+ validateForm!: FormGroup;
+ constructor(private http: HttpClient, private router: Router, public token: CacheTokenService, private cookieService: CookieService, 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 //这一步是回显后让勾选框为选中状态
+ }
- ngOnInit(): void {
- // this.validateForm = this.fb.group({
- // userName: [null, [Validators.required]],
- // password: [null, [Validators.required]],
- // remember: [null],
- // autologin: [null],
- // });
}
- validateForm!: FormGroup;
- submitForm() {
+ 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/TokenAuth/Authenticate', {
+ userNameOrEmailAddress: this.validateForm.value.userName,
+ password: this.validateForm.value.password
+ }).subscribe(
+ (data: any) => {
+ sessionStorage.setItem("token", data.result.accessToken);
+ sessionStorage.setItem("encryptedAccessToken", data.result.encryptedAccessToken);
+ this.cookieService.set("token", data.result.accessToken, null, '/');
+ this.cookieService.set("refreshToken", data.result.encryptedAccessToken, null, '/');
+ this.router.navigate(['/system/organization'])
+ this.message.create('success', `登录成功`);
+ },
+ (err) => {
+ this.isLoading = false;
+ this.message.create('error', err.error.error.details);
+ }
+ )
+ }
+ forget() {
+ this.message.create('warning', `请联系管理员`);
}
}
diff --git a/src/app/pages/pages.module.ts b/src/app/pages/pages.module.ts
index eadba17..11ddac6 100644
--- a/src/app/pages/pages.module.ts
+++ b/src/app/pages/pages.module.ts
@@ -9,34 +9,14 @@ import { CdkTableModule } from '@angular/cdk/table';
import { CdkTreeModule } from '@angular/cdk/tree';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
-import { NzMenuModule } from 'ng-zorro-antd/menu';
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 { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
-import { NzIconModule } from 'ng-zorro-antd/icon';
-import { NzGridModule } from 'ng-zorro-antd/grid';
-import { NzModalModule } from 'ng-zorro-antd/modal';
-import { NzPaginationModule } from 'ng-zorro-antd/pagination';
-import { NzDropDownModule } from 'ng-zorro-antd/dropdown';
-import { NzMessageModule } from 'ng-zorro-antd/message';
-import { NzSpinModule } from 'ng-zorro-antd/spin';
-import { NzTreeModule } from 'ng-zorro-antd/tree';
-import { NzCollapseModule } from 'ng-zorro-antd/collapse';
-import { NzStepsModule } from 'ng-zorro-antd/steps';
-import { NzTableModule } from 'ng-zorro-antd/table';
-import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
-import { NzTimePickerModule } from 'ng-zorro-antd/time-picker';
-import { NzProgressModule } from 'ng-zorro-antd/progress';
-import { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm';
-import { NzBadgeModule } from 'ng-zorro-antd/badge';
-import { NzTreeSelectModule } from 'ng-zorro-antd/tree-select';
-import { NzNotificationModule } from 'ng-zorro-antd/notification';
-
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';
-
+import { NzMessageModule } from 'ng-zorro-antd/message';
+import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';
@NgModule({
declarations: [
LoginComponent,
@@ -54,30 +34,12 @@ import { HomeComponent } from './home/home.component';
FormsModule,
ReactiveFormsModule,
RouterModule,
- NzMenuModule,
NzFormModule,
NzButtonModule,
NzInputModule,
NzSelectModule,
- NzDatePickerModule,
- NzIconModule,
- NzGridModule,
- NzModalModule,
- NzPaginationModule,
- NzDropDownModule,
NzMessageModule,
- NzSpinModule,
- NzTreeModule,
- NzCollapseModule,
- NzStepsModule,
- NzTableModule,
- NzCheckboxModule,
- NzTimePickerModule,
- NzProgressModule,
- NzPopconfirmModule,
- NzBadgeModule,
- NzTreeSelectModule,
- NzNotificationModule
+ NzCheckboxModule
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
diff --git a/src/app/service/cache-token.service.ts b/src/app/service/cache-token.service.ts
new file mode 100644
index 0000000..092b63d
--- /dev/null
+++ b/src/app/service/cache-token.service.ts
@@ -0,0 +1,44 @@
+import { Injectable } from '@angular/core';
+import { HttpClient } from '@angular/common/http'
+import { CookieService } from 'ngx-cookie-service';
+
+@Injectable({
+ providedIn: 'root'
+})
+export class CacheTokenService {
+
+ constructor(private http: HttpClient, private cookieService: CookieService) { }
+
+ public timer: number | undefined;
+
+ //刷新token令牌定时器
+ startUp = (): void => {
+ window.clearInterval(this.timer)
+ this.timer = window.setInterval(() => {
+ var token = this.cookieService.get("token");
+ var refreshToken = this.cookieService.get("refreshToken");
+ this.http.post('/api/CompanyAccount/RefreshToken', {
+ token: token,
+ refreshToken: refreshToken
+ }).subscribe((data: any) => {
+ sessionStorage.setItem("token", data.token);
+ this.cookieService.set("token", data.token, undefined, '/');
+ this.cookieService.set("refreshToken", data.refreshToken, undefined, '/');
+ })
+ }, 18 * 60 * 1000)
+ }
+
+
+
+
+
+ //删除定时器
+ 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)
+ }
+
+}
diff --git a/src/app/service/tree.service.ts b/src/app/service/tree.service.ts
new file mode 100644
index 0000000..b22705b
--- /dev/null
+++ b/src/app/service/tree.service.ts
@@ -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;
+ }
+}
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.html b/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.html
new file mode 100644
index 0000000..46c34cc
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.html
@@ -0,0 +1,25 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.scss b/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.ts b/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.ts
new file mode 100644
index 0000000..9a76b2d
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/addcamera/addcamera.component.ts
@@ -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-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 {
+ this.validateForm = this.fb.group({
+ name: [null, [Validators.required]],
+ ip: [null, [Validators.required]],
+ code: [null, [Validators.required]]
+ });
+ }
+
+}
diff --git a/src/app/system-management/analysis-of-the-host/addhost/addhost.component.html b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.html
new file mode 100644
index 0000000..06d354d
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.html
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/addhost/addhost.component.scss b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.scss
new file mode 100644
index 0000000..6f8c35d
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.scss
@@ -0,0 +1,3 @@
+.ant-form-item{
+ margin-bottom: 0;
+}
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/addhost/addhost.component.ts b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.ts
new file mode 100644
index 0000000..73d5163
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/addhost/addhost.component.ts
@@ -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]]
+ });
+ }
+}
diff --git a/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.html b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.html
new file mode 100644
index 0000000..0d9a1d8
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.html
@@ -0,0 +1,103 @@
+
+
+
+
+ 组织机构
+
+
+
+
+
+
+ {{ node.title }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{selectedOilStation ? selectedOilStation.displayName : '加油站'}} 分析主机列表
+ (请从左侧选择加油站)
+
+
+
+
+
+
+
+
+
+
+ ip |
+ 操作 |
+
+
+
+
+ {{data.hostIPAddress}} |
+
+ 编辑
+ 删除
+ |
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.scss b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.scss
new file mode 100644
index 0000000..b6dee8d
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.scss
@@ -0,0 +1,93 @@
+.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;
+}
diff --git a/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.ts b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.ts
new file mode 100644
index 0000000..9279087
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/analysis-of-the-host.component.ts
@@ -0,0 +1,280 @@
+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 { AddcameraComponent } from './addcamera/addcamera.component';
+import { EdithostComponent } from './edithost/edithost.component';
+import { EditcameraComponent } from './editcamera/editcamera.component';
+@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 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 OrganizationUnitId = ''
+ let params = {
+ OrganizationUnitId: OrganizationUnitId,
+ IsContainsChildren: "true"
+ }
+ this.http.get('/api/services/app/Organization/GetAll', {
+ params: params
+ }).subscribe((data: any) => {
+ this.totalCount = data.result.totalCount
+ data.result.items.forEach(element => {
+ element.key = element.id
+ element.title = element.displayName
+ element.selectable = false
+ });
+ this.nodes = [...this.toTree.toTree(data.result.items)]
+ this.defaultExpandedKeys = [...this.defaultExpandedKeys]
+ })
+ }
+
+
+ @ViewChild('nzTreeComponent', { static: false }) nzTreeComponent!: NzTreeComponent;
+
+ defaultExpandedKeys = [];
+
+ nodes: any[] = []
+ nzSelectedKeys: any[] = []
+ selectedOilStation: any
+ nzClick(event: NzFormatEmitEvent): void {
+ console.log(event.node.origin);
+ if (event.node.origin['isGasStation']) {//如果点击的是加油站才生效
+ this.nzSelectedKeys[0] = event.node.origin.id
+ this.nzSelectedKeys = [...this.nzSelectedKeys]
+ this.selectedOilStation = event.node.origin
+ this.getHost()
+ // this.getCamera()
+ } else {
+ this.message.info('只有加油站才可以增加主机');
+ }
+ }
+
+ //获得加油站的主机
+ listOfData: any[] = [];
+ getHost() {
+ this.http.get('/api/services/app/EdgeDevice/GetAll', {
+ params: {
+ organizationUnitId: this.selectedOilStation.id,
+ SkipCount: '0',
+ MaxResultCount: '100',
+ }
+ }).subscribe((data: any) => {
+ console.log('主机列表', data.result.items)
+ this.listOfData = data.result.items
+ })
+ }
+
+
+ //获得加油站摄像头
+ listOfDataCamera: any[] = [];
+ getCamera() {
+ this.http.get('/api/services/app/Camera/GetAll', {
+ params: {
+ organizationUnitId: this.selectedOilStation.id,
+ SkipCount: '0',
+ MaxResultCount: '100',
+ }
+ }).subscribe((data: any) => {
+ // console.log('摄像头列表', data)
+ this.listOfDataCamera = data.result.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,
+ organizationUnitId: this.selectedOilStation.id
+ }
+ this.http.post('/api/services/app/EdgeDevice/Create', 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/services/app/EdgeDevice/Update', 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/services/app/EdgeDevice/Delete', {
+ params: {
+ Id: item.id
+ }
+ }).subscribe(data => {
+ this.message.create('success', '删除成功!');
+ this.getHost()
+ })
+ },
+ nzCancelText: '取消'
+ });
+ }
+
+
+ //摄像头
+ addCamera() {
+ console.log(this.selectedOilStation)
+ const modal = this.modal.create({
+ nzTitle: '新增加油站摄像头',
+ nzContent: AddcameraComponent,
+ nzViewContainerRef: this.viewContainerRef,
+ nzWidth: 288,
+ nzComponentParams: {},
+ nzOnOk: async () => {
+ if (instance.validateForm.valid) {
+ await new Promise(resolve => {
+ console.log('表单信息', instance.validateForm)
+ let body = {
+ organizationUnitId: this.selectedOilStation.id,
+ ipAdress: instance.validateForm.value.ip,
+ code: instance.validateForm.value.code,
+ name: instance.validateForm.value.name,
+ // description: "",
+ }
+ this.http.post('/api/services/app/Camera/Create', body).subscribe(data => {
+ resolve(data)
+ this.message.create('success', '创建成功!');
+ this.getCamera()
+ return true
+ }, 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: 288,
+ nzComponentParams: {
+ data: data
+ },
+ nzOnOk: async () => {
+ if (instance.validateForm.valid) {
+ await new Promise(resolve => {
+ console.log('表单信息', instance.validateForm)
+ data.name = instance.validateForm.value.name
+ data.code = instance.validateForm.value.code
+ data.ipAdress = instance.validateForm.value.ip
+ this.http.put('/api/services/app/Camera/Update', data).subscribe(data => {
+ resolve(data)
+ this.message.create('success', '编辑成功!');
+ this.getCamera()
+ return true
+ }, err => {
+ return false
+ })
+ })
+ } else {
+ this.message.create('warning', '请填写完整!');
+ return false
+ }
+ }
+ });
+ const instance = modal.getContentComponent();
+ }
+ deleteCamera(item) {
+ console.log(item)
+ this.modal.confirm({
+ nzTitle: `确定要删除${item.name}这个摄像头吗?`,
+ nzOkText: '确定',
+ nzOkType: 'primary',
+ nzOnOk: () => {
+ this.http.delete('/api/services/app/Camera/Delete', {
+ params: {
+ Id: item.id
+ }
+ }).subscribe(data => {
+ this.message.create('success', '删除成功!');
+ this.getCamera()
+ })
+ },
+ nzCancelText: '取消'
+ });
+ }
+}
diff --git a/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.html b/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.html
new file mode 100644
index 0000000..46c34cc
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.html
@@ -0,0 +1,25 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.scss b/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.ts b/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.ts
new file mode 100644
index 0000000..62d2d0c
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/editcamera/editcamera.component.ts
@@ -0,0 +1,25 @@
+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-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 {
+ let datacopy = JSON.parse(JSON.stringify(this.data))
+ this.validateForm = this.fb.group({
+ name: [datacopy.name, [Validators.required]],
+ ip: [datacopy.ipAdress, [Validators.required]],
+ code: [datacopy.code, [Validators.required]]
+ });
+ }
+
+}
diff --git a/src/app/system-management/analysis-of-the-host/edithost/edithost.component.html b/src/app/system-management/analysis-of-the-host/edithost/edithost.component.html
new file mode 100644
index 0000000..4e62039
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/edithost/edithost.component.html
@@ -0,0 +1,11 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/analysis-of-the-host/edithost/edithost.component.scss b/src/app/system-management/analysis-of-the-host/edithost/edithost.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/system-management/analysis-of-the-host/edithost/edithost.component.ts b/src/app/system-management/analysis-of-the-host/edithost/edithost.component.ts
new file mode 100644
index 0000000..22fc01b
--- /dev/null
+++ b/src/app/system-management/analysis-of-the-host/edithost/edithost.component.ts
@@ -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]]
+ });
+ }
+}
diff --git a/src/app/system-management/navigation/navigation.component.html b/src/app/system-management/navigation/navigation.component.html
new file mode 100644
index 0000000..8da84c5
--- /dev/null
+++ b/src/app/system-management/navigation/navigation.component.html
@@ -0,0 +1,37 @@
+
+
+
+
+

+
+
+
+

+
+
Administrator
+
管理员
+
+
+
+
组织机构管理
+
分析主机管理
+
+
+
+
+
+ Hey,欢迎登录加油站智能安全管理系统
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/app/system-management/navigation/navigation.component.scss b/src/app/system-management/navigation/navigation.component.scss
new file mode 100644
index 0000000..036102a
--- /dev/null
+++ b/src/app/system-management/navigation/navigation.component.scss
@@ -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;
+}
diff --git a/src/app/system-management/navigation/navigation.component.ts b/src/app/system-management/navigation/navigation.component.ts
new file mode 100644
index 0000000..d5ca598
--- /dev/null
+++ b/src/app/system-management/navigation/navigation.component.ts
@@ -0,0 +1,18 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+
+@Component({
+ selector: 'app-navigation',
+ templateUrl: './navigation.component.html',
+ styleUrls: ['./navigation.component.scss']
+})
+export class NavigationComponent implements OnInit {
+
+ constructor(private router: Router) { }
+
+ ngOnInit(): void {
+ }
+ signOut() {
+ this.router.navigate(['/login'])
+ }
+}
diff --git a/src/app/system-management/organization/addor/addor.component.html b/src/app/system-management/organization/addor/addor.component.html
new file mode 100644
index 0000000..a56e67b
--- /dev/null
+++ b/src/app/system-management/organization/addor/addor.component.html
@@ -0,0 +1,23 @@
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/organization/addor/addor.component.scss b/src/app/system-management/organization/addor/addor.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/system-management/organization/addor/addor.component.ts b/src/app/system-management/organization/addor/addor.component.ts
new file mode 100644
index 0000000..177ff23
--- /dev/null
+++ b/src/app/system-management/organization/addor/addor.component.ts
@@ -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' });
+ }
+
+}
diff --git a/src/app/system-management/organization/editor/editor.component.html b/src/app/system-management/organization/editor/editor.component.html
new file mode 100644
index 0000000..d2a5386
--- /dev/null
+++ b/src/app/system-management/organization/editor/editor.component.html
@@ -0,0 +1,23 @@
+
+
+
diff --git a/src/app/system-management/organization/editor/editor.component.scss b/src/app/system-management/organization/editor/editor.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/system-management/organization/editor/editor.component.ts b/src/app/system-management/organization/editor/editor.component.ts
new file mode 100644
index 0000000..a154f55
--- /dev/null
+++ b/src/app/system-management/organization/editor/editor.component.ts
@@ -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' });
+ }
+
+
+}
diff --git a/src/app/system-management/organization/organization.component.html b/src/app/system-management/organization/organization.component.html
new file mode 100644
index 0000000..44c77bf
--- /dev/null
+++ b/src/app/system-management/organization/organization.component.html
@@ -0,0 +1,52 @@
+
+
+
+
组织机构列表
+
+ {{totalCount}}个单位
+
+
+
+
+
+
+
+
+
+
+ 组织机构
+ 操作
+
+
+
+
+
+ {{ node.title }}
+
+ 新增
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/app/system-management/organization/organization.component.scss b/src/app/system-management/organization/organization.component.scss
new file mode 100644
index 0000000..a365d13
--- /dev/null
+++ b/src/app/system-management/organization/organization.component.scss
@@ -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: 700px;
+ 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);
+ 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);
+ }
+}
diff --git a/src/app/system-management/organization/organization.component.ts b/src/app/system-management/organization/organization.component.ts
new file mode 100644
index 0000000..dbb1c7f
--- /dev/null
+++ b/src/app/system-management/organization/organization.component.ts
@@ -0,0 +1,315 @@
+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';
+@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()
+ }
+ //搜索框提交
+ 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"
+ }
+ this.http.get('/api/services/app/Organization/GetAll', {
+ params: params
+ }).subscribe((data: any) => {
+ this.totalCount = data.result.totalCount
+ data.result.items.forEach(element => {
+ element.key = element.id
+ element.title = element.displayName
+ element.selectable = false
+ });
+ this.allOrList = data.result.items
+ this.nodes = [...this.toTree.toTree(data.result.items)]
+ 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 () => {
+ console.log('hhhhhhh', instance.validateForm)
+ if (instance.validateForm.valid) {
+ await new Promise(resolve => {
+ let body = {
+ parentId: node ? Number(node.key) : null,
+ // code: instance.validateForm.value.code,
+ displayName: instance.validateForm.value.name,
+ isGasStation: instance.validateForm.value.isGasStation
+ }
+ this.http.post('/api/services/app/Organization/Create', 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 () => {
+ console.log('hhhhhhh', instance.validateForm)
+ if (instance.validateForm.valid) {
+ await new Promise(resolve => {
+ let body = {
+ id: node.origin.id,
+ parentId: node.origin.parentId,
+ // code: instance.validateForm.value.code,
+ displayName: instance.validateForm.value.name,
+ isGasStation: instance.validateForm.value.isGasStation
+ }
+ this.http.put('/api/services/app/Organization/Update', 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/services/app/Organization/Delete', {
+ params: {
+ Id: 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 = {
+ id: event.dragNode.key,
+ parentId: parentId,
+ // code: instance.validateForm.value.code,
+ displayName: event.dragNode.origin.displayName,
+ isGasStation: event.dragNode.origin.isGasStation
+ }
+ this.http.put('/api/services/app/Organization/Update', 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)
+ }
+ }
+}
diff --git a/src/app/system-management/system-management-routing.module.ts b/src/app/system-management/system-management-routing.module.ts
new file mode 100644
index 0000000..857584d
--- /dev/null
+++ b/src/app/system-management/system-management-routing.module.ts
@@ -0,0 +1,16 @@
+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';
+
+
+const routes: Routes = [
+ { path: 'organization', component: OrganizationComponent },
+ { path: 'host', component: AnalysisOfTheHostComponent },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class SystemRoutingModule { }
diff --git a/src/app/system-management/system-management.module.ts b/src/app/system-management/system-management.module.ts
new file mode 100644
index 0000000..c940b64
--- /dev/null
+++ b/src/app/system-management/system-management.module.ts
@@ -0,0 +1,55 @@
+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 { 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 './analysis-of-the-host/addcamera/addcamera.component';
+import { EditcameraComponent } from './analysis-of-the-host/editcamera/editcamera.component';
+@NgModule({
+ declarations: [OrganizationComponent, NavigationComponent, AddorComponent, EditorComponent, AnalysisOfTheHostComponent, AddhostComponent, EdithostComponent, AddcameraComponent, EditcameraComponent],
+ imports: [
+ CommonModule,
+ SystemRoutingModule,
+ NzLayoutModule,
+ NzIconModule,
+ NzTableModule,
+ NzDropDownModule,
+ NzPaginationModule,
+ NzInputModule,
+ NzButtonModule,
+ NzFormModule,
+ FormsModule,
+ ReactiveFormsModule,
+ NzModalModule,
+ NzSelectModule,
+ NzMessageModule,
+ NzTreeModule,
+ NzSpinModule,
+ NzTreeSelectModule,
+ NzCheckboxModule
+ ],
+ entryComponents :[AddorComponent,EditorComponent,AddhostComponent,EdithostComponent,AddcameraComponent,EditcameraComponent]
+
+})
+export class SystemManagementModule { }
diff --git a/src/assets/images/bgImg.png b/src/assets/images/bgImg.png
new file mode 100644
index 0000000..0c9cc2a
Binary files /dev/null and b/src/assets/images/bgImg.png differ
diff --git a/src/assets/images/icon/admin.png b/src/assets/images/icon/admin.png
new file mode 100644
index 0000000..f7f11ef
Binary files /dev/null and b/src/assets/images/icon/admin.png differ
diff --git a/src/assets/images/icon/host.png b/src/assets/images/icon/host.png
new file mode 100644
index 0000000..20d356c
Binary files /dev/null and b/src/assets/images/icon/host.png differ
diff --git a/src/assets/images/icon/organization.png b/src/assets/images/icon/organization.png
new file mode 100644
index 0000000..6fc46c2
Binary files /dev/null and b/src/assets/images/icon/organization.png differ
diff --git a/src/assets/images/icon/orgrey.png b/src/assets/images/icon/orgrey.png
new file mode 100644
index 0000000..b29d3f9
Binary files /dev/null and b/src/assets/images/icon/orgrey.png differ
diff --git a/src/assets/images/icon/power.png b/src/assets/images/icon/power.png
new file mode 100644
index 0000000..d9e9600
Binary files /dev/null and b/src/assets/images/icon/power.png differ
diff --git a/src/assets/images/icon/push.png b/src/assets/images/icon/push.png
new file mode 100644
index 0000000..f52e818
Binary files /dev/null and b/src/assets/images/icon/push.png differ
diff --git a/src/assets/images/icon/role.png b/src/assets/images/icon/role.png
new file mode 100644
index 0000000..9ec88e9
Binary files /dev/null and b/src/assets/images/icon/role.png differ
diff --git a/src/assets/images/icon/user.png b/src/assets/images/icon/user.png
new file mode 100644
index 0000000..6962ffd
Binary files /dev/null and b/src/assets/images/icon/user.png differ
diff --git a/src/assets/images/logo2.png b/src/assets/images/logo2.png
new file mode 100644
index 0000000..afada94
Binary files /dev/null and b/src/assets/images/logo2.png differ
diff --git a/src/assets/images/userbig.png b/src/assets/images/userbig.png
new file mode 100644
index 0000000..e3a8388
Binary files /dev/null and b/src/assets/images/userbig.png differ
diff --git a/tsconfig.json b/tsconfig.json
index f531992..7d06704 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,26 +2,27 @@
{
"compileOnSave": false,
"compilerOptions": {
+ "allowJs": true,
"baseUrl": "./",
"outDir": "./dist/out-tsc",
- "forceConsistentCasingInFileNames": true,
- "strict": true,
- "noImplicitOverride": true,
- "noPropertyAccessFromIndexSignature": true,
- "noImplicitReturns": true,
- "noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
+ "module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
- "target": "es2017",
- "module": "es2020",
+ "target": "es2015",
+ "typeRoots": [
+ "node_modules/@types"
+ ],
"lib": [
- "es2020",
+ "es2018",
"dom"
- ]
+ ],
+ "paths": {
+ "@node_modules/*": [ "../node_modules/*" ]
+ }
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,