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,