Browse Source

[新增]提交架构文件

master
邵佳豪 4 years ago
commit
7d9abedf5f
  1. 13
      .editorconfig
  2. 46
      .gitignore
  3. 3
      README.md
  4. 133
      angular.json
  5. 12
      browserslist
  6. 32
      e2e/protractor.conf.js
  7. 23
      e2e/src/app.e2e-spec.ts
  8. 11
      e2e/src/app.po.ts
  9. 13
      e2e/tsconfig.json
  10. 32
      karma.conf.js
  11. 17754
      package-lock.json
  12. 60
      package.json
  13. 7
      proxy.config.json
  14. 27
      reset.css
  15. 5098
      src/app/_theming.scss
  16. 32
      src/app/app-routing.module.ts
  17. 1
      src/app/app.component.html
  18. 0
      src/app/app.component.scss
  19. 35
      src/app/app.component.spec.ts
  20. 44
      src/app/app.component.ts
  21. 42
      src/app/app.module.ts
  22. 31
      src/app/auth.guard.ts
  23. 11
      src/app/component-service.service.ts
  24. 82
      src/app/http-interceptors/base-interceptor.ts
  25. 38
      src/app/http-interceptors/cache-token.service.ts
  26. 9
      src/app/http-interceptors/index.ts
  27. 38
      src/app/http-interceptors/tree.service.ts
  28. 14
      src/app/interface.ts
  29. 103
      src/app/is-login.service.ts
  30. 14
      src/app/navigation/adddatabank.html
  31. 14
      src/app/navigation/editdatabankname.html
  32. 30
      src/app/navigation/navigation.component.html
  33. 191
      src/app/navigation/navigation.component.scss
  34. 280
      src/app/navigation/navigation.component.ts
  35. 116
      src/app/navigation/navigation.module.ts
  36. 39
      src/app/pages/lockscreen/lockscreen.component.html
  37. 143
      src/app/pages/lockscreen/lockscreen.component.scss
  38. 25
      src/app/pages/lockscreen/lockscreen.component.spec.ts
  39. 67
      src/app/pages/lockscreen/lockscreen.component.ts
  40. 33
      src/app/pages/login/login.component.html
  41. 103
      src/app/pages/login/login.component.scss
  42. 25
      src/app/pages/login/login.component.spec.ts
  43. 62
      src/app/pages/login/login.component.ts
  44. 17
      src/app/pages/pages-routing.module.ts
  45. 1
      src/app/pages/pages.component.html
  46. 0
      src/app/pages/pages.component.scss
  47. 25
      src/app/pages/pages.component.spec.ts
  48. 15
      src/app/pages/pages.component.ts
  49. 112
      src/app/pages/pages.module.ts
  50. 280
      src/app/pages/personaldata/personaldata.component.html
  51. 110
      src/app/pages/personaldata/personaldata.component.scss
  52. 25
      src/app/pages/personaldata/personaldata.component.spec.ts
  53. 15
      src/app/pages/personaldata/personaldata.component.ts
  54. 81
      src/app/pages/register/register.component.html
  55. 88
      src/app/pages/register/register.component.scss
  56. 25
      src/app/pages/register/register.component.spec.ts
  57. 19
      src/app/pages/register/register.component.ts
  58. 45
      src/app/pipes/size.pipe.ts
  59. 31
      src/app/tabbar/tabbar.component.html
  60. 12
      src/app/tabbar/tabbar.component.scss
  61. 25
      src/app/tabbar/tabbar.component.spec.ts
  62. 78
      src/app/tabbar/tabbar.component.ts
  63. 18
      src/app/theme.scss
  64. 159
      src/app/ui/all-file/all-file.component.html
  65. 265
      src/app/ui/all-file/all-file.component.scss
  66. 25
      src/app/ui/all-file/all-file.component.spec.ts
  67. 918
      src/app/ui/all-file/all-file.component.ts
  68. 14
      src/app/ui/all-file/folderdalog.html
  69. 12
      src/app/ui/all-file/viewdetails.html
  70. 48
      src/app/ui/changepassword/changepassword.component.html
  71. 15
      src/app/ui/changepassword/changepassword.component.scss
  72. 39
      src/app/ui/changepassword/changepassword.component.ts
  73. 30
      src/app/ui/changepassword/equal-validator.directive.ts
  74. 20
      src/app/ui/changeuserdata/changeuserdata.component.html
  75. 0
      src/app/ui/changeuserdata/changeuserdata.component.scss
  76. 25
      src/app/ui/changeuserdata/changeuserdata.component.spec.ts
  77. 22
      src/app/ui/changeuserdata/changeuserdata.component.ts
  78. 1
      src/app/ui/create-exam/create-exam.component.html
  79. 0
      src/app/ui/create-exam/create-exam.component.scss
  80. 25
      src/app/ui/create-exam/create-exam.component.spec.ts
  81. 15
      src/app/ui/create-exam/create-exam.component.ts
  82. 39
      src/app/ui/eharts-statistics/eharts-statistics.component.html
  83. 50
      src/app/ui/eharts-statistics/eharts-statistics.component.scss
  84. 25
      src/app/ui/eharts-statistics/eharts-statistics.component.spec.ts
  85. 228
      src/app/ui/eharts-statistics/eharts-statistics.component.ts
  86. 49
      src/app/ui/enterpriseuser/addenterpriseuser.component.html
  87. 67
      src/app/ui/enterpriseuser/addenterpriseuser.component.ts
  88. 46
      src/app/ui/enterpriseuser/editenterpriseuser.html
  89. 68
      src/app/ui/enterpriseuser/enterpriseuser.component.html
  90. 63
      src/app/ui/enterpriseuser/enterpriseuser.component.scss
  91. 25
      src/app/ui/enterpriseuser/enterpriseuser.component.spec.ts
  92. 302
      src/app/ui/enterpriseuser/enterpriseuser.component.ts
  93. 0
      src/app/ui/enterpriseuser/seeenterpriseuser.html
  94. 1
      src/app/ui/join-exam/join-exam.component.html
  95. 0
      src/app/ui/join-exam/join-exam.component.scss
  96. 25
      src/app/ui/join-exam/join-exam.component.spec.ts
  97. 15
      src/app/ui/join-exam/join-exam.component.ts
  98. 49
      src/app/ui/learning-record-details/learning-record-details.component.html
  99. 57
      src/app/ui/learning-record-details/learning-record-details.component.scss
  100. 188
      src/app/ui/learning-record-details/learning-record-details.component.ts
  101. Some files were not shown because too many files have changed in this diff Show More

13
.editorconfig

@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

46
.gitignore vendored

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

3
README.md

@ -0,0 +1,3 @@
# AnxinCloudDisk
安信云盘-前端项目

133
angular.json

@ -0,0 +1,133 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"anxin119": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss",
"spec": false
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/anxin119",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": [
"node_modules/echarts/dist/echarts.js",
"src/assets/echarts/echarts.common.min.js"
]
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "anxin119:build",
"proxyConfig": "proxy.config.json"
},
"configurations": {
"production": {
"browserTarget": "anxin119:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "anxin119:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "anxin119:serve"
},
"configurations": {
"production": {
"devServerTarget": "anxin119:serve:production"
}
}
}
}
}},
"defaultProject": "anxin119"
}

12
browserslist

@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

32
e2e/protractor.conf.js

@ -0,0 +1,32 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

23
e2e/src/app.e2e-spec.ts

@ -0,0 +1,23 @@
import { AppPage } from './app.po';
import { browser, logging } from 'protractor';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', () => {
page.navigateTo();
expect(page.getTitleText()).toEqual('anxin119 app is running!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});

11
e2e/src/app.po.ts

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css('app-root .content span')).getText() as Promise<string>;
}
}

13
e2e/tsconfig.json

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

32
karma.conf.js

@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/anxin119'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

17754
package-lock.json generated

File diff suppressed because it is too large Load Diff

60
package.json

@ -0,0 +1,60 @@
{
"name": "anxin119",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.config.json --open --port 4300 ",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^9.0.0",
"@angular/cdk": "^9.0.0",
"@angular/common": "~9.0.0",
"@angular/compiler": "~9.0.0",
"@angular/core": "~9.0.0",
"@angular/fire": "^5.3.0",
"@angular/forms": "~9.0.0",
"@angular/material": "^9.0.0",
"@angular/platform-browser": "~9.0.0",
"@angular/platform-browser-dynamic": "~9.0.0",
"@angular/router": "~9.0.0",
"@types/cesium": "^1.59.5",
"angular-calendar": "^0.28.2",
"cesium": "^1.64.0",
"date-fns": "^2.9.0",
"e-ngx-cesium": "^6.3.2",
"echarts": "^4.6.0",
"firebase": "^7.6.2",
"ng2-file-upload": "^1.4.0",
"ngx-echarts": "^4.2.2",
"ngx-perfect-scrollbar": "^8.0.0",
"rxjs": "~6.5.4",
"tslib": "^1.10.0",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.900.1",
"@angular/cli": "~9.0.1",
"@angular/compiler-cli": "~9.0.0",
"@angular/language-service": "~9.0.0",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"@types/node": "^12.11.1",
"codelyzer": "^5.1.2",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.7.5"
}
}

7
proxy.config.json

@ -0,0 +1,7 @@
{
"/api": {
"target": "http://121.37.20.190:8100/",
"secure": false,
"changeOrigin": true
}
}

27
reset.css

@ -0,0 +1,27 @@
@charset "utf-8";
html,body,ul,ol,dl,li,dt,dd,p,form,input,h1,h2,h3,h4,h5,h6,section,article,aside,header,footer,nav,figure,time,mark,main,canvas{
margin:0;
padding:0;
font-size:16px;
}
b,strong,i,em,h1,h2,h3,h4,h5,h6{
font-weight:500;
font-style:normal;
}
img{
border:none;
}
a{
text-decoration: none;
color:#000;
ul,ol,li{
list-style:none;
}
.clearfn:after{
content:"";
clear:both;
display: block;
overflow:hidden;
height:0;
visibility: hidden;
}

5098
src/app/_theming.scss

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,32 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { RegisterComponent } from './pages/register/register.component';
import { NavigationComponent } from './navigation/navigation.component';
import { LockscreenComponent } from './pages/lockscreen/lockscreen.component';
//路由守卫
import {AuthGuard} from './auth.guard'
const routes: Routes = [
{path:'',redirectTo:'login',pathMatch:'full'},
{
path:'home',
component:NavigationComponent,
canActivate: [AuthGuard],//守卫验证
children:[
{path:'',loadChildren:() => import('./ui/ui.module').then(m => m.UiModule)}
]
},
{ path:'adminLogin', component:LoginComponent}, //管理员登录路由
{ path:'login', component:LockscreenComponent}, //教员学员登录路由
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

1
src/app/app.component.html

@ -0,0 +1 @@
<router-outlet></router-outlet>

0
src/app/app.component.scss

35
src/app/app.component.spec.ts

@ -0,0 +1,35 @@
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'anxin119'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('anxin119');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('anxin119 app is running!');
});
});

44
src/app/app.component.ts

@ -0,0 +1,44 @@
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Data } from './interface'
import { Router,ActivatedRoute } from '@angular/router'
import { IsLoginService } from './is-login.service' //引入服务
import {CacheTokenService} from './http-interceptors/cache-token.service' //引入服务
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(private http:HttpClient,private router:Router,public token:CacheTokenService,public isLogin:IsLoginService) { }
ngOnInit(): void {
let token = sessionStorage.getItem("token");
let refreshToken = sessionStorage.getItem("refreshToken");
if(token && refreshToken) {
this.http.post('/api/Account/RefreshToken', {
token: token,
refreshToken: refreshToken
}).subscribe((data:any) => {
sessionStorage.setItem('realName',data.realName)
sessionStorage.setItem('roleType',data.roleType)
sessionStorage.setItem("token",data.token);
sessionStorage.setItem("refreshToken",data.refreshToken);
this.token.startUp()
})
} else {
sessionStorage.clear()
this.token.delete()
}
}
}

42
src/app/app.module.ts

@ -0,0 +1,42 @@
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 { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatIconModule } from '@angular/material/icon';
import { MatSidenavModule } from '@angular/material/sidenav';
import { NavigationModule } from './navigation/navigation.module';
import { TabbarComponent } from './tabbar/tabbar.component';
import { PagesModule } from './pages/pages.module';
import { FormsModule } from '@angular/forms';
import { UiModule } from './ui/ui.module';
import { HttpClientModule } from '@angular/common/http';
import { httpInterceptorProviders } from './http-interceptors/index'
import {CacheTokenService} from './http-interceptors/cache-token.service'
import { TreeService } from'./http-interceptors/tree.service'
import { IsLoginService } from './is-login.service';
import { ComponentServiceService } from './component-service.service';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule,
BrowserAnimationsModule,
MatButtonModule,
MatCheckboxModule,
MatSidenavModule,
NavigationModule,
MatIconModule,
PagesModule,
FormsModule,
HttpClientModule
],
providers: [httpInterceptorProviders, CacheTokenService,TreeService,ComponentServiceService],
bootstrap: [AppComponent]
})
export class AppModule { }

31
src/app/auth.guard.ts

@ -0,0 +1,31 @@
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router) {
}
// 路由守卫
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.checkLogin();
}
checkLogin(): boolean {
// 判断本地有没有token
const token = sessionStorage.getItem('token');
// 如果有token,允许访问
if (token) { return true; }
//如果没有token,跳转登录页
this.router.navigate(['/login']);
return false;
}
}

11
src/app/component-service.service.ts

@ -0,0 +1,11 @@
import { Injectable, EventEmitter, OnInit } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ComponentServiceService {
public eventEmit: any;
constructor() {
this.eventEmit = new EventEmitter();
}
}

82
src/app/http-interceptors/base-interceptor.ts

@ -0,0 +1,82 @@
import { Injectable } from '@angular/core';
import {
HttpClient, HttpEvent, HttpInterceptor, HttpHandler, HttpRequest,
HttpErrorResponse
} from '@angular/common/http';
import { throwError } from 'rxjs'
import { catchError, retry } from 'rxjs/operators';
import { Router,ActivatedRoute } from '@angular/router'
import { CacheTokenService } from './cache-token.service'
import { IsLoginService } from '../is-login.service'
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
//baseurl
// const baseurl = 'http://39.106.78.171:8008';
@Injectable()
export class BaseInterceptor implements HttpInterceptor {
constructor(private http:HttpClient,private router:Router,private route:ActivatedRoute,public token:CacheTokenService,public snackBar: MatSnackBar,public isLogin: IsLoginService) {}
intercept(req, next: HttpHandler) {
let newReq = req.clone({
url: req.hadBaseurl ? `${req.url}` : `${req.url}`,
});
if(!req.cancelToken) {
/*获取token*/
let token = sessionStorage.getItem("token") || ''
/*此处设置额外请求头,token令牌*/
newReq.headers =
newReq.headers.set('Authorization', `Bearer ${token}`)
}
// 携带请求头发送下一次请求
return next.handle(newReq)
.pipe(
//箭头函数,注意this指向
catchError((err) => this.handleError(err))
)
}
// 捕获错误
//401 token过期 403没权限!!! 400参数错误 404未找到 614刷新令牌过期!!!
private handleError(error: HttpErrorResponse) {
// 用户认证失败返回登录页
if (error.status === 401||error.status === 614) {
sessionStorage.clear()
this.router.navigate(['/login'])
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('用户认证信息过期,请重新登录','确定',config);
}
if (error.status === 403) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('对不起,您无此权限','确定',config);
}
if (error.status === 400) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('您输入的参数有误','确定',config);
}
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.error);
};
}

38
src/app/http-interceptors/cache-token.service.ts

@ -0,0 +1,38 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'
@Injectable({
providedIn: 'root'
})
export class CacheTokenService {
constructor(private http:HttpClient) { }
public timer;
//刷新token令牌定时器
startUp = ():void=>{
window.clearInterval(this.timer) //清一遍定时器
this.timer = window.setInterval(()=>{
var token = sessionStorage.getItem("token");
var refreshToken = sessionStorage.getItem("refreshToken");
if (token && refreshToken) {
this.http.post('/api/Account/RefreshToken', {
token: token,
refreshToken: refreshToken,
}).subscribe((data:any) => {
sessionStorage.setItem('realName',data.realName)
sessionStorage.setItem('roleType',data.roleType)
sessionStorage.setItem("token",data.token);
sessionStorage.setItem("refreshToken",data.refreshToken);
})
} else { this.delete() }
},18*60*1000)
}
//删除定时器
delete = ():void=> {
window.clearInterval(this.timer)
}
}

9
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 },
];

38
src/app/http-interceptors/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;
}
}

14
src/app/interface.ts

@ -0,0 +1,14 @@
export interface Data {
token:string,
refreshToken:string,
expires: number,
realName:string
}
export interface windows {
token:string
}
export enum isno {
"是",
"否"
}

103
src/app/is-login.service.ts

@ -0,0 +1,103 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class IsLoginService {
constructor(private http: HttpClient) { }
isDownloading:boolean = false; //下载状态
downloadProgress:number = 0;//下载进度
//下载
download (e) {
this.isDownloading = true //开启下载进度条
let file = e //传递过来的文件元数据
let fileSize = file.fileLength //下载文件的总大小
let shardSize = 10 * 1024 * 1024 //文件大小是否大于10MB
if (file && fileSize<=shardSize) { //<=10MB时直接下载
this.downloadProgress = 70
this.http.get(`/api/Objects/drives/${file.objectName}`,{responseType: 'blob'},).subscribe(data=>{
let url = window.URL.createObjectURL(new Blob([data])); //createObjectURL创建一个下载Blob的url地址
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.setAttribute("download", e.fileName);
document.body.appendChild(link);
link.click();
this.isDownloading = false //关闭下载进度条
this.downloadProgress = 0 //初始化进度条
this.handleData(e.objectName,'下载') //存储用户操作记录
})
} else if (file && fileSize>shardSize) { //>10MB时分块下载
this.blockingDownload(e) //分段下载
}
}
//分段下载并合并
async blockingDownload (e) {
let file = e //传递过来的文件元数据
let fileSize = file.fileLength //下载文件的总大小
let shardSize = 3 * 1024 * 1024 //3MB一个分片
let allSlice = Math.ceil(fileSize / shardSize) //总文件/3MB===共分多少段
let allFile:any = [] //所有的file分段
for (let i=0;i<allSlice;i++) {
let start = i * shardSize //每次下载文件开始位置
let end = Math.min(fileSize, start + shardSize-1); //每次下载文件结束为止
let result = await new Promise ((result,reject)=>{
this.http.get(`/api/Objects/drives/${file.objectName}`,{headers:{'range':`bytes= ${start}-${end}`},responseType:'blob'}).subscribe(data=>{
result(data) })
})
allFile.push(result)
this.downloadProgress = Number((i/allSlice).toFixed(2))*100 //文件进度数
if (allFile.length === allSlice) { //合并文件输出给浏览器
let url = window.URL.createObjectURL(new Blob(allFile)); //createObjectURL创建一个下载Blob的url地址
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.setAttribute("download", e.fileName);
document.body.appendChild(link);
link.click();
this.isDownloading = false //关闭下载进度条
this.downloadProgress = 0 //初始化进度条
this.handleData(e.objectName,'下载') //存储用户操作记录
}
} //for循环结束
}
//处理学习记录数据
handleData (data,operate) {
let msg = data.split('/')
let bodyData = {
creationTime: new Date(), //时间
operation: operate, //操作
postName: msg[1], //职务名称
catalog: msg[2], //目录
target: data, //objectName
}
this.operationLog(bodyData)
}
//存储用户操作行为 学习记录
operationLog (data) {
this.http.post('/api/StudyRecords',data).subscribe(data=>{})
}
}

14
src/app/navigation/adddatabank.html

@ -0,0 +1,14 @@
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<mat-form-field>
<input matInput id="name" name="name" type='text'
required
ngModel #name="ngModel" placeholder="请输入资料库名称">
</mat-form-field>
<div class="btn">
<button type="submit" class="savebtn" mat-raised-button color="primary" [disabled]='form.invalid'>确定</button>
<button type="button" mat-button (click)="onNoClick()" mat-raised-button>取消</button>
</div>
</form>

14
src/app/navigation/editdatabankname.html

@ -0,0 +1,14 @@
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<mat-form-field>
<input matInput id="name" name="name" type='text'
required
[(ngModel)]="dataBankName" placeholder="修改资料库名称">
</mat-form-field>
<div class="btn">
<button type="submit" class="savebtn" mat-raised-button color="primary" [disabled]='form.invalid'>确定</button>
<button type="button" mat-button (click)="onNoClick()" mat-raised-button>取消</button>
</div>
</form>

30
src/app/navigation/navigation.component.html

@ -0,0 +1,30 @@
<mat-sidenav-container class="example-container" autosize [class.myapp-dark-theme]="darktheme">
<mat-sidenav #drawer class="example-sidenav" mode="side" opened="true" color="primary" style="overflow-x: hidden;">
<div class="biglogobox">
<img src="../../assets/images/logo.png" alt="logo">
</div>
<div class="navbox">
<ul class="teacher">
<li [routerLink]="['/home/createexam']" routerLinkActive="router-link-active" >创建考试</li>
<li [routerLink]="['/home/looktest']" routerLinkActive="router-link-active" >阅卷</li>
<li [routerLink]="['/home/statisticAnalysis']" routerLinkActive="router-link-active" >统计分析</li>
</ul>
<ul class="student">
<li [routerLink]="['/home/joinExam']" routerLinkActive="router-link-active" >参加考试</li>
<li [routerLink]="['/home/testRecords']" routerLinkActive="router-link-active" >考试记录</li>
</ul>
</div>
</mat-sidenav>
<div class="example-sidenav-content">
<app-tabbar (toggleDarkTheme)="switchTheme($event)" (defaulttheme)="defaulttheme()" (redtheme)="redtheme()"></app-tabbar>
<router-outlet></router-outlet>
<!-- <app-all-file #child></app-all-file> -->
</div>
</mat-sidenav-container>

191
src/app/navigation/navigation.component.scss

@ -0,0 +1,191 @@
.example-container {
width: 100%;
height:100%;
}
mat-accordion{
height: 100%;
}
mat-sidenav{
box-shadow: 2px 0px 5px #888888;
color: white;
background: url(../../assets/images/main_bg.png) 100% 100%;
width: 194px;
overflow-x: hidden;
p{
height: 48px;
cursor: pointer;
font-size: 16px;
line-height: 48px;
}
ul{
width: 100%;
li{
list-style: none;
height: 48px;
line-height: 48px;
cursor: pointer;
color: white;
width: 194px;
// text-align: center;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
li:hover{
background-color: #5d9cf2;
}
}
}
.logobox{
border-radius: 50%;
width: 64px;
height: 64px;
background:url("https://img5.tianyancha.com/logo/lll/cce72488294fb8f4bc670a5bb7f0cc4d.png@!f_200x200") no-repeat;
background-size: 100%;
margin: 0px auto;
img{
width: 100%;
height: 100%;
}
}
.shownav{
position: absolute;
top: 13px;
z-index: 200;
}
.mat-accordion .mat-expansion-panel:first-of-type {
border-top-right-radius:0px;
border-top-left-radius:0px;
}
.mat-accordion .mat-expansion-panel:last-of-type {
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
}
.mat-expansion-panel{
border-radius: 0px;
}
.mat-expansion-panel-spacing {
margin: 0px;
}
.superdiv{
padding-left: 31px;
}
mat-icon{
color: white;
}
.navbox{
position: absolute;
overflow: hidden;
left: 0px;
top: 149px;
right: -18px;
bottom: 0px;
overflow-y: scroll;
font-size: 15px;
.router-link-active{
background-color: #5d9cf2;
}
ul{
li{
position: relative;
text-align: center;
border-bottom: 1px solid #326db1;
}
}
}
mat-sidenav-container.myapp-dark-theme{
background-color: #fafafa;
color: black;
mat-panel-title{
color: black;
}
ul li{
background-color: white;
color: black;
}
.biglogobox{
background-color: #d50000;
}
color: black;
}
.biglogobox{
width: 194px;
height: 148px;
background-color: #4699f6;
display: block;
text-align: center;
position: relative;
left: 0;
margin-bottom: 20px;
color: #FFF;
margin: 0 auto;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
img{
width: 138px;
height: 138px;
margin-top: 6px;
}
}
mat-panel-title mat-icon{
color: #afb2bb;
font-size: 16px;
line-height: 24px;
margin-right: 6px;
}
mat-expansion-panel{
background-color: #4699f6;
mat-expansion-panel-header{
padding-left: 15px;
color: white;
}
ul{
li{
text-align: left;
padding-left: 60px;
}
}
// mat-panel-title{
// color: white;
// }
}
.mat-expansion-indicator::after {
color: white;
}
.example-container .navbox .router-link-active {
background-color: rgba(225,225,225,.5);
border:0
}
.btn{
text-align: center;
button{
margin: 0 5px;
}
}
.example-sidenav-content{
height: 100%;
overflow: hidden;
}
//一级目录前图标
.logoIcon{
display: inline-block;
margin-right: 10px;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
border-radius: 50%;
border: 2px solid #fff;
font-weight: 550;
}

280
src/app/navigation/navigation.component.ts

@ -0,0 +1,280 @@
import { Component, OnInit ,Inject,ViewChild} from '@angular/core';
import { CacheTokenService } from '../http-interceptors/cache-token.service'//引入服务
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { FormControl } from '@angular/forms';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { IsLoginService } from '../is-login.service'
import { AllFileComponent } from '../ui/all-file/all-file.component';
import { ComponentServiceService } from '../component-service.service';
import { Router,ActivatedRoute } from '@angular/router'
@Component({
selector: 'app-navigation',
templateUrl: './navigation.component.html',
styleUrls: ['./navigation.component.scss']
})
export class NavigationComponent implements OnInit {
constructor(private router:Router,public emitService: ComponentServiceService,public navmenus:CacheTokenService,private http: HttpClient,public dialog: MatDialog,public snackBar: MatSnackBar,public islogin:IsLoginService) { }
@ViewChild('child') child:AllFileComponent; //父组件中获得子组件的引用
allDataBank:any //所有的资料库
selectedDataBank:any //当前选中的资料库
hoverDataBank:any //当前鼠标移入的资料库
isOneClick:boolean //是否第一次进入网页
//支队级菜单
detachmentMenus:any = [
{ id:"支队级-主官", name:"主官" },
{ id:"支队级-副官", name:"副官" },
{ id:"支队级-灭火救援指挥岗位", name:"灭火救援指挥岗位" },
{ id:"支队级-政工岗位", name:"政工岗位" },
{ id:"支队级-后勤与保障岗位", name:"后勤与保障岗位" },
{ id:"支队级-防火监督岗位", name:"防火监督岗位" },
{ id:"支队级-指挥中心", name:"指挥中心" },
{ id:"支队级-安全员", name:"安全员" },
]
//大队级菜单
brigadeMenus:any = [
{ id:"大队级-主官", name:"主官" },
{ id:"大队级-副官", name:"副官" },
{ id:"大队级-灭火救援指挥岗位", name:"灭火救援指挥岗位" },
{ id:"大队级-政工岗位", name:"政工岗位" },
{ id:"大队级-后勤与保障岗位", name:"后勤与保障岗位" },
{ id:"大队级-防火监督岗位", name:"防火监督岗位" },
{ id:"大队级-安全员", name:"安全员" },
]
//消防救援站菜单
rescueStationMenus:any = [
{ id:"消防救援站-消防站指挥员", name:"消防站指挥员" },
{ id:"消防救援站-站长助理", name:"站长助理" },
{ id:"消防救援站-战斗员", name:"战斗员" },
{ id:"消防救援站-供水源", name:"供水源" },
{ id:"消防救援站-训导员", name:"训导员" },
{ id:"消防救援站-通信员", name:"通信员" },
{ id:"消防救援站-无人机飞手", name:"无人机飞手" },
{ id:"消防救援站-消防车驾驶员", name:"消防车驾驶员" },
{ id:"消防救援站-装备技师", name:"装备技师" }
]
//系统管理菜单
systemManagement:any = [
{ id:"学员管理", name:"学员管理" },
{ id:"教员管理", name:"教员管理" }
]
isAdmin:boolean = false
ngOnInit() {
// this.http.get('/api/DataBanks').subscribe((data:any) => {
// if(data && data.length != 0){
// this.selectedDataBank = data[0].id
// }
// })
// this.getAllDataBank()
this.selectedDataBank = "支队级-主官"
if(sessionStorage.getItem("roleType") == "0"){
this.isAdmin = true
}
}
darktheme = false;//黑夜主题
switchTheme(dark) {
this.darktheme = dark;
}
defaulttheme(){
this.darktheme = false
}
redtheme(){
this.darktheme = true
}
//点击用户管理
clickUser(item){
this.selectedDataBank = item.id
if(item.name == "学员管理"){
this.router.navigate([`/home/userManagement`])
}else if(item.name == "教员管理"){
this.router.navigate([`/home/teacherManagement`])
}
}
//新增资料库
// addDataBank(){
// const dialogRef = this.dialog.open(AddDataBank, {//调用open方法打开对话框并且携带参数过去
// width: '260px',
// data: {}
// });
// dialogRef.afterClosed().subscribe(
// (data:any)=>{
// if(data){
// let headers = new HttpHeaders({
// 'Content-Type': 'text/json'
// });
// let options = {
// headers
// };
// let body = JSON.stringify(data.name);
// this.http.post('/api/DataBanks',body,options).subscribe(data => {
// this.getAllDataBank()
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open('创建资料库成功','确定',config);
// },
// err => {
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open(err,'确定',config);
// })
// }
// }
// );
// }
//获得所有资料库
// getAllDataBank(){
// this.http.get('/api/DataBanks').subscribe(data => {
// this.allDataBank = data
// // console.log(123,data)
// }
// ,
// err=>{
// // console.log(456,err)
// })
// }
//点击资料库
clickLi(item){
this.selectedDataBank = item.id
//触发子组件的方法
// this.child.getALLFileList(item.id);
// this.child.selection.clear();
this.router.navigate([`/home`])
this.emitService.eventEmit.emit(item.id);
}
//鼠标移入资料库
liEnter(item){
this.hoverDataBank = item.id
}
//鼠标移出资料库
liLeave(item){
this.hoverDataBank = ""
}
//修改资料库名称
editDataBankName(e,item){
e.stopPropagation()
const dialogRef = this.dialog.open(EditDataBankName, {//调用open方法打开对话框并且携带参数过去
width: '260px',
data: {name:item.name}
});
dialogRef.afterClosed().subscribe(
(data:any)=>{
if(data){
if(data != item.name){
let headers = new HttpHeaders({
'Content-Type': 'text/json'
});
let options = {
headers
};
let body = JSON.stringify(data.name);
this.http.put(`/api/DataBanks/${item.id}`,body,options).subscribe(data => {
// this.getAllDataBank()
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('修改资料库名称成功','确定',config);
})
}
}
}
);
}
//删除资料库
deleteDataBank(e,item){
e.stopPropagation()
var r = confirm(`您确定要删除 ${item.name} 资料库吗?`);
if (r == true) {
this.http.delete(`/api/DataBanks/${item.id}`).subscribe(data => {
// this.getAllDataBank()
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除成功','确定',config);
},
err=>{
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除失败,请联系管理员','确定',config);
})
}
}
}
//新增资料库
@Component({
selector: 'adddatabank',
templateUrl: './adddatabank.html',
styleUrls: ['./navigation.component.scss']
})
export class AddDataBank {
myControl = new FormControl();
constructor(private http: HttpClient,public dialogRef: MatDialogRef<AddDataBank>,@Inject(MAT_DIALOG_DATA) public data,public snackBar: MatSnackBar) {}
onNoClick(): void {
this.dialogRef.close();
}
onSubmit(value){
if ( value.name.includes('/') ) {
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('名称不允许有特殊字符','确定',config);
} else {
this.dialogRef.close(value);
}
}
}
//更改资料库名称
@Component({
selector: 'editdatabankname',
templateUrl: './editdatabankname.html',
styleUrls: ['./navigation.component.scss']
})
export class EditDataBankName {
myControl = new FormControl();
constructor(private http: HttpClient,public dialogRef: MatDialogRef<EditDataBankName>,@Inject(MAT_DIALOG_DATA) public data,public snackBar: MatSnackBar) {}
dataBankName:any = this.data.name//要修改的资料库原名称
onNoClick(): void {
this.dialogRef.close();
}
onSubmit(value){
if ( value.name.includes('/') ) {
let config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('名称不允许有特殊字符','确定',config);
} else {
this.dialogRef.close(value);
}
}
}

116
src/app/navigation/navigation.module.ts

@ -0,0 +1,116 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NavigationComponent, AddDataBank, EditDataBankName } from './navigation.component';
import { MatIconModule } from '@angular/material/icon';
import { MatSidenavModule } from '@angular/material/sidenav';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { TabbarComponent } from '../tabbar/tabbar.component';
import { UiModule } from '../ui/ui.module';
import {A11yModule} from '@angular/cdk/a11y';
import {DragDropModule} from '@angular/cdk/drag-drop';
import {PortalModule} from '@angular/cdk/portal';
import {ScrollingModule} from '@angular/cdk/scrolling';
import {CdkStepperModule} from '@angular/cdk/stepper';
import {CdkTableModule} from '@angular/cdk/table';
import {CdkTreeModule} from '@angular/cdk/tree';
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import {MatBadgeModule} from '@angular/material/badge';
import {MatBottomSheetModule} from '@angular/material/bottom-sheet';
import {MatButtonModule} from '@angular/material/button';
import {MatButtonToggleModule} from '@angular/material/button-toggle';
import {MatCardModule} from '@angular/material/card';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatChipsModule} from '@angular/material/chips';
import {MatStepperModule} from '@angular/material/stepper';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatDialogModule} from '@angular/material/dialog';
import {MatDividerModule} from '@angular/material/divider';
import {MatExpansionModule} from '@angular/material/expansion';
import {MatGridListModule} from '@angular/material/grid-list';
import {MatInputModule} from '@angular/material/input';
import {MatListModule} from '@angular/material/list';
import {MatMenuModule} from '@angular/material/menu';
import {MatNativeDateModule, MatRippleModule} from '@angular/material/core';
import {MatPaginatorModule} from '@angular/material/paginator';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatRadioModule} from '@angular/material/radio';
import {MatSelectModule} from '@angular/material/select';
import {MatSliderModule} from '@angular/material/slider';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatSnackBarModule} from '@angular/material/snack-bar';
import {MatSortModule} from '@angular/material/sort';
import {MatTableModule} from '@angular/material/table';
import {MatTabsModule} from '@angular/material/tabs';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatTreeModule} from '@angular/material/tree';
@NgModule({
declarations: [
NavigationComponent,
TabbarComponent,
AddDataBank,
EditDataBankName
],
imports: [
CommonModule,
MatSidenavModule,
RouterModule,
MatIconModule,
FormsModule,
UiModule,
A11yModule,
CdkStepperModule,
CdkTableModule,
CdkTreeModule,
DragDropModule,
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatStepperModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
PortalModule,
ScrollingModule
],
exports: [
NavigationComponent
]
})
export class NavigationModule { }

39
src/app/pages/lockscreen/lockscreen.component.html

@ -0,0 +1,39 @@
<div class="content">
<h1 class="header">考试系统</h1>
<div class="loginBox">
<div class="center">
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<div class="input" style="margin-bottom: 50px;">
<label class="role" [ngClass]="{'isCheck': roleType=='2'}" (click)='toggle(2)'>学员</label>
<label class="role" [ngClass]="{'isCheck': roleType=='1'}" (click)='toggle(1)'>教员</label>
</div>
<div class="input">
<mat-icon class="icon">account_box</mat-icon>
<input id="name" name="name" required ngModel placeholder="请输入用户名" maxlength="20">
</div>
<div class="input">
<mat-icon class="icon2">lock</mat-icon>
<input id="password" name="password" type='password' required ngModel placeholder="请输入登录密码" maxlength="20">
</div>
<div class="forget">
<label (click)='forget()'>忘记密码?</label>
</div>
<div *ngIf="errmsg" class="alert-danger">
{{errmsg}}
</div>
<button type="submit" [disabled]="!form.form.valid" class="loginBtn" mat-raised-button>登录</button>
</form>
</div>
<img src="../../../assets/images/login.png" class="loginBackground">
</div>
<p class="toLogin" title="管理员登录" (click)='toAdminLogin()'><mat-icon>arrow_drop_down_circle</mat-icon></p>
<p class="footer">Copyright <mat-icon style="vertical-align: top; font-size: 20px;">copyright</mat-icon> 2019 北京安信科创软件有限公司出品</p>
</div>

143
src/app/pages/lockscreen/lockscreen.component.scss

@ -0,0 +1,143 @@
.content {
width: 100%;
height: 100%;
max-height: 100%;
display: flex;
justify-content:center;
align-items: center;
background: url('../../../assets//images/loginBGC.png');
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
.loginBox {
min-width: 1080px;
min-height: 610px;
margin: 0 auto;
width: 70%;
text-align: center;
box-sizing: border-box;
position: relative;
.loginBackground{
width: 100%;
height: 100%;
margin: 0 auto;
}
.center {
width: 30%;
box-sizing: border-box;
margin: 0 auto;
position: absolute;
top: 24%;
right: 16%;
}
}
.header {
width: 100%;
text-align: center;
position: fixed;
top: 60px;
font-size: 46px;
font-weight: 800;
color: #fff;
font-family: 'NSimSun';
}
.footer {
width: 100%;
text-align: center;
position: fixed;
bottom: 35px;
font-size: 14px;
color: white;
}
.toLogin{
color: #B0B0B0;
transform: rotate(90deg);
transform-origin: center center;
position: fixed;
left: 1%;
bottom: 1%;
cursor:pointer;
mat-icon{
width: 36px;
height: 36px;
font-size: 36px;
cursor:pointer;
}
}
// 表单内部样式
.forget{
width: 100%;
text-align: right;
margin: 30px auto;
label {
box-sizing: border-box;
font-size: 14px;
color: #2196f3;
cursor:pointer;
}
}
.alert-danger {
margin-bottom: 10px;
text-align: left;
font-size: 14px;
color: red;
}
.loginBtn {
width: 100%;
color: white;
border-radius: 5px;
background:linear-gradient(to right,#4DA3FE,#52b9fe,#56cdff)
}
//input + 字体图标
.input {
width: 100%;
margin: 30px auto;
position: relative;
.role{
box-sizing: border-box;
margin: 0px 15px;
display: inline-block;
width: 30%;
text-align: center;
font-size: 26px;
font-weight: 800;
font-family: 'NSimSun';
color: #4DA1FE;
cursor:pointer;
}
input {
width: 90%;
border-radius: 5px;
border: 1px solid #999;
height: 36px;
padding-left: 30px;
}
}
.icon {
width: 24px;
color: #B5BBBC;
font-size: 24px;
position: absolute;
top: 7px;
left: 8px;
}
.icon2 {
width: 24px;
color: #B5BBBC;
font-size: 24px;
position: absolute;
top: 7px;
left: 8px;
}
//class名是否选中
.isCheck {
border-bottom: 3px solid #4DA1FE;
}

25
src/app/pages/lockscreen/lockscreen.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LockscreenComponent } from './lockscreen.component';
describe('LockscreenComponent', () => {
let component: LockscreenComponent;
let fixture: ComponentFixture<LockscreenComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LockscreenComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LockscreenComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

67
src/app/pages/lockscreen/lockscreen.component.ts

@ -0,0 +1,67 @@
import { Component, OnInit } from '@angular/core';
import { Router,ActivatedRoute } from '@angular/router'
import { MatSnackBarConfig, MatSnackBar } from '@angular/material/snack-bar';
import { HttpClient } from '@angular/common/http';
import { IsLoginService } from '../../is-login.service'//引入服务
import {CacheTokenService} from '../../http-interceptors/cache-token.service'//引入服务
@Component({
selector: 'app-lockscreen',
templateUrl: './lockscreen.component.html',
styleUrls: ['./lockscreen.component.scss']
})
export class LockscreenComponent implements OnInit {
constructor(private http:HttpClient,private router:Router,private route:ActivatedRoute,public token:CacheTokenService,public snackBar: MatSnackBar,private isLogin:IsLoginService) { }
ngOnInit() {
}
roleType:string = '2'; //登录角色
errmsg :string = ''; //错误信息
//登录
onSubmit(e){
let params = { roleType: this.roleType }
this.http.post('/api/Account/SignIn',e,{params}).subscribe((data:any)=>{
sessionStorage.setItem('username',e.name)
sessionStorage.setItem('expires',data.expires)
sessionStorage.setItem('realName',data.realName)
sessionStorage.setItem('roleType',data.roleType)
sessionStorage.setItem("token",data.token);
sessionStorage.setItem("refreshToken",data.refreshToken);
this.token.startUp(); //登陆成功启动定时器刷新token
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.router.navigate(['/home/createexam']) //登陆成功跳转页面
this.snackBar.open('登陆成功','确定',config);
},(err) => {this.errmsg = err})
}
//切换登录角色
toggle (e) {
this.roleType = e
}
//跳转管理员登录页面
toAdminLogin () {
this.router.navigate(['/adminLogin']) //跳转管理员登录页面
}
//忘记密码弹窗
forget () {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('请联系管理员重置密码','确定',config);
}
}

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

@ -0,0 +1,33 @@
<div class="content">
<div class="loginBox">
<h1 class="header">灭火救援指挥培训系统 (管理员)</h1>
<div class="center">
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<div class="input">
<mat-icon class="icon">account_box</mat-icon>
<input id="name" name="name" required ngModel placeholder="请输入用户名" maxlength="18">
</div>
<div class="input">
<mat-icon class="icon2">lock</mat-icon>
<input id="password" name="password" type='password' required ngModel placeholder="请输入登录密码" maxlength="18">
</div>
<div class="forget">
<label (click)='forget()'>忘记密码?</label>
</div>
<div *ngIf="errmsg" class="alert-danger">
{{errmsg}}
</div>
<button type="submit" [disabled]="!form.form.valid" class="loginBtn" mat-raised-button color="primary">登录</button>
</form>
</div>
</div>
<p class="toLogin" title="教员学员登录" (click)='toAdminLogin()'><mat-icon>arrow_drop_down_circle</mat-icon></p>
<p class="footer">Copyright <mat-icon style="vertical-align: top; font-size: 20px;">copyright</mat-icon> 2019 北京安信科创软件有限公司出品</p>
</div>

103
src/app/pages/login/login.component.scss

@ -0,0 +1,103 @@
.content {
width: 100%;
height: 100%;
max-height: 100%;
background: url('../../../assets//images/loginBackground.jpg');
background-repeat:no-repeat;
background-size:100% 100%;
-moz-background-size:100% 100%;
}
.loginBox {
margin: 0 auto;
width: 40%;
text-align: center;
box-sizing: border-box;
padding: 8% 0;
.header {
font-size: 34px;
font-weight: 650;
font-family: 'NSimSun';
}
.center {
padding: 100px 0;
width: 50%;
box-sizing: border-box;
margin: 0 auto;
}
}
.footer {
width: 100%;
text-align: center;
position: fixed;
bottom: 35px;
color: #858688;
font-size: 14px;
}
.toLogin{
color: #B0B0B0;
transform: rotate(270deg);
transform-origin: center center;
position: fixed;
left: 1%;
bottom: 1%;
cursor:pointer;
mat-icon{
width: 36px;
height: 36px;
font-size: 36px;
cursor:pointer;
}
}
// 表单内部样式
.forget{
margin: 30px auto;
label {
margin-left: 80%;
box-sizing: border-box;
font-size: 14px;
color: #2196f3;
cursor:pointer;
}
}
.alert-danger {
margin-bottom: 30px;
text-align: left;
font-size: 14px;
color: red;
}
.loginBtn {
width: 100%;
}
//input + 字体图标
.input {
width: 100%;
margin: 30px auto;
position: relative;
input {
width: 90%;
border-radius: 5px;
border: 1px solid #999;
height: 36px;
padding-left: 30px;
}
}
.icon {
width: 24px;
color: #B5BBBC;
font-size: 24px;
position: absolute;
top: 7px;
left: 8px;
}
.icon2 {
width: 24px;
color: #B5BBBC;
font-size: 24px;
position: absolute;
top: 7px;
left: 8px;
}

25
src/app/pages/login/login.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

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

@ -0,0 +1,62 @@
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Router,ActivatedRoute } from '@angular/router'
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { IsLoginService } from '../../is-login.service'//引入服务
import {CacheTokenService} from '../../http-interceptors/cache-token.service'//引入服务
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit {
constructor(private http:HttpClient,private router:Router,private route:ActivatedRoute,public token:CacheTokenService,public snackBar: MatSnackBar,private isLogin:IsLoginService) { }
ngOnInit() {
}
errmsg :string = ''; //错误信息
//登录
onSubmit(e){
let params = { roleType: '0' }
this.http.post('/api/Account/SignIn',e,{params}).subscribe((data:any)=>{
sessionStorage.setItem('username',e.name)
sessionStorage.setItem('expires',data.expires)
sessionStorage.setItem('realName',data.realName)
sessionStorage.setItem('roleType',data.roleType)
sessionStorage.setItem("token",data.token);
sessionStorage.setItem("refreshToken",data.refreshToken);
this.token.startUp(); //登陆成功启动定时器刷新token
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.router.navigate(['/home/createexam']) //登陆成功跳转页面
this.snackBar.open('登陆成功','确定',config);
},(err) => {this.errmsg = err})
}
//跳转教员学员登录页面
toAdminLogin () {
this.router.navigate(['/login']) //跳转管理员登录页面
}
//忘记密码弹窗
forget () {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('请联系 系统维护技术人员','确定',config);
}
}

17
src/app/pages/pages-routing.module.ts

@ -0,0 +1,17 @@
// import { Routes, RouterModule } from '@angular/router';
// import { NgModule } from '@angular/core';
// import { PagesComponent } from './pages.component';
// import { PersonaldataComponent } from './personaldata/personaldata.component';
// const routes: Routes = [
// { path: '', component: PagesComponent},
// { path: 'personaldata ', component: PersonaldataComponent},
// ];
// @NgModule({
// imports: [RouterModule.forChild(routes)],
// exports: [RouterModule]
// })
// export class PagesRoutingModule {}

1
src/app/pages/pages.component.html

@ -0,0 +1 @@
<p>pages works!</p>

0
src/app/pages/pages.component.scss

25
src/app/pages/pages.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PagesComponent } from './pages.component';
describe('PagesComponent', () => {
let component: PagesComponent;
let fixture: ComponentFixture<PagesComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PagesComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PagesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

15
src/app/pages/pages.component.ts

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-pages',
templateUrl: './pages.component.html',
styleUrls: ['./pages.component.scss']
})
export class PagesComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

112
src/app/pages/pages.module.ts

@ -0,0 +1,112 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PagesComponent } from './pages.component';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
// import { PagesRoutingModule } from './pages-routing.module'
import {A11yModule} from '@angular/cdk/a11y';
import {DragDropModule} from '@angular/cdk/drag-drop';
import {PortalModule} from '@angular/cdk/portal';
import {ScrollingModule} from '@angular/cdk/scrolling';
import {CdkStepperModule} from '@angular/cdk/stepper';
import {CdkTableModule} from '@angular/cdk/table';
import {CdkTreeModule} from '@angular/cdk/tree';
import {MatAutocompleteModule} from '@angular/material/autocomplete';
import {MatBadgeModule} from '@angular/material/badge';
import {MatBottomSheetModule} from '@angular/material/bottom-sheet';
import {MatButtonModule} from '@angular/material/button';
import {MatButtonToggleModule} from '@angular/material/button-toggle';
import {MatCardModule, MatCardTitle} from '@angular/material/card';
import {MatCheckboxModule} from '@angular/material/checkbox';
import {MatChipsModule} from '@angular/material/chips';
import {MatStepperModule} from '@angular/material/stepper';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatDialogModule} from '@angular/material/dialog';
import {MatDividerModule} from '@angular/material/divider';
import {MatExpansionModule} from '@angular/material/expansion';
import {MatGridListModule} from '@angular/material/grid-list';
import {MatIconModule} from '@angular/material/icon';
import {MatInputModule} from '@angular/material/input';
import {MatListModule} from '@angular/material/list';
import {MatMenuModule} from '@angular/material/menu';
import {MatNativeDateModule, MatRippleModule} from '@angular/material/core';
import {MatPaginatorModule} from '@angular/material/paginator';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
import {MatRadioModule} from '@angular/material/radio';
import {MatSelectModule} from '@angular/material/select';
import {MatSidenavModule} from '@angular/material/sidenav';
import {MatSliderModule} from '@angular/material/slider';
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
import {MatSnackBarModule} from '@angular/material/snack-bar';
import {MatSortModule} from '@angular/material/sort';
import {MatTableModule} from '@angular/material/table';
import {MatTabsModule} from '@angular/material/tabs';
import {MatToolbarModule} from '@angular/material/toolbar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {MatTreeModule} from '@angular/material/tree';
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { PersonaldataComponent } from './personaldata/personaldata.component';
import { RouterModule } from '@angular/router';
import { LockscreenComponent } from './lockscreen/lockscreen.component';
// import { PagesRoutingModule } from './pages-routing.module';
@NgModule({
declarations: [PagesComponent, LoginComponent, RegisterComponent, LockscreenComponent],
imports: [
CommonModule,
A11yModule,
CdkStepperModule,
CdkTableModule,
CdkTreeModule,
DragDropModule,
MatAutocompleteModule,
MatBadgeModule,
MatBottomSheetModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatStepperModule,
MatDatepickerModule,
MatDialogModule,
MatDividerModule,
MatExpansionModule,
MatGridListModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule,
PortalModule,
ScrollingModule,
FormsModule,
ReactiveFormsModule,
RouterModule
// PagesRoutingModule,
]
})
export class PagesModule { }

280
src/app/pages/personaldata/personaldata.component.html

@ -0,0 +1,280 @@
<div class="pages-profile">
<div fxLayout.gt-sm="row nowrap" fxLayout.lt-md="column nowrap" fxLayoutAlign.gt-sm="space-between start"
fxLayoutGap="30px" id="xxx">
<mat-card fxFlex="30" class="profile-card">
<mat-card-content>
<img mat-card-avatar src="">
<mat-card-title class="profile-user">安信科创</mat-card-title>
<mat-card-subtitle class="profile-job">嘻嘻嘻嘻</mat-card-subtitle>
<p class="profile-introduction">
不要做程序员,要做问题解决者
</p>
<div class="profile-social">
<mat-icon size="1" class="secondary-text s-24"></mat-icon>
<mat-icon size="1" class="secondary-text s-24"></mat-icon>
<mat-icon size="1" class="secondary-text s-24"></mat-icon>
<mat-icon size="1" class="secondary-text s-24"></mat-icon>
</div>
<button mat-flat-button color="accent">关注</button>
</mat-card-content>
<mat-card-actions class="profile-card-footer" fxLayout="row nowrap">
<div fxFlex="32">
<strong class="profile-stat-count">260</strong>
<span>粉丝</span>
</div>
<div fxFlex="32">
<strong class="profile-stat-count">180</strong>
<span>关注</span>
</div>
<div fxFlex="32">
<strong class="profile-stat-count">2000</strong>
<span>博客</span>
</div>
</mat-card-actions>
</mat-card>
<mat-card fxFlex="70" class="profile-board">
<mat-tab-group>
<mat-tab label="活动">
<mat-list>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
</mat-list>
<div class="pt-40 pb-40">
<button mat-flat-button class="show-more-btn">更多</button>
</div>
</mat-tab>
<mat-tab label="评论">
<mat-list>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
</div>
</mat-list-item>
</mat-list>
</mat-tab>
<mat-tab label="消息">
<mat-list>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
<img src="" alt="">
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
<mat-list-item>
<div matLine fxLayoutAlign="start center" fxLayoutGap="16px">
<img matListAvatar src="">
<div>
<div>我是假数据
<span class="secondary-text font-size-12">我是假数据</span>
</div>
<span class="secondary-text font-size-12">我是假数据</span>
</div>
</div>
<div matLine class="profile-item-content">
我是假数据
</div>
</mat-list-item>
</mat-list>
</mat-tab>
</mat-tab-group>
</mat-card>
</div>
</div>

110
src/app/pages/personaldata/personaldata.component.scss

@ -0,0 +1,110 @@
#xxx{
display: flex;
justify-content: space-around;
}
.pages-profile {
padding: 30px;
.profile-card {
padding: 9px;
text-align: center;
font-family: Roboto, sans-serif;
width: 500px;
height: 600px;
mat-card-content {
padding: 40px 15px;
margin: 0;
}
.mat-card-avatar {
width: 130px;
height: 130px;
margin-bottom: 10px;
}
.profile-user {
margin: 10px 0;
font-weight: normal;
}
.profile-job {
margin-bottom: 20px;
color: #9e9e9e;
font-weight: 500;
}
.profile-introduction {
margin: 0 0 1rem;
color: #757575;
}
.profile-social {
margin: 25px 0;
mat-icon {
margin: 0 10px;
color: rgba(66, 66, 66, .4);
}
}
mat-card-actions {
padding: 10px;
background: #f6f9fd;
}
.profile-card-footer {
display: flex;
justify-content: space-around;
.profile-stat-count {
display: block;
margin-bottom: 3px;
font-size: 20px;
font-weight: bold;
color: #616161;
+span {
color: #9e9e9e;
}
}
}
}
.profile-board {
padding: 30px;
width: 500px;
mat-list {
padding-bottom: 20px;
}
mat-list-item {
height: auto;
padding: 25px 0;
margin-left: -16px;
border-bottom: 1px solid #dfe0df;
.profile-item-content {
padding: 20px 0 0 56px;
line-height: 1.571429;
color: #757575;
white-space: normal;
display: flex;
flex-wrap: wrap;
img {
width: 100%;
max-width: 220px;
max-height: 150px;
padding: 0 20px 20px 0;
}
}
}
}
.show-more-btn {
width: 100%;
background-color: #eee;
color: #3949ab;
}
}

25
src/app/pages/personaldata/personaldata.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { PersonaldataComponent } from './personaldata.component';
describe('PersonaldataComponent', () => {
let component: PersonaldataComponent;
let fixture: ComponentFixture<PersonaldataComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ PersonaldataComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(PersonaldataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

15
src/app/pages/personaldata/personaldata.component.ts

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-personaldata',
templateUrl: './personaldata.component.html',
styleUrls: ['./personaldata.component.scss']
})
export class PersonaldataComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

81
src/app/pages/register/register.component.html

@ -0,0 +1,81 @@
<div class="login">
<div class="loginbox">
<div class="intro">
<p>北京安信科创有限公司</p>
<span>北京安信科创软件有限公司作为中国应急服务领跑者,于2006年进入消防救援领域,是一家专注于应急领域仿真培训演练与应急数据预判领域的软件服务供应商。安信主要利用大数据与虚拟现实技术实现对消防、公安、机场相关安防人员与企业安全监管人员的仿真培训与考核,致力于为我国应急产业的发展构建更美好的未来。目前,安信的业务遍布全国20多个省份和地区,服务全国将近四分之一以上的人口
</span>
</div>
<div class="card">
<mat-card>
<p class="cardheader">注册</p>
<p>Please register first</p>
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<mat-form-field>
<input matInput id="name" name="name"
required
ngModel #name="ngModel" placeholder="请输入账号">
</mat-form-field>
<!-- <div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert-danger">
<div *ngIf="name.errors.required">
账号不能为空
</div>
</div> -->
<mat-form-field>
<input matInput id="email" name="email"
required pattern="^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$"
ngModel #email="ngModel" placeholder="请输入邮箱">
</mat-form-field>
<!--
<div *ngIf="email.invalid && (email.dirty || email.touched)"
class="alert-danger">
<div *ngIf="email.errors.required">
邮箱不能为空
</div>
<div *ngIf="email.errors.pattern">
邮箱格式不正确
</div>
</div> -->
<mat-form-field>
<input matInput id="password" name="password" type='password'
required minlength="8"
ngModel #password="ngModel" placeholder="请输入密码">
</mat-form-field>
<!-- <div *ngIf="password.invalid && (password.dirty || password.touched)"
class="alert-danger">
<div *ngIf="password.errors.required">
密码不能为空
</div>
<div *ngIf="password.errors.minlength">
密码最少8位
</div>
</div> -->
<mat-checkbox style="margin-top: 25px;">请同意不扩散核武器条约条约</mat-checkbox>
<button type="submit" [disabled]="!form.form.valid" class="loginbtn"mat-button>注册</button>
</form>
<div class="applyfor">
<p>已有账号?去<a href="/login">登录</a></p>
</div>
<div class="website">
<p>WEBSITE BY AnXin</p>
<p>© 2020. All RIGHT RESERVED.</p>
</div>
</mat-card>
</div>
</div>
</div>

88
src/app/pages/register/register.component.scss

@ -0,0 +1,88 @@
.login {
width: 100%;
height: 100%;
// background: url('../../../assets/images/bg_login.jpg');
.loginbox {
width: 100%;
height: 100%;
background-color: #000;
background: rgba(0,0,0,0.5);/*盒子背景透明*/
// opacity: 0.5;
position: relative;
}
.intro {
width: 650px;
// height: 350px;
position: fixed;
top:35%;
left: 15%;
p {
font-size: 36px;
color:white;
margin-bottom: 35px;
}
span {
font-size: 16px;
color:white;
opacity: 0.5;
}
}
.card{
width: 460px;
height: 100%;
padding-left: 20px;
background-color: #fff;
position: absolute;
right: 0;
p {
width: 100%;
margin: 18px 0;
}
.cardheader{
font-size: 26px;
font-weight: 500;
}
}
}
.example-container {
display: flex;
flex-direction: column;
}
.example-container > * {
width: 100%;
}
.loginbtn {
margin-top: 18px;
height: 35px;
background-color:#039be5;
border-radius: 15px;
color: #fff;;
}
.mat-card {
box-shadow: 0 0 0;
margin-top: 70px;
}
.applyfor {
font-size: 16px;
a {
color: #039be5;
}
}
.website {
font-size: 14px;
text-align: center;
margin-top: 50px;
}
.alert-danger {
font-size: 14px;
color: red;
}

25
src/app/pages/register/register.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { RegisterComponent } from './register.component';
describe('RegisterComponent', () => {
let component: RegisterComponent;
let fixture: ComponentFixture<RegisterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ RegisterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RegisterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

19
src/app/pages/register/register.component.ts

@ -0,0 +1,19 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss']
})
export class RegisterComponent implements OnInit {
constructor() { }
ngOnInit() {
}
onSubmit(e){
// console.log(e)
}
}

45
src/app/pipes/size.pipe.ts

@ -0,0 +1,45 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'size'})
export class SizePipe implements PipeTransform {
transform(byte: number): string {
if(byte < 1048576 && byte != 0){//如果小于1M
let size = byte / 1024
return size.toFixed(1) + 'KB'
}
if(byte >= 1048576 && byte < 1073741824){//如果大于1M 小于1G
let size = byte / 1048576
return size.toFixed(1) + 'MB'
}
if(byte >= 1073741824){//如果大于1G
let size = byte / 1073741824
return size.toFixed(1) + 'GB'
}
if(byte < 1048576 && byte == 0){//如果是文件夹
return '--'
}
}
}
@Pipe({name: 'name'})
export class NamePipe implements PipeTransform {
transform(name: string): string {
let nameArr = name.split("/")
return nameArr[nameArr.length - 1]
}
}
@Pipe({name: 'name2'})
export class NamePipe2 implements PipeTransform {
transform(name: string): string {
let nameArr = name.split("/")
return nameArr[nameArr.length - 2]
}
}
@Pipe({name: 'name3'})
export class NamePipe3 implements PipeTransform {
transform(name: string): string {
if(name.charAt(name.length-1) == "/"){
return name.substr(0, name.length - 1).replace(/\//g,'>').substring(9,name.length)
}else{
return name.replace(/\//g,'>').substring(9,name.length)
}
}
}

31
src/app/tabbar/tabbar.component.html

@ -0,0 +1,31 @@
<mat-toolbar style="background-color: #3b8cff;">
<!-- <mat-toolbar> -->
<p style="color: white;border-bottom: 3px solid #fff;border-radius: 3px; font-size: 16px;padding: 0 4px;">考核系统</p>
<!-- 未登录状态 -->
<!-- <button mat-icon-button class="login" *ngIf="!isLogin.isLogin" (click)='login()'>
<mat-icon>account_circle</mat-icon>
</button> -->
<span style="position: absolute;right:100px;color: white;font-size: 16px;">欢迎您,{{realName}}</span>
<!-- 已登录状态 -->
<button mat-icon-button [matMenuTriggerFor]="appMenu" class="login">
<mat-icon>account_circle</mat-icon>
</button>
<mat-menu #appMenu="matMenu">
<!-- <button mat-menu-item (click)='changeUserData()'>
<mat-icon>perm_identity</mat-icon>
<span>修改资料</span>
</button> -->
<button mat-menu-item (click)='changPassword()'>
<mat-icon>verified_user</mat-icon>
<span>修改密码</span>
</button>
<button mat-menu-item (click)='signOut()'>
<mat-icon>power_settings_new</mat-icon>
<span>退出系统</span>
</button>
</mat-menu>
</mat-toolbar>

12
src/app/tabbar/tabbar.component.scss

@ -0,0 +1,12 @@
mat-toolbar{
position: relative;
padding-left: 65px;
}
mat-icon{
color: white;
}
.login{
position: absolute;
right:60px;
}

25
src/app/tabbar/tabbar.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TabbarComponent } from './tabbar.component';
describe('TabbarComponent', () => {
let component: TabbarComponent;
let fixture: ComponentFixture<TabbarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TabbarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TabbarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

78
src/app/tabbar/tabbar.component.ts

@ -0,0 +1,78 @@
import { Component, OnInit,Output,EventEmitter } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { Router,ActivatedRoute } from '@angular/router'
import { MatDialog } from '@angular/material/dialog';
import {ChangepasswordComponent} from '../ui/changepassword/changepassword.component'
import {ChangeuserdataComponent} from '../ui/changeuserdata/changeuserdata.component'
import {LoginComponent} from '../ui/login/login.component'
import {CacheTokenService} from '../http-interceptors/cache-token.service'//引入服务
import {IsLoginService} from '../is-login.service'//引入服务
import { MatSnackBarConfig, MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-tabbar',
templateUrl: './tabbar.component.html',
styleUrls: ['./tabbar.component.scss']
})
export class TabbarComponent implements OnInit {
theme: boolean = true;
@Output()
toggle = new EventEmitter<void>();
@Output()
toggleDarkTheme = new EventEmitter<boolean>();
@Output()
defaulttheme = new EventEmitter<boolean>();
@Output()
redtheme = new EventEmitter<boolean>();
constructor(private http:HttpClient,private router:Router,private route:ActivatedRoute,public token:CacheTokenService,public dialog: MatDialog,public isLogin:IsLoginService,public snackBar: MatSnackBar,) { }
ngOnInit() {
this.realName = sessionStorage.getItem('realName')
}
realName:string; //登录用户角色
//登录系统
login () {
let dialogRef = this.dialog.open(LoginComponent);
dialogRef.afterClosed().subscribe();
}
//退出系统
signOut () {
let out = confirm("您确定要退出吗")
if(out) {
this.http.post('/api/Account/SignOut',{}).subscribe(data=>{
sessionStorage.clear()
this.token.delete()
this.router.navigate(['/login'])
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('退出成功','确定',config);
})
} //if
}
//修改用户资料
changeUserData () {
let dialogRef = this.dialog.open(ChangeuserdataComponent);
dialogRef.afterClosed().subscribe();
}
//修改密码
changPassword() {
let dialogRef = this.dialog.open(ChangepasswordComponent);
dialogRef.afterClosed().subscribe();
}
}

18
src/app/theme.scss

@ -0,0 +1,18 @@
@import "./theming";
@include mat-core();
$my-app-primary:mat-palette($mat-blue,500);
$my-app-accent :mat-palette($mat-pink,A200,A100,A400);
$my-app-warn :mat-palette($mat-red);
$my-app-theme :mat-light-theme($my-app-primary,$my-app-accent,$my-app-warn);
@include angular-material-theme($my-app-theme);
$my-dark-primary:mat-palette($mat-red,A700);
$my-dark-accent :mat-palette($mat-amber,A200,A100,A400);
$my-dark-warn :mat-palette($mat-deep-orange);
$my-dark-theme :mat-dark-theme($my-dark-primary,$my-dark-accent,$my-dark-warn);
.myapp-dark-theme{
@include angular-material-theme($my-dark-theme);
}

159
src/app/ui/all-file/all-file.component.html

@ -0,0 +1,159 @@
<div class="topbox">
<div class="leftbox">
<div class="upload" (mouseenter)="uploadBtnEnter()" (mouseleave)="uploadBtnLeave()" *ngIf="isAdmin">
<div class="btn" style="width: 88px;height: 33px;" >
<mat-icon>backup</mat-icon><span> 上传</span>
<input type="file" (change)='selectFile($event)'>
</div>
<div class="openbtn" style="position: absolute;" *ngIf="isOpenUpload">
<div>
<span>上传文件</span>
<input type="file" (change)='selectFile($event)'>
</div>
<div>
<span>上传文件夹</span>
<input multiple webkitdirectory type="file" (change)='selectFiles($event)'>
</div>
</div>
</div>
<div class="newFile" (click)="createFolder()" *ngIf="isAdmin">
<mat-icon>create_new_folder</mat-icon> <span>新建文件夹</span>
</div>
<div class="newFile" style="width: 88px;" (click)='downLoadFile()'>
<mat-icon>save_alt</mat-icon> <span>下载</span>
</div>
<div class="newFile delete" style="width: 88px;" *ngIf="isAdmin" (click)="deleteFiles()" >
<mat-icon>delete</mat-icon> <span>删除</span>
</div>
<div class="progressBox" *ngIf="uploadisLoading">
<button mat-raised-button style="margin-right: 5px;width: 84px;height: 33px;" (click)="cancel()">取消上传</button>
<span style="font-size: 12px;">上传中...</span>
<mat-progress-bar mode="determinate" [value]="uploadProgress" class="progress"></mat-progress-bar>
</div>
<!-- <div class="progressBox" *ngIf="uploadisLoading2">
<button mat-raised-button style="margin-right: 5px;width: 84px;height: 33px;" (click)="cancel2()">取消上传</button>
<span style="font-size: 12px;">文件夹上传中...(当前上传 {{uploadProgress2}} )</span>
<mat-spinner determinate style="position: absolute;right: 0;right: 260px;bottom: -10px;" diameter=40></mat-spinner>
</div> -->
<div class="progressBox" *ngIf="downloadFile.isDownloading">
<!-- <button mat-raised-button style="margin-right: 5px;" (click)="cancelDowload()">取消下载</button> -->
<span style="font-size: 12px;">下载中...</span>
<mat-progress-bar mode="determinate" [value]="downloadFile.downloadProgress" class="progress" style="left: 52px;top: 13px;"></mat-progress-bar>
</div>
</div>
<!-- <div class="rightbox">
<div class="inputbox">
<input type="text" [(ngModel)]="searchData" (focus)="searchfocus($event)" (blur)="searchblur($event)">
<span class="cancel" *ngIf="isCancel" (click)="cancelbtn()"><mat-icon style="font-size: 16px;">cancel</mat-icon></span>
<span class="search" (click)="search()"><mat-icon>search</mat-icon></span>
</div>
</div> -->
</div>
<div class="titlebox">
<div class="titleleft">
<span class="goBack" (click)='backToTop()' *ngIf="selectedDataBank.includes('/')">返回根目录</span>
&nbsp;
<span class="goBack" (click)='backTominTop()' *ngIf="selectedDataBank.includes('/')">返回上一级</span>
<span style="margin: 0 3px;color: #c5d8f3;">|</span>
<span class="allFile" *ngIf="!selectedDataBank.includes('/')">全部文件</span>
<span style="margin: 0 3px;color: #c5d8f3;"></span>
<span class="allFile">{{selectedDataBank}}</span>
</div>
<div class="titleright">
<span>已全部加载,共 {{fileNum}} 个</span>
</div>
</div>
<div class="mainbox" style="overflow-y: auto;max-height: 80%;width: 100%;">
<table style="width: 100%;" mat-table [dataSource]="dataSource" matSort (matSortChange)="sortData($event)" class="mat-elevation-z8">
<ng-container matColumnDef="select">
<th style="width: 4%;" mat-header-cell *matHeaderCellDef>
<mat-checkbox (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
color="primary"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let row">
<mat-checkbox (click)="clickCheckBox($event)"
color="primary"
(change)="$event ? selection.toggle(row) : null"
[checked]="selection.isSelected(row)">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th style="width: 63%;" mat-header-cell *matHeaderCellDef> 文件名 </th>
<td mat-cell *matCellDef="let element">
<img *ngIf="element.type == 'pdf'" src="../../../assets/images/pdf.png" alt="">
<img *ngIf="element.type == 'jpeg' || element.type == 'jpg' || element.type == 'png' || element.type == 'gif' || element.type == 'svg'|| element.type == 'webp' || element.type == 'bmp'|| element.type == 'JPG'" src="../../../assets/images/img.png" alt="">
<img *ngIf="element.type == 'doc' || element.type == 'docx'" src="../../../assets/images/word.png" alt="">
<img *ngIf="element.type == 'xlsx'" src="../../../assets/images/excel.png" alt="">
<img *ngIf="element.type == 'zip'" src="../../../assets/images/zip.png" alt="">
<img *ngIf="element.type == 'MP4' || element.type == 'mp4'" src="../../../assets/images/video.png" alt="">
<img *ngIf="element.type == 'txt'" src="../../../assets/images/text.png" alt="">
<img *ngIf="element.type == 'pptx'" src="../../../assets/images/ppt.png" alt="">
<img *ngIf="element.type == 'cad' || element.type == 'CAD'" src="../../../assets/images/cad.png" alt="">
<img *ngIf="element.type == 'avi' || element.type == 'swf'|| element.type == 'mov'" src="../../../assets/images/video.png" alt="">
<img *ngIf="element.type == 'mp3' || element.type == 'aif' || element.type == 'wav' || element.type == 'flac'" src="../../../assets/images/music.png" alt="">
<img *ngIf="element.isDir" src="../../../assets/images/file.png" alt="">
<img *ngIf="element.type == 'gaopenche' || element.type == 'denggao'" src="../../../assets/images/gaopenche.gif" alt="">
<img *ngIf="element.type == 'jiqiren' || element.type == 'konghuqi'" src="../../../assets/images/shebei.jpg" alt="">
<img *ngIf="element.type == 'waifu' || element.type == 'neifu' || element.type == 'gong' || element.type == 'qiu'" src="../../../assets/images/sheshi.jpg" alt="">
<span *ngIf="element.isDir == false" class="filename" (click)="clickName($event,element)">
{{element.key | name}}
</span>
<span *ngIf="element.isDir == true" class="filename" (click)="clickName($event,element)">
{{element.key | name2}}
</span>
<span class="font3d" *ngIf="element.type == 'waifu' || element.type == 'neifu' || element.type == 'gong' || element.type == 'qiu' || element.type == 'gaopenche' || element.type == 'denggao' || element.type == 'jiqiren' || element.type == 'konghuqi'">
&nbsp; 3D &nbsp;
</span>
</td>
</ng-container>
<ng-container matColumnDef="weight">
<th mat-header-cell style="width: 15%;" *matHeaderCellDef> 大小 </th>
<td mat-cell *matCellDef="let element"> {{element.size | size}} </td>
</ng-container>
<ng-container matColumnDef="time">
<th style="width: 18%;" mat-header-cell *matHeaderCellDef mat-sort-header> 修改日期 </th>
<td mat-cell *matCellDef="let element"> {{element.lastModified | date:'yyyy-MM-dd HH:mm:ss'}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
(click)="clickCheckBoxLi($event,row)">
</tr>
</table>
<div class="nofiles" *ngIf="isNoFileTitle && selectedDataBank.includes('/')">
<span style="font-size: 14px;cursor: default;">您还没上传过文件哦~</span>
</div>
</div>
<div class="openSystem" *ngIf="!selectedDataBank.includes('/') && roleType =='1' " >
<a (click)="openteacher()" [href]='aHrefUnsafeLearnFun()'> <mat-icon style="vertical-align: middle; font-size: 24px;">account_balance</mat-icon> 战术授课<span>进入</span></a>
</div>
<div class="openSystem" *ngIf="!selectedDataBank.includes('/') && roleType == '2' ">
<a (click)="openlearn()" [href]='aHrefUnsafeLearnFun()'> <mat-icon style="vertical-align: middle; font-size: 24px;">account_balance</mat-icon> 战术学习<span>进入</span></a>
</div>
<div class="fixedBox" [hidden]="!uploadisLoading2">
<app-upload-files [thatFile]='this' #child></app-upload-files>
</div>
<ul>
<li *ngFor="let item of checkedAllFiles">{{item.key}}</li>
</ul>

265
src/app/ui/all-file/all-file.component.scss

@ -0,0 +1,265 @@
// @import "//at.alicdn.com/t/font_1863119_sy1f800ck9h.css";
.topbox{
height: 33px;
position: relative;
padding: 11px 10px;
.leftbox{
float: left;
display: flex;
.upload{
margin-left:16px;
background-color: #09AAFF;
border-radius: 4px;
cursor: pointer;
.btn{
position: relative;
color: white;
font-size: 13px;
mat-icon{
position: absolute;
top: 5px;
left: 10px;
}
span{
position: absolute;
left: 41px;
top: 9px;
}
input{
width: 88px;
height: 33px;
opacity: 0;
}
}
.openbtn{
background-color: white;
width: 86px;
text-align: center;
font-size: 12px;
border-radius: 0px 0px 4px 4px;
border: 1px solid #09AAFF;
div{
position: relative;
height: 30px;
line-height: 30px;
color: #09AAFF;
input{
width: 86px;
height: 30px;
opacity: 0;
position: absolute;
left: 0;
top: 0;
}
}
div:hover{
background-color: whitesmoke;
}
}
}
.newFile{
cursor: pointer;
background-color: #fff;
color: #09AAFF;
border: 1px solid #C3EAFF;
border-radius: 4px;
margin-left: 12px;
height: 33px;
line-height: 33px;
font-size: 13px;
position: relative;
width: 130px;
height: 33px;
float: left;
mat-icon{
position: absolute;
top: 5px;
left: 10px;
}
span{
position: absolute;
left: 41px;
}
}
.delete{
color: rgba(245, 59, 59);
border: 0.5px solid rgba(245, 59, 59);
// background-color: red;
// color: white;
}
}
.rightbox{
float: right;
width: 21%;
.inputbox{
float: right;
width: 21%;
min-width: 165px;
max-width: 315px;
height: 30px;
// margin: 12px 8px 12px 0;
position: relative;
right: 100px;
border-radius: 33px;
padding-left: 15px;
padding-right: 54px;
background: #f1f2f4;
border-radius: 33px;
input{
width: 100%;
height: 30px;
background: 0 0;
border: 0;
outline: 0;
line-height: 29px!important;
position: relative;
font-size: 12px;
}
.search{
cursor: pointer;
position: absolute;
right: 5px;
top: 3px;
color: grey;
}
.cancel{
cursor: pointer;
position: absolute;
right: 22px;
top: 5px;
color: #808080;
}
.cancel:hover{
mat-icon{
color: #808090;
;
}
}
}
}
//进度条
.progressBox{
position: absolute;
display: inline-block;
width: 550px;
left: 480px;
}
.progress{
position: absolute;
width: 350px;
top: 18px;
left: 160px;
}
}
.titlebox{
height: 30px;
line-height: 30px;
padding-left: 18px;
padding-right: 18px;
span{
font-size: 12px;
}
.titleleft{
float: left;
.goBack{
color: #09aaff;
}
.goBack:hover{
cursor: pointer;
text-decoration: underline;
}
}
.titleright{
float: right;
}
}
.mainbox{
// overflow-y: auto;
table{
td{
img{
position: relative;
width: 26px;
height: 26px;
top: 6px;
margin-right: 3px;
}
.filename:hover{
cursor: pointer;
color: #09aaff;
}
}
}
}
.btn{
width: 100%;
text-align: center;
button{
margin: 0 5px;
}
}
.font3d{
font-size: 13px;
background-color: #2cbe4e;
display: inline-block;
font-weight: 600;
line-height: 20px;
color: #fff;
text-align: center;
white-space: nowrap;
border-radius: 3px;
box-sizing: border-box;
}
//上传文件夹弹窗
.fixedBox {
position: fixed;
bottom: 3%;
right: 3%;
width: 500px;
}
.nofiles{
background: url("../../../assets/images/nofiles.png") no-repeat scroll center 0 transparent;
padding-top: 150px;
width: 488px;
position: absolute;
left: 50%;
top: 50%;
text-align: center;
margin: -78px 0 0 -244px;
}
.openSystem{
position: relative;
a{
color: rgba(0, 0, 0, 0.87);
font-size: 14px;
display: block;
width: 100%;
height: 48px;
line-height: 48px;
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
padding-left: 4%;
background-color: white;
img{
position: relative;
width: 26px;
height: 26px;
top: 6px;
margin-right: 8px;
}
span{
position: absolute;
right: 31.3%;
line-height: 48px;
font-size: 14px;
}
}
}

25
src/app/ui/all-file/all-file.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AllFileComponent } from './all-file.component';
describe('AllFileComponent', () => {
let component: AllFileComponent;
let fixture: ComponentFixture<AllFileComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AllFileComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AllFileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

918
src/app/ui/all-file/all-file.component.ts

@ -0,0 +1,918 @@
import { Component, OnInit,ViewChild ,Inject,NgZone } from '@angular/core';
import { SelectionModel } from '@angular/cdk/collections';
import {MatSort} from '@angular/material/sort';
import {MatTableDataSource} from '@angular/material/table';
import { HttpClient,HttpHeaders } from '@angular/common/http';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { IsLoginService } from '../../is-login.service';
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import {UploadFilesComponent} from '../upload-files/upload-files.component';
import { ComponentServiceService } from '../../component-service.service';
import { DomSanitizer } from "@angular/platform-browser";
@Component({
selector: 'app-all-file',
templateUrl: './all-file.component.html',
styleUrls: ['./all-file.component.scss'],
})
export class AllFileComponent {
displayedColumns: string[] = ['select', 'name', 'weight', 'time'];
dataSource:any = new MatTableDataSource;
constructor(private sanitizer: DomSanitizer,public emitService: ComponentServiceService,private http: HttpClient,public snackBar: MatSnackBar,public downloadFile:IsLoginService,public dialog: MatDialog,private zone: NgZone) { }
isCancel:boolean = false //搜索框的X是否显示
searchData:any = "搜索您的文件" //搜索框内容
isClickFile:boolean = false //是否点击过文件
isOpenUpload:boolean = false //是否移入上传按钮
isDelete:boolean = false //是否删除按钮
isNoFileTitle:boolean = false //无文件时提示
isAdmin:boolean = false //是否是管理员
selectedDataBank:string = '' //当前需要显示的资料库
fileNum:any = 0 //当前资料库文件数量
selection = new SelectionModel(true, []);
@ViewChild(MatSort) sort: MatSort;
@ViewChild( 'child',{static: false} ) child:UploadFilesComponent //上传文件夹子组件
oldDataSource:any; //原始表格数据
//表头排序
sortData (e) {
let data = this.oldDataSource.concat();
data.forEach(element => {
if(element.key.indexOf(".") != -1){
let typeArr = element.key.split('.')
element.type = typeArr[typeArr.length - 1]
element.newTime = new Date(element.lastModified).getTime()
}
});
if( e.direction=='asc' ) { //从小到大排序
data.sort( function(a,b) {
return a.newTime - b.newTime
} )
this.dataSource = new MatTableDataSource(data);
} else if ( e.direction=='desc' ) {//从大到小排序
data.sort( function(a,b) {
return b.newTime - a.newTime
} )
this.dataSource = new MatTableDataSource(data);
} else { //原始数据
this.dataSource = new MatTableDataSource(this.oldDataSource);
}
}
roleType:any
aHrefUnsafe:any //战术授课a标签 去除unsafe标志
ngOnInit(): void {
this.roleType = sessionStorage.getItem('roleType')
this.dataSource.sort = this.sort;
this.getALLFileList("支队级-主官")
// 接收发射过来的数据
this.emitService.eventEmit.subscribe((value: any) => {
this.getALLFileList(value)
this.selection.clear();
});
if(sessionStorage.getItem("roleType") == "0"){
this.isAdmin = true
}
}
aHrefUnsafeLearnFun(){
this.roleType = sessionStorage.getItem('roleType')
let username = sessionStorage.getItem('username')
let expires = sessionStorage.getItem('expires')
let realName = sessionStorage.getItem('realName')
let roleType = sessionStorage.getItem('roleType')
let token = sessionStorage.getItem('token')
let refreshToken = sessionStorage.getItem('refreshToken')
let aHref = `ax://startup?username=${username}&token=${token}&refreshToken=${refreshToken}&expires=${expires}&realname=${realName}&roleType=${roleType}`
this.aHrefUnsafe = this.sanitizer.bypassSecurityTrustUrl(aHref);
return this.aHrefUnsafe
}
//获得当前资料库的文件列表
getALLFileList(name){
this.selectedDataBank = name
let paramsdata = {
prefix : "allFiles/" + this.selectedDataBank + "/",
delimiter : "/"
}
this.http.get(`/api/Objects/drives`,{
params:paramsdata
}).subscribe((data:any) => {
this.selection.clear()
data.contents.forEach((item)=>{
let typeArr = item.key.split('.')
item.type = typeArr[typeArr.length - 1]
})
if(name.split('/')[1] == "装备"){
data.contents.unshift(
{ key: "装备车辆/高喷车",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "gaopenche"
},
{ key: "装备车辆/登高平台车",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "denggao"
},
{ key: "装备车辆/机器人",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "jiqiren"
},
{ key: "装备车辆/空气呼吸器",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "konghuqi"
}
)
}
if(name.split('/')[1] == "消防设施"){
data.contents.unshift(
{ key: "设备设施/外浮顶罐",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "waifu"
},
{ key: "设备设施/内浮顶罐",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "neifu"
},
{ key: "设备设施/拱顶罐",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "gong"
},
{ key: "设备设施/球罐",
lastModified: null,
eTag: null,
size: 0,
isDir: false,
type: "qiu"
}
)
}
this.oldDataSource = data.contents //保存表格数据
this.dataSource = new MatTableDataSource(data.contents);
this.fileNum = data.contents.length
if(data.contents.length == 0){
this.isNoFileTitle = true
}else{
this.isNoFileTitle = false
}
})
}
//判断是否全部选中
isAllSelected() {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.data.length;
return numSelected === numRows;
}
//控制全选按钮
masterToggle() {
this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach(row => this.selection.select(row));
this.isAllSelected() ? this.isDelete = true : this.isDelete = false;
}
//搜索框获得焦点事件
searchfocus(e){
this.isCancel = true
if(e.target.value == "搜索您的文件"){
e.target.value = ""
}
}
//搜索框失去焦点事件
searchblur(e){
if(e.target.value == ""){
e.target.value = "搜索您的文件"
this.isCancel = false
}
}
//搜索框点击X事件
cancelbtn(){
this.getALLFileList(this.selectedDataBank)
this.searchData = "搜索您的文件"
this.isCancel = false
}
allFiles:any //搜索出来的全部文件
checkedAllFiles:any = []
//点击搜索
search(){
if(this.searchData != "搜索您的文件"){
this.http.get("/api/Objects/drives",{
params:{
prefix : "allFiles",
delimiter : ""
}
}).subscribe((data:any)=>{
this.allFiles = data.contents
this.allFiles.forEach(item=>{
if(item.key.indexOf(this.searchData) != -1){
this.checkedAllFiles.push(item)
}
})
// console.log(888888,data.contents)
},
err=>{
})
}
}
goback:any //记录上一级目录
//点击列表每一条的名字
clickName(e,item){
e.stopPropagation()
if(item.type == "jpg" || item.type == "png" || item.type == "bmp"|| item.type == "gif" || item.type == "jpeg"&& !item.isDir){
const dialogRef = this.dialog.open(ViewDetails, {//调用open方法打开对话框并且携带参数过去
data: {url:item.key,type:"img"}
});
this.downloadFile.handleData(item.key,"查看")
}else if(item.type == "mp4" || item.type == "MP4" && !item.isDir){
const dialogRef = this.dialog.open(ViewDetails, {//调用open方法打开对话框并且携带参数过去
width: '1400px',
height:'800px',
data: {url:item.key,type:"video"}
});
dialogRef.afterClosed().subscribe();
this.downloadFile.handleData(item.key,"查看")
}else if(item.type == "mp3" || item.type == "MP3"&& !item.isDir){
const dialogRef = this.dialog.open(ViewDetails, {//调用open方法打开对话框并且携带参数过去
width: '400px',
height:'108px',
data: {url:item.key,type:"mp3"}
});
dialogRef.afterClosed().subscribe();
this.downloadFile.handleData(item.key,"查看")
}else if(item.type == "pdf" && item.size < 20971520){
window.open("/api/Objects/drives/" + item.key)
this.downloadFile.handleData(item.key,"查看")
}else if(item.type == "pdf" && item.size > 20971520){
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('暂不支持在线预览大于20M的pdf文件,请下载查看','确定',config)
}else if(item.type == "gaopenche"){
window.open("3dWidgets/GaoPenChe")
}else if(item.type == "denggao"){
window.open("3dWidgets/denggaoche")
}else if(item.type == "jiqiren"){
window.open("3dWidgets/jiqiren")
}else if(item.type == "konghuqi"){
window.open("3dWidgets/konghuqi")
}else if(item.type == "waifu"){
window.open("3dWidgets/waifudingguan")
}else if(item.type == "neifu"){
window.open("3dWidgets/neifudingguan")
}else if(item.type == "gong"){
window.open("3dWidgets/gongdingguan")
}else if(item.type == "qiu"){
window.open("3dWidgets/qiuguan")
}else if (item.isDir) {
//将allFiles后面的内容截取出来
this.selectedDataBank = item.key.substring(9, item.key.length - 1)
this.getALLFileList(this.selectedDataBank)
}else{
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('该文件类型暂不支持在线查看,请下载查看','确定',config)
}
}
//记录战术授课
openteacher(){
let key = `allFiles/${this.selectedDataBank}/战术授课/`
this.downloadFile.handleData(key,"进入")
}
//记录战术学习
openlearn(){
let key = `allFiles/${this.selectedDataBank}/战术学习/`
this.downloadFile.handleData(key,"进入")
}
//返回上一级目录
backTominTop(){
let topnum = this.gettoplist(this.selectedDataBank)
this.getALLFileList(topnum)
}
//上级目录产生函数
gettoplist(item){
let list = item
let listArr = list.split("/")
let listresult = ""
for(let i = 0;i < listArr.length - 1;i++){
listresult += listArr[i] + "/"
}
let listresult2 = listresult.substring(0, listresult.length - 1)
return listresult2
}
//上传按钮鼠标移入
uploadBtnEnter(){
this.isOpenUpload = true
}
//上传按钮鼠标移出
uploadBtnLeave(){
this.isOpenUpload = false
}
//点击每条的checkbox
clickCheckBox(e){
e.stopPropagation();
setTimeout(() => {
if(this.selection.selected.length != 0){
this.isDelete = true
} else{
this.isDelete = false
}
}, 0);
}
//点击每条的li
clickCheckBoxLi(e,row){
this.selection.toggle(row)
setTimeout(() => {
if(this.selection.selected.length != 0){
this.isDelete = true
} else{
this.isDelete = false
}
}, 0);
}
file:any //需要上传的文件
//input file 选择文件
selectFile (e) {
this.file = e.target.files[0] || null //上传的文件
this.http.get(`/api/ObjectMetadata/drives/${this.selectedDataBank}/${this.file.name}`).subscribe(
data=>{
var r = confirm(`已有同名文件,继续将替换该文件,是否替换?`);
if (r == true) {
this.startUploading()
}
},
err => {
this.startUploading()
}
)
}
fileArr:any
//上传文件夹
async selectFiles (e) {
this.fileArr = e.target.files || null //上传的文件
this.uploadisLoading2 = true
this.child.handleData() //子组件处理数据格式
let _this = this
for (var i = 0;i < this.fileArr.length; i++) {
let f = this.fileArr[i];
let lastIndex = f.webkitRelativePath.lastIndexOf("/")
let url = f.webkitRelativePath.substring(0, lastIndex)
let adddress = this.selectedDataBank + "/" + url
let filesnum = _this.fileArr.length
let result = await new Promise ((result,reject)=>{
this.startUploading2(f,adddress,result,reject,filesnum,this.selectedDataBank)
})
}
}
//上传文件
objectName2:any //上传对象名
uploadisLoading2:boolean = false //上传进度条显示
uploadProgress2:any
uploadId2:any; //上传分块上传事件编号
filesTag2:any = [] //每上传成功一个文件就往里面加一个标识
//e是上传的文件 selectedDataBank是需要上传的地址 包括 XXX资料库 + 文件夹路径
startUploading2 (e,selectedDataBank,result,reject,filesnum,selectedDataBank2) {
let file = e || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
this.uploadisLoading2 = true
this.uploadProgress2 = 0 + "/" + filesnum
this.child.uploading(file) //子组件 当前文件正在上传
if (file && fileSize<=shardSize) { //上传文件<=5MB时
let formData = new FormData()
formData.append("file",file)
this.http.post(`/api/Objects/drives/allFiles/${selectedDataBank2}`,formData).subscribe((data:any)=>{
this.objectName2 = data.objectName
this.filesTag2.push("data")
this.zone.run(() => {
  setTimeout(() => this.uploadProgress2 = this.filesTag2.length + "/" + filesnum, 0);
});
result("成功了")
this.child.endUpload(file) //子组件 当前文件上传成功
if(this.filesTag2.length == filesnum){
this.filesTag2 = [] //清空计数文件夹
this.uploadProgress2 = filesnum + "/" + filesnum
this.uploadisLoading2 = false
this.child.delete() //清空上传文件夹子组件数据
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('文件夹全部上传完毕','确定',config)
// 当全部循环完毕重新加载列表
this.getALLFileList(selectedDataBank2)
}
})
} else if (file && fileSize>shardSize) { //上传文件>5MB时,分块上传
let data = {fileName: file.name}
this.uploadisLoading2 = true
this.http.post(`/api/NewMultipartUpload/drives/allFiles/${selectedDataBank}`,{},{params:data}).subscribe((data:any)=>{ //初始化分段上传
this.objectName2 = data.objectName
this.uploadId2 = data.uploadId
this.subsectionUploading2(e,result,reject,filesnum,selectedDataBank2)
})
}
}
PartNumberETag2:any=[]; //每次返回需要保存的信息
//开始分段上传
async subsectionUploading2 (e,result,reject,filesnum,selectedDataBank2) {
let file = e || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
let allSlice = Math.ceil(fileSize / shardSize) //总文件/5MB===共分多少段
let _result = result
for (let i = 0;i < allSlice;i++) { //循环分段上传
let start = i * shardSize //切割文件开始位置
let end = Math.min(fileSize, start + shardSize); //切割文件结束位置
let formData = new FormData()
formData.append("file",file.slice(start, end))
//同步写法实现异步调用
let result = await new Promise((resolve, reject) => {
// await 需要后面返回一个 promise 对象
this.http.post(`/api/MultipartUpload/drives/${this.objectName2}?uploadId=${this.uploadId2}&partNumber=${i+1}`,formData).subscribe((data:any)=>{
let msg = {
"partNumber":data.partNumber || null,
"eTag": data.eTag || null}
resolve(msg) // 调用 promise 内置方法处理成功
})
});
this.PartNumberETag2.push(result)
if (this.PartNumberETag2.length === allSlice) {
this.endUploading2(e,_result,reject,filesnum,selectedDataBank2)
}
}//for循环
}
//完成分块上传
endUploading2 (e,result,reject,filesnum,selectedDataBank2) {
let data = this.PartNumberETag2
let paramsData = {uploadId:this.uploadId2}
this.http.post(`/api/CompleteMultipartUpload/drives/${this.objectName2}`,data,{params:paramsData}).subscribe(data=>{
this.filesTag2.push("data")
this.zone.run(() => {
  setTimeout(() => this.uploadProgress2 = this.filesTag2.length + "/" + filesnum, 0);
});
result("成功了")
this.child.endUpload(e) //子组件 当前文件上传成功
if(this.filesTag2.length == filesnum){
this.uploadProgress2 = filesnum + "/" + filesnum
this.uploadisLoading2 = false
this.filesTag2 = [] //清空计数文件夹
this.child.delete() //清空上传文件夹子组件数据
this.getALLFileList(selectedDataBank2)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('文件夹全部上传完毕','确定',config)
}
this.PartNumberETag2 =[] //清空保存返回的信息
})
}
//取消分块上传
cancel2 () {
this.http.delete(`/api/MultipartUpload/drives/${this.objectName2}?uploadId=${this.uploadId2}`).subscribe(data=>{
this.uploadisLoading2= false
this.fileArr = {}
this.PartNumberETag2 =[] //清空保存返回的信息
this.filesTag2 = [] //清空计数文件夹
this.child.delete() //清空上传文件夹子组件数据
this.getALLFileList(this.selectedDataBank)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('取消上传成功!','确定',config);
})
}
//新建文件夹
createFolder(){
const dialogRef = this.dialog.open(FolderDialog);
dialogRef.afterClosed().subscribe((data)=>{
if(data){
//创建空文件夹
this.http.post(`/api/Objects/drives/allFiles/${this.selectedDataBank}/${data.name}/`,{}).subscribe(data=>{
this.getALLFileList(this.selectedDataBank)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('新建文件夹成功','确定',config)
})
}
});
}
//返回顶级目录
backToTop () {
if (this.selectedDataBank.includes('/')) {
let arr = this.selectedDataBank.split('/')
this.selectedDataBank = arr[0]
this.getALLFileList(arr[0])
} else {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('目前已是一级目录','确定',config)
}
}
//上传文件
objectName:any //上传对象名
uploadisLoading:boolean = false //上传进度条显示
uploadProgress:any = 0
uploadId:any; //上传分块上传事件编号
startUploading () {
let file = this.file || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
if (file && fileSize<=shardSize) { //上传文件<=5MB时
let formData = new FormData()
formData.append("file",file)
this.http.post(`/api/Objects/drives/allFiles/${this.selectedDataBank}`,formData).subscribe((data:any)=>{
this.objectName = data.objectName
this.getALLFileList(this.selectedDataBank)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('上传成功','确定',config)
})
} else if (file && fileSize>shardSize) { //上传文件>5MB时,分块上传
let data = {fileName: file.name}
this.uploadisLoading = true
this.http.post(`/api/NewMultipartUpload/drives/allFiles/${this.selectedDataBank}`,{},{params:data}).subscribe((data:any)=>{ //初始化分段上传
this.objectName = data.objectName
this.uploadId = data.uploadId
this.subsectionUploading()
})
}
}
PartNumberETag:any=[]; //每次返回需要保存的信息
//开始分段上传
async subsectionUploading () {
let file = this.file || null //获取上传的文件
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
let allSlice = Math.ceil(fileSize / shardSize) //总文件/5MB===共分多少段
for (let i = 0;i < allSlice;i++) { //循环分段上传
let start = i * shardSize //切割文件开始位置
let end = Math.min(fileSize, start + shardSize); //切割文件结束位置
let formData = new FormData()
formData.append("file",file.slice(start, end))
//同步写法实现异步调用
let result = await new Promise((resolve, reject) => {
// await 需要后面返回一个 promise 对象
this.http.post(`/api/MultipartUpload/drives/${this.objectName}?uploadId=${this.uploadId}&partNumber=${i+1}`,formData).subscribe((data:any)=>{
let msg = {
"partNumber":data.partNumber || null,
"eTag": data.eTag || null}
resolve(msg) // 调用 promise 内置方法处理成功
// console.log(2)
})
});
this.PartNumberETag.push(result)
this.uploadProgress = Number((i/allSlice).toFixed(2))*100
if (this.PartNumberETag.length === allSlice) {
this.uploadProgress = 100
this.endUploading()}
}//for循环
}
//完成分块上传
endUploading () {
let data = this.PartNumberETag;
let paramsData = {uploadId:this.uploadId};
this.http.post(`/api/CompleteMultipartUpload/drives/${this.objectName}`,data,{params:paramsData}).subscribe(data=>{
// console.log(3)
this.getALLFileList(this.selectedDataBank);
this.uploadProgress = 0;
this.uploadisLoading = false;
this.PartNumberETag =[]; //清空保存返回的信息
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000;
this.snackBar.open('上传成功','确定',config);
})
}
//取消分块上传
cancel () {
this.http.delete(`/api/MultipartUpload/drives/${this.objectName}?uploadId=${this.uploadId}`).subscribe(data=>{
this.uploadProgress = 0;
this.uploadisLoading = false;
this.PartNumberETag = []; //清空保存返回的信息
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000;
this.snackBar.open('取消上传成功!','确定',config);
})
}
isTrueDelete:any = ['基础知识','装备','技战术','消防设施','资料库']; //匹配内置一级目录 是否被选择删除
// 删除文件
deleteFiles(){
if (this.selection.selected.length != 0) {
let isDelete = confirm('您确定要删除选中文件吗')
let arr = []
if (isDelete) {
let arrList = [] //匹配到 禁止删除的 目录
this.selection.selected.forEach((element)=>{
let data = element.key.split("/");
this.isTrueDelete.forEach(elements => {
if (elements==data[data.length-2] && data.length-2==2 && !data[data.length-1]) {
arrList.push('true')
}
});
})
if (arrList.length) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('内置文件夹不允许删除','确定',config);
} else {
this.selection.selected.forEach( async (element,index) => {
let result = await new Promise((result,reject)=>{
if(element.isDir){ //如果是文件夹
let paramsdata:any = {
prefix : element.key,
recursive : true
}
this.http.delete(`/api/Objects/drives`,{
params:paramsdata
}).subscribe(data=>{
arr.push("删除成功了")
if (arr.length == this.selection.selected.length) {
this.getALLFileList(this.selectedDataBank)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除文件成功','确定',config);
this.selection.clear()
this.isDelete = false
}
result(data)
})
}else{
this.http.delete(`/api/Objects/drives/${element.key}`).subscribe(data=>{
arr.push("删除成功了")
if (arr.length == this.selection.selected.length) {
this.getALLFileList(this.selectedDataBank)
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除文件成功','确定',config);
this.selection.clear()
this.isDelete = false
}
result(data)
})
}
})
});
} // if arrList
}
} else {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('请选择要删除的文件','确定',config);
}
}
// deleteFiles(){
// if (this.selection.selected.length == 1) {
// let isDelete = confirm('您确定要删除吗')
// let arr = []
// if (isDelete) {
// let item = this.selection.selected[0]
// if(item.isDir){//如果是文件夹
// let paramsdata:any = {
// prefix : item.key,
// recursive : true
// }
// this.http.delete(`/api/Objects/drives`,{
// params:paramsdata
// }).subscribe(data=>{
// this.getALLFileList(this.selectedDataBank)
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open('删除文件夹成功','确定',config);
// this.selection.clear()
// this.isDelete = false
// })
// }
// else{
// this.http.delete(`/api/Objects/drives/${item.key}`).subscribe(data=>{
// this.getALLFileList(this.selectedDataBank)
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open('删除文件成功','确定',config);
// this.selection.clear()
// this.isDelete = false
// })
// }
// }
// }
// if (this.selection.selected.length == 0) {
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open('请选择要删除的文件','确定',config);
// }
// if (this.selection.selected.length > 1) {
// const config = new MatSnackBarConfig();
// config.verticalPosition = 'top';
// config.duration = 3000
// this.snackBar.open('暂不支持批量删除','确定',config);
// }
// }
//下载↓
selectDownloadFile:any; //选择下载的文件
download:any; //下载文件元数据
downloadisLoading:boolean = false; //进度条loading加载
downloadProgress:number = 0; //进度条进度
downLoadFile(){
if (this.selection.selected.length === 1) {
this.selectDownloadFile = this.selection.selected[0]
if(this.selectDownloadFile.isDir){
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('文件夹不支持下载','确定',config)
}else{
this.http.get('/api/ObjectMetadata/drives/' + this.selectDownloadFile.key).subscribe(data=>{
// console.log(123,data)
this.download = data
this.downloadFile.download(this.download)
})
}
} else if (this.selection.selected.length>1) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('暂时不支持批量下载','确定',config)
} else if (this.selection.selected.length == 0) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('请选择要下载的文件','确定',config)
}
}
}
//查看图片大图和视频
@Component({
selector: 'viewdetails',
templateUrl: './viewdetails.html',
styleUrls: ['./all-file.component.scss']
})
export class ViewDetails {
// myControl = new FormControl();
//注入MatDialogRef,可以用来关闭对话框
//要访问对话框组件中的数据,必须使用MAT_DIALOG_DATA注入令牌
constructor(private http: HttpClient,public dialogRef: MatDialogRef<ViewDetails>,@Inject(MAT_DIALOG_DATA) public data) {}
Url:string
onNoClick(): void {
this.dialogRef.close();
}
ngOnInit(): void {
this.Url = "/api/Objects/drives/" + this.data.url
}
closeDialog(){
this.dialogRef.close();
}
}
@Component({
selector: 'folderdalog',
templateUrl: './folderdalog.html',
styleUrls: ['./all-file.component.scss']
})
export class FolderDialog {
constructor(private http: HttpClient,public dialogRef: MatDialogRef<FolderDialog>,@Inject(MAT_DIALOG_DATA) public data) {}
newFolderName:string
onNoClick(): void {
this.dialogRef.close();
}
ngOnInit(): void {
var myDate = new Date();
var year = myDate.getFullYear();
var month = myDate.getMonth();
var day = myDate.getDate();
var hour = myDate.getHours(); //获取当前小时数(0-23)
var minutes = myDate.getMinutes(); //获取当前分钟数(0-59)
var seconds = myDate.getSeconds(); //获取当前秒数(0-59)
var data = year + '' + month + day + hour + minutes + seconds
this.newFolderName = "新建文件夹_" + data;
}
onSubmit(value){
this.dialogRef.close(value);
}
}

14
src/app/ui/all-file/folderdalog.html

@ -0,0 +1,14 @@
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<mat-form-field>
<input matInput id="name" name="name" type='text'
required
style="font-size: 12px;"
onfocus="this.select()"
[(ngModel)]="newFolderName" placeholder="创建文件夹">
</mat-form-field>
<div class="btn">
<button type="submit" class="savebtn" mat-raised-button color="primary" [disabled]='form.invalid'>确定</button>
<button type="button" mat-button (click)="onNoClick()" mat-raised-button>取消</button>
</div>
</form>

12
src/app/ui/all-file/viewdetails.html

@ -0,0 +1,12 @@
<div style="position: relative;">
<div style="position: absolute;right: 0;top: 0;cursor: pointer;" (click)="closeDialog()">
<span><mat-icon>clear</mat-icon></span>
</div>
<div class="imgbox" style="text-align: center;">
<img *ngIf="data.type == 'img'" style="max-width: 96%;max-height: 100%;margin-top: 20px;" class="imgitemdefault" [src]="Url">
<video style="margin-top:18px;" autoplay controls *ngIf="data.type == 'video'" [src]="Url"></video>
<audio autoplay controls *ngIf="data.type == 'mp3'" [src]="Url"></audio>
<!-- <pre *ngIf="data.type == 'txt'">{{Url}}</pre> -->
<!-- <iframe *ngIf="data.type == 'txt'" [src]="Url" frameborder="1" width="100%" height="600"></iframe> -->
</div>
</div>

48
src/app/ui/changepassword/changepassword.component.html

@ -0,0 +1,48 @@
<div mat-dialog-title>
修改密码
</div>
<div class="passwordCard" mat-dialog-content>
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<span class="cardLeft">原密码</span>
<mat-form-field>
<input matInput id="password" name="password"
required type="password"
ngModel #password="ngModel" placeholder="请输入原密码">
</mat-form-field>
<span class="cardLeft">新密码</span>
<mat-form-field>
<input matInput id="newPassword" name="newPassword" type="password"
required pattern="^(?=.*[a-zA-Z])(?=.*[0-9])[A-Za-z0-9]{8,20}$"
ngModel #newPassword="ngModel" placeholder="请输入新密码">
</mat-form-field>
<div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)">
<div class="group-error-content">密码格式8-20位,字母+数字</div>
</div>
<span class="cardLeft">确认新密码</span>
<mat-form-field>
<input matInput id="newsPassword" name="newsPassword" type="password"
required
ngModel #newsPassword="ngModel" placeholder="请确认新密码"
[appConfirmpsw] = "newPassword.value">
</mat-form-field>
<div *ngIf="newsPassword.touched&&newsPassword.invalid">
<div class="group-error-content">密码输入不一致!</div>
</div>
<div *ngIf="errmsg" class="group-error-content">
{{errmsg}}
</div>
<div mat-dialog-actions class="btnbox">
<button mat-raised-button color="primary" type="submit"
[disabled]="!form.form.valid">
确定
</button>
<button mat-raised-button color="primary" mat-dialog-close>取消</button>
</div>
</form>
</div>

15
src/app/ui/changepassword/changepassword.component.scss

@ -0,0 +1,15 @@
.passwordCard {
width: 300px;
height: 100%;
}
.mat-form-field {
display: block;
width: 300px;
}
.group-error-content {
font-size: 8px;
color: red;
}
.mat-dialog-content {
overflow: visible
}

39
src/app/ui/changepassword/changepassword.component.ts

@ -0,0 +1,39 @@
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http'
import { MatDialogRef } from '@angular/material/dialog';
import { MatSnackBarConfig, MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-changepassword',
templateUrl: './changepassword.component.html',
styleUrls: ['./changepassword.component.scss']
})
export class ChangepasswordComponent implements OnInit {
constructor(private http:HttpClient,public snackBar: MatSnackBar,
public dialogRef: MatDialogRef<ChangepasswordComponent>) { }
ngOnInit() {
}
errmsg :string = ''
onSubmit(e){
this.http.put('/api/Account/Password', {
password: e.password,
newPassword: e.newPassword,
}).subscribe(data=> {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('密码修改成功','确定',config);
this.dialogRef.close(data);
},(err) =>
{this.errmsg = err}
)
}
}

30
src/app/ui/changepassword/equal-validator.directive.ts

@ -0,0 +1,30 @@
import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl, ValidatorFn} from '@angular/forms';
@Directive({
selector: '[appConfirmpsw]',
providers: [{
provide : NG_VALIDATORS,
useExisting : ConfirmpswDirective,
multi: true
}]
})
export class ConfirmpswDirective implements Validator {
@Input('appConfirmpsw') confirmpsw: string;
constructor() {
}
validate(control: AbstractControl): {[key: string]: any} {
return this.confirmpsw ? comfirmPswValidator(this.confirmpsw)(control) : null;
}
}
export function comfirmPswValidator(_confirmpsw: string): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
if ( !control.value ) {
return { 'required' : true };
}
return control.value !== _confirmpsw ? {'confirmpsw' : {value: true}} : null;
};
}

20
src/app/ui/changeuserdata/changeuserdata.component.html

@ -0,0 +1,20 @@
<div mat-dialog-title>
修改资料
</div>
<div mat-dialog-content>
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<mat-form-field>
<input matInput id="password" name="password"
required type="password"
ngModel #password="ngModel" placeholder="请输入原密码">
</mat-form-field>
<div mat-dialog-actions class="btnbox">
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid">确定</button>
<button mat-raised-button color="primary" mat-dialog-close>取消</button>
</div>
</form>
</div>

0
src/app/ui/changeuserdata/changeuserdata.component.scss

25
src/app/ui/changeuserdata/changeuserdata.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChangeuserdataComponent } from './changeuserdata.component';
describe('ChangeuserdataComponent', () => {
let component: ChangeuserdataComponent;
let fixture: ComponentFixture<ChangeuserdataComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChangeuserdataComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChangeuserdataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

22
src/app/ui/changeuserdata/changeuserdata.component.ts

@ -0,0 +1,22 @@
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-changeuserdata',
templateUrl: './changeuserdata.component.html',
styleUrls: ['./changeuserdata.component.scss']
})
export class ChangeuserdataComponent implements OnInit {
constructor(private http:HttpClient,) { }
ngOnInit(): void {
}
//修改资料
onSubmit (e) {
// console.log(e)
}
}

1
src/app/ui/create-exam/create-exam.component.html

@ -0,0 +1 @@
<p>创建考试</p>

0
src/app/ui/create-exam/create-exam.component.scss

25
src/app/ui/create-exam/create-exam.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateExamComponent } from './create-exam.component';
describe('CreateExamComponent', () => {
let component: CreateExamComponent;
let fixture: ComponentFixture<CreateExamComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CreateExamComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateExamComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

15
src/app/ui/create-exam/create-exam.component.ts

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-create-exam',
templateUrl: './create-exam.component.html',
styleUrls: ['./create-exam.component.scss']
})
export class CreateExamComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

39
src/app/ui/eharts-statistics/eharts-statistics.component.html

@ -0,0 +1,39 @@
<div class="content">
<div class="header">
<form #form="ngForm">
<div class="queryBox">
<div class="queryField" style="margin-right: 90px;">
<!-- <button type="button" mat-raised-button color="primary" style="margin-right: 10px;" (click)='goBack()'><mat-icon style="vertical-align: middle; font-size: 20px;">reply</mat-icon>返回</button> -->
<button type="button" mat-raised-button color="primary" (click)='queryAll()'>查看全部详情</button>
</div>
<div class="queryField">
<label style="margin-right: 10px;">开始时间:</label>
<input matInput [matDatepicker]="start" placeholder="请选择开始时间" readonly (dateChange)="startEvent($event)" [formControl]='startTime'>
<mat-datepicker-toggle matSuffix [for]="start"></mat-datepicker-toggle>
<mat-datepicker #start></mat-datepicker>
</div>
<div class="queryField">
<label style="margin-right: 10px;">结束时间:</label>
<input matInput [matDatepicker]="end" placeholder="请选择结束时间" readonly (dateChange)="endEvent($event)" [formControl]='endTime'>
<mat-datepicker-toggle matSuffix [for]="end"></mat-datepicker-toggle>
<mat-datepicker #end></mat-datepicker>
</div>
<div class="btnbox" style="margin-left: 90px;">
<button mat-raised-button color="primary" (click)='query()'>查询</button>
<button mat-raised-button style="margin-left: 10px;" type="button" (click)='getList()'>重置</button>
</div>
</div>
</form>
</div>
<div class="center" id="center"></div>
<div class="nofiles" *ngIf="!echartsData.length">
<span style="font-size: 14px;cursor: default;">暂无学习记录~</span>
</div>
</div>

50
src/app/ui/eharts-statistics/eharts-statistics.component.scss

@ -0,0 +1,50 @@
.content{
width: 100%;
height: 93%;
display: flex;
flex-direction: column;
}
.header {
padding: 10px;
box-sizing: border-box;
border-bottom: 1px solid #999;
.queryBox {
box-sizing: border-box;
padding: 5px 15px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items:center;
justify-content:center;
.queryField {
margin: 0 15px;
font-size: 14px;
input {
width: 180px;
height: 22px;
line-height: 22px;
}
}
.btnbox{
float: right;
}
} //queryBox
}
.center {
flex: 1;
box-sizing: border-box;
padding: 10px;
}
.nofiles{
background: url("../../../assets/images/nofiles.png") no-repeat scroll center 0 transparent;
padding-top: 150px;
width: 488px;
position: absolute;
left: 50%;
top: 50%;
text-align: center;
margin: -96px 0 0 -244px;
}

25
src/app/ui/eharts-statistics/eharts-statistics.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EhartsStatisticsComponent } from './eharts-statistics.component';
describe('EhartsStatisticsComponent', () => {
let component: EhartsStatisticsComponent;
let fixture: ComponentFixture<EhartsStatisticsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EhartsStatisticsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EhartsStatisticsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

228
src/app/ui/eharts-statistics/eharts-statistics.component.ts

@ -0,0 +1,228 @@
import { Component, OnInit } from '@angular/core';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
import {MatDatepickerInputEvent} from '@angular/material/datepicker';
import { HttpClient } from '@angular/common/http';
import { FormControl } from '@angular/forms';
import { MatSnackBarConfig, MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, Router } from '@angular/router';
declare var echarts : any;
@Component({
selector: 'app-eharts-statistics',
templateUrl: './eharts-statistics.component.html',
styleUrls: ['./eharts-statistics.component.scss'],
})
export class EhartsStatisticsComponent implements OnInit {
constructor(private adapter: DateAdapter<any>,private http:HttpClient,public snackBar: MatSnackBar,private route:ActivatedRoute,private router:Router) { }
ngOnInit(): void {
this.idCard = this.route.snapshot.queryParams.id || ''
this.idName = this.route.snapshot.queryParams.name || ''
this.adapter.setLocale('CH')
this.getList()
}
ngAfterViewInit(): void {
}
startTime:any; //查询开始时间
endTime:any; //查询结束时间
oneMonthDate:number = 30*24*60*60*1000; //一个月的时间戳
echartsData:any = []; //图表数据
idCard:string; //用户身份证
idName:string; //用户姓名
//初始化 + 重置
getList () {
this.startTime = new FormControl( new Date((new Date(new Date().getTime()-this.oneMonthDate)).toLocaleDateString()) )
this.endTime = new FormControl( new Date() )
let msg = {
Name: this.idCard,
// StartTime: new Date(new Date().getTime()-this.oneMonthDate).toLocaleDateString(),
// EndTime: new Date().toLocaleDateString(),
}
this.http.get('/api/StudyRecords/Statistics',{params:msg}).subscribe((data:any)=>{
this.echartsData = data
if (data.length) {
this.handleData(data)
} else { //数据为空时销毁图表
let chartHynyxf = echarts.init(document.getElementById('center'), 'skinUpp');
chartHynyxf.dispose();
}
})
}
//查询
query () {
let msg = {
Name: this.idCard,
StartTime: this.getTime(this.startTime.value), //开始时间
EndTime: this.getTime(this.endTime.value), //结束时间
}
this.http.get('/api/StudyRecords/Statistics',{params:msg}).subscribe((data:any)=>{
this.echartsData = data
if (data.length) {
this.handleData(data)
} else { //数据为空时销毁图表
let chartHynyxf = echarts.init(document.getElementById('center'), 'skinUpp');
chartHynyxf.dispose();
}
})
}
//查询全部详情
queryAll () {
this.router.navigate(['/home/learningrecorddetails'],{queryParams:{'Catalog': '','id':this.idCard}});
}
//返回上一页
goBack () {
history.go(-1)
}
//处理时间 传入 new Date()格式
getTime(date){
let year = date.getFullYear(); //年
let month = date.getMonth() + 1; //月
let day = date.getDate(); //日
let hour = date.getHours() //时
let min = date.getMinutes(); //分
let seconds = date.getSeconds(); //秒
return year+'-'+month+'-'+ day + " "+ hour +':'+ min +':'+ seconds;
}
//选择开始时间
startEvent (e: MatDatepickerInputEvent<Date>) {
let nowTime = new Date()
if (nowTime < e.value) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('选择时间不能大于现在时间段','确定',config);
this.startTime = new FormControl( new Date(new Date().toLocaleDateString()) )
} else {
this.startTime = new FormControl(e.value)
}
}
//选择结束时间
endEvent (e: MatDatepickerInputEvent<Date>) {
let oneDay:number = 86399000; //一天的毫秒数
let selectDay = (e.value).toLocaleDateString() //选择的年月日
let newDay = (new Date()).toLocaleDateString() //现在的年月日
let nowTime = new Date() //现在的时间
if (nowTime < e.value && selectDay!=newDay) { //选择时间段大于现在时间段时
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('选择时间不能大于现在时间段','确定',config);
this.endTime = new FormControl( new Date() )
} else if (nowTime > e.value && selectDay!=newDay) { //正常情况下 时间+1天
this.endTime = new FormControl( new Date(e.value.getTime()+oneDay) )
} else if ( selectDay == newDay ) { //选择时间段是今天时
this.endTime = new FormControl( new Date() )
}
}
//处理图表数据
handleData (data) {
let postNames = [] //y轴坐标
let catalogs = [] //学习目标
let counts = [] //统计次数
let newData = data.sort( function (a,b) {
return b.count - a.count
} )
newData.forEach(element => {
postNames.push(element.postName ? element.postName : '暂无数据')
catalogs.push(element.catalog ? element.catalog : '暂无数据')
counts.push(element.count ? element.count : 0)
});
this.echartsInit(postNames,catalogs,counts)
}
//图表初始化
echartsInit (postNames,catalogs,counts) {
let that = this
let chartHynyxf = echarts.init(document.getElementById('center'), 'skinUpp');
let option = {
title: {
text: that.idName,
left:45,
top:20
},
tooltip: {
trigger: 'axis',
axisPointer: {type: 'shadow'}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
show: false,
type: 'value',
boundaryGap: [0, 0.01]
},
yAxis: {
inverse: true,
"axisLine":{ //y轴
"show":false
},
"axisTick":{ //y轴刻度线
"show":false,
},
"splitLine": { //网格线
"show": false
},
type: 'category',
data: postNames,
max: 15
},
series: [
{
type: 'bar',
data: counts,
barMinWidth: 10, // 最小宽度
barMaxWidth: 30, // 最大宽度
barCategoryGap: 5,
itemStyle:{
normal:{
color:'#40B4E8',
barBorderRadius:[10, 10, 10, 10],
label: {
formatter: function (e) {
return `${catalogs[e.dataIndex]}`+` (统计次数: ${e.value})`
},
show: true,
position: 'insideLeft',
textStyle: { color: '#555'},
fontSize: 14,
fontWeight: 550
},
},
} //itemStyle
},
] //series
};
chartHynyxf.setOption(option);
//柱状图点击事件
chartHynyxf.on('click', function(e) {
that.router.navigate(['/home/learningrecorddetails'],{queryParams:{'Catalog':catalogs[e.dataIndex],'id':that.idCard,'PostName':e.name}});
});
}
}

49
src/app/ui/enterpriseuser/addenterpriseuser.component.html

@ -0,0 +1,49 @@
<h2 mat-dialog-title>创建用户</h2>
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<div>
<mat-form-field>
<input matInput id="idNumber" name="idNumber"
required ngModel placeholder="请输入身份证号" autocomplete="off" pattern="^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$">
<mat-error>
<strong>请输入正确身份证号</strong>
</mat-error>
</mat-form-field>
</div>
<div>
<mat-form-field>
<input matInput id="realName" name="realName"
maxlength="100"
required ngModel placeholder="请输入真实姓名" autocomplete="off">
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-select placeholder="请选择职务" [formControl]="toppings" multiple required>
<div style="float: left;">
<mat-option *ngFor="let item of detachmentPosts" [value]="item.id">{{item.name}}</mat-option>
</div>
<div style="float: left;">
<mat-option *ngFor="let item of brigadePosts" [value]="item.id">{{item.name}}</mat-option>
</div>
<div style="float: left;">
<mat-option *ngFor="let item of RescueStationPosts" [value]="item.id">{{item.name}}</mat-option>
</div>
</mat-select>
</mat-form-field>
</div>
<div mat-dialog-content *ngIf="errmsg">
<p style="font-size: 14px; color: red;">{{errmsg}}</p>
</div>
<div mat-dialog-actions>
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid || toppings.value == null">确定</button>
<button mat-raised-button mat-dialog-close>取消</button>
</div>
</form>

67
src/app/ui/enterpriseuser/addenterpriseuser.component.ts

@ -0,0 +1,67 @@
import { Component, OnInit, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {MatDialogRef} from '@angular/material/dialog';
import {FormControl} from '@angular/forms';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
@Component({
selector: 'addenterpriseuser',
templateUrl: './addenterpriseuser.component.html',
styleUrls: ['./enterpriseuser.component.scss']
})
export class AddEnterpriserUser {
toppings = new FormControl();
constructor(private http: HttpClient,public dialogRef: MatDialogRef<AddEnterpriserUser>,public snackBar: MatSnackBar) {}
errmsg:any; //捕获错误信息
detachmentPosts: any = []//支队职务列表
brigadePosts: any = []//大队职务列表
RescueStationPosts: any = []//救援站职务列表
ngOnInit(): void {
this.getAllPosts()
}
//获得所有职务
getAllPosts(){
this.http.get("/api/Posts").subscribe( (data:any) =>{
data.forEach(item => {
if(item.name.indexOf("支队级") != -1){
this.detachmentPosts.push(item)
}else if(item.name.indexOf("大队级") != -1){
this.brigadePosts.push(item)
}else{
this.RescueStationPosts.push(item)
}
});
})
}
//提交创建表单
onSubmit (e) {
let date = new Date()
let postsArr = this.toppings.value
let postsObj = []
postsArr.forEach((item) => {
postsObj.push({id:item, name:""})
})
let body = {
name : e.idNumber,
realName : e.realName,
roleType : 2,
enabled : true,
creationTime : date,
posts : postsObj
}
this.http.post("/api/Users",body).subscribe( data => {
this.dialogRef.close(data);
},err => {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open(err,'确定',config);
})
}
}

46
src/app/ui/enterpriseuser/editenterpriseuser.html

@ -0,0 +1,46 @@
<h2 mat-dialog-title>编辑用户</h2>
<form (ngSubmit)="onSubmit(form.value)" #form="ngForm" class="example-container">
<div>
<mat-form-field>
<input matInput id="idNumber" name="idNumber"
required [(ngModel)]="IdNumber" placeholder="请输入身份证号" autocomplete="off" disabled pattern="^[1-9]\d{5}(18|19|20|(3\d))\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$">
</mat-form-field>
</div>
<div>
<mat-form-field>
<input matInput id="realName" name="realName"
maxlength="100"
required [(ngModel)]="realName" placeholder="请输入真实姓名" autocomplete="off">
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-select placeholder="请选择职务" [formControl]="toppings" multiple required>
<div style="float: left;">
<mat-option *ngFor="let item of detachmentPosts" [value]="item.id">{{item.name}}</mat-option>
</div>
<div style="float: left;">
<mat-option *ngFor="let item of brigadePosts" [value]="item.id">{{item.name}}</mat-option>
</div>
<div style="float: left;">
<mat-option *ngFor="let item of RescueStationPosts" [value]="item.id">{{item.name}}</mat-option>
</div>
</mat-select>
</mat-form-field>
</div>
<div mat-dialog-content *ngIf="errmsg">
<p style="font-size: 14px; color: red;">{{errmsg}}</p>
</div>
<div mat-dialog-actions>
<button mat-raised-button color="primary" type="submit" [disabled]="!form.form.valid || toppings.value == null">确定</button>
<button mat-raised-button mat-dialog-close>取消</button>
</div>
</form>

68
src/app/ui/enterpriseuser/enterpriseuser.component.html

@ -0,0 +1,68 @@
<div class="header">
<form #form="ngForm">
<div class="queryBox">
<div class="queryField"style="margin-right: 90px;">
<button type="button" mat-raised-button color="primary" (click)='open()'>创建用户</button>
</div>
<div class="queryField">
<label style="margin-right: 10px;">姓名:</label>
<input type="text" [(ngModel)]="name" name="name" autocomplete="off">
</div>
<div class="queryField">
<label style="margin-right: 10px;">身份证号:</label>
<input type="text" [(ngModel)]="identityCard" name="identityCard" autocomplete="off">
</div>
<div class="btnbox" style="margin-left: 90px;">
<button mat-raised-button color="primary" (click)='initData()'>查询</button>
<button mat-raised-button style="margin-left: 10px;" type="button" (click)='empty()'>重置</button>
</div>
</div>
</form>
</div>
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef>姓名</th>
<td mat-cell *matCellDef="let element">{{element.realName}}</td>
</ng-container>
<ng-container matColumnDef="identitycard">
<th mat-header-cell *matHeaderCellDef>身份证号</th>
<td mat-cell *matCellDef="let element">{{element.name}}</td>
</ng-container>
<ng-container matColumnDef="post">
<th mat-header-cell *matHeaderCellDef>职务</th>
<td mat-cell *matCellDef="let element">
<span *ngFor="let item of element.posts">
{{item.name}}
</span>
</td>
</ng-container>
<ng-container matColumnDef="operation">
<th mat-header-cell *matHeaderCellDef>操作</th>
<td mat-cell *matCellDef="let element">
<span class="operationSpan"><mat-icon class="icon">assessment</mat-icon><span class="spanbtn blue" (click)="openRecord(element)">查看学习记录</span></span>
<span class="operationSpan"><mat-icon class="icon">cached</mat-icon><span class="spanbtn blue" (click)="reset(element)">重置密码</span></span>
<span class="operationSpan"><mat-icon class="icon">edit</mat-icon><span class="spanbtn blue" (click)="edit(element)">修改</span></span>
<span *ngIf="element.enabled" class="operationSpan"><mat-icon class="icon" style="color: rgb(245, 34, 45);">remove_circle</mat-icon><span class="spanbtn blue" (click)="noEnabled(element)">禁用</span></span>
<span *ngIf="!element.enabled" class="operationSpan"><mat-icon class="icon" style="color: gray;">remove_circle</mat-icon><span class="spanbtn gray" (click)="enabled(element)">禁用</span></span>
<span class="operationSpan"><mat-icon class="icon">delete</mat-icon><span class="spanbtn red" (click)="delete(element)">删除</span></span>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [length]="length"
[pageSize]="pageSize"
[pageSizeOptions]="pageSizeOptions"
(page)="chagePage($event)">
</mat-paginator>

63
src/app/ui/enterpriseuser/enterpriseuser.component.scss

@ -0,0 +1,63 @@
table {
width: 100%;
text-align: center;
.cdk-header-cell {
text-align: center;
}
}
.maginleft {
margin-left: 5px;
}
.header {
width: 100%;
padding: 10px;
margin-bottom: 10px;
box-sizing: border-box;
.queryBox {
box-sizing: border-box;
padding: 5px 15px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items:center;
justify-content:center;
.queryField {
margin: 0 15px;
font-size: 14px;
input {
width: 280px;
height: 22px;
line-height: 22px;
// border-radius: 3px;
}
}
.btnbox{
float: right;
}
} //queryBox
}
.operationSpan{
margin: 0 5px;
.spanbtn:hover{
text-decoration: underline;
cursor: pointer;
}
.blue{
color:rgb(24, 144, 255) ;
}
.red{
color: rgb(245, 34, 45);
}
.gray{
color: gray;
}
}
.icon{
font-size: 18px;
vertical-align: top;
}

25
src/app/ui/enterpriseuser/enterpriseuser.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EnterpriseuserComponent } from './enterpriseuser.component';
describe('EnterpriseuserComponent', () => {
let component: EnterpriseuserComponent;
let fixture: ComponentFixture<EnterpriseuserComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EnterpriseuserComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EnterpriseuserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

302
src/app/ui/enterpriseuser/enterpriseuser.component.ts

@ -0,0 +1,302 @@
import { Component, OnInit, ViewChild, Inject } from '@angular/core';
import {HttpClient} from '@angular/common/http'
import { MatDialogRef, MatDialog, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { PageEvent } from '@angular/material/paginator';
import { AddEnterpriserUser } from './addenterpriseuser.component'
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import {FormControl} from '@angular/forms';
import { Router,ActivatedRoute } from '@angular/router'
@Component({
selector: 'app-enterpriseuser',
templateUrl: './enterpriseuser.component.html',
styleUrls: ['./enterpriseuser.component.scss']
})
export class EnterpriseuserComponent implements OnInit {
constructor(public http: HttpClient,public dialog: MatDialog,public snackBar: MatSnackBar,private router:Router,private route:ActivatedRoute) { }
ngOnInit() {
this.initData()
}
displayedColumns: string[] = ['name', 'identitycard', 'post', 'operation',];
dataSource:any; //所有企业用户
userLogin:string; //搜索账号
userName:string; //搜索名称
creditcode:string//统一社会信用代码
name:any //姓名
identityCard:any //身份证
//分页
@ViewChild(MatPaginator, {static: true})
pageEvent: PageEvent;
paginator: MatPaginator;
length:any; //共多少条数据
pageSize:any; //每页条数
pageSizeOptions: number[] = [10] //设置每页条数
pageNumber:number = 1; //第几页
//分页切换
chagePage (e) {
this.pageNumber = e.pageIndex+1
let data= {
Name: this.identityCard || '',
RealName: this.name || '',
RoleType: '2',
PageNumber: String(this.pageNumber),
}
this.http.get('/api/Users',{params:data}).subscribe((data:any)=>{
this.length = data.totalCount
this.pageSize = data.pageSize
this.dataSource = new MatTableDataSource<any>(data.items)
})
}
//页面初始化 + 查询 + 重置
initData () {
let data= {
Name: this.identityCard || '',
RealName: this.name || '',
RoleType: '2',
}
this.http.get('/api/Users',{params:data}).subscribe((data:any)=>{
this.length = data.totalCount
this.pageSize = data.pageSize
this.pageEvent.pageIndex = 0
this.dataSource = new MatTableDataSource<any>(data.items)
})
}
//更新当前页数据
getAllUsers () {
let data= {
Name: this.identityCard || '',
RealName: this.name || '',
RoleType: '2',
PageNumber: String(this.pageNumber),
}
this.http.get('/api/Users',{params:data}).subscribe((data:any)=>{
this.length = data.totalCount
this.pageSize = data.pageSize
this.dataSource = new MatTableDataSource<any>(data.items)
})
}
//清空搜索
empty () {
this.identityCard = ''
this.name = ''
this.initData()
}
//跳转学习记录
openRecord(e){
// this.router.navigate([`/home/statistics`],{queryParams:{'name':`${e.realName}`,'id':`${e.name}`}})
window.open(`/home/statistics?name=${e.realName}&id=${e.name}`)
}
//创建用户
open(){
let dialogRef = this.dialog.open(AddEnterpriserUser, {//调用open方法打开对话框并且携带参数过去
width: '250px',
});
dialogRef.afterClosed().subscribe(data=>{
if (data) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('创建成功!','确定',config);
this.getAllUsers()
}
});
}
//编辑企业用户
edit (e) {
let dialogRef = this.dialog.open(editenterpriseuser,{
width: '250px',
data:e
});
dialogRef.afterClosed().subscribe(data=>{
if (data) {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('修改成功!','确定',config);
this.getAllUsers()
}
});
}
//重置密码
reset (e) {
this.http.put(`/api/Users/${e.name}/ResetPassword`,{}).subscribe(
data=>{
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('重置密码成功!','确定',config);
},err=>{
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('重置密码失败!','确定',config);
})
}
//查看企业信息
see (e) {
this.http.get(`/api/CompanyUsers/${e.name}`).subscribe(
data=> {
let dialogRef = this.dialog.open(seeenterpriseuser, {data});
dialogRef.afterClosed().subscribe();
}
)
}
//启用
enabled (e) {
let date = new Date()
let body = {
name : e.name,
realName : e.realName,
roleType : e.roleType,
enabled : true,
creationTime : date,
posts : e.posts
}
this.http.put(`/api/Users/${e.name}`,body).subscribe(data => {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000;
this.snackBar.open('启用成功!','确定',config);
this.getAllUsers();
})
}
//禁用
noEnabled (e) {
let date = new Date()
let body = {
name : e.name,
realName : e.realName,
roleType : e.roleType,
enabled : false,
creationTime : date,
posts : e.posts
}
this.http.put(`/api/Users/${e.name}`,body).subscribe(data => {
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000;
this.snackBar.open('禁用成功!','确定',config);
this.getAllUsers();
})
}
//删除
delete (e) {
let isTrue = confirm('您确定要删除吗')
if (isTrue) {
this.http.delete(`/api/Users/${e.name}`).subscribe(data=>{
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('删除成功!','确定',config);
this.getAllUsers()
})
}
}
}
//编辑企业用户
@Component({
selector: 'app-editenterpriseuser',
templateUrl: './editenterpriseuser.html',
styleUrls: ['./enterpriseuser.component.scss']
})
export class editenterpriseuser {
toppings:any = new FormControl();
constructor(private http: HttpClient,public dialogRef: MatDialogRef<editenterpriseuser>,@Inject(MAT_DIALOG_DATA) public data) {}
errmsg:any; //捕获错误信息
detachmentPosts: any = []//支队职务列表
brigadePosts: any = []//大队职务列表
RescueStationPosts: any = []//救援站职务列表
IdNumber:any //身份证号
realName:any //真实姓名
ngOnInit(): void {
this.toppings.value = []
this.IdNumber = this.data.name
this.realName = this.data.realName
this.data.posts.forEach((item) => {
this.toppings.value.push(item.id)
})
this.getAllPosts()
}
//获得所有职务
getAllPosts(){
this.http.get("/api/Posts").subscribe( (data:any) =>{
data.forEach(item => {
if(item.name.indexOf("支队级") != -1){
this.detachmentPosts.push(item)
}else if(item.name.indexOf("大队级") != -1){
this.brigadePosts.push(item)
}else{
this.RescueStationPosts.push(item)
}
});
})
}
//提交创建表单
onSubmit (e) {
let date = new Date()
let postsArr = this.toppings.value
let postsObj = []
postsArr.forEach((item) => {
postsObj.push({id:item, name:""})
})
let body = {
name : this.data.name,
realName : e.realName,
roleType : 2,
enabled : this.data.enabled,
creationTime : date,
posts : postsObj
}
this.http.put(`/api/Users/${this.data.name}`,body).subscribe(data => {
this.dialogRef.close("修改成功");
})
}
}
//查看企业用户
@Component({
selector: 'app-seeenterpriseuser',
templateUrl: './seeenterpriseuser.html',
styleUrls: ['./enterpriseuser.component.scss']
})
export class seeenterpriseuser {
constructor(public http: HttpClient,public dialog: MatDialog,
@Inject(MAT_DIALOG_DATA) public data) { }
ngOnInit() {}
}

0
src/app/ui/enterpriseuser/seeenterpriseuser.html

1
src/app/ui/join-exam/join-exam.component.html

@ -0,0 +1 @@
<p>参加考试!</p>

0
src/app/ui/join-exam/join-exam.component.scss

25
src/app/ui/join-exam/join-exam.component.spec.ts

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { JoinExamComponent } from './join-exam.component';
describe('JoinExamComponent', () => {
let component: JoinExamComponent;
let fixture: ComponentFixture<JoinExamComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ JoinExamComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(JoinExamComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

15
src/app/ui/join-exam/join-exam.component.ts

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-join-exam',
templateUrl: './join-exam.component.html',
styleUrls: ['./join-exam.component.scss']
})
export class JoinExamComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

49
src/app/ui/learning-record-details/learning-record-details.component.html

@ -0,0 +1,49 @@
<div style="height: 100%; width: 100%;">
<div class="topbox">
<div class="backtop">
<button type="button" mat-raised-button color="primary" (click)="backtop()"><mat-icon style="vertical-align: middle;font-size: 20px;">reply</mat-icon>返回</button>
</div>
<div class="datasearch">
<div class="starttime">
<span>开始时间 :</span>
<input style="width: 220px; height:21px;line-height: 21px;font-size: 15px;" matInput [matDatepicker]="dp" readonly [formControl]="startdate">
<mat-datepicker-toggle matSuffix [for]="dp"></mat-datepicker-toggle>
<mat-datepicker #dp disabled="false"></mat-datepicker>
</div>
<div class="endtime">
<span>结束时间 :</span>
<input style="width: 220px; height:21px;line-height: 21px;font-size: 15px;" matInput [matDatepicker]="dp2" readonly [formControl]="enddate">
<mat-datepicker-toggle matSuffix [for]="dp2"></mat-datepicker-toggle>
<mat-datepicker #dp2 disabled="false"></mat-datepicker>
</div>
</div>
<div class="btnbox">
<button type="button" mat-raised-button color="primary" (click)="onSubmit()">查询</button>
<button type="button" mat-raised-button (click)="reset()">重置</button>
</div>
</div>
<mat-divider></mat-divider>
<div class="listbox" [hidden]="noRecord">
<ul>
<li *ngFor="let item of recordList;let key = index">
<p class="timeTitle" *ngIf="key ==0 || item.time != recordList[key - 1].time">{{item.time}}</p>
<span class="listitem">
<span style="margin-right: 5px;">{{item.time2}}</span>
{{item.operation}} : {{item.target | name3}}
</span>
</li>
</ul>
<mat-paginator
[length]="length"
[pageSize]="pageSize"
(page)="chagePage($event)">
</mat-paginator>
</div>
<div class="nofiles" *ngIf="noRecord">
<span style="font-size: 14px;cursor: default;">该时间段未查询到学习记录~</span>
</div>
</div>

57
src/app/ui/learning-record-details/learning-record-details.component.scss

@ -0,0 +1,57 @@
.topbox{
display: flex;
width: 100%;
height:7%;
line-height: 66px;
// border-bottom: 1px solid gray;
justify-content: space-around;
.datasearch{
display: flex;
div{
margin: 0 10px;
span{
margin-right: 5px;
}
mat-form-field{
input{
padding-left: 3px;
}
}
}
}
.btnbox{
button{
margin: 0 10px;
}
}
}
.listbox{
margin-top: 18px;
margin-left: 26%;
height: 84%;
overflow-y: auto;
.timeTitle{
font-weight: 800;
font-size: 18px;
}
.listitem{
margin-left: 80px;
font-size: 16px;
line-height: 30px;
}
}
.mat-paginator {
background-color: hsla(0,0%,100%,0);
padding-right: 10%;
}
.nofiles{
background: url("../../../assets/images/nofiles.png") no-repeat scroll center 0 transparent;
padding-top: 150px;
width: 488px;
position: absolute;
left: 50%;
top: 50%;
text-align: center;
margin: -88px 0 0 -244px;
}

188
src/app/ui/learning-record-details/learning-record-details.component.ts

@ -0,0 +1,188 @@
import { Component, OnInit ,ViewChild} from '@angular/core';
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from '@angular/material/core';
import {MatDatepicker} from '@angular/material/datepicker';
import {FormControl} from '@angular/forms';
import {HttpClient} from '@angular/common/http';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { MatPaginator } from '@angular/material/paginator';
import { PageEvent } from '@angular/material/paginator';
import { Router,ActivatedRoute } from '@angular/router'
@Component({
selector: 'app-learning-record-details',
templateUrl: './learning-record-details.component.html',
styleUrls: ['./learning-record-details.component.scss']
})
export class LearningRecordDetailsComponent implements OnInit {
startdate:any //开始时间
enddate:any //结束时间
constructor(private adapter: DateAdapter<any>,private http:HttpClient,public snackBar: MatSnackBar,private router:Router,private route:ActivatedRoute) { }
lastdate:any //上个月日期
startTime:any //开始时间查询条件
endTime:any //结束时间查询条件
Catalog:any = this.route.snapshot.queryParams.Catalog || "" //目录
PageNumber:any = 1//当前页数
id:any = this.route.snapshot.queryParams.id//身份证
PostName:any = this.route.snapshot.queryParams.PostName || "" //传过来的职务名称
recordList:any = false//渲染的100条列表
oneMonthDate:number = 30*24*60*60*1000; //一个月的时间戳
noRecord:boolean
//分页
@ViewChild(MatPaginator, {static: true})
pageEvent: PageEvent;
paginator: MatPaginator;
length:any; //共多少条数据
pageSize:any; //每页条数
// pageSizeOptions: number[] = [10] //设置每页条数
pageNumber:number = 1; //第几页
ngOnInit(): void {
this.adapter.setLocale('CH');
let nowdate = new Date().toLocaleDateString() //本月日期 2020/07/11 形式
this.lastdate = new Date(new Date().getTime()-this.oneMonthDate).toLocaleDateString() //上个月日期 2020/06/11 形式
this.startdate = new FormControl(new Date(this.lastdate)); //日历开始时间显示
this.enddate = new FormControl(new Date()); //日历结束时间显示
this.startTime = this.getTIme(new Date(this.lastdate))
this.endTime = this.getTIme(new Date())
this.getAllStudyRecords()
}
//分页切换
chagePage (e) {
this.pageNumber = e.pageIndex+1
let date:any = new Date()
let data = {
Name : this.id,
StartTime : this.startTime,
EndTime : this.endTime,
Catalog : this.Catalog,
PageNumber : String(this.pageNumber),
PageSize:"100",
PostName : this.PostName
}
this.http.get("/api/StudyRecords",{params:data}).subscribe((data:any) => {
this.recordList = data.items
if(data.items.length == 0){
this.noRecord = true
}else{
this.noRecord = false
}
this.recordList.forEach((item) => {
item.time = item.creationTime.substring(0,10)
item.time2 = item.creationTime.substring(11,16)
})
this.length = data.totalCount
this.pageSize = data.pageSize
})
}
//传入 new Date()格式 将日期变为 年月日时分秒
getTIme(date){
let year = date.getFullYear(); //年
let month = date.getMonth() + 1; //月
let day = date.getDate(); //日
let hour = date.getHours() //时
let min = date.getMinutes(); //分
let seconds = date.getSeconds(); //秒
return year+'-'+month+'-'+ day + " "+ hour +':'+ min +':'+ seconds;
}
//初始获得所有学习记录
getAllStudyRecords(){
let date:any = new Date()
let data = {
Name : this.id,
Catalog : this.Catalog || "",
PageNumber : this.PageNumber,
PageSize:"100",
PostName:this.PostName
}
this.http.get("/api/StudyRecords",{params:data}).subscribe((data:any) => {
this.recordList = data.items
if(data.items.length == 0){
this.noRecord = true
}else{
this.noRecord = false
}
this.recordList.forEach((item) => {
item.time = item.creationTime.substring(0,10)
item.time2 = item.creationTime.substring(11,16)
})
this.length = data.totalCount
this.pageSize = data.pageSize
this.pageEvent.pageIndex = 0
})
}
//返回上一页
backtop(){
history.go(-1)
}
//带查询时间获得所有学习记录
getAllStudyRecords2(){
let date:any = new Date()
let data = {
Name : this.id,
StartTime : this.startTime,
EndTime : this.endTime,
Catalog : this.Catalog || "",
PageNumber : this.PageNumber,
PageSize:"100",
PostName:this.PostName
}
this.http.get("/api/StudyRecords",{params:data}).subscribe((data:any) => {
this.recordList = data.items
if(data.items.length == 0){
this.noRecord = true
}else{
this.noRecord = false
}
this.recordList.forEach((item) => {
item.time = item.creationTime.substring(0,10)
item.time2 = item.creationTime.substring(11,16)
})
this.length = data.totalCount
this.pageSize = data.pageSize
this.pageEvent.pageIndex = 0
})
}
//
//查询
onSubmit(){
if(this.startdate.value > this.enddate.value){
const config = new MatSnackBarConfig();
config.verticalPosition = 'top';
config.duration = 3000
this.snackBar.open('起始时间大于结束时间','确定',config);
}
if(this.enddate.value.toLocaleDateString() == new Date().toLocaleDateString() || this.enddate.value > new Date()){
this.enddate.value = new Date()
}
if(this.enddate.value < new Date() && this.enddate.value.toLocaleDateString() != new Date().toLocaleDateString()){
this.enddate.value = new Date(this.enddate.value.getTime() + 24*60*60*1000)
}
this.startTime = this.getTIme(this.startdate.value)
this.endTime = this.getTIme(this.enddate.value)
this.getAllStudyRecords2()
}
//重置
reset(){
this.startdate = new FormControl(new Date(this.lastdate)); //日历开始时间显示
this.enddate = new FormControl(new Date()); //日历结束时间显示
this.startTime = this.getTIme(this.startdate.value)
this.endTime = this.getTIme(this.enddate.value)
this.getAllStudyRecords()
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save