This commit is contained in:
xiaoxing.liu
2022-04-08 15:57:04 +08:00
1341 changed files with 251840 additions and 4657 deletions

1
.gitignore vendored
View File

@ -25,6 +25,7 @@ scripts/var.less
# IDE - VSCode
.vscode/*
.vscode
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"compile-hero.disable-compile-files-on-did-save-code": true
}

View File

@ -41,7 +41,7 @@ function getRule(params: any): any {
if (params.no) {
ret = ret.filter(data => data.no.indexOf(params.no) > -1);
}
return { data: ret, success: true };
return { data: { records: ret, total: ret.length }, success: true };
}
function removeRule(nos: string): any {
@ -51,7 +51,7 @@ function removeRule(nos: string): any {
list.splice(idx, 1);
}
});
return { data: true, success: true };
}
@ -78,6 +78,6 @@ function saveRule(description: string): void {
export const RULES = {
'POST /rule': (req: MockRequest) => getRule(req.queryString),
'POST /delete/rule': (req: MockRequest) => removeRule(req.body.nos),
'POST /delete/rule': (req: MockRequest) => removeRule(req.body.nos)
// 'POST /rule': (req: MockRequest) => saveRule(req.body.description)
};

View File

@ -35,11 +35,23 @@
"styles": [
"node_modules/perfect-scrollbar/css/perfect-scrollbar.css",
"node_modules/quill/dist/quill.snow.css",
"src/styles.less"
"src/styles.less",
{
"input": "src/styles/default.less",
"bundleName": "default",
"inject": false
},
{
"input": "src/styles/compact.less",
"bundleName": "compact",
"inject": false
}
],
"scripts": [
"node_modules/quill/dist/quill.min.js",
"node_modules/perfect-scrollbar/dist/perfect-scrollbar.js"
"node_modules/perfect-scrollbar/dist/perfect-scrollbar.js",
"node_modules/qrious/dist/qrious.min.js"
],
"allowedCommonJsDependencies": [
"ajv",
@ -48,20 +60,28 @@
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}],
"outputHashing": "all",
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
"budgets": [{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "10mb"
}]
},
"dev": {
"fileReplacements": [{
"replace": "src/environments/environment.ts",
"with": "src/environments/eascs/environment.dev.ts"
}],
"outputHashing": "all",
"budgets": [{
"type": "initial",
"maximumWarning": "4mb",
"maximumError": "10mb"
}]
},
"development": {
"buildOptimizer": false,
@ -84,6 +104,9 @@
"production": {
"browserTarget": "ng-alain:build:production"
},
"dev": {
"browserTarget": "app:build:dev"
},
"development": {
"browserTarget": "ng-alain:build:development"
}
@ -131,6 +154,9 @@
"configurations": {
"production": {
"devServerTarget": "ng-alain:serve:production"
},
"dev": {
"devServerTarget": "app:build:dev"
}
}
}

101
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "ng-alain-pro",
"name": "tms-obc-web",
"version": "0.0.0",
"lockfileVersion": 1,
"requires": true,
@ -19,6 +19,11 @@
}
}
},
"@amap/amap-jsapi-loader": {
"version": "1.0.1",
"resolved": "https://registry.nlark.com/@amap/amap-jsapi-loader/download/@amap/amap-jsapi-loader-1.0.1.tgz",
"integrity": "sha1-nsS01dJGfqxFH2yFLjXbaen58MA="
},
"@ampproject/remapping": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@ampproject/remapping/download/@ampproject/remapping-1.0.1.tgz",
@ -2728,11 +2733,46 @@
"integrity": "sha1-ayxRCnrXA56Y57jT1lmPQ1nlwIA=",
"dev": true
},
"@types/d3-geo": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.2.tgz",
"integrity": "sha512-DbqK7MLYA8LpyHQfv6Klz0426bQEf7bRTvhMy44sNGVyZoWn//B0c+Qbeg8Osi2Obdc9BLLXYAKpyWege2/7LQ==",
"dev": true,
"requires": {
"@types/geojson": "*"
}
},
"@types/d3-path": {
"version": "2.0.1",
"resolved": "https://registry.nlark.com/@types/d3-path/download/@types/d3-path-2.0.1.tgz",
"integrity": "sha1-ygPfqLlNit2XrQzZfpbiAGtHY8s="
},
"@types/d3-sankey": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/@types/d3-sankey/-/d3-sankey-0.11.2.tgz",
"integrity": "sha512-U6SrTWUERSlOhnpSrgvMX64WblX1AxX6nEjI2t3mLK2USpQrnbwYYK+AS9SwiE7wgYmOsSSKoSdr8aoKBH0HgQ==",
"dev": true,
"requires": {
"@types/d3-shape": "^1"
},
"dependencies": {
"@types/d3-path": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz",
"integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==",
"dev": true
},
"@types/d3-shape": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.8.tgz",
"integrity": "sha512-gqfnMz6Fd5H6GOLYixOZP/xlrMtJms9BaS+6oWxTKHNqPGZ93BkWWupQSCYm6YHqx6h9wjRupuJb90bun6ZaYg==",
"dev": true,
"requires": {
"@types/d3-path": "^1"
}
}
}
},
"@types/d3-shape": {
"version": "2.1.3",
"resolved": "https://registry.npmmirror.com/@types/d3-shape/download/@types/d3-shape-2.1.3.tgz",
@ -2778,6 +2818,12 @@
"integrity": "sha512-sPZYQEIF/SOnLAvaz9lTuydniP+afBMtElRTdYkeV1QtEgvtJ7qolCPjly6O32QI8CbEmP5O/fztMXEDWfEcrg==",
"dev": true
},
"@types/geojson": {
"version": "7946.0.8",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.8.tgz",
"integrity": "sha512-1rkryxURpr6aWP7R786/UQOkJ3PcpQiWkAXBmdWc7ryFWqN6a4xfK7BtjXvFBKO9LjQ+MWQSWxYeZX1OApnArA==",
"dev": true
},
"@types/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmmirror.com/@types/glob/download/@types/glob-7.2.0.tgz?cache=0&sync_timestamp=1637267477186&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Fglob%2Fdownload%2F%40types%2Fglob-7.2.0.tgz",
@ -3426,14 +3472,6 @@
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
"dev": true
},
"angular-baidu-maps": {
"version": "12.0.0",
"resolved": "https://registry.nlark.com/angular-baidu-maps/download/angular-baidu-maps-12.0.0.tgz",
"integrity": "sha1-I/Sn52ggJcLJRnGdIR6eNmt6sXQ=",
"requires": {
"tslib": "^2.1.0"
}
},
"ansi-colors": {
"version": "4.1.1",
"resolved": "https://registry.nlark.com/ansi-colors/download/ansi-colors-4.1.1.tgz",
@ -5175,6 +5213,14 @@
}
}
},
"css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"requires": {
"utrie": "^1.0.2"
}
},
"css-loader": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/css-loader/download/css-loader-6.2.0.tgz?cache=0&sync_timestamp=1635967924209&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fcss-loader%2Fdownload%2Fcss-loader-6.2.0.tgz",
@ -8116,6 +8162,15 @@
"integrity": "sha1-e15vfmZen7QfMAB+2eDUHpf7IUA=",
"dev": true
},
"html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"requires": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
}
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmmirror.com/htmlparser2/download/htmlparser2-3.10.1.tgz?cache=0&sync_timestamp=1636640940074&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fhtmlparser2%2Fdownload%2Fhtmlparser2-3.10.1.tgz",
@ -14814,6 +14869,11 @@
"integrity": "sha1-xF6cYYAL0IfviNfiVkI73Unl0HE=",
"dev": true
},
"qrious": {
"version": "4.0.2",
"resolved": "http://npm.eascs.com/qrious/-/qrious-4.0.2.tgz",
"integrity": "sha1-CcTUB50rlhYX9ixpz/O5u2ajlpM="
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.nlark.com/qs/download/qs-6.7.0.tgz",
@ -22660,6 +22720,14 @@
}
}
},
"text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"requires": {
"utrie": "^1.0.2"
}
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npm.taobao.org/text-table/download/text-table-0.2.0.tgz",
@ -23209,6 +23277,21 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
"dev": true
},
"utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"requires": {
"base64-arraybuffer": "^1.0.2"
},
"dependencies": {
"base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
}
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmmirror.com/uuid/download/uuid-3.4.0.tgz",

View File

@ -1,7 +1,7 @@
{
"name": "ng-alain-pro",
"name": "tms-obc-web",
"version": "0.0.0",
"description": "Ng-alain business theme, ng-zorro-antd admin panel front-end framework",
"description": "运营后台-WEB",
"author": "cipchk <cipchk@qq.com>",
"repository": {
"type": "git",
@ -11,9 +11,11 @@
"scripts": {
"ng-high-memory": "node --max_old_space_size=8000 ./node_modules/@angular/cli/bin/ng",
"ng": "ng",
"start": "ng s -o --port 4202",
"start": "ng s -o --port 4202 --host 0.0.0.0",
"startIp": "ng serve -o --port 4202 --host 172.29.9.71 --open",
"hmr": "ng s -o --hmr",
"build": "npm run ng-high-memory build",
"build": "npm run ng-high-memory build --",
"build:dev": "npm run build -- -c dev",
"analyze": "npm run ng-high-memory build -- --source-map",
"analyze:view": "source-map-explorer dist/**/*.js",
"lint": "npm run lint:ts && npm run lint:style",
@ -29,6 +31,7 @@
},
"dependencies": {
"@agm/core": "^1.1.0",
"@amap/amap-jsapi-loader": "^1.0.1",
"@angular/animations": "~12.2.0",
"@angular/common": "~12.2.0",
"@angular/compiler": "~12.2.0",
@ -53,8 +56,8 @@
"@fullcalendar/timegrid": "^5.9.0",
"@swimlane/ngx-charts": "^18.0.1",
"ajv": "^8.6.2",
"angular-baidu-maps": "^12.0.0",
"file-saver": "^2.0.5",
"html2canvas": "^1.4.1",
"js-base64": "^3.6.1",
"masonry-layout": "^4.2.2",
"ng-gallery": "^5.0.0",
@ -62,6 +65,7 @@
"ngx-tinymce": "^12.0.0",
"ngx-trend": "^7.0.0",
"perfect-scrollbar": "^1.5.2",
"qrious": "^4.0.2",
"quill": "^1.3.7",
"quill-image-resize-module": "^3.0.0",
"rxjs": "~6.6.0",
@ -71,22 +75,22 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "~12.2.0",
"@angular/cli": "~12.2.0",
"@angular/compiler-cli": "~12.2.0",
"@types/jasmine": "~3.8.0",
"@types/node": "^12.11.1",
"jasmine-core": "~3.8.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.3.5",
"@angular-eslint/builder": "~12.3.1",
"@angular-eslint/eslint-plugin": "~12.3.1",
"@angular-eslint/eslint-plugin-template": "~12.3.1",
"@angular-eslint/schematics": "~12.3.1",
"@angular-eslint/template-parser": "~12.3.1",
"@angular/cli": "~12.2.0",
"@angular/compiler-cli": "~12.2.0",
"@angular/language-service": "~12.2.0",
"@delon/testing": "^12.3.0",
"@types/d3-geo": "^3.0.2",
"@types/d3-sankey": "^0.11.2",
"@types/file-saver": "^2.0.3",
"@types/jasmine": "~3.8.0",
"@types/jasminewd2": "~2.0.3",
"@types/js-base64": "^3.0.0",
"@types/node": "^12.11.1",
"@typescript-eslint/eslint-plugin": "~4.29.2",
"@typescript-eslint/parser": "~4.29.2",
"eslint": "^7.32.0",
@ -95,29 +99,31 @@
"eslint-plugin-jsdoc": "~36.0.7",
"eslint-plugin-prefer-arrow": "~1.2.3",
"eslint-plugin-prettier": "~3.4.1",
"@angular/language-service": "~12.2.0",
"source-map-explorer": "^2.5.2",
"husky": "^6.0.0",
"jasmine-core": "~3.8.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"lint-staged": "^11.1.2",
"ng-alain": "^12.3.0",
"ng-alain-plugin-theme": "^12.0.0",
"ng-alain-sts": "^0.0.1",
"node-fetch": "^2.6.1",
"prettier": "^2.2.1",
"protractor": "~7.0.0",
"source-map-explorer": "^2.5.2",
"stylelint": "^13.13.1",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-rational-order": "^0.1.2",
"stylelint-config-standard": "^22.0.0",
"stylelint-declaration-block-no-ignored-properties": "^2.4.0",
"stylelint-order": "^4.1.0",
"@delon/testing": "^12.3.0",
"ng-alain": "^12.3.0",
"ng-alain-plugin-theme": "^12.0.0",
"ng-alain-sts": "^0.0.1",
"@types/jasminewd2": "~2.0.3",
"jasmine-spec-reporter": "~5.0.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"node-fetch": "^2.6.1",
"husky": "^6.0.0",
"lint-staged": "^11.1.2",
"@types/file-saver": "^2.0.3",
"@types/js-base64": "^3.0.0"
"typescript": "~4.3.5"
},
"lint-staged": {
"(src)/**/*.{html,ts}": [

View File

@ -1,10 +1,14 @@
/**
* For more configuration, please refer to https://angular.io/guide/build#proxying-to-a-backend-server
*
* 更多配置描述请参考 https://angular.cn/guide/build#proxying-to-a-backend-server
*
* Note: The proxy is only valid for real requests, Mock does not actually generate requests, so the priority of Mock will be higher than the proxy
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-18 09:51:21
* @LastEditors : Shiming
* @LastEditTime : 2022-04-08 14:26:28
* @FilePath : \\tms-obc-web\\proxy.conf.js
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
module.exports = {
/**
* The following means that all requests are directed to the backend `https://localhost:9000/`
@ -14,4 +18,14 @@ module.exports = {
// secure: false, // Ignore invalid SSL certificates
// changeOrigin: true
// }
'//api': {
target: {
host: 'tms-api-dev.eascs.com',
protocol: 'https:',
port: 443
},
secure: false,
changeOrigin: true,
logLevel: 'debug'
},
};

View File

@ -2,8 +2,10 @@ import { Component, ElementRef, OnInit, Renderer2 } from '@angular/core';
import { NavigationEnd, NavigationError, RouteConfigLoadStart, Router } from '@angular/router';
import { TitleService, VERSION as VERSION_ALAIN } from '@delon/theme';
import { environment } from '@env/environment';
import { NzIconService } from 'ng-zorro-antd/icon';
import { NzModalService } from 'ng-zorro-antd/modal';
import { VERSION as VERSION_ZORRO } from 'ng-zorro-antd/version';
import { ThemeService } from './theme.service';
@Component({
selector: 'app-root',
@ -15,10 +17,15 @@ export class AppComponent implements OnInit {
renderer: Renderer2,
private router: Router,
private titleSrv: TitleService,
private modalSrv: NzModalService
private modalSrv: NzModalService,
private iconService: NzIconService,
private themeService: ThemeService
) {
renderer.setAttribute(el.nativeElement, 'ng-alain-version', VERSION_ALAIN.full);
renderer.setAttribute(el.nativeElement, 'ng-zorro-version', VERSION_ZORRO.full);
this.iconService.fetchFromIconfont({
scriptUrl: 'https://at.alicdn.com/t/font_3153207_udngwyp35db.js'
});
}
ngOnInit(): void {
@ -42,5 +49,15 @@ export class AppComponent implements OnInit {
this.modalSrv.closeAll();
}
});
// 适配放大150%的屏幕
const screen: any = window.screen
var zoom = window.devicePixelRatio || screen.deviceXDPI / screen?.logicalXDPI;
// console.log(zoom)
if (document.body.clientWidth >= 1280) {
if (zoom != 1 && zoom != 2 && zoom != 3) {
this.themeService.toggleTheme().then();
}
}
}
}

View File

@ -2,7 +2,7 @@
/* eslint-disable import/no-duplicates */
import { HttpClientModule } from '@angular/common/http';
import { default as ngLang } from '@angular/common/locales/zh';
import { APP_INITIALIZER, LOCALE_ID, NgModule, Type } from '@angular/core';
import { APP_INITIALIZER, DEFAULT_CURRENCY_CODE, LOCALE_ID, NgModule, Type } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { SimpleInterceptor } from '@delon/auth';
@ -19,10 +19,11 @@ const GLOBAL_THIRD_MODULES: Array<Type<any>> = [BidiModule];
// #region Http Interceptors
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { DefaultInterceptor } from '@core';
import { BusinessInterceptor, DefaultInterceptor } from '@core';
const INTERCEPTOR_PROVIDES = [
{ provide: HTTP_INTERCEPTORS, useClass: SimpleInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: BusinessInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: DefaultInterceptor, multi: true }
];
// #endregion
@ -39,7 +40,9 @@ const APPINIT_PROVIDES = [
useFactory: StartupServiceFactory,
deps: [StartupService],
multi: true
}
},
{ provide: DEFAULT_CURRENCY_CODE, useValue: '¥' },
AuthGuard
];
// #endregion
@ -50,8 +53,8 @@ import { LayoutModule } from './layout/layout.module';
import { RoutesModule } from './routes/routes.module';
import { SharedModule } from './shared/shared.module';
import { STWidgetModule } from './shared/widget/st-widget.module';
import { Observable } from 'rxjs';
import { registerLocaleData } from '@angular/common';
import { AuthGuard } from './core/guards/auth.guard';
@NgModule({
declarations: [AppComponent],

View File

@ -1,9 +1,10 @@
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { EATokenGuard } from './guards/token.guard';
import { throwIfAlreadyLoaded } from './module-import-guard';
@NgModule({
providers: []
providers: [EATokenGuard]
})
export class CoreModule {
constructor(@Optional() @SkipSelf() parentModule: CoreModule) {

View File

@ -15,14 +15,16 @@ import { EnvironmentService } from '@env/environment.service';
import { NzMessageService } from 'ng-zorro-antd/message';
@Injectable({
providedIn: 'root',
providedIn: 'root'
})
export class CoreService {
// 获取当前登录用户信息
public $api_get_current_user_info = `/scm/cuc/cuc/user/getUserDetail`;
// 获取当前用户所拥有的菜单
public $api_get_current_user_menus = `/scm/cuc/cuc/functionInfo/getUserHaveFunctionsList`;
public $api_get_current_user_menus = `/api/mdc/cuc/functionInfo/getUserHaveFunctionsList`;
position = { lat: '', lng: '' };
constructor(private injector: Injector) {}
// 注入路由

View File

@ -0,0 +1,89 @@
import { Injectable, Injector } from '@angular/core';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
import { ACLGuard, ACLService } from '@delon/acl';
import { MenuService, SettingsService } from '@delon/theme';
import { EAUserService } from '@shared';
import { Observable, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';
@Injectable()
export class AuthGuard extends ACLGuard {
constructor(
srv: ACLService,
public srv1: ACLService,
private menuService: MenuService,
private settings: SettingsService,
private userService: EAUserService,
router: Router,
private inject: Injector
) {
super(srv, router, inject);
}
canActivate(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Observable<boolean> {
// if (Object.keys(route.params)?.length > 0 || !route.routeConfig?.path) {
// return super.canActivate(route, _state);
// } else {
// return super.canActivate(route, _state);
// }
return super.canActivate(route, _state);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
if (childRoute.routeConfig?.loadChildren || childRoute.routeConfig?.children) {
return super.canActivateChild(childRoute, state);
} else {
return this.handle(childRoute, state, 2, this.settingRoute(childRoute.params, state.url));
}
}
private handle(route: ActivatedRouteSnapshot, state: RouterStateSnapshot, type: 1 | 2, router?: string): Observable<boolean> {
if (!router) {
return type === 1 ? super.canActivate(route, state) : super.canActivateChild(route, state);
}
return this.userService
.request('/api/mdc/cuc/userAuthority/isUserAdmin', {
appUserId: this.settings.user.appUserId
})
.pipe(
switchMap(res => {
if (res) {
// 超级管理员赋值全量权限
this.srv1.setFull(true);
return of(true);
} else {
// 如果不是超级管理员 获取权限
return this.userService.request('/api/mdc/cuc/functionButton/getUserFunctionButton', { link: router });
}
}),
switchMap(res => {
if (res?.abilities) {
this.srv1.setAbility(res.abilities || []);
// this.menuService.resume();
this.userService.loadUserMenus();
}
return type === 1 ? super.canActivate(route, state) : super.canActivateChild(route, state);
})
);
}
/**
* 根据参数拼接原始路由
* @param params 参数
* @param route 实际路由
* @returns
*/
private settingRoute(params: any, route: string) {
let _route = route;
if (_route.indexOf('?') > -1) {
_route = route.split('?')[0];
}
for (const key of Object.keys(params)) {
if (_route.indexOf(params[key]) > -1) {
_route = _route.replace(params[key], ':' + key);
}
}
return _route;
}
}

View File

@ -0,0 +1,38 @@
import { Inject, Injectable, Injector } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot } from '@angular/router';
import { sysConf } from '@conf/sys.conf';
import { CoreService } from '@core';
import { ACLGuard, ACLService } from '@delon/acl';
import { EAUserService } from '@shared';
import { Observable, of } from 'rxjs';
@Injectable()
export class EATokenGuard implements CanActivate, CanActivateChild {
constructor(srv: ACLService, router: Router, private eaUserSrv: CoreService, private router2: Router, private inject: Injector) {}
canActivate(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot | null): Observable<boolean> {
const canOpen = this.eaUserSrv.loginStatus;
if (!canOpen) {
this.router2.navigate([sysConf.login_url], {
queryParams: {
returnUrl: _state?.url
}
});
return of(!canOpen);
}
return of(true);
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
const canOpen = this.eaUserSrv.loginStatus;
if (!canOpen) {
this.router2.navigate([sysConf.login_url], {
queryParams: {
returnUrl: state?.url
}
});
return of(!canOpen);
}
return of(true);
}
}

View File

@ -1,6 +1,9 @@
export * from './module-import-guard';
export * from './net/default.interceptor';
export * from './net/business.interceptor';
// Services
export * from './core.service';
export * from './startup/startup.service';
export * from './guards/token.guard';

View File

@ -0,0 +1,108 @@
import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse,
HttpResponseBase
} from '@angular/common/http';
import { Inject, Injectable, Optional } from '@angular/core';
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { environment } from '@env/environment';
import { EAEnvironmentService, EAUserService } from '@shared';
import { Observable, of } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
import { CoreService } from '../core.service';
@Injectable()
export class BusinessInterceptor implements HttpInterceptor {
constructor(
private envSrv: EAEnvironmentService,
private eaUserSrv: EAUserService,
@Optional()
@Inject(DA_SERVICE_TOKEN)
private tokenSrv: ITokenService,
private coreSrv: CoreService
) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// 构造新的请求URL
req = this.constructNewRequestUrl(req);
// 附加额外的请求头
req = this.attachAdditionalHeaders(req);
// 后续操作
return next.handle(req).pipe(
mergeMap(ev => this.handlingBussinessResponseData(ev)),
catchError((err: HttpErrorResponse) => this.handlingBusinessErrors(err))
);
}
/**
* 构造新的请求URL
*/
private constructNewRequestUrl(req: HttpRequest<any>): HttpRequest<any> {
let url = req.url;
if (!url.startsWith('https://') && !url.startsWith('http://')) {
if (!url.startsWith('assets')) {
url = environment.api.baseUrl + url;
}
}
return req.clone({ url });
}
/**
* 附加额外的请求头
*/
private attachAdditionalHeaders(req: HttpRequest<any>): HttpRequest<any> {
let position = {};
if (this.coreSrv.position.lat && this.coreSrv.position.lng) {
position = { lat: this.coreSrv.position.lat.toString(), lng: this.coreSrv.position.lng.toString() };
}
// 附加环境变量
const header: any = {
appId: this.envSrv.env.appId,
tenantId: this.envSrv.env.tenantId,
enterpriseId: this.envSrv.env.enterpriseId,
...position
};
// 附加授权声明
const token = this.tokenSrv.get()?.token;
if (token) {
header.Authorization = `Bearer ${token}`;
}
return req.clone({ setHeaders: header });
}
/**
* 处理业务数据
*/
private handlingBussinessResponseData(ev: HttpEvent<any>): Observable<any> {
if (ev instanceof HttpResponseBase) {
const body = (ev as HttpResponse<any>).body;
if (body) {
switch (body.status) {
case 505001:
case 505002:
this.eaUserSrv.logout();
break;
default:
break;
}
}
}
if (ev instanceof HttpErrorResponse) {
return this.handlingBusinessErrors(ev);
}
return of(ev);
}
/**
* 处理响应错误
*/
private handlingBusinessErrors(err: HttpErrorResponse): Observable<any> {
/** Http响应异常已在默认拦截器处理完成 ,该处不再处理 */
return of(err);
}
}

View File

@ -1,20 +1,8 @@
import {
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpHeaders,
HttpInterceptor,
HttpRequest,
HttpResponseBase
} from '@angular/common/http';
import { Injectable, Injector } from '@angular/core';
import { Router } from '@angular/router';
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { _HttpClient } from '@delon/theme';
import { environment } from '@env/environment';
import { NzNotificationService } from 'ng-zorro-antd/notification';
import { BehaviorSubject, Observable, of, throwError } from 'rxjs';
import { catchError, filter, mergeMap, switchMap, take } from 'rxjs/operators';
import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponseBase } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { catchError, mergeMap } from 'rxjs/operators';
import { CoreService } from './../core.service';
const CODEMESSAGE: { [key: number]: string } = {
200: '服务器成功返回请求的数据。',
@ -34,228 +22,38 @@ const CODEMESSAGE: { [key: number]: string } = {
504: '网关超时。'
};
/**
* 默认HTTP拦截器其注册细节见 `app.module.ts`
*/
@Injectable()
export class DefaultInterceptor implements HttpInterceptor {
private refreshTokenEnabled = environment.api.refreshTokenEnabled;
private refreshTokenType: 're-request' | 'auth-refresh' = environment.api.refreshTokenType;
private refreshToking = false;
private refreshToken$: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private injector: Injector) {
if (this.refreshTokenType === 'auth-refresh') {
this.buildAuthRefresh();
}
}
private get notification(): NzNotificationService {
return this.injector.get(NzNotificationService);
}
private get tokenSrv(): ITokenService {
return this.injector.get(DA_SERVICE_TOKEN);
}
private get http(): _HttpClient {
return this.injector.get(_HttpClient);
}
private goTo(url: string): void {
setTimeout(() => this.injector.get(Router).navigateByUrl(url));
}
private checkStatus(ev: HttpResponseBase): void {
if ((ev.status >= 200 && ev.status < 300) || ev.status === 401) {
return;
}
const errortext = CODEMESSAGE[ev.status] || ev.statusText;
this.notification.error(`请求错误 ${ev.status}: ${ev.url}`, errortext);
}
/**
* 刷新 Token 请求
*/
private refreshTokenRequest(): Observable<any> {
const model = this.tokenSrv.get();
return this.http.post(`/api/auth/refresh`, null, null, { headers: { refresh_token: model?.refresh_token || '' } });
}
// #region 刷新Token方式一使用 401 重新刷新 Token
private tryRefreshToken(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
// 1、若请求为刷新Token请求表示来自刷新Token可以直接跳转登录页
if ([`/api/auth/refresh`].some(url => req.url.includes(url))) {
this.toLogin();
return throwError(ev);
}
// 2、如果 `refreshToking` 为 `true` 表示已经在请求刷新 Token 中,后续所有请求转入等待状态,直至结果返回后再重新发起请求
if (this.refreshToking) {
return this.refreshToken$.pipe(
filter(v => !!v),
take(1),
switchMap(() => next.handle(this.reAttachToken(req)))
);
}
// 3、尝试调用刷新 Token
this.refreshToking = true;
this.refreshToken$.next(null);
return this.refreshTokenRequest().pipe(
switchMap(res => {
// 通知后续请求继续执行
this.refreshToking = false;
this.refreshToken$.next(res);
// 重新保存新 token
this.tokenSrv.set(res);
// 重新发起请求
return next.handle(this.reAttachToken(req));
}),
catchError(err => {
this.refreshToking = false;
this.toLogin();
return throwError(err);
})
);
}
/**
* 重新附加新 Token 信息
*
* > 由于已经发起的请求,不会再走一遍 `@delon/auth` 因此需要结合业务情况重新附加新的 Token
*/
private reAttachToken(req: HttpRequest<any>): HttpRequest<any> {
// 以下示例是以 NG-ALAIN 默认使用 `SimpleInterceptor`
const token = this.tokenSrv.get()?.token;
return req.clone({
setHeaders: {
token: `Bearer ${token}`
}
});
}
// #endregion
// #region 刷新Token方式二使用 `@delon/auth` 的 `refresh` 接口
private buildAuthRefresh(): void {
if (!this.refreshTokenEnabled) {
return;
}
this.tokenSrv.refresh
.pipe(
filter(() => !this.refreshToking),
switchMap(res => {
console.log(res);
this.refreshToking = true;
return this.refreshTokenRequest();
})
)
.subscribe(
res => {
// TODO: Mock expired value
res.expired = +new Date() + 1000 * 60 * 5;
this.refreshToking = false;
this.tokenSrv.set(res);
},
() => this.toLogin()
);
}
// #endregion
private toLogin(): void {
this.notification.error(`未登录或登录已过期,请重新登录。`, ``);
this.goTo(this.tokenSrv.login_url!);
}
private handleData(ev: HttpResponseBase, req: HttpRequest<any>, next: HttpHandler): Observable<any> {
this.checkStatus(ev);
// 业务处理:一些通用操作
switch (ev.status) {
case 200:
// 业务层级错误处理以下是假定restful有一套统一输出格式指不管成功与否都有相应的数据格式情况下进行处理
// 例如响应内容:
// 错误内容:{ status: 1, msg: '非法参数' }
// 正确内容:{ status: 0, response: { } }
// 则以下代码片断可直接适用
// if (ev instanceof HttpResponse) {
// const body = ev.body;
// if (body && body.status !== 0) {
// this.injector.get(NzMessageService).error(body.msg);
// // 注意这里如果继续抛出错误会被行254的 catchError 二次拦截,导致外部实现的 Pipe、subscribe 操作被中断例如this.http.get('/').subscribe() 不会触发
// // 如果你希望外部实现需要手动移除行254
// return throwError({});
// } else {
// // 忽略 Blob 文件体
// if (ev.body instanceof Blob) {
// return of(ev);
// }
// // 重新修改 `body` 内容为 `response` 内容,对于绝大多数场景已经无须再关心业务状态码
// return of(new HttpResponse(Object.assign(ev, { body: body.response })));
// // 或者依然保持完整的格式
// return of(ev);
// }
// }
break;
case 401:
if (this.refreshTokenEnabled && this.refreshTokenType === 're-request') {
return this.tryRefreshToken(ev, req, next);
}
this.toLogin();
break;
case 403:
case 404:
case 500:
this.goTo(`/exception/${ev.status}`);
break;
default:
if (ev instanceof HttpErrorResponse) {
console.warn(
'未可知错误大部分是由于后端不支持跨域CORS或无效配置引起请参考 https://ng-alain.com/docs/server 解决跨域问题',
ev
);
}
break;
}
if (ev instanceof HttpErrorResponse) {
return throwError(ev);
} else {
return of(ev);
}
}
private getAdditionalHeaders(headers?: HttpHeaders): { [name: string]: string } {
const res: { [name: string]: string } = {};
// const lang = this.injector.get(ALAIN_I18N_TOKEN).currentLang;
// if (!headers?.has('Accept-Language') && lang) {
// res['Accept-Language'] = lang;
// }
return res;
}
constructor(private coreSrv: CoreService) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// 统一加上服务端前缀
let url = req.url;
if (!url.startsWith('https://') && !url.startsWith('http://')) {
const { baseUrl } = environment.api;
url = baseUrl + (baseUrl.endsWith('/') && url.startsWith('/') ? url.substring(1) : url);
}
const newReq = req.clone({ url, setHeaders: this.getAdditionalHeaders(req.headers) });
return next.handle(newReq).pipe(
mergeMap(ev => {
// 允许统一对请求错误处理
if (ev instanceof HttpResponseBase) {
return this.handleData(ev, newReq, next);
}
// 若一切都正常,则后续操作
return of(ev);
}),
catchError((err: HttpErrorResponse) => this.handleData(err, newReq, next))
return next.handle(req).pipe(
mergeMap(ev => this.handlingHttpResponseData(ev)),
catchError((err: HttpErrorResponse) => this.handlingHttpErrorResponse(err))
);
}
/**
* 处理Http响应数据
*/
private handlingHttpResponseData(ev: HttpEvent<any>): Observable<any> {
if (ev instanceof HttpResponseBase) {
// 正常情况直接返回到下个业务拦截器处理
if (ev.status >= 200 && ev.status < 300) {
return of(ev);
}
// 所有状态不是2xx和3xx都当作异常处理
if (ev instanceof HttpErrorResponse) {
return this.handlingHttpErrorResponse(ev);
}
}
return of(ev);
}
/**
* 处理默认Http响应错误
*/
private handlingHttpErrorResponse(err: HttpErrorResponse): Observable<any> {
return of(err);
}
}

View File

@ -1,7 +1,11 @@
import { HttpClient } from '@angular/common/http';
import { Inject, Injectable } from '@angular/core';
import { cacheConf } from '@conf/cache.conf';
import { sysConf } from '@conf/sys.conf';
import { ACLService } from '@delon/acl';
import { MenuService, SettingsService, TitleService, _HttpClient } from '@delon/theme';
import { environment } from '@env/environment';
import { AmapService, EACacheService, EAUserService } from '@shared';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzIconService } from 'ng-zorro-antd/icon';
import { Observable, zip } from 'rxjs';
@ -24,15 +28,25 @@ export class StartupService {
private aclService: ACLService,
private titleService: TitleService,
private httpClient: _HttpClient,
private userSrv: EAUserService,
private amapService: AmapService,
public cacheSrv: EACacheService,
private coreSrv: CoreService
) {
iconSrv.addIcon(...ICONS_AUTO, ...ICONS);
this.settingService.setLayout('fixSiderbar', true);
}
// TODO: 退出登录时需要清理用户信息
load(): Promise<void> {
return new Promise(resolve => {
this.amapService.getCurrentPosition().subscribe(res => {
if (res.position) {
this.coreSrv.position = { lat: res.position.lat, lng: res.position.lng };
}
});
let data;
if (this.coreSrv.loginStatus) {
// 本地菜单
@ -74,10 +88,17 @@ export class StartupService {
this.settingService.setApp(appData);
// 用户信息:包括姓名、头像、邮箱地址
this.settingService.setUser(userData);
this.cacheSrv.set(cacheConf.env, {
appId: sysConf.appId,
tenantId: userData?.tenantId || sysConf.tenantId,
enterpriseId: userData?.enterpriseId || sysConf.enterpriseId
});
// ACL设置权限为全量
this.aclService.setFull(true);
this.aclService.setFull(false);
// 初始化菜单
this.menuService.add(menuData);
if (menuData) {
this.menuService.add(menuData);
}
// 设置页面标题的后缀
this.titleService.default = '';
this.titleService.suffix = appData.name;
@ -94,12 +115,10 @@ export class StartupService {
const appData = this.httpClient.get(`assets/mocks/app-data.json`).pipe(map((res: any) => res.app));
// 用户数据
const userData = this.coreSrv.loginStatus
? this.httpClient.post(this.coreSrv.$api_get_current_user_info, {}).pipe(map((res: any) => res.data))
: this.httpClient.get('assets/mocks/user-data.json').pipe(map((res: any) => res.user));
const userData = this.httpClient.get('assets/mocks/user-data.json').pipe(map((res: any) => res.user));
// 菜单数据
const menuData = this.httpClient.get('assets/mocks/menu-data.json').pipe(map((res: any) => res.menu));
const menuData = this.httpClient.get('assets/mocks/menu-data.json').pipe(map((res: any) => res.data.menu));
return zip(appData, userData, menuData);
}
@ -115,9 +134,7 @@ export class StartupService {
const appData = this.httpClient.get(`assets/mocks/app-data.json`).pipe(map((res: any) => res.app));
// 用户数据
const userData = this.coreSrv.loginStatus
? this.httpClient.post(this.coreSrv.$api_get_current_user_info, {}).pipe(map((res: any) => res.data))
: this.httpClient.get('assets/mocks/user-data.json').pipe(map((res: any) => res.user));
const userData = this.httpClient.post(this.userSrv.$api_get_user_by_token, {}).pipe(map((res: any) => res.data));
// 菜单数据
const menuData = this.httpClient
@ -125,6 +142,7 @@ export class StartupService {
appId: this.coreSrv.envSrv.getEnvironment().appId
})
.pipe(map((res: any) => res.data));
// const menuData = this.httpClient.get('assets/mocks/menu-data.json').pipe(map((res: any) => res.data.menu));
return zip(appData, userData, menuData);
}

View File

@ -11,9 +11,23 @@ import { environment } from '@env/environment';
// #region NG-ALAIN Config
const alainConfig: AlainConfig = {
st: { modal: { size: 'lg' } },
st: {
req: { method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' } },
res: { reName: { list: 'data.records', total: 'data.total' } },
page: { show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000], toTop: false },
modal: { size: 'lg' }
},
sf: { button: { search: '查询' } },
pageHeader: { homeI18n: 'home', recursiveBreadcrumb: true },
auth: { login_url: '/passport/login' }
auth: { login_url: '/passport/login' },
acl: { guard_url: '/exception/403' },
chart: {
// 以下是默认配置,如果项目无法外网访问,可以根据 `angular.json` 配置将依赖包直接使用 `./assets***` 路径
libs: [
'https://gw.alipayobjects.com/os/lib/antv/g2/4.1.4/dist/g2.min.js',
'https://gw.alipayobjects.com/os/lib/antv/data-set/0.11.7/dist/data-set.js'
]
},
};
const alainModules = [AlainThemeModule.forRoot(), DelonACLModule.forRoot()];
@ -21,12 +35,12 @@ const alainProvides = [{ provide: ALAIN_CONFIG, useValue: alainConfig }];
// #region reuse-tab
import { RouteReuseStrategy } from '@angular/router';
alainProvides.push({
provide: RouteReuseStrategy,
useClass: ReuseTabStrategy,
deps: [ReuseTabService]
} as any);
// import { RouteReuseStrategy } from '@angular/router';
// alainProvides.push({
// provide: RouteReuseStrategy,
// useClass: ReuseTabStrategy,
// deps: [ReuseTabService]
// } as any);
// #endregion
@ -51,9 +65,9 @@ export class GlobalConfigModule {
throwIfAlreadyLoaded(parentModule, 'GlobalConfigModule');
// NOTICE: Only valid for menus with reuse property
// Pls refer to the E-Mail demo effect
reuseTabService.mode = ReuseTabMatchMode.MenuForce;
// reuseTabService.mode = ReuseTabMatchMode.MenuForce;
// Shouled be trigger init, you can ingore when used `reuse-tab` component in layout component
reuseTabService.init();
// reuseTabService.init();
}
static forRoot(): ModuleWithProviders<GlobalConfigModule> {

View File

@ -24,7 +24,7 @@ import { NzSpinModule } from 'ng-zorro-antd/spin';
import { NzSwitchModule } from 'ng-zorro-antd/switch';
import { NzTimelineModule } from 'ng-zorro-antd/timeline';
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
import { NzGridModule } from 'ng-zorro-antd/grid';
import { LayoutPassportComponent } from './passport/passport.component';
import { PRO_COMPONENTS } from './pro/index';
@ -56,6 +56,7 @@ const COMPONENTS: Array<Type<any>> = [...PRO_COMPONENTS, LayoutPassportComponent
NoticeIconModule,
ThemeBtnModule,
ScrollbarModule,
NzGridModule,
NzMessageModule
],
declarations: COMPONENTS,

View File

@ -1,13 +1,15 @@
<div class="container">
<!-- <pro-langs class="langs" btnClass></pro-langs> -->
<div class="wrap">
<div class="top">
<div class="head">
<img class="logo" src="./assets/logo-color.svg">
<span class="title">ng-alain pro</span>
<nz-layout class="layout">
<nz-header>
<div nz-row>
<div nz-col nzSpan="24" style="display: flex;align-items: center;">
<img width="32" height="32" src="./assets/images/user/logo.svg" [routerLink]="['/']" />
<label class="title ml-sm">运多星网络货运管理平台</label>
</div>
<div class="desc">武林中最有影响力的《葵花宝典》;欲练神功,挥刀自宫</div>
</div>
<router-outlet></router-outlet>
</div>
</div>
</nz-header>
<nz-content class="content">
<div class="inner-content">
<router-outlet></router-outlet>
</div>
</nz-content>
</nz-layout>

View File

@ -1,74 +1,22 @@
@import '~@delon/theme/index';
:host {
::ng-deep {
.container {
display: flex;
flex-direction: column;
min-height: 100%;
background: #f0f2f5;
}
.langs {
width: 100%;
height: 40px;
line-height: 44px;
text-align: right;
.ant-dropdown-trigger {
display: inline-block;
}
.anticon {
margin-top: 24px;
margin-right: 24px;
font-size: 14px;
vertical-align: top;
cursor: pointer;
}
}
.wrap {
flex: 1;
padding: 32px 0;
}
.ant-form-item {
margin-bottom: 24px;
.layout {
height: 100%;
}
@media (min-width: @screen-md-min) {
.container {
background-image: url('https://gw.alipayobjects.com/zos/rmsportal/TVYTbAXWheQpRcWDaDMu.svg');
background-repeat: no-repeat;
background-position: center 110px;
background-size: 100%;
}
.wrap {
padding: 32px 0 24px;
}
}
.top {
text-align: center;
}
.header {
height: 44px;
line-height: 44px;
a {
text-decoration: none;
}
}
.logo {
height: 44px;
margin-right: 16px;
}
.title {
position: relative;
color: @heading-color;
font-weight: 600;
font-size: 33px;
font-family: 'Myriad Pro', 'Helvetica Neue', Arial, Helvetica, sans-serif;
vertical-align: middle;
}
.desc {
margin-top: 12px;
margin-bottom: 40px;
color: @text-color-secondary;
font-size: @font-size-base;
.ant-layout-header {
background: #ffffff;
box-shadow: 0px 5px 5px #d1d1d1;
}
}
}
.title {
font-size : 18px;
font-weight: 600;
color : #26282A;
}

View File

@ -7,24 +7,9 @@ import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
styleUrls: ['./passport.component.less']
})
export class LayoutPassportComponent implements OnInit {
links = [
{
title: '帮助',
href: ''
},
{
title: '隐私',
href: ''
},
{
title: '条款',
href: ''
}
];
constructor(@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService) {}
constructor() {}
ngOnInit(): void {
this.tokenService.clear();
// this.tokenService.clear();
}
}

View File

@ -1,7 +1,7 @@
<div *ngIf="pro.isTopMenu" class="alain-pro__top-nav">
<div class="alain-pro__top-nav-main" [ngClass]="{ 'alain-pro__top-nav-main-wide': pro.isFixed }">
<div class="alain-pro__top-nav-main-left">
<layout-pro-logo class="alain-pro__top-nav-logo"></layout-pro-logo>
<layout-pro-logo class="alain-pro__top-nav-logo" style="width: 195px;"></layout-pro-logo>
<div class="alain-pro__menu-wrap">
<div layout-pro-menu mode="horizontal"></div>
</div>

View File

@ -1,4 +1,4 @@
<a [routerLink]="['/']" class="d-flex align-items-center">
<img src="./assets/logo-color.svg" alt="{{ name }}" height="32" />
<img src="./assets/images/user/logo.png" alt="{{ name }}" height="32" />
<h1>{{ name }}</h1>
</a>

View File

@ -1,9 +1,9 @@
<ng-template #icon let-i>
<ng-container *ngIf="i" [ngSwitch]="i.type">
<i *ngSwitchCase="'icon'" nz-icon [nzType]="i.value" class="alain-pro__menu-icon"></i>
<i *ngSwitchCase="'iconfont'" nz-icon [nzIconfont]="i.iconfont" class="alain-pro__menu-icon"></i>
<i *ngSwitchCase="'iconfont'" nz-icon [nzIconfont]="i.iconfont" class="alain-pro__menu-icon icon"></i>
<img *ngSwitchCase="'img'" src="{{ i.value }}" class="anticon alain-pro__menu-icon alain-pro__menu-img" />
<i *ngSwitchDefault class="anticon alain-pro__menu-icon {{ i.value }}"></i>
<i *ngSwitchDefault class="icon alain-pro__menu-icon {{ i.value }}"></i>
</ng-container>
</ng-template>
<ng-template #mainLink let-i>
@ -17,39 +17,22 @@
<a *ngIf="!i.externalLink" [routerLink]="i.link" [target]="i.target">{{ i.text }} </a>
<a *ngIf="i.externalLink" [attr.href]="i.externalLink" [attr.target]="i.target">{{ i.text }} </a>
</ng-template>
<ul *ngIf="menus" nz-menu [nzMode]="mode" [nzTheme]="pro.theme" [nzInlineCollapsed]="pro.isMobile ? false : pro.collapsed">
<ul *ngIf="menus" nz-menu [nzMode]="mode" [nzTheme]="pro.theme"
[nzInlineCollapsed]="pro.isMobile ? false : pro.collapsed">
<ng-container *ngFor="let l1 of menus">
<li
*ngIf="l1.children!.length === 0"
nz-menu-item
class="alain-pro__menu-item"
[class.alain-pro__menu-item--disabled]="l1.disabled"
[nzSelected]="l1._selected"
[nzDisabled]="l1.disabled"
>
<li *ngIf="l1.children!.length === 0" nz-menu-item class="alain-pro__menu-item"
[class.alain-pro__menu-item--disabled]="l1.disabled" [nzSelected]="l1._selected" [nzDisabled]="l1.disabled">
<a *ngIf="!l1.externalLink" [routerLink]="l1.link" (click)="closeCollapsed()" class="alain-pro__menu-title">
<ng-template [ngTemplateOutlet]="mainLink" [ngTemplateOutletContext]="{ $implicit: l1 }"></ng-template>
</a>
<a
*ngIf="l1.externalLink"
[attr.href]="l1.externalLink"
[attr.target]="l1.target"
(click)="closeCollapsed()"
class="alain-pro__menu-title"
>
<a *ngIf="l1.externalLink" [attr.href]="l1.externalLink" [attr.target]="l1.target" (click)="closeCollapsed()"
class="alain-pro__menu-title">
<ng-template [ngTemplateOutlet]="mainLink" [ngTemplateOutletContext]="{ $implicit: l1 }"></ng-template>
</a>
</li>
<li
*ngIf="l1.children!.length > 0"
nz-submenu
[nzTitle]="l1TitleTpl"
class="alain-pro__menu-item"
[class.text-white]="pro.theme === 'dark' && l1._selected"
[nzOpen]="l1._open"
[nzDisabled]="l1.disabled"
(nzOpenChange)="openChange(l1, $event)"
>
<li *ngIf="l1.children!.length > 0" nz-submenu [nzTitle]="l1TitleTpl" class="alain-pro__menu-item"
[class.text-white]="pro.theme === 'dark' && l1._selected" [nzOpen]="l1._open" [nzDisabled]="l1.disabled"
(nzOpenChange)="openChange(l1, $event)">
<ng-template #l1TitleTpl>
<span title class="alain-pro__menu-title">
<ng-template [ngTemplateOutlet]="icon" [ngTemplateOutletContext]="{ $implicit: l1.icon }"></ng-template>
@ -61,34 +44,17 @@
</ng-template>
<ul>
<ng-container *ngFor="let l2 of l1.children">
<li
*ngIf="!l2._hidden && l2.children!.length === 0"
nz-menu-item
[class.alain-pro__menu-item--disabled]="l2.disabled"
[nzSelected]="l2._selected"
[nzDisabled]="l2.disabled"
(click)="closeCollapsed()"
>
<li *ngIf="!l2._hidden && l2.children!.length === 0" nz-menu-item
[class.alain-pro__menu-item--disabled]="l2.disabled" [nzSelected]="l2._selected" [nzDisabled]="l2.disabled"
(click)="closeCollapsed()">
<ng-template [ngTemplateOutlet]="subLink" [ngTemplateOutletContext]="{ $implicit: l2 }"></ng-template>
</li>
<li
*ngIf="!l2._hidden && l2.children!.length > 0"
nz-submenu
[nzTitle]="l2.text!"
[nzOpen]="l2._open"
[nzDisabled]="l2.disabled"
(nzOpenChange)="openChange(l2, $event)"
>
<li *ngIf="!l2._hidden && l2.children!.length > 0" nz-submenu [nzTitle]="l2.text!" [nzOpen]="l2._open"
[nzDisabled]="l2.disabled" (nzOpenChange)="openChange(l2, $event)">
<ul>
<ng-container *ngFor="let l3 of l2.children">
<li
*ngIf="!l3._hidden"
nz-menu-item
[class.alain-pro__menu-item--disabled]="l3.disabled"
[nzSelected]="l3._selected"
[nzDisabled]="l3.disabled"
(click)="closeCollapsed()"
>
<li *ngIf="!l3._hidden" nz-menu-item [class.alain-pro__menu-item--disabled]="l3.disabled"
[nzSelected]="l3._selected" [nzDisabled]="l3.disabled" (click)="closeCollapsed()">
<ng-template [ngTemplateOutlet]="subLink" [ngTemplateOutletContext]="{ $implicit: l3 }"></ng-template>
</li>
</ng-container>
@ -98,4 +64,4 @@
</ul>
</li>
</ng-container>
</ul>
</ul>

View File

@ -51,7 +51,6 @@ export class LayoutProMenuComponent implements OnInit, OnDestroy {
}
});
this.menus = res;
this.openStatus();
}

View File

@ -1,10 +1,4 @@
<notice-icon
btnClass="alain-pro__header-item"
btnIconClass="alain-pro__header-item-icon"
[data]="data"
[count]="count"
[loading]="loading"
(select)="select($event)"
(clear)="clear($event)"
(popoverVisibleChange)="loadData()"
></notice-icon>
<notice-icon btnClass="alain-pro__header-item" btnIconClass="alain-pro__header-item-icon" [data]="data" [count]="count"
[loading]="loading" (select)="select($event)" (clear)="clear($event)" (popoverVisibleChange)="loadData()">
</notice-icon>

View File

@ -1,21 +1,21 @@
<div nz-dropdown [nzDropdownMenu]="userMenu" nzPlacement="bottomRight" class="alain-pro__header-item">
<nz-avatar [nzSrc]="settings.user.avatar" nzSize="small" class="mr-sm"></nz-avatar>
{{ settings.user.name }}
<nz-avatar [nzSrc]="settings.user?.avatar" nzSize="small" class="mr-sm"></nz-avatar>
{{ settings.user?.realName }}
</div>
<nz-dropdown-menu #userMenu="nzDropdownMenu">
<div nz-menu class="width-sm">
<div nz-menu-item routerLink="/pro/account/center">
<div nz-menu-item routerLink="/account/center">
<i nz-icon nzType="user" class="mr-sm"></i>
个人中心
</div>
<div nz-menu-item routerLink="/pro/account/settings">
<!-- <div nz-menu-item routerLink="/pro/account/settings">
<i nz-icon nzType="setting" class="mr-sm"></i>
个人设置
</div>
<div nz-menu-item routerLink="/exception/trigger">
<i nz-icon nzType="close-circle" class="mr-sm"></i>
触发错误
</div>
</div> -->
<li nz-menu-divider></li>
<div nz-menu-item (click)="logout()">
<i nz-icon nzType="logout" class="mr-sm"></i>

View File

@ -9,6 +9,10 @@
<!-- <quick-chat-status class="hidden-xs"></quick-chat-status> -->
<!--Notify-->
<layout-pro-notify class="hidden-xs"></layout-pro-notify>
<a nz-tooltip nzTooltipTitle="下载中心" nzTooltipPlacement="bottom" class="hidden-xs" target="_blank" href="/#/download"
rel="noopener noreferrer" class="alain-pro__header-item">
<i nz-icon nzType="cloud-download" nzTheme="outline" style="font-size: 18px;" ></i>
</a>
<!--RTL-->
<!-- <layout-pro-rtl></layout-pro-rtl> -->
<!--User-->

View File

@ -23,7 +23,7 @@ export class BrandService {
* @alain-pro-sider-menu-width: 256px;
* ```
*/
readonly width = 256;
readonly width = 205;
/**
* Specify width of the sidebar after collapsed, If you change it, muse be synchronize change less parameter:

View File

@ -29,7 +29,7 @@
@alain-pro-light-color: #fff;
@alain-pro-light-slider-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
@alain-pro-logo-font-size: 20px;
@alain-pro-logo-font-size: 17px;
@alain-pro-logo-font-family: 'Myriad Pro', 'Helvetica Neue', Arial, Helvetica, sans-serif;
@alain-pro-content-margin: 24px;

View File

@ -0,0 +1,31 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 20:15:41
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:30
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\account-routing.module.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccountComponentsCenterComponent } from './components/center/center.component';
const routes: Routes = [
{ path: '', redirectTo: 'center', pathMatch: 'full' },
{
path: 'center',
component: AccountComponentsCenterComponent,
data: {
title: '账户中心'
}
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AccountRoutingModule {}

View File

@ -0,0 +1,30 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-11-29 11:06:01
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:34
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\account.module.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { NgModule } from '@angular/core';
import { SharedModule } from '@shared';
import { AccountRoutingModule } from './account-routing.module';
import { AccountComponentsCenterComponent } from './components/center/center.component';
import { AccountComponentsEditNameComponent } from './components/edit-name/edit-name.component';
import { AccountComponentsCenterEditComponent } from './components/edit-password/edit-password.component';
const COMPONENTS = [
AccountComponentsCenterComponent,
AccountComponentsEditNameComponent,
AccountComponentsCenterEditComponent
];
const COMPONENTS_NOROUNT = [AccountComponentsEditNameComponent];
@NgModule({
imports: [SharedModule, AccountRoutingModule],
declarations: [...COMPONENTS, ...COMPONENTS_NOROUNT],
})
export class AccountModule {}

View File

@ -0,0 +1,48 @@
<div class="main">
<nz-card style="margin-top: 20px; min-height: 780px;">
<h3 style="font-size: 20px; font-weight: 700;">个人中心</h3>
<nz-list style="border-bottom: 1px solid #f0f0f0">
<nz-list-item>
<nz-list-item-meta>
<nz-list-item-meta-title>
<div nz-row [nzGutter]="16">
<div nz-col [nzSpan]="4" class="li-label">
<span class="icon iconfont icon-shoujihao" style="color: #aaa"></span> 手机号码/账号
</div>
<div nz-col [nzSpan]="10">{{ infoData.phone }}</div>
<div nz-col [nzSpan]="10">
<span *ngIf="infoData.phone; else elsePhone"><i nz-icon [nzType]="'check-circle'" [nzTheme]="'fill'"
style="color: #52c41a"></i> 已绑定</span>
<ng-template #elsePhone><i nz-icon [nzType]="'question-circle'" [nzTheme]="'fill'"
style="color: #ccc"></i> 未绑定</ng-template>
</div>
</div>
</nz-list-item-meta-title>
</nz-list-item-meta>
<div class="item-btn"><a (click)="edit('phone')">修改</a></div>
</nz-list-item>
<nz-list-item>
<nz-list-item-meta>
<nz-list-item-meta-title>
<div nz-row [nzGutter]="16">
<div nz-col [nzSpan]="4" class="li-label">
<span class="icon iconfont icon-mima" style="color: #aaa"></span> 账户密码
</div>
<div nz-col [nzSpan]="10">定期更换密码有助于账号安全</div>
<div nz-col [nzSpan]="10">
<span *ngIf="infoData.isPwd; else elsePwd"
><i nz-icon [nzType]="'check-circle'" [nzTheme]="'fill'" style="color: #52c41a"></i> 已设置</span
>
<ng-template #elsePwd
><i nz-icon [nzType]="'question-circle'" [nzTheme]="'fill'" style="color: #ccc"></i> 未设置</ng-template
>
</div>
</div>
</nz-list-item-meta-title>
</nz-list-item-meta>
<div class="item-btn"><a (click)="edit('password')">修改</a></div>
</nz-list-item>
</nz-list>
</nz-card>
</div>

View File

@ -0,0 +1,46 @@
:host {
::ng-deep {
.info-main {
padding: 30px;
}
.info-main h3 {
margin-bottom: 30px;
color: #333;
font-size: 24px;
}
.info {
position: relative;
}
.info-btn {
position: absolute;
top: 20px;
right: 20px;
}
.item-btn {
width: 28px;
text-align: center;
}
.li-label {
color: #333;
font-weight: bold;
font-size: 14px;
}
page-grid {
background-color: #f0f3f7;
div.container {
width: 80%;
margin: 0 auto;
padding: 1rem;
}
}
}
.info-row {
padding: 24px 0;
.info-icon {
margin-right: 15px;
color: #3875fb;
font-size: 16px;
}
}
}

View File

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

View File

@ -0,0 +1,202 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { SFComponent, SFSchema, SFSelectWidgetSchema, SFUISchema, SFUploadWidgetSchema } from '@delon/form';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { Observable, Observer } from 'rxjs';
import { AccountService } from '../../services/account.service';
import { AccountComponentsEditNameComponent } from '../edit-name/edit-name.component';
import { NzModalService } from 'ng-zorro-antd/modal';
import { AccountComponentsCenterEditComponent } from '../edit-password/edit-password.component';
@Component({
selector: 'app-account-components-center',
templateUrl: './center.component.html',
styleUrls: ['./center.component.less'],
})
export class AccountComponentsCenterComponent implements OnInit {
url = `/rule?_allow_anonymous=true`;
@ViewChild('sf', { static: false }) sf!: SFComponent;
i: any;
formDate: any = {};
schema!: SFSchema;
ui: SFUISchema = {};
infoData: any = {
appId: '',
appTypeId: 0,
appTypeName: '',
appUserId: 0,
avatar: 'https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png?_allow_anonymous=true',
birthday: '',
cert: 0,
createTime: '',
email: '',
id: 0,
isPwd: true,
lastLoginDate: '',
name: '',
nickName: '',
openId: '',
phone: '',
remark: '',
sex: 0,
state: 0,
stateLocked: true,
token: '',
userType: 0,
};
tabs = [
{
name: '基本设置',
},
{
name: '安全设置',
},
];
idx: any = 0;
constructor(public service: AccountService, private modal: ModalHelper, private http: _HttpClient, private router: Router, private modalService: NzModalService,) {}
ngOnInit() {
this.initSF();
this.getInfo();
}
initSF() {
this.schema = {
properties: {
avatar: {
type: 'string',
title: '头像',
ui: {
action: `/cms/upload/multipartFile/fileModel?_allow_anonymous=true`,
fileType: 'image/png,image/jpeg,image/jpg,image/png,image/gif,image/bmp',
limit: 1,
limitFileCount: 1,
resReName: 'url',
urlReName: 'url',
widget: 'upload',
descriptionI18n: '支持JPG、GIF、PNG、JPEG、BMP格式文件小于2M',
data: {
// appId: environment.appId,
},
name: 'multipartFile',
multiple: false,
listType: 'picture-card',
change: (args: any) => {
if (args.type === 'success') {
const avatar = [
{
uid: -1,
name: 'LOGO',
status: 'done',
url: args.fileList[0].response.url,
response: {
url: args.fileList[0].response.url,
},
},
];
this.sf?.setValue('/avatar', avatar);
}
},
beforeUpload: (file: any, _fileList) => {
return new Observable((observer: Observer<boolean>) => {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.service.msgSrv.warning('图片大小超过2M!');
observer.complete();
return;
}
observer.next(isLt2M);
observer.complete();
});
},
} as SFUploadWidgetSchema,
},
nickName: {
title: '昵称',
type: 'string',
minLength: 1,
maxLength: 18,
ui: {
placeholder: '请输入昵称',
width: 400,
errors: {
required: '请输入昵称',
},
},
},
},
required: ['nickName', 'avatar'],
};
this.ui = {
'*': {
spanLabel: 5,
grid: { span: 24 },
},
};
}
getInfo() {
this.service.http.post(this.service.$api_get_current_user_info).subscribe((res) => {
this.infoData = res.data;
});
}
edit(tpye: string) {
if (tpye === 'phone') {
const modalRef = this.modalService.create({
nzTitle: '验证手机号码',
nzContent: AccountComponentsEditNameComponent,
nzComponentParams: {
i: this.infoData
},
nzFooter: null
});
modalRef.afterClose.subscribe((result: any) => {
if (result === true) {
// this.st.load(1);
}
});
}
if (tpye === 'password') {
const modalRef = this.modalService.create({
nzTitle: '设置/修改登录密码',
nzContent: AccountComponentsCenterEditComponent,
nzComponentParams: {
record: this.infoData
},
});
modalRef.afterClose.subscribe((result: any) => {
if (result === true) {
// this.st.load(1);
}
});
}
// if (tpye === 'info') {
// this.router.navigate(['/account/editInfo'], {
// queryParams: { realName: this.infoData.realName, certificateNumber: this.infoData.certificateNumber },
// });
// }
// if (tpye === 'name') {
// this.modal
// .createStatic(AccountComponentsEditNameComponent, { i: { name: this.infoData.name, phone: this.infoData.phone } })
// .subscribe(() => {
// this.getInfo();
// // this.st.reload();
// });
// }
}
changeType(type: number): void {
this.idx = type;
}
formSubmit(value: any): void {
const params = { ...value };
this.service.request(`${this.service.$api_get_current_user_info}`, params).subscribe((res) => {
if (res === true) {
this.service.msgSrv.success('保存成功');
this.getInfo();
// this.initSF();
}
});
}
}

View File

@ -0,0 +1,75 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-11-29 11:06:01
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:39
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\components\\edit-name\\edit-name.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<sf #sf [compact]="true" [ui]="ui" [schema]="schema" [button]="'none'" [formData]="formData">
<ng-template sf-template="smsVerifyCode" let-me let-ui="ui" let-schema="schema">
<div class="valid-code">
<input
type="text"
maxlength="6"
nz-input
[ngModel]="me.formProperty.value"
(ngModelChange)="me.setValue($event)"
placeholder="请输入验证码"
/>
<button class="btn-code" nz-button nzType="link" [disabled]="count > 0" (click)="getCaptcha()">
{{ count > 0 ? '请等待' + count + 's' : '获取验证码' }}
</button>
</div>
</ng-template>
</sf>
<div class="modal-footer">
<button nz-button type="button" (click)="close()">关闭</button>
<button nz-button type="button" nzType="primary" (click)="submitForm()" [disabled]="!sf.valid">下一步</button>
</div>
<nz-modal [(nzVisible)]="isVisibleView" [nzWidth]="600" [nzFooter]="nzModalFooterview" nzTitle="修改手机号码" (nzOnOk)="handleOK()" (nzOnCancel)="handleCancel('1')">
<ng-container *nzModalContent>
<sf #sfView [schema]="schemaView" [ui]="uiView" [compact]="true" [button]="'none'">
<ng-template sf-template="smsVerifyCode" let-me let-ui="uiView" let-schema="schemaView">
<div style="position: relative;">
<input
type="text"
maxlength="6"
nz-input
[ngModel]="me.formProperty.value"
(ngModelChange)="me.setValue($event)"
placeholder="请输入验证码"
/>
<button style="position: absolute;
top: 0;
right: 0;
z-index: 9;" nz-button nzType="link" [disabled]="count2 > 0" (click)="getCaptcha2()">
{{ count2 > 0 ? '请等待' + count2 + 's' : '获取验证码' }}
</button>
</div>
</ng-template>
</sf>
</ng-container>
<ng-template #nzModalFooterview>
<button nz-button nzType="default" (click)="handleCancel('1')">取消</button>
<button nz-button nzType="primary" (click)="handleNew()">确定</button>
</ng-template>
</nz-modal>
<nz-modal [(nzVisible)]="isVisibleOk" [nzWidth]="600" (nzOnCancel)="handleCancel('1')" [nzFooter]='null' >
<ng-container *nzModalContent>
<nz-result
nzStatus="success"
nzTitle="修改成功!"
nzSubTitle="您已绑定新手机号,以后可用新手机号登录!"
>
<div nz-result-extra>
<button nz-button nzType="primary" (click)="handleCancel('3')">确定</button>
</div>
</nz-result>
</ng-container>
</nz-modal>

View File

@ -0,0 +1,20 @@
:host {
.valid-code {
position: relative;
}
.btn-code {
position: absolute;
top: 0;
right: 0;
z-index: 9;
}
.valid-code2 {
position: relative;
}
.btn-code2 {
position: absolute;
top: 0;
right: 0;
z-index: 9;
}
}

View File

@ -0,0 +1,34 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-11-29 11:06:01
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:44
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\components\\edit-name\\edit-name.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AccountComponentsEditNameComponent } from './edit-name.component';
describe('AccountComponentsEditNameComponent', () => {
let component: AccountComponentsEditNameComponent;
let fixture: ComponentFixture<AccountComponentsEditNameComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AccountComponentsEditNameComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AccountComponentsEditNameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,271 @@
import { AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { ErrorData, SFComponent, SFSchema, SFStringWidgetSchema, SFUISchema } from '@delon/form';
import { _HttpClient } from '@delon/theme';
// import { CaptchaComponent } from '@shared';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { interval, Observable, Observer } from 'rxjs';
import { take } from 'rxjs/operators';
import { AccountService } from '../../services/account.service';
@Component({
selector: 'app-account-components-edit-name',
templateUrl: './edit-name.component.html',
styleUrls: ['./edit-name.component.less'],
})
export class AccountComponentsEditNameComponent implements OnInit, AfterViewInit {
// @ViewChild('dun', { static: false })
// private dun!: CaptchaComponent;
@ViewChild('sf', { static: false }) sf!: SFComponent;
@ViewChild('sfView', { static: false }) sfView!: SFComponent;
record: any = {};
i: any;
schema!: SFSchema;
schemaView!: SFSchema;
ui!: SFUISchema;
uiView: SFUISchema = {};
isVisibleView = false;
isVisibleOk = false;
formData: any = {};
count = 0;
count2 = 0;
oldName: any;
voucher: any;
codeTips: any;
interval$: any;
constructor(private modal: NzModalRef, public msgSrv: NzMessageService, public http: _HttpClient, public service: AccountService,private cdr: ChangeDetectorRef,) {}
ngAfterViewInit(): void {
// this.dun.init();
}
ngOnInit() {
this.codeTips = '为了账户安全,需您的手机验证(' + this.i?.phone + '';
this.formData.oldName = this.i?.phone;
this.initSF();
this.initSFNew();
// this.getInfo();
}
initSF() {
this.schema = {
properties: {
oldName: {
title: '手机号',
type: 'string',
default: this.formData?.oldName,
ui: {
widget: 'text',
},
},
// userName: {
// title: '用户名(新)',
// type: 'string',
// minLength: 3,
// maxLength: 30,
// description: '3-30个字符支持中英文、数字、符号“_”和“-”,只能修改一次',
// ui: {
// placeholder: '请输入新用户名',
// errors: {
// required: '请输入新用户名',
// },
// } as SFStringWidgetSchema,
// },
smsVerifyCode: {
title: '验证码',
type: 'string',
maxLength: 6,
minLength: 6,
description: this.codeTips,
ui: {
widget: 'custom',
placeholder: '请输入验证码',
errors: {
required: '请输入6位数字验证码',
minLength: '请输入6位数字验证码',
},
},
},
},
required: ['userName', 'smsVerifyCode'],
};
this.ui = {
'*': {
spanLabelFixed: 100,
grid: { span: 24 },
},
};
}
initSFNew() {
this.schemaView = {
properties: {
phone: {
title: '新手机号',
type: 'string',
format: 'mobile',
maxLength: 11,
ui: {
placeholder: '请输入新手机号',
errors: {
required: '请输入新手机号',
},
} as SFStringWidgetSchema,
},
smsVerifyCode: {
title: '验证码',
type: 'string',
maxLength: 6,
minLength: 6,
ui: {
widget: 'custom',
placeholder: '请输入验证码',
errors: {
required: '请输入6位验证码',
minLength: '请输入6位验证码',
},
},
},
},
required: ['phone', 'smsVerifyCode'],
};
this.uiView = {
'*': {
spanLabelFixed: 100,
grid: { span: 24 },
},
};
}
getCaptcha() {
const params = {
// phoneNumber: phone
};
this.service.request(this.service.$api_get_current_user_smVerification, params, 'POST', true, 'FORM').subscribe((res) => {
// code==503046 弹出网易盾
if (res && res.code === '1') {
this.service.msgSrv.success('发送成功');
this.createInterval();
} else if (res.code === '503046') {
// this.dun.popUp();
} else {
this.service.msgSrv.success(res.msg);
}
});
}
getCaptcha2() {
const params = {
phoneNumber: this.sfView.value.phone
};
this.service.request(this.service.$api_get_getSMVerificationCode, params, 'POST', true, 'FORM').subscribe((res) => {
// code==503046 弹出网易盾
if (res && res.code === '1') {
this.service.msgSrv.success('发送成功');
this.createInterval2();
} else if (res.code === '503046') {
// this.dun.popUp();
} else {
this.service.msgSrv.success(res.msg);
}
});
}
// /* code倒计时 */
// codeCountDown() {
// this.count = 59;
// this.interval$ = setInterval(() => {
// this.count -= 1;
// if (this.count <= 0) {
// clearInterval(this.interval$);
// }
// }, 1000);
// }
private createInterval() {
this.count = 59;
interval(1000)
.pipe(take(60))
.subscribe((x: any) => {
this.count = 59 - (x + 1);
this.cdr.detectChanges();
});
}
private createInterval2() {
this.count2 = 59;
interval(1000)
.pipe(take(60))
.subscribe((x: any) => {
this.count2 = 59 - (x + 1);
this.cdr.detectChanges();
});
}
// codeCountDown2() {
// this.count2 = 59;
// this.interval$ = setInterval(() => {
// this.count2 -= 1;
// if (this.count <= 0) {
// clearInterval(this.interval$);
// }
// }, 1000);
// }
/* 网易盾验证通过 */
captchaDone(validate: any) {
this.createInterval();
}
getInfo() {
const params = {
// id: this.i.id,
};
this.service.http.post(this.service.$api_get_current_user_info, params).subscribe((res) => {
// if (res) {
// this.getCaptcha(res.data.phone);
// }
});
}
close() {
this.modal.destroy();
}
submitForm() {
const params = {
smsVerifyCode: this.sf.value.smsVerifyCode,
};
this.service.http.post(this.service.$api_get_verifyPhone, params).subscribe((res) => {
if (res.success) {
// this.modal.close(true);
this.voucher = res.data.voucher
this.isVisibleView = true
} else {
this.service.msgSrv.error(res.msg)
}
});
}
handleCancel(type: string) {
if(type === '1') {
this.isVisibleView = false
} else if(type === '2') {
console.log(type)
} else if(type === '3') {
this.modal.close()
}
}
handleOK() {
}
handleNew() {
if(!this.sfView.valid) {
return;
}
const params = {
voucher: this.voucher,
...this.sfView.value,
}
this.service.http.post(this.service.$api_set_voucherUpdatePhone, params).subscribe((res) => {
if (res.success) {
this.isVisibleOk = true;
} else {
this.service.msgSrv.error(res.msg)
}
});
}
}

View File

@ -0,0 +1,94 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-11-29 13:50:46
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:50
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\components\\edit-password\\edit-password.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<nz-alert style="margin-bottom: 15px;" nzType="info" nzMessage="密码为字母和数字组成的8-16个字符支持符号“_”和“-”。" nzShowIcon></nz-alert>
<form nz-form [formGroup]="validateForm">
<nz-form-item>
<nz-form-label nzRequired>新密码</nz-form-label>
<nz-form-control nzErrorTip="密码格式错误">
<nz-input-group [nzSuffix]="suffixTemplate" name='passWord'>
<input
[type]="passwordVisible ? 'text' : 'password'"
nz-input
placeholder="请输入新密码"
[(ngModel)]="password"
formControlName="passWord"
/>
</nz-input-group>
<ng-template #suffixTemplate>
<i nz-icon [nzType]="passwordVisible ? 'eye-invisible' : 'eye'" (click)="passwordVisible = !passwordVisible"></i>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>确认新密码</nz-form-label>
<nz-form-control nzErrorTip="密码不一致">
<nz-input-group [nzSuffix]="suffixTemplate2" name='passWordTo'>
<input
[type]="passwordVisible2 ? 'text' : 'password'"
nz-input
formControlName="passWordTo"
placeholder="请确认输入新密码"
[(ngModel)]="password2"
/>
</nz-input-group>
<ng-template #suffixTemplate2>
<i nz-icon [nzType]="passwordVisible2 ? 'eye-invisible' : 'eye'" (click)="passwordVisible2 = !passwordVisible2"></i>
</ng-template>
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label nzRequired>手机号</nz-form-label>
{{this.record?.phone}}
</nz-form-item>
<nz-form-item>
<nz-form-label
nzFor="smsVerifyCode"
nzRequired
[nzTooltipIcon]="captchaTooltipIcon"
>
验证码
</nz-form-label>
<nz-form-control
[nzSm]="14"
[nzXs]="24"
>
<div nz-row [nzGutter]="8">
<div nz-col [nzSpan]="12">
<input nz-input [maxlength]="6" formControlName="smsVerifyCode" id="smsVerifyCode" />
</div>
<div nz-col [nzSpan]="12" style="display: flex; align-items: center;">
<button nz-button *ngIf="count < 1;" (click)="getCaptcha($event)">获取验证码</button>
<span *ngIf="count > 1;">{{ count > 0 ? '请等待' + count + 's' : '获取验证码' }}</span>
</div>
</div>
</nz-form-control>
</nz-form-item>
</form>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="destroyModal()">取消</button>
<button nz-button nzType="primary" (click)="save()" >确定</button>
</div>
<nz-modal [(nzVisible)]="isVisibleView" [nzWidth]="600" (nzOnCancel)="handleCancel()" [nzFooter]='null' >
<ng-container *nzModalContent>
<nz-result
nzStatus="success"
nzTitle="密码设置成功!"
nzSubTitle="请牢记您的新密码修改密码后需重新登录3秒后自动跳转至登录页..."
>
<div nz-result-extra>
<button nz-button nzType="primary" (click)="handleOK()">重新登录</button>
</div>
</nz-result>
</ng-container>
</nz-modal>

View File

@ -0,0 +1,130 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-12-27 10:30:56
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:54
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\components\\edit-password\\edit-password.component.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { STChange, STColumn, STComponent, STData, STRequestOptions } from '@delon/abc/st';
import { DA_SERVICE_TOKEN, ITokenService } from '@delon/auth';
import { SFComponent, SFSchema, SFSelectWidgetSchema, SFUISchema } from '@delon/form';
import { NzDrawerRef, NzDrawerService } from 'ng-zorro-antd/drawer';
import { NzFormTooltipIcon } from 'ng-zorro-antd/form';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { AccountService } from '../../services/account.service';
@Component({
selector: 'app-account-components-edit',
templateUrl: './edit-password.component.html'
})
export class AccountComponentsCenterEditComponent implements OnInit {
validateForm!: FormGroup;
record: any;
count = 0;
type = 'create';
isVisibleView = false
passwordVisible = false;
passwordVisible2 = false;
password: any;
password2: any;
interval$: any;
confirmationValidator =
(control: FormControl): { [s: string]: boolean } => {
if (!control.value) {
return { required: true };
} else if (control?.value !== this.validateForm?.value?.passWord) {
return { confirm: true, error: true };
}
return {};
};
captchaTooltipIcon: NzFormTooltipIcon = {
type: 'info-circle',
theme: 'twotone'
};
constructor(
public router: Router,
public ar: ActivatedRoute,
private modalRef: NzModalRef,
private fb: FormBuilder,
public service: AccountService,
@Inject(DA_SERVICE_TOKEN) private tokenService: ITokenService
) {}
ngOnInit() {
this.initForm();
}
initForm () {
this.validateForm = this.fb.group({
passWord: [null,
[
Validators.required,
Validators.maxLength(16),
Validators.minLength(8),
Validators.pattern('^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z-_]{8,16}$')
]],
passWordTo: [null, [ Validators.required, Validators.maxLength(16), Validators.minLength(8), this.confirmationValidator,]],
smsVerifyCode: [null, [Validators.required]],
});
}
destroyModal(): void {
this.modalRef.destroy();
}
getCaptcha(e: MouseEvent): void {
this.service.request(this.service.$api_get_current_user_smVerification).subscribe(res => {
// code==503046 弹出网易盾
if (res && res.code === '1') {
this.service.msgSrv.success('发送成功');
e.preventDefault();
this.codeCountDown();
}else {
this.service.msgSrv.success(res.msg);
}
});
}
save() {
if(!this.validateForm.valid) {
this.service.msgSrv.warning('必填项为空或格式错误,请检查!')
return;
}
const params = {
...this.validateForm.value
};
this.service.request(this.service.$api_set_phoneUpdatePassword, params).subscribe((res) => {
if (res) {
this.service.msgSrv.success('修改密码成功!');
this.isVisibleView = true;
setTimeout(() => {
this.tokenService.clear();
this.router.navigate(['/passport/login'])
this.modalRef.close()
}, 3000)
}
});
}
/* code倒计时 */
codeCountDown() {
this.count = 59;
this.interval$ = setInterval(() => {
this.count -= 1;
if (this.count <= 0) {
clearInterval(this.interval$);
}
}, 1000);
}
handleCancel() {
this.isVisibleView = false
}
handleOK() {
this.modalRef.close()
this.tokenService.clear();
this.router.navigate(['/passport/login'])
}
}

View File

@ -0,0 +1,42 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-12-27 10:30:56
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:14:59
* @FilePath : \\tms-obc-web\\src\\app\\routes\\account\\services\\account.service.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { Injectable, Injector } from '@angular/core';
import { _HttpClient } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { map } from 'rxjs/operators';
import { BaseService } from 'src/app/shared/services/core/base.service';
import { EAFileUtil } from 'src/app/shared/utils/file.util';
@Injectable({
providedIn: 'root',
})
export class AccountService extends BaseService {
// 获取当前登录用户详情
$api_get_current_user_info = `/api/mdc/cuc/user/getUserInfo`;
// 根据当前登录用户绑定的手机号码获取短信验证码
$api_get_current_user_smVerification = `/api/mdc/pbc/smsSend/getSmVerificationCodeByToken`;
// 获取短信验证码
$api_get_getSMVerificationCode = `/api/mdc/pbc/smsSend/getSMVerificationCode`;
// 验证手机号
$api_get_verifyPhone = `/api/mdc/cuc/userBasicInfo/forgetPassword/verifyPhone`;
// 凭证修改手机号
$api_set_voucherUpdatePhone = `/api/mdc/cuc/userBasicInfo/forgetPassword/voucherUpdatePhone`;
// 凭证修改密码
$api_set_phoneUpdatePassword = `/api/mdc/cuc/userBasicInfo/phoneUpdatePassword`;
constructor(public injector: Injector) {
super(injector);
}
}

View File

@ -0,0 +1,40 @@
import { AfterViewInit, Component, OnInit } from '@angular/core';
import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
@Component({
template: ''
})
export class BasicTableComponent implements AfterViewInit {
scrollY = '400px';
constructor() {}
ngAfterViewInit(): void {
setTimeout(() => {
this.getScrollY();
}, 100);
fromEvent(window, 'resize')
.pipe(debounceTime(100))
.subscribe(event => {
this.getScrollY();
});
}
getScrollY() {
const windowHeight = window.innerHeight || Math.max(document.documentElement.clientHeight, document.body.clientHeight);
const header = document.getElementsByTagName('layout-pro-header')?.[0];
if (windowHeight && header) {
let scrollY = windowHeight - header.clientHeight - 35 - 49;
const headerWrapper = document.getElementsByTagName('page-header-wrapper')?.[0];
if (headerWrapper) {
scrollY -= headerWrapper.clientHeight;
}
const tabset = document.getElementsByTagName('nz-tabset')?.[0];
if (tabset) {
scrollY -= tabset.clientHeight;
}
this.scrollY = scrollY + 'px';
}
}
}

View File

@ -0,0 +1,5 @@
:host::ng-deep {
.ant-form-item {
margin-bottom: 0;
}
}

View File

@ -0,0 +1,42 @@
:host::ng-deep {
.search-box {
.ant-card-body {
padding-bottom: 18px;
}
}
.content-box {
.ant-card-body {
padding-top: 0;
}
}
nz-range-picker {
width: 100%;
}
.ant-tabs-tab-btn {
padding-right: 16px;
padding-left : 16px;
}
.text-truncate {
white-space: normal;
}
.bold {
.ant-statistic-title {
font-weight: 600;
color : #000;
font-size : 16px;
}
}
}
.total-footer {
position : absolute;
bottom : 25px;
height : 32px;
margin : 16px 0;
line-height: 32px;
}

View File

@ -0,0 +1,70 @@
:host {
::ng-deep {
nz-card {
margin: -24px -24px 0;
.ant-tabs-nav {
margin: 0;
}
}
.ant-tabs-tab {
margin: 0 0 0 16px;
padding: 12px 0;
}
.ant-table-body {
border-bottom: 1px solid #f0f0f0;
}
.table-box {
.ant-card-body {
padding: 0;
}
}
.ant-table-pagination.ant-pagination {
margin: 8px;
}
.ant-table-thead > tr > th,
.ant-table-tbody > tr > td,
.ant-table tfoot > tr > th,
.ant-table tfoot > tr > td {
padding: 8px;
}
.ant-table.ant-table-bordered > .ant-table-container {
border-top: 0;
}
.ant-pagination-item {
min-width: 24px;
height: 24px;
line-height: 21px;
}
.ant-pagination-total-text {
height: 24px;
line-height: 24px;
}
.ant-pagination-prev,
.ant-pagination-next,
.ant-pagination-jump-prev,
.ant-pagination-jump-next {
min-width: 24px;
height: 24px;
line-height: 21px;
}
.ant-select-single:not(.ant-select-customize-input) .ant-select-selector {
height: 24px;
}
.ant-select-single .ant-select-selector .ant-select-selection-item,
.ant-select-single .ant-select-selector .ant-select-selection-placeholder {
line-height: 21px;
}
}
}

View File

@ -0,0 +1,13 @@
.expend-options {
margin-top: 0;
}
@media (min-width: 1200px) {
.expend-options {
position : absolute;
right : 0;
bottom : 25px;
max-width: 450px;
}
}

View File

@ -0,0 +1,26 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-10 14:44:57
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:15:13
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-detail\\contract-detail.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<!-- 页头 -->
<page-header-wrapper [logo]="logo" [title]="textStatus" >
<ng-template #logo>
<button nz-button nz-tooltip nzTooltipTitle="返回上一页" (click)="goBack()">
<i nz-icon nzType="left" nzTheme="outline"></i>
</button>
</ng-template>
</page-header-wrapper>
<nz-card>
<div nz-col nzSpan="20" style="overflow: scroll">
<nz-card class="card-height" >
<div [innerHTML]="detailList?.contractContent | safehtml"></div>
</nz-card>
</div>
</nz-card>

View File

@ -0,0 +1,4 @@
.title {
padding-right: 4px;
padding-left: 14px !important;
}

View File

@ -0,0 +1,34 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-10 14:44:57
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:15:18
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-detail\\contract-detail.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContractManagementDetailComponent } from './contract-detail.component';
describe('ContractManagementDetailComponent', () => {
let component: ContractManagementDetailComponent;
let fixture: ComponentFixture<ContractManagementDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ContractManagementDetailComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContractManagementDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,59 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-10 14:44:57
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:15:43
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-detail\\contract-detail.component.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { DatePipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-detail-complaint',
templateUrl: './contract-detail.component.html',
styleUrls: ['./contract-detail.component.less'],
providers: [DatePipe]
})
export class ContractManagementDetailComponent implements OnInit {
constructor(
private nzModalService: NzModalService,
public service: ContractManagementService,
public route: ActivatedRoute,
private datePipe: DatePipe,
private router: Router
) {}
textStatus = '合同详情';
name: any;
code: any;
templateHTML: any;
detailList: any = {
templateName: ''
};
ngOnInit() {
this.initData(this.service.$api_contract_get);
}
goBack() {
window.history.go(-1);
}
initData(url: string) {
this.service.request(url, { id: this.route.snapshot.params.id }).subscribe(res => {
if (res) {
this.detailList = res;
this.detailList = res;
let value: any = JSON.parse(res.contractParameter);
this.code = value['${code}'];
this.name = value['${name}'];
}
});
}
cancel() {
window.history.go(-1);
}
}

View File

@ -0,0 +1,101 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:29:57
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:08:53
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-frame\\contract-frame.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<ng-template sf-template="effectiveEndTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.effectiveEndTime"></nz-range-picker>
</ng-template>
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button
nz-button
nzType="primary"
[disabled]="!sf.valid"
[nzLoading]="isLoading && st.loading"
(click)="st?.load(1)"
acl
[acl-ability]="['CONTRACT-INDEX-listFrame']"
>查询</button
>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card class="content-box" nzBordered>
<div style="position: relative">
<nz-alert
nzType="info"
[nzMessage]="'当前共' + st?.total + '行记录已选择' + selectedRows.length + ''"
nzShowIcon
[ngStyle]="{ margin: '0 0 1rem 0' }"
>
</nz-alert>
</div>
<st
#st
[data]="service.$api_listFrame_page"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="service.http.loading"
[scroll]="{ x: '1200px', y: '370px' }"
(change)="stChange($event)"
>
<ng-template st-row="contractCode" let-item let-index="index">
<a [routerLink]="'/contract-management/index/detail/' + item.id">{{ item?.contractCode }}</a>
</ng-template>
</st>
</nz-card>
<ng-template #auditModal>
<div nz-row nzGutter="8">
<div nz-col nzSpan="24" se-container [labelWidth]="80">
<se [col]="1" label="备注">
<textarea
nz-input
rows="3"
placeholder="同意可以不用填写原因 ,拒绝必须说明原因"
style="width: 325px; margin-left: 14px"
></textarea>
</se>
</div>
</div>
</ng-template>

View File

@ -0,0 +1,35 @@
:host::ng-deep {
.search-box {
.ant-card-body {
padding-bottom: 18px;
}
}
.content-box {
.ant-card-body {
padding-top: 0;
}
}
nz-range-picker {
width: 100%;
}
.ant-tabs-tab-btn {
padding-right: 16px;
padding-left : 16px;
}
}
.expend-options {
margin-top: 0;
}
@media (min-width: 1200px) {
.expend-options {
z-index : -99;
margin-top: -40px;
}
}

View File

@ -0,0 +1,307 @@
import { DatePipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { STComponent, STColumn, STChange } from '@delon/abc/st';
import { SFComponent, SFSchema, SFDateWidgetSchema, SFUISchema, SFSelectWidgetSchema } from '@delon/form';
import { ShipperBaseService } from '@shared';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-contract-frame',
templateUrl: './contract-frame.component.html',
styleUrls: ['./contract-frame.component.less'],
providers: [DatePipe]
})
export class ContractManagementFrameComponent implements OnInit {
url = `/rule?_allow_anonymous=true`;
@ViewChild('st', { static: true })
st!: STComponent;
@ViewChild('sf', { static: false })
sf!: SFComponent;
@ViewChild('auditModal', { static: false })
auditModal!: any;
schema: SFSchema = {};
columns: STColumn[] = [];
ui: SFUISchema = {};
_$expand = false;
selectedRows: any[] = [];
isLoading: boolean = false;
constructor(
public service: ContractManagementService,
private nzModalService: NzModalService,
private router: Router,
public shipperservice: ShipperBaseService,
private datePipe: DatePipe,
) {}
ngOnInit(): void {
this.initST();
this.initSF();
}
/**
* 查询参数
*/
get reqParams() {
const params = {
...this.sf?.value,
}
delete params.signTime;
delete params._$expand;
if(this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss') && this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss')) {
params.signTime = {
start: this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss'),
end: this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss'),
}
}
if(this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[0], 'yyyy-MM-dd HH:mm:ss') && this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[1], 'yyyy-MM-dd HH:mm:ss')) {
params.effectiveEndTime = {
start: this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[0], 'yyyy-MM-dd HH:mm:ss'),
end: this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[1], 'yyyy-MM-dd HH:mm:ss'),
}
}
return {
...params
};
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同编号',
width: '100px',
className: 'text-center',
render: 'contractCode'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractTypeLabel'
},
{
title: '合同名称',
width: '100px',
className: 'text-center',
index: 'templateName'
},
{ title: '网络货运人', index: 'enterpriseInfoName', width: '120px', className: 'text-center' },
{ title: '合同对象', index: 'contractObjectName', width: '120px', className: 'text-center' },
{
title: '有效期至',
className: 'text-center',
width: '120px',
index: 'effectiveEndTime'
},
{
title: '签署日期',
className: 'text-center',
width: '120px',
index: 'signTime'
},
{
title: '状态',
className: 'text-center',
width: '120px',
type: 'badge',
index: 'esignFlowStatus',
badge: {
'0': { text: '未发起', color: 'default' },
'1': { text: '待签章', color: 'default' },
'2': { text: '已生效', color: 'success' },
'3': { text: '已撤销', color: 'warning' },
'4': { text: '已作废', color: 'warning' },
'5': { text: '已过期', color: 'warning' },
'7': { text: '已拒签', color: 'warning' }
}
}
];
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
contractCode: {
type: 'string',
title: '合同编号'
},
signingObject: {
type: 'string',
title: '签约对象',
enum: [
{ label: '全部', value: '' },
{ label: '货主', value: 1 },
{ label: '司机', value: 2 },
],
ui: {
widget: 'select',
placeholder: '请选择',
}
},
contractType: {
title: '合同类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'contract:type' },
containAllLable:true,
} as SFSelectWidgetSchema,
},
enterpriseInfoId: {
type: 'string',
title: '网络货运人',
ui: {
widget: 'select',
placeholder: '请选择',
allowClear: true,
visibleIf: {
_$expand: (value: boolean) => value
},
asyncData: () => this.shipperservice.getNetworkFreightForwarder()
}
},
contractObjectName: {
type: 'string',
title: '合同对象',
ui: {
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
signTime: {
title: '签署日期',
type: 'string',
ui: {
widget: 'custom',
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
effectiveEndTime: {
title: '有效期',
type: 'string',
ui: {
widget: 'custom',
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
esignFlowStatus: {
title: '状态',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'esign:flow:status' },
containAllLable:true,
visibleIf: {
_$expand: (value: boolean) => value,
},
} as SFSelectWidgetSchema,
},
},
type: 'object'
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
stChange(e: STChange): void {
switch (e.type) {
case 'checkbox':
this.selectedRows = e.checkbox!;
break;
case 'filter':
this.st.load();
break;
}
}
approval(): void {}
add(): void {}
routeTo(item: any) {
this.router.navigate(['/ticket/invoice-requested-detail/1']);
}
auditAction(item: any) {
const modal = this.nzModalService.create({
nzTitle: '审核',
nzContent: this.auditModal,
nzFooter: [
{
label: '拒绝',
type: 'default',
onClick: () => {
modal.destroy();
}
},
{
label: '通过',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
modal.afterClose.subscribe(res => {
this.st.load();
});
}
showReason(item: any) {
const modal = this.nzModalService.create({
nzTitle: '查看原因',
nzContent: '运单数据异常暂时无法开票请联系客服400-xxxx-xxxx',
nzFooter: [
{
label: '关闭',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
}
/**
* 重置表单
*/
resetSF() {
this.sf.reset();
this._$expand = false;
this.isLoading = true;
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
}

View File

@ -0,0 +1,72 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2021-12-07 15:57:49
* @LastEditors : Shiming
* @LastEditTime : 2022-02-23 20:11:50
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-list\\contract-list.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf #sf [schema]="schema" [ui]="ui" [mode]="'search'" [disabled]="!sf?.valid" [loading]="false"
(formSubmit)="st?.load(1)" (formReset)="resetSF()"></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<!-- <input placeholder="请输入1-30" type="number" [ngModel]="sf.value.description3" style="width: 200px;" nz-input />
<span> 天内支付运费</span> -->
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button nz-button nzType="primary" [disabled]="!sf.valid" [nzLoading]="isLoading && st.loading"
(click)="st?.load(1)" acl [acl-ability]="['CONTRACT-INDEX-searchDetail']">查询</button>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card class="content-box" nzBordered>
<div style="position: relative">
<nz-alert nzType="info" [nzMessage]="'当前共' + st?.total + '行记录已选择' + selectedRows.length + ''" nzShowIcon
[ngStyle]="{ margin: '0 0 1rem 0' }">
</nz-alert>
</div>
<st #st [data]="service.$api_listDetailed_page" [columns]="columns" [req]="{ params: reqParams }"
[loading]="false" [scroll]="{ x: '1200px', y: '370px' }" (change)="stChange($event)">
<ng-template st-row="contractCode" let-item let-index="index">
<a [routerLink]="'/contract-management/index/detail/' + item.id">{{ item?.contractCode }}</a>
</ng-template>
<ng-template st-row="signingObject" let-item let-index="index">
<span *ngIf="item.signingObject == 0"></span>
<span></span>
</ng-template>
</st>
</nz-card>
<ng-template #auditModal>
<div nz-row nzGutter="8">
<div nz-col nzSpan="24" se-container [labelWidth]="80">
<se [col]="1" label="备注">
<textarea nz-input rows="3" placeholder="同意可以不用填写原因 ,拒绝必须说明原因"
style="width: 325px; margin-left: 14px"></textarea>
</se>
</div>
</div>
</ng-template>

View File

@ -0,0 +1,35 @@
:host::ng-deep {
.search-box {
.ant-card-body {
padding-bottom: 18px;
}
}
.content-box {
.ant-card-body {
padding-top: 0;
}
}
nz-range-picker {
width: 100%;
}
.ant-tabs-tab-btn {
padding-left : 16px;
padding-right: 16px;
}
}
.expend-options {
margin-top: 0px;
}
@media (min-width: 1200px) {
.expend-options {
margin-top: -40px;
z-index : -99;
}
}

View File

@ -0,0 +1,248 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { STComponent, STColumn, STChange } from '@delon/abc/st';
import { SFComponent, SFSchema, SFDateWidgetSchema, SFUISchema, SFSelectWidgetSchema } from '@delon/form';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
import { DatePipe } from '@angular/common';
import { ShipperBaseService } from '@shared';
@Component({
selector: 'app-contract-management-contract-list',
templateUrl: './contract-list.component.html',
styleUrls: ['./contract-list.component.less'],
providers: [DatePipe]
})
export class ContractManagementContractListComponent implements OnInit {
url = `/rule?_allow_anonymous=true`;
@ViewChild('st', { static: true })
st!: STComponent;
@ViewChild('sf', { static: false })
sf!: SFComponent;
@ViewChild('auditModal', { static: false })
auditModal!: any;
schema: SFSchema = {};
columns: STColumn[] = [];
ui: SFUISchema = {};
_$expand = false;
isLoading: boolean = false;
/**
* 查询参数
*/
get reqParams() {
const params = {
...this.sf?.value,
}
delete params.signTime;
delete params._$expand;
if (this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss') && this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss')) {
params.signTime = {
start: this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss'),
end: this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss'),
}
}
return {
...params
};
}
selectedRows: any[] = [];
constructor(
public service: ContractManagementService,
private nzModalService: NzModalService,
public shipperservice: ShipperBaseService,
private router: Router,
private datePipe: DatePipe,
) { }
ngOnInit(): void {
this.initST()
this.initSF()
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同编号',
width: '100px',
className: 'text-center',
render: 'contractCode'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractName'
},
{
title: '业务单号',
className: 'text-center',
width: '120px',
index: 'businessCode'
},
{
title: '签署日期',
className: 'text-center',
width: '120px',
index: 'signTime'
},
{
title: '状态',
className: 'text-center',
width: '120px',
type: 'badge',
index: 'esignFlowStatus',
badge: {
'0': { text: '未发起', color: 'default' },
'1': { text: '待签章', color: 'default' },
'2': { text: '已生效', color: 'success' },
'3': { text: '已撤销', color: 'warning' },
'4': { text: '已作废', color: 'warning' },
'5': { text: '已过期', color: 'warning' },
'7': { text: '已拒签', color: 'warning' },
},
},
];
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
contractCode: {
type: 'string',
title: '合同编号',
},
businessCode: {
type: 'string',
title: '业务单号'
},
shipperName: {
type: 'string',
title: '托运人'
},
carrierName: {
type: 'string',
title: '承运人',
ui: {
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
documentType: {
title: '单据类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLabel: true,
params: { dictKey: 'contract:document:type' },
containAllLable: true,
visibleIf: {
_$expand: (value: boolean) => value,
},
} as SFSelectWidgetSchema,
},
signTime: {
title: '签署日期',
type: 'string',
ui: {
widget: 'custom',
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
},
type: 'object',
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
stChange(e: STChange): void {
switch (e.type) {
case 'checkbox':
this.selectedRows = e.checkbox!;
break;
case 'filter':
this.st.load();
break;
}
}
routeTo(item: any) {
this.router.navigate(['/ticket/invoice-requested-detail/1']);
}
auditAction(item: any) {
const modal = this.nzModalService.create({
nzTitle: '审核',
nzContent: this.auditModal,
nzFooter: [
{
label: '拒绝',
type: 'default',
onClick: () => {
modal.destroy();
}
},
{
label: '通过',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
modal.afterClose.subscribe(res => {
this.st.load();
});
}
showReason(item: any) {
const modal = this.nzModalService.create({
nzTitle: '查看原因',
nzContent: '运单数据异常暂时无法开票请联系客服400-xxxx-xxxx',
nzFooter: [
{
label: '关闭',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
}
/**
* 重置表单
*/
resetSF() {
this.sf.reset();
this._$expand = false;
this.isLoading = true
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
}

View File

@ -0,0 +1,101 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:29:57
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:08:28
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-partner\\contract-partner.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
<ng-template sf-template="effectiveEndTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.effectiveEndTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button
nz-button
nzType="primary"
[disabled]="!sf.valid"
[nzLoading]="service.http.loading"
(click)="st?.load(1)"
acl
[acl-ability]="['CONTRACT-INDEX-listFrame']"
>查询</button
>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card class="content-box" nzBordered>
<div style="position: relative">
<nz-alert
nzType="info"
[nzMessage]="'当前共' + st?.total + '行记录已选择' + selectedRows.length + ''"
nzShowIcon
[ngStyle]="{ margin: '0 0 1rem 0' }"
>
</nz-alert>
</div>
<st
#st
[data]="service.$api_listPartner_page"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="false"
[scroll]="{ x: '1200px', y: '370px' }"
(change)="stChange($event)"
>
<ng-template st-row="contractCode" let-item let-index="index">
<a [routerLink]="'/contract-management/index/detail/' + item.id">{{ item?.contractCode }}</a>
</ng-template>
</st>
</nz-card>
<ng-template #auditModal>
<div nz-row nzGutter="8">
<div nz-col nzSpan="24" se-container [labelWidth]="80">
<se [col]="1" label="备注">
<textarea
nz-input
rows="3"
placeholder="同意可以不用填写原因 ,拒绝必须说明原因"
style="width: 325px; margin-left: 14px"
></textarea>
</se>
</div>
</div>
</ng-template>

View File

@ -0,0 +1,35 @@
:host::ng-deep {
.search-box {
.ant-card-body {
padding-bottom: 18px;
}
}
.content-box {
.ant-card-body {
padding-top: 0;
}
}
nz-range-picker {
width: 100%;
}
.ant-tabs-tab-btn {
padding-right: 16px;
padding-left : 16px;
}
}
.expend-options {
margin-top: 0;
}
@media (min-width: 1200px) {
.expend-options {
z-index : -99;
margin-top: -40px;
}
}

View File

@ -0,0 +1,305 @@
import { DatePipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Router } from '@angular/router';
import { STComponent, STColumn, STChange } from '@delon/abc/st';
import { SFComponent, SFSchema, SFDateWidgetSchema, SFUISchema, SFSelectWidgetSchema } from '@delon/form';
import { ShipperBaseService } from '@shared';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-contract-partner',
templateUrl: './contract-partner.component.html',
styleUrls: ['./contract-partner.component.less'],
providers: [DatePipe]
})
export class ContractManagementPartnerComponent implements OnInit {
url = `/rule?_allow_anonymous=true`;
@ViewChild('st', { static: true })
st!: STComponent;
@ViewChild('sf', { static: false })
sf!: SFComponent;
@ViewChild('auditModal', { static: false })
auditModal!: any;
schema: SFSchema = {};
columns: STColumn[] = [];
ui: SFUISchema = {};
_$expand = false;
selectedRows: any[] = [];
constructor(
public service: ContractManagementService,
private nzModalService: NzModalService,
private router: Router,
public shipperservice: ShipperBaseService,
private datePipe: DatePipe,
) {}
ngOnInit(): void {
this.initST();
this.initSF();
}
/**
* 查询参数
*/
get reqParams() {
const params = {
...this.sf?.value,
}
delete params.signTime;
delete params._$expand;
if(this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss') && this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss')) {
params.signTime = {
start: this.datePipe.transform(this.sf?.value?.signTime?.[0], 'yyyy-MM-dd HH:mm:ss'),
end: this.datePipe.transform(this.sf?.value?.signTime?.[1], 'yyyy-MM-dd HH:mm:ss'),
}
}
if(this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[0], 'yyyy-MM-dd HH:mm:ss') && this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[1], 'yyyy-MM-dd HH:mm:ss')) {
params.effectiveEndTime = {
start: this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[0], 'yyyy-MM-dd HH:mm:ss'),
end: this.datePipe.transform(this.sf?.value?.effectiveEndTime?.[1], 'yyyy-MM-dd HH:mm:ss'),
}
}
return {
...params
};
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同编号',
width: '100px',
className: 'text-center',
render: 'contractCode'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractType'
},
{ title: '合同名称', index: 'contractName', width: '120px', className: 'text-center' },
{ title: '网络货运人', index: 'enterpriseInfoName', width: '120px', className: 'text-center' },
{
title: '合同对象',
className: 'text-center',
width: '120px',
index: 'contractObjectName'
},
{
title: '有效期至',
className: 'text-center',
width: '120px',
index: 'effectiveEndTime'
},
{
title: '签署日期',
className: 'text-center',
width: '120px',
index: 'signTime'
},
{
title: '状态',
className: 'text-center',
width: '120px',
type: 'badge',
index: 'esignFlowStatus',
badge: {
'0': { text: '未发起', color: 'default' },
'1': { text: '待签章', color: 'default' },
'2': { text: '已生效', color: 'success' },
'3': { text: '已撤销', color: 'warning' },
'4': { text: '已作废', color: 'warning' },
'5': { text: '已过期', color: 'warning' },
'7': { text: '已拒签', color: 'warning' }
}
}
];
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
contractCode: {
type: 'string',
title: '合同编号'
},
signingObject: {
type: 'string',
title: '签约对象',
enum: [
{ label: '全部', value: '' },
{ label: '货主', value: 1 },
{ label: '司机', value: 2 }
],
ui: {
widget: 'select',
placeholder: '请选择'
}
},
contractType: {
title: '合同类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'contract:type' },
containAllLable: true,
} as SFSelectWidgetSchema
},
enterpriseInfoId: {
type: 'string',
title: '网络货运人',
ui: {
widget: 'select',
placeholder: '请选择',
allowClear: true,
visibleIf: {
_$expand: (value: boolean) => value
},
asyncData: () => this.shipperservice.getNetworkFreightForwarder()
}
},
contractObjectName: {
type: 'string',
title: '合同对象',
ui: {
visibleIf: {
_$expand: (value: boolean) => value
}
}
},
signTime: {
title: '签署日期',
type: 'string',
ui: {
widget: 'custom',
visibleIf: {
_$expand: (value: boolean) => value
}
}
},
effectiveEndTime: {
title: '有效期',
type: 'string',
ui: {
widget: 'custom',
visibleIf: {
_$expand: (value: boolean) => value,
},
}
},
esignFlowStatus: {
title: '状态',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'esign:flow:status' },
containAllLable: true,
visibleIf: {
_$expand: (value: boolean) => value
}
} as SFSelectWidgetSchema
}
},
type: 'object'
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
stChange(e: STChange): void {
switch (e.type) {
case 'checkbox':
this.selectedRows = e.checkbox!;
break;
case 'filter':
this.st.load();
break;
}
}
approval(): void {}
add(): void {}
routeTo(item: any) {
this.router.navigate(['/ticket/invoice-requested-detail/1']);
}
auditAction(item: any) {
const modal = this.nzModalService.create({
nzTitle: '审核',
nzContent: this.auditModal,
nzFooter: [
{
label: '拒绝',
type: 'default',
onClick: () => {
modal.destroy();
}
},
{
label: '通过',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
modal.afterClose.subscribe(res => {
this.st.load();
});
}
showReason(item: any) {
const modal = this.nzModalService.create({
nzTitle: '查看原因',
nzContent: '运单数据异常暂时无法开票请联系客服400-xxxx-xxxx',
nzFooter: [
{
label: '关闭',
type: 'primary',
onClick: () => {
modal.destroy();
}
}
]
});
}
/**
* 重置表单
*/
resetSF() {
this.sf.reset();
this._$expand = false;
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
}

View File

@ -0,0 +1,60 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 11:01:55
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:16:27
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template-detail\\contract-template-detail.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<!-- 页头 -->
<page-header-wrapper [logo]="logo" [title]="textStatus" [content]="headerContent">
<ng-template #logo>
<button nz-button nz-tooltip nzTooltipTitle="返回上一页" (click)="goBack()">
<i nz-icon nzType="left" nzTheme="outline"></i>
</button>
</ng-template>
<ng-template #headerContent>
<div nz-row style="display: flex; justify-content: end;">
<div nz-col *ngIf="isUpdate">
<button nz-button nzSize="default" nzType="default" (click)="cancel()">取消</button>
<button class="ml-lg" nz-button nzSize="default" nzType="primary" (click)="save()">保存</button>
</div>
</div>
</ng-template>
</page-header-wrapper>
<nz-card >
<sf #sf [schema]="schema" [formData]="sfdata" [button]="'none'" [ui]="ui"></sf>
</nz-card>
<nz-card>
<div nz-col nzSpan="20" style="overflow: scroll">
<nz-card class="card-height" *ngIf="!isUpdate">
<div class="mb-md">
<div>{{detailList?.templateName}}</div>
</div>
<div [innerHTML]="detailList?.templateContent | safehtml"></div>
</nz-card>
<nz-card class="card-height" *ngIf="isUpdate">
<div nz-row nzGutter="8">
<div class="title" style="width: 100%;">
<input style="width: 100%;" nz-input placeholder="请输入合同标题" [(ngModel)]="detailList.templateName" />
</div>
<div nz-col nzSpan="24" style="margin-top: 15px;">
<sf #sf2 mode="edit" [formData]="sfdata2" [schema]="schema2" [ui]="{ '*': { spanLabelFixed: 10, grid: { span: 24 }} }"
button="none"> </sf>
</div>
</div>
</nz-card>
</div>
</nz-card>
<!-- <div class="mb-md save-btn">
<button nz-button nzSize="large" nzType="default" (click)="cancel()">取消</button>
<button class="ml-lg" nz-button nzSize="large" nzType="primary" (click)="save()">保存</button>
</div> -->

View File

@ -0,0 +1,4 @@
.title {
padding-right: 4px;
padding-left: 14px !important;
}

View File

@ -0,0 +1,34 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 11:01:55
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:16:31
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template-detail\\contract-template-detail.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContractManagementTemplateDetailComponent } from './contract-template-detail.component';
describe('ContractManagementTemplateDetailComponent', () => {
let component: ContractManagementTemplateDetailComponent;
let fixture: ComponentFixture<ContractManagementTemplateDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ContractManagementTemplateDetailComponent],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContractManagementTemplateDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,248 @@
import { OnChanges } from '@angular/core';
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 11:01:55
* @LastEditors : Shiming
* @LastEditTime : 2022-03-30 10:45:19
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template-detail\\contract-template-detail.component.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { DatePipe } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { SFComponent, SFSchema, SFSelectWidgetSchema, SFUISchema } from '@delon/form';
import { ShipperBaseService } from '@shared';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-template-text-complaint',
templateUrl: './contract-template-detail.component.html',
styleUrls: ['./contract-template-detail.component.less'],
providers: [DatePipe]
})
export class ContractManagementTemplateTextComponent implements OnInit {
constructor(
private nzModalService: NzModalService,
public service: ContractManagementService,
public route: ActivatedRoute,
private datePipe: DatePipe,
private router: Router,
public shipperservice: ShipperBaseService
) {}
textStatus = '新建模板';
@ViewChild('sf', { static: false }) sf!: SFComponent;
schema: SFSchema = {};
@ViewChild('sf2', { static: false }) sf2!: SFComponent;
schema2: SFSchema = {};
ui!: SFUISchema;
sfdata: any;
sfdata2: any;
title: any;
Types: any;
templateHTML: any;
detailList: any = {
templateName: ''
};
isUpdate = false;
ngOnInit() {
this.initSF();
this.initSF2();
if (this.route.snapshot.queryParams.status == 1) {
// 新建
this.isUpdate = true;
} else if (this.route.snapshot.queryParams.status == 2) {
// 编辑
this.textStatus = '编辑模板';
this.isUpdate = true;
this.initData(this.service.$api_get_contractTemplate);
} else if (this.route.snapshot.queryParams.status == 3) {
// 编辑
this.textStatus = '查看模板';
this.isUpdate = false;
this.initData(this.service.$api_get_contractTemplate);
}
}
goBack() {
window.history.go(-1);
}
initSF() {
this.schema = {
properties: {
templateName: {
type: 'string',
title: '模版名称'
},
templateType: {
title: '模板类型',
type: 'string',
enum: [
{ label: '框架合同', value: 'KJ' },
{ label: '明细合同', value: 'MX' },
{ label: '合伙人合同', value: 'HHR' }
],
ui: {
widget: 'select',
placeholder: '请选择',
change: (tag: any, org: any) => {
console.log(tag);
switch (tag) {
case 'MX':
this.Types = [
{ label: '订单合同', value: '1' },
{ label: '订单补充协议', value: '2' },
{ label: '运单合同', value: '3' },
{ label: '运单补充协议', value: '4' },
{ label: '委托代收合同', value: '5' },
{ label: '电子提货单', value: '10' },
{ label: '电子卸货单', value: '11' },
];
this.sf.getProperty('/contractType')!.schema.enum = this.Types;
this.sf.getProperty('/contractType')!.widget.reset(this.Types);
this.sf.setValue('/contractType', this.Types);
return;
break;
case 'KJ':
this.Types = [
{ label: '网络货物运输服务合同', value: '6' },
{ label: '运输服务承揽合同', value: '7' }
];
this.sf.getProperty('/contractType')!.schema.enum = this.Types;
this.sf.getProperty('/contractType')!.widget.reset(this.Types);
this.sf.setValue('/contractType', this.Types);
return;
break;
case 'HHR':
this.Types = [
{ label: '企业合伙人入驻合同', value: '8' },
{ label: '个人合伙人入驻合同', value: '9' }
];
this.sf.getProperty('/contractType')!.schema.enum = this.Types;
this.sf.getProperty('/contractType')!.widget.reset(this.Types);
this.sf.setValue('/contractType', this.Types);
return;
break;
default:
break;
}
}
}
},
signingObject: {
type: 'string',
title: '承包商对象',
enum: [
{ label: '货主', value: '1' },
{ label: '司机', value: '2' }
],
ui: {
widget: 'select',
placeholder: '请选择'
}
},
contractType: {
title: '合同类型',
type: 'string',
enum: this.Types,
ui: {
widget: 'select',
placeholder: '请选择'
}
},
resourceType: {
title: '货源类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
params: { dictKey: 'goodresource:type' },
containsAllLable: true,
visibleIf: {
templateType: value => value === 'MX'
}
} as SFSelectWidgetSchema
},
enterpriseInfoId: {
type: 'string',
title: '网络货运人',
ui: {
widget: 'select',
placeholder: '请选择',
allowClear: true,
visibleIf: {
templateType: value => value === 'KJ' || value === 'HHR'
},
asyncData: () => this.shipperservice.getNetworkFreightForwarder()
}
}
},
required: ['templateName', 'templateType']
};
this.ui = {
'*': {
spanLabelFixed: 120,
grid: { span: 8 }
}
};
}
initSF2(data?: any) {
this.schema2 = {
properties: {
templateContent: {
type: 'string',
title: '',
ui: {
widget: 'tinymce',
loadingTip: 'loading...',
config: {
height: 650
}
},
default: data?.agreementContent || ''
}
}
};
}
initData(url: string) {
console.log('编辑');
this.service.request(url, { id: this.route.snapshot.params.id }).subscribe(res => {
if (res) {
this.detailList = res;
this.title = this.detailList?.templateName;
this.sfdata = res;
this.sfdata2 = res;
}
});
}
cancel() {
window.history.go(-1);
}
save() {
// if (!this.sf.value.templateName || !this.sf.value.templateType || !this.sf2.value.templateContent || !this.title) {
// this.service.msgSrv.error('必填参数为空,请检查再重新保存!');
// return;
// }
// if (this.sf.value.templateType == 'MX') {
// if (this.sf.value.contractType == '') {
// this.service.msgSrv.error('必填参数为空,请检查再重新保存!');
// return;
// }
// }
const params = {
...this.sf.value,
...this.sf2.value,
templateTitle: this.title || this.detailList.templateName
};
console.log(params);
this.service.request(this.service.$api_save_contractTemplate, params).subscribe((res: any) => {
if (res) {
this.service.msgSrv.success('保存成功!');
this.router.navigate(['/contract-management/template']);
}
});
}
}

View File

@ -0,0 +1,86 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-12 10:52:50
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 20:01:42
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template-frame\\contract-template-frame.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<!-- 搜索表单 -->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
<ng-template sf-template="effectiveEndTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.effectiveEndTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button
nz-button
nzType="primary"
[disabled]="!sf.valid"
[nzLoading]="service.http.loading"
(click)="st?.load(1)"
acl
[acl-ability]="['CONTRACT-INDEX-listFrame']"
>查询</button
>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card>
<div class="NewBtn">
<button nz-button nzType="primary" (click)="creatTemplate()" acl [acl-ability]="['CONTRACT-TEMPLATE-new']"> 新建 </button>
</div>
<div style="margin-top: 15px">
<st
#st
[bordered]="true"
[data]="service.$api_get_contractTemplate_page"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="false"
>
<ng-template st-row="templateName" let-item let-index="index">
<a (click)="view(item)">{{ item.templateName }}</a>
</ng-template>
<ng-template st-row="signingObject" let-item let-index="index">
<span *ngIf="item?.signingObject == 1">货主</span>
<span *ngIf="item?.signingObject == 2">司机</span>
</ng-template>
</st>
</div>
</nz-card>

View File

@ -0,0 +1,4 @@
.NewBtn{
float: right;
margin-bottom: 15px;
}

View File

@ -0,0 +1,35 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 09:45:47
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:25:58
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template\\contract-template.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContractManagementTemplateFrameComponent } from './contract-template-frame.component';
describe('ContractManagementTemplateFrameComponent', () => {
let component: ContractManagementTemplateFrameComponent;
let fixture: ComponentFixture<ContractManagementTemplateFrameComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ContractManagementTemplateFrameComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContractManagementTemplateFrameComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,252 @@
import { Router } from '@angular/router';
import { Component, OnInit, ViewChild } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';
import { SFComponent, SFDateWidgetSchema, SFSchema, SFSelectWidgetSchema, SFUISchema } from '@delon/form';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { NzModalService } from 'ng-zorro-antd/modal';
import { map } from 'rxjs/operators';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-template-frame-complaint',
templateUrl: './contract-template-frame.component.html',
styleUrls: ['./contract-template-frame.component.less']
})
export class ContractManagementTemplateFrameComponent implements OnInit {
ui: SFUISchema = {};
uiView: SFUISchema = {};
schema: SFSchema = {};
schemaView: SFSchema = {};
auditMany = false;
_$expand = false;
channelId: any;
@ViewChild('st') private readonly st!: STComponent;
@ViewChild('sf', { static: false }) sf!: SFComponent;
columns: STColumn[] = [];
datass: any = [
{
one: '1',
two: '1',
three: '1',
id: 1
},
{
one: '2',
two: '2',
three: '2',
id: 2
},
];
constructor(
public service: ContractManagementService,
private modal: NzModalService,
private router: Router
) { }
/**
* 查询参数
*/
get reqParams() {
return {
templateType: 'kj',
...this.sf?.value,
};
}
get selectedRows() {
return this.st?.list.filter((item) => item.checked) || [];
}
ngOnInit(): void {
this.initSF();
this.initST();
this.initSTAudit();
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
templateName: {
type: 'string',
title: '模板名称',
},
signingObject: {
type: 'string',
title: '签约对象',
enum: [
{ label: '全部', value: '' },
{ label: '货主', value: 1 },
{ label: '司机', value: 2 }
],
ui: {
widget: 'select',
placeholder: '请选择'
}
},
contractType: {
title: '合同类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'contract:type' },
containAllLable: true,
} as SFSelectWidgetSchema
},
resourceType: {
title: '货源类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
params: { dictKey: 'goodresource:type' },
containsAllLable: true,
visibleIf: {
_$expand: (value: boolean) => value
},
} as SFSelectWidgetSchema,
},
},
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同模板名称',
className: 'text-center',
render: 'templateName'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractTypeLabel'
},
{
title: '货源类型',
width: '100px',
className: 'text-center',
index: 'resourceTypeLabel'
},
{ title: '创建人', index: 'createUserIdLabel', width: '120px', className: 'text-center' },
{
title: '创建时间',
className: 'text-center',
index: 'createTime',
width: '200px'
},
{
title: '操作',
fixed: 'right',
width: '110px',
className: 'text-center',
buttons: [
{
text: '编辑',
click: (_record) => this.edit(_record),
acl: { ability: ['CONTRACT-TEMPLATE-edit'] },
},
{
text: '删除',
click: (_record) => this.delete(_record),
acl: { ability: ['CONTRACT-TEMPLATE-delete'] },
},
],
},
];
}
initSTAudit() {
this.schemaView = {
properties: {
handleResult: {
title: '处理结果',
type: 'string',
maxLength: 50,
ui: {
placeholder: '最多不超过50字',
widget: 'textarea',
autosize: { minRows: 3, maxRows: 6 }
},
},
},
required: ['handleResult']
};
this.uiView = { '*': { spanLabelFixed: 110, grid: { span: 24 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
tabChange(item: any) {
}
/**
* 重置表单
*/
resetSF(): void {
this.sf.reset();
this._$expand = false;
}
edit(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 2
}
})
}
creatTemplate() {
this.router.navigate(['/contract-management/template/text/' + 0], {
queryParams: {
status: 1
}
})
}
goBack() {
window.history.go(-1)
}
view(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 3
}
})
}
delete(value: any) {
this.modal.confirm({
nzTitle: '<i>删除确认</i>',
nzOnOk: () =>
this.service.request(this.service.$api_deletebatch_contractTemplate, [value.id]).subscribe(res => {
if (res) {
this.service.msgSrv.success('删除成功!');
this.st.reload()
}
})
});
}
}

View File

@ -0,0 +1,82 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-12 10:52:50
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:31:05
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template\\contract-template.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<!-- 搜索表单 -->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
<ng-template sf-template="effectiveEndTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.effectiveEndTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button
nz-button
nzType="primary"
[disabled]="!sf.valid"
[nzLoading]="service.http.loading"
(click)="st?.load(1)"
acl
[acl-ability]="['CONTRACT-INDEX-listFrame']"
>查询</button
>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card>
<div class="NewBtn">
<button nz-button nzType="primary" (click)="creatTemplate()" acl [acl-ability]="['CONTRACT-TEMPLATE-new']"> 新建 </button>
</div>
<div style="margin-top: 15px">
<st
#st
[bordered]="true"
[data]="service.$api_get_contractTemplate_page"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="false"
>
<ng-template st-row="templateName" let-item let-index="index">
<a (click)="view(item)">{{ item.templateName }}</a>
</ng-template>
</st>
</div>
</nz-card>

View File

@ -0,0 +1,4 @@
.NewBtn{
float: right;
margin-bottom: 15px;
}

View File

@ -0,0 +1,35 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 09:45:47
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 14:09:28
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template-partner\\contract-template-partner.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContractManagementTemplatePartnerComponent } from './contract-template-partner.component';
describe('ContractManagementTemplatePartnerComponent', () => {
let component: ContractManagementTemplatePartnerComponent;
let fixture: ComponentFixture<ContractManagementTemplatePartnerComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ContractManagementTemplatePartnerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContractManagementTemplatePartnerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,252 @@
import { Router } from '@angular/router';
import { Component, OnInit, ViewChild } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';
import { SFComponent, SFDateWidgetSchema, SFSchema, SFSelectWidgetSchema, SFUISchema } from '@delon/form';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { NzModalService } from 'ng-zorro-antd/modal';
import { map } from 'rxjs/operators';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-template-partner-complaint',
templateUrl: './contract-template-partner.component.html',
styleUrls: ['./contract-template-partner.component.less']
})
export class ContractManagementTemplatePartnerComponent implements OnInit {
ui: SFUISchema = {};
uiView: SFUISchema = {};
schema: SFSchema = {};
schemaView: SFSchema = {};
auditMany = false;
_$expand = false;
channelId: any;
@ViewChild('st') private readonly st!: STComponent;
@ViewChild('sf', { static: false }) sf!: SFComponent;
columns: STColumn[] = [];
datass: any = [
{
one: '1',
two: '1',
three: '1',
id: 1
},
{
one: '2',
two: '2',
three: '2',
id: 2
},
];
constructor(
public service: ContractManagementService,
private modal: NzModalService,
private router: Router
) { }
/**
* 查询参数
*/
get reqParams() {
return {
templateType: 'HHR',
...this.sf?.value,
};
}
get selectedRows() {
return this.st?.list.filter((item) => item.checked) || [];
}
ngOnInit(): void {
this.initSF();
this.initST();
this.initSTAudit();
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
templateName: {
type: 'string',
title: '模板名称',
},
signingObject: {
type: 'string',
title: '签约对象',
enum: [
{ label: '全部', value: '' },
{ label: '货主', value: 1 },
{ label: '司机', value: 2 }
],
ui: {
widget: 'select',
placeholder: '请选择'
}
},
contractType: {
title: '合同类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'contract:type' },
containAllLable: true,
} as SFSelectWidgetSchema
},
resourceType: {
title: '货源类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
params: { dictKey: 'goodresource:type' },
containsAllLable: true,
visibleIf: {
_$expand: (value: boolean) => value
},
} as SFSelectWidgetSchema,
},
},
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同模板名称',
className: 'text-center',
render: 'templateName'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractTypeLabel'
},
{
title: '货源类型',
width: '100px',
className: 'text-center',
index: 'resourceTypeLabel'
},
{ title: '创建人', index: 'createUserIdLabel', width: '120px', className: 'text-center' },
{
title: '创建时间',
className: 'text-center',
index: 'createTime',
width: '200px'
},
{
title: '操作',
fixed: 'right',
width: '110px',
className: 'text-center',
buttons: [
{
text: '编辑',
click: (_record) => this.edit(_record),
acl: { ability: ['CONTRACT-TEMPLATE-edit'] },
},
{
text: '删除',
click: (_record) => this.delete(_record),
acl: { ability: ['CONTRACT-TEMPLATE-delete'] },
},
],
},
];
}
initSTAudit() {
this.schemaView = {
properties: {
handleResult: {
title: '处理结果',
type: 'string',
maxLength: 50,
ui: {
placeholder: '最多不超过50字',
widget: 'textarea',
autosize: { minRows: 3, maxRows: 6 }
},
},
},
required: ['handleResult']
};
this.uiView = { '*': { spanLabelFixed: 110, grid: { span: 24 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
tabChange(item: any) {
}
/**
* 重置表单
*/
resetSF(): void {
this.sf.reset();
this._$expand = false;
}
edit(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 2
}
})
}
creatTemplate() {
this.router.navigate(['/contract-management/template/text/' + 0], {
queryParams: {
status: 1
}
})
}
goBack() {
window.history.go(-1)
}
view(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 3
}
})
}
delete(value: any) {
this.modal.confirm({
nzTitle: '<i>删除确认</i>',
nzOnOk: () =>
this.service.request(this.service.$api_deletebatch_contractTemplate, [value.id]).subscribe(res => {
if (res) {
this.service.msgSrv.success('删除成功!');
this.st.reload()
}
})
});
}
}

View File

@ -0,0 +1,82 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-12 10:52:50
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:31:05
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template\\contract-template.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<!-- 搜索表单 -->
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'">
<ng-template sf-template="signTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.signTime"></nz-range-picker>
</ng-template>
<ng-template sf-template="effectiveEndTime" let-me let-ui="ui" let-schema="schema">
<nz-range-picker [nzShowTime]="true" [(ngModel)]="sf.value.effectiveEndTime"></nz-range-picker>
</ng-template>
</sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button
nz-button
nzType="primary"
[disabled]="!sf.valid"
[nzLoading]="service.http.loading"
(click)="st?.load(1)"
acl
[acl-ability]="['CONTRACT-INDEX-listFrame']"
>查询</button
>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card>
<div class="NewBtn">
<button nz-button nzType="primary" (click)="creatTemplate()" acl [acl-ability]="['CONTRACT-TEMPLATE-new']"> 新建 </button>
</div>
<div style="margin-top: 15px">
<st
#st
[bordered]="true"
[data]="service.$api_get_contractTemplate_page"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="false"
>
<ng-template st-row="templateName" let-item let-index="index">
<a (click)="view(item)">{{ item.templateName }}</a>
</ng-template>
</st>
</div>
</nz-card>

View File

@ -0,0 +1,4 @@
.NewBtn{
float: right;
margin-bottom: 15px;
}

View File

@ -0,0 +1,35 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-05 09:45:47
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:25:58
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\contract-template\\contract-template.component.spec.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { ContractManagementTemplateDetailComponent } from './contract-template.component';
describe('ContractManagementTemplateDetailComponent', () => {
let component: ContractManagementTemplateDetailComponent;
let fixture: ComponentFixture<ContractManagementTemplateDetailComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ContractManagementTemplateDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ContractManagementTemplateDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,252 @@
import { Router } from '@angular/router';
import { Component, OnInit, ViewChild } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';
import { SFComponent, SFDateWidgetSchema, SFSchema, SFSelectWidgetSchema, SFUISchema } from '@delon/form';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { NzModalService } from 'ng-zorro-antd/modal';
import { map } from 'rxjs/operators';
import { ContractManagementService } from '../../services/contract-management.service';
@Component({
selector: 'app-contract-management-template-detail-complaint',
templateUrl: './contract-template.component.html',
styleUrls: ['./contract-template.component.less']
})
export class ContractManagementTemplateDetailComponent implements OnInit {
ui: SFUISchema = {};
uiView: SFUISchema = {};
schema: SFSchema = {};
schemaView: SFSchema = {};
auditMany = false;
_$expand = false;
channelId: any;
@ViewChild('st') private readonly st!: STComponent;
@ViewChild('sf', { static: false }) sf!: SFComponent;
columns: STColumn[] = [];
datass: any = [
{
one: '1',
two: '1',
three: '1',
id: 1
},
{
one: '2',
two: '2',
three: '2',
id: 2
},
];
constructor(
public service: ContractManagementService,
private modal: NzModalService,
private router: Router
) { }
/**
* 查询参数
*/
get reqParams() {
return {
templateType: 'MX',
...this.sf?.value,
};
}
get selectedRows() {
return this.st?.list.filter((item) => item.checked) || [];
}
ngOnInit(): void {
this.initSF();
this.initST();
this.initSTAudit();
}
/**
* 初始化查询表单
*/
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
templateName: {
type: 'string',
title: '模板名称',
},
signingObject: {
type: 'string',
title: '签约对象',
enum: [
{ label: '全部', value: '' },
{ label: '货主', value: 1 },
{ label: '司机', value: 2 }
],
ui: {
widget: 'select',
placeholder: '请选择'
}
},
contractType: {
title: '合同类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
containsAllLable: true,
params: { dictKey: 'contract:type' },
containAllLable: true,
} as SFSelectWidgetSchema
},
resourceType: {
title: '货源类型',
type: 'string',
default: '',
ui: {
widget: 'dict-select',
params: { dictKey: 'goodresource:type' },
containsAllLable: true,
visibleIf: {
_$expand: (value: boolean) => value
},
} as SFSelectWidgetSchema,
},
},
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 初始化数据列表
*/
initST() {
this.columns = [
{
title: '合同模板名称',
className: 'text-center',
render: 'templateName'
},
{
title: '签约对象',
width: '100px',
className: 'text-center',
index: 'signingObjectLabel'
},
{
title: '合同类型',
width: '100px',
className: 'text-center',
index: 'contractTypeLabel'
},
{
title: '货源类型',
width: '100px',
className: 'text-center',
index: 'resourceTypeLabel'
},
{ title: '创建人', index: 'createUserIdLabel', width: '120px', className: 'text-center' },
{
title: '创建时间',
className: 'text-center',
index: 'createTime',
width: '200px'
},
{
title: '操作',
fixed: 'right',
width: '110px',
className: 'text-center',
buttons: [
{
text: '编辑',
click: (_record) => this.edit(_record),
acl: { ability: ['CONTRACT-TEMPLATE-edit'] },
},
{
text: '删除',
click: (_record) => this.delete(_record),
acl: { ability: ['CONTRACT-TEMPLATE-delete'] },
},
],
},
];
}
initSTAudit() {
this.schemaView = {
properties: {
handleResult: {
title: '处理结果',
type: 'string',
maxLength: 50,
ui: {
placeholder: '最多不超过50字',
widget: 'textarea',
autosize: { minRows: 3, maxRows: 6 }
},
},
},
required: ['handleResult']
};
this.uiView = { '*': { spanLabelFixed: 110, grid: { span: 24 } } };
}
/**
* 查询字段个数
*/
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
tabChange(item: any) {
}
/**
* 重置表单
*/
resetSF(): void {
this.sf.reset();
this._$expand = false;
}
edit(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 2
}
})
}
creatTemplate() {
this.router.navigate(['/contract-management/template/text/' + 0], {
queryParams: {
status: 1
}
})
}
goBack() {
window.history.go(-1)
}
view(value: any) {
this.router.navigate(['/contract-management/template/text/' + value.id],{
queryParams: {
status: 3
}
})
}
delete(value: any) {
this.modal.confirm({
nzTitle: '<i>删除确认</i>',
nzOnOk: () =>
this.service.request(this.service.$api_deletebatch_contractTemplate, [value.id]).subscribe(res => {
if (res) {
this.service.msgSrv.success('删除成功!');
this.st.reload(1)
}
})
});
}
}

View File

@ -0,0 +1,26 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:27:10
* @LastEditors : Shiming
* @LastEditTime : 2022-02-23 19:39:38
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\index\\index.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<page-header-wrapper title="合同管理" [tab]="tpTab">
</page-header-wrapper>
<ng-template #tpTab>
<nz-tabset [(nzSelectedIndex)]="selectedIndex">
<nz-tab nzTitle="明细合同">
<app-contract-management-contract-list></app-contract-management-contract-list>
</nz-tab>
<nz-tab nzTitle="框架合同">
<app-contract-management-contract-frame></app-contract-management-contract-frame>
</nz-tab>
<nz-tab nzTitle="合伙人合同">
<app-contract-management-contract-partner></app-contract-management-contract-partner>
</nz-tab>
</nz-tabset>
</ng-template>

View File

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

View File

@ -0,0 +1,27 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:27:10
* @LastEditors : Shiming
* @LastEditTime : 2022-01-18 17:17:01
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\index\\index.component.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { Component, OnInit } from '@angular/core';
import { ModalHelper, _HttpClient } from '@delon/theme';
@Component({
selector: 'app-supply-management-index',
templateUrl: './index.component.html',
})
export class ContractManagementIndexComponent implements OnInit {
selectedIndex = 0;
constructor(private http: _HttpClient, private modal: ModalHelper) { }
ngOnInit(): void { }
}

View File

@ -0,0 +1,72 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-12 10:52:50
* @LastEditors : Shiming
* @LastEditTime : 2022-03-23 13:56:14
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\policy\\policy.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<page-header-wrapper title="保单管理" >
</page-header-wrapper>
<nz-card>
<div nz-row nzGutter="8">
<!-- 查询字段小于或等于3个时不显示伸缩按钮 -->
<div nz-col nzSpan="24" *ngIf="queryFieldCount <= 4">
<sf
#sf
[schema]="schema"
[ui]="ui"
[mode]="'search'"
[disabled]="!sf?.valid"
[loading]="false"
(formSubmit)="st?.load(1)"
(formReset)="resetSF()"
></sf>
</div>
<!-- 查询字段大于3个时根据展开状态调整布局 -->
<ng-container>
<div nz-col [nzSpan]="_$expand ? 24 : 18">
<sf #sf [schema]="schema" [ui]="ui" [compact]="true" [button]="'none'"></sf>
</div>
<div nz-col [nzSpan]="_$expand ? 24 : 6" [class.text-right]="_$expand">
<button nz-button nzType="primary" [disabled]="!sf.valid" [nzLoading]="isLoading && st.loading" (click)="st?.load(1)" acl [acl-ability]="['CONTRACT-POLICY-search']">查询</button>
<button nz-button (click)="resetSF()">重置</button>
<button nz-button nzType="link" (click)="expandToggle()">
{{ !_$expand ? '展开' : '收起' }}
<i nz-icon [nzType]="!_$expand ? 'down' : 'up'"></i>
</button>
</div>
</ng-container>
</div>
</nz-card>
<nz-card>
<st
#st
[data]="service.$api_get_getPremiumInformationPage"
[columns]="columns"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [10, 20, 30, 50, 100, 200, 300, 500, 1000] }"
[loading]="false"
>
</st>
</nz-card>
<ng-template #promoterModal>
<div nz-row nzGutter="8">
<div nz-col nzSpan="24" se-container [labelWidth]="80">
<sv-container col="1">
<sv label="传入值" [col]="1">
{{paramValue}}
</sv>
</sv-container>
</div>
</div>
</ng-template>

View File

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

View File

@ -0,0 +1,213 @@
import { Component, OnInit, ViewChild } from '@angular/core';
import { STColumn, STComponent, STChange } from '@delon/abc/st';
import { SFComponent, SFSchema, SFDateWidgetSchema, SFUISchema } from '@delon/form';
import { ModalHelper, _HttpClient } from '@delon/theme';
import { NzModalService } from 'ng-zorro-antd/modal';
import { ContractManagementService } from '../../services/contract-management.service';
import { Router } from '@angular/router';
@Component({
selector: 'app-contract-management-policy',
templateUrl: './policy.component.html'
})
export class ContractManagementPolicyComponent implements OnInit {
@ViewChild('st', { static: true })
st!: STComponent;
@ViewChild('sf', { static: false })
sf!: SFComponent;
@ViewChild('auditModal', { static: false })
auditModal!: any;
schema: SFSchema = {};
columns: STColumn[] = [];
ui: SFUISchema = {};
@ViewChild('promoterModal', { static: false })
promoterModal!: any;
_$expand = false;
selectedRows: any[] = [];
paramValue = '';
isLoading: boolean = false;
constructor(public service: ContractManagementService, private modal: NzModalService, private router: Router) {}
/**
* 查询参数
*/
get reqParams() {
const params: any = {
...(this.sf && this.sf.value)
};
delete params.expand;
return params;
}
ngOnInit(): void {
this.initST();
this.initSF();
}
openDetail(item?: any) {
this.paramValue = item?.paramValue
const modal = this.modal.create({
nzTitle: '传入值',
nzContent: this.promoterModal,
nzOnOk: () => {
return;
}
});
}
initST() {
this.columns = [
{ title: '', type: 'checkbox', width: '50px', className: 'text-center' },
{
title: '订单ID',
width: '100px',
className: 'text-center',
index: 'billId'
},
{
title: '项目ID',
width: '100px',
className: 'text-center',
index: 'enterpriseProjectId'
},
{
title: '保险公司',
width: '100px',
className: 'text-center',
index: 'insuranceCompany'
},
{
title: '投保金额',
width: '100px',
className: 'text-center',
index: 'insureAmount'
},
{
title: '保单号',
width: '100px',
className: 'text-center',
index: 'policyNo'
},
{
title: '保单地址',
width: '100px',
className: 'text-center',
index: 'policyUrl'
},
{
title: '保费',
width: '100px',
className: 'text-center',
index: 'premium'
},
{
title: '处理消息',
width: '100px',
className: 'text-center',
index: 'processMessage'
},
{
title: '处理结果',
width: '100px',
className: 'text-center',
index: 'processResult'
},
{
title: '操作',
width: '170px',
className: 'text-center',
buttons: [
{
text: '查看传入值',
click: item => {
this.openDetail(item)
},
acl: { ability: ['CONTRACT-POLICY-view'] },
}
]
}
];
}
initSF() {
this.schema = {
properties: {
_$expand: { type: 'boolean', ui: { hidden: true } },
billId: {
type: 'string',
title: '订单id'
},
enterpriseProjectId: {
type: 'string',
title: '项目id'
},
insuranceCompany: {
type: 'string',
title: '保险公司'
},
policyNo: {
type: 'string',
title: '保单号',
ui: {
visibleIf: {
_$expand: (value: boolean) => value
},
}
},
processResult: {
type: 'string',
title: '处理结果',
enum: [
{ label: '全部', value: '' },
{ label: '成功', value: 1 },
{ label: '失败', value: 2 }
],
ui: {
widget: 'select',
placeholder: '请选择',
visibleIf: {
_$expand: (value: boolean) => value
},
allowClear: true
}
}
},
type: 'object'
};
this.ui = { '*': { spanLabelFixed: 110, grid: { span: 8, gutter: 4 } } };
}
/**
* 重置表单
*/
resetSF() {
this.sf.reset();
this._$expand = false;
this.isLoading = true
}
/**
* 伸缩查询条件
*/
expandToggle(): void {
this._$expand = !this._$expand;
this.sf?.setValue('/_$expand', this._$expand);
}
get queryFieldCount(): number {
return Object.keys(this.schema?.properties || {}).length;
}
stChange(e: STChange): void {
switch (e.type) {
case 'checkbox':
this.selectedRows = e.checkbox!;
break;
case 'filter':
this.st.load();
break;
}
}
}

View File

@ -0,0 +1,26 @@
<!--
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:27:10
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 14:10:45
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\template\\template.component.html
* Copyright (C) 2022 huzhenhong. All rights reserved.
-->
<page-header-wrapper title="合同模板" [tab]="tpTab">
</page-header-wrapper>
<ng-template #tpTab>
<nz-tabset [(nzSelectedIndex)]="selectedIndex">
<nz-tab nzTitle="明细合同">
<app-contract-management-template-detail-complaint></app-contract-management-template-detail-complaint>
</nz-tab>
<nz-tab nzTitle="框架合同">
<app-contract-management-template-frame-complaint></app-contract-management-template-frame-complaint>
</nz-tab>
<nz-tab nzTitle="合伙人合同">
<app-contract-management-template-partner-complaint></app-contract-management-template-partner-complaint>
</nz-tab>
</nz-tabset>
</ng-template>

View File

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

View File

@ -0,0 +1,27 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-07 13:27:10
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:20:23
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\components\\template\\template.component.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { Component, OnInit } from '@angular/core';
import { ModalHelper, _HttpClient } from '@delon/theme';
@Component({
selector: 'app-supply-management-template',
templateUrl: './template.component.html',
})
export class ContractManagementTemplateComponent implements OnInit {
selectedIndex = 0;
constructor(private http: _HttpClient, private modal: ModalHelper) { }
ngOnInit(): void { }
}

View File

@ -0,0 +1,34 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-04 21:05:49
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:24:16
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\contract-management-routing.module.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ContractManagementDetailComponent } from './components/contract-detail/contract-detail.component';
import { ContractManagementContractListComponent } from './components/contract-list/contract-list.component';
import { ContractManagementPartnerComponent } from './components/contract-partner/contract-partner.component';
import { ContractManagementTemplateTextComponent } from './components/contract-template-detail/contract-template-detail.component';
import { ContractManagementIndexComponent } from './components/index/index.component';
import { ContractManagementPolicyComponent } from './components/policy/policy.component';
import { ContractManagementTemplateComponent } from './components/template/template.component';
const routes: Routes = [
{ path: 'index', component: ContractManagementIndexComponent },
{ path: 'index/detail/:id', component: ContractManagementDetailComponent },
{ path: 'template', component: ContractManagementTemplateComponent },
{ path: 'template/text/:id', component: ContractManagementTemplateTextComponent },
{ path: 'policy', component: ContractManagementPolicyComponent },
{ path: 'partner', component: ContractManagementPartnerComponent },
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class ContractManagementManagementRoutingModule {}

View File

@ -0,0 +1,47 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-04 21:05:49
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 14:09:24
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\contract-management.module.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '@shared';
import { ContractManagementManagementRoutingModule } from './contract-management-routing.module';
import { ContractManagementContractListComponent } from './components/contract-list/contract-list.component';
import { ContractManagementPolicyComponent } from './components/policy/policy.component';
import { ContractManagementTemplateDetailComponent } from './components/contract-template/contract-template.component';
import { ContractManagementIndexComponent } from './components/index/index.component';
import { ContractManagementFrameComponent } from './components/contract-frame/contract-frame.component';
import { ContractManagementDetailComponent } from './components/contract-detail/contract-detail.component';
import { ContractManagementPartnerComponent } from './components/contract-partner/contract-partner.component';
import { ContractManagementTemplateComponent } from './components/template/template.component';
import { ContractManagementTemplateTextComponent } from './components/contract-template-detail/contract-template-detail.component';
import { ContractManagementTemplateFrameComponent } from './components/contract-template-frame/contract-template-frame.component';
import { ContractManagementTemplatePartnerComponent } from './components/contract-template-partner/contract-template-partner.component';
const COMPONENTS: any = [
ContractManagementContractListComponent,
ContractManagementPolicyComponent,
ContractManagementTemplateDetailComponent,
ContractManagementTemplateDetailComponent,
ContractManagementIndexComponent,
ContractManagementFrameComponent,
ContractManagementDetailComponent,
ContractManagementPartnerComponent,
ContractManagementTemplateComponent,
ContractManagementTemplateTextComponent,
ContractManagementTemplateFrameComponent,
ContractManagementTemplatePartnerComponent
];
const NOTROUTECOMPONENTS: any = [];
@NgModule({
declarations: [...COMPONENTS, ...NOTROUTECOMPONENTS],
imports: [CommonModule, ContractManagementManagementRoutingModule, SharedModule]
})
export class ContractManagementManagementModule {}

View File

@ -0,0 +1,41 @@
/*
* @Description :
* @Version : 1.0
* @Author : Shiming
* @Date : 2022-01-04 21:05:49
* @LastEditors : Shiming
* @LastEditTime : 2022-02-24 10:00:59
* @FilePath : \\tms-obc-web\\src\\app\\routes\\contract-management\\services\\contract-management.service.ts
* Copyright (C) 2022 huzhenhong. All rights reserved.
*/
import { Injectable, Injector } from '@angular/core';
import { BaseService } from 'src/app/shared/services';
@Injectable({
providedIn: 'root'
})
export class ContractManagementService extends BaseService {
$api_get_getPremiumInformationPage = `/api/sdc/billOperate/listPremiumInformationPage`;
// 查询投诉列表
$api_get_operate_listPage = `/api/sdc/complaint/operate/listPage`;
// 新增/更新信息
$api_save_contractTemplate = `/api/sdc/contractTemplate/save`;
// 查询合同模板表
$api_get_contractTemplate_page = `/api/sdc/contractTemplate/list/page`;
// 查询合同模板表详情
$api_get_contractTemplate = `/api/sdc/contractTemplate/get`;
// 删除合同模板
$api_deletebatch_contractTemplate = `/api/sdc/contractTemplate/deletebatch`;
// 查询明细合同
$api_listDetailed_page = `/api/sdc/contract/listDetailed/page`;
// 查询框架合同
$api_listFrame_page = `/api/sdc/contract/listFrame/page`;
// 查询合伙人合同
$api_listPartner_page = `/api/sdc/contract/listPartner/page`;
// 获取订单合同表
$api_contract_get = `/api/sdc/contract/get`;
constructor(public injector: Injector) {
super(injector);
}
}

View File

@ -1,9 +0,0 @@
<div class="modal-header">
<div class="modal-title">编辑 {{ record.id }} 信息</div>
</div>
<sf #sf mode="edit" [schema]="schema" [ui]="ui" [formData]="i" button="none">
<div class="modal-footer">
<button nz-button type="button" (click)="close()">关闭</button>
<button nz-button type="submit" nzType="primary" (click)="save(sf.value)" [disabled]="!sf.valid" [nzLoading]="http.loading">保存</button>
</div>
</sf>

View File

@ -1,6 +0,0 @@
@import '~@delon/theme/index';
:host {
::ng-deep {
}
}

View File

@ -1,66 +1,8 @@
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, TemplateRef, ViewChild } from '@angular/core';
import { STComponent, STColumn, STData, STChange } from '@delon/abc/st';
import { SFSchema, SFUISchema } from '@delon/form';
import { _HttpClient } from '@delon/theme';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { map, tap } from 'rxjs/operators';
import { Component } from '@angular/core';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.less'],
changeDetection: ChangeDetectionStrategy.OnPush
styleUrls: ['./dashboard.component.less']
})
export class DashboardComponent {
@ViewChild('sf')
sf!: SFSchema;
record: any = {};
i: any;
schema: any = {
properties: {
no: { type: 'string', title: '编号' },
owner: { type: 'string', title: '姓名' },
callNo: { type: 'number', title: '调用次数' },
href: { type: 'string', title: '链接', format: 'uri', ui: { errors: { uri: '11' } } },
description: { type: 'string', title: '描述' }
},
required: ['owner', 'callNo', 'href', 'description']
};
ui: SFUISchema = {
'*': {
spanLabelFixed: 100,
grid: { span: 12 }
},
$no: {
widget: 'text'
},
$href: {
widget: 'string'
},
$description: {
widget: 'textarea',
grid: { span: 24 }
}
};
constructor(private msgSrv: NzMessageService, public http: _HttpClient) {}
ngOnInit(): void {
// if (this.record.id > 0) this.http.get(`/user/${this.record.id}`).subscribe(res => (this.i = res));
}
save(value: any): void {
console.log(this.sf.value);
// this.http.post(`/user/${this.record.id}`, value).subscribe(res => {
// this.msgSrv.success('保存成功');
// // this.modal.close(true);
// });
}
close(): void {
// this.modal.destroy();
}
}
export class DashboardComponent {}

View File

@ -0,0 +1,58 @@
<!-- 页头 -->
<page-header-wrapper [title]="'业务报表'"></page-header-wrapper>
<nz-card nzTitle="运多星平台业务情况" [nzExtra]="extraTemplate">
<ng-template #extraTemplate>
<div class="chooseBox">
<button nz-button nzType="primary" (click)="exportFun()">导出</button>
<div class="timeBox">
<nz-radio-group [(ngModel)]="mode" nzButtonStyle="solid" (ngModelChange)="changeData()">
<label nz-radio-button nzValue="year"></label>
<label nz-radio-button nzValue="month"></label>
<label nz-radio-button nzValue="date"></label>
<label nz-radio-button nzValue="define">自定义</label>
</nz-radio-group>
<div class="dateBox">
<nz-date-picker [(ngModel)]="date" [nzMode]="mode" [nzFormat]="dateFormat" *ngIf="mode !== 'define'" [nzDisabledDate]="disabledDate" (ngModelChange)="onChange($event)"></nz-date-picker>
<nz-range-picker [(ngModel)]="defineDate" [nzFormat]="dateFormat" *ngIf="mode === 'define'" [nzDisabledDate]="disabledDate" (ngModelChange)="onChange($event)"></nz-range-picker>
</div>
</div>
</div>
</ng-template>
<st #st multiSort [columns]="columns" [ps]="20" [data]="service.$api_listPerformanceReportPage"
[req]="{ method: 'POST', allInBody: true, reName: { pi: 'pageIndex', ps: 'pageSize' }, params: reqParams }"
[scroll]="{ x: '1200px' }" [res]="{ reName: { list: 'data.records', total: 'data.total' } }"
[page]="{ show: true, showSize: true, pageSizes: [20, 50, 100] }"></st>
</nz-card>
<nz-card nzTitle="业绩报表" [nzExtra]="extraTemplate01">
<ng-template #extraTemplate01>
<div class="chooseBox">
<div class="timeBox">
<nz-radio-group [(ngModel)]="modeNext" nzButtonStyle="solid" (ngModelChange)="changeDataNext()">
<label nz-radio-button nzValue="year"></label>
<label nz-radio-button nzValue="month"></label>
</nz-radio-group>
<div class="dateBox">
<nz-date-picker [(ngModel)]="dateNext" [nzDisabledDate]="disabledDate" [nzMode]="modeNext" (ngModelChange)="onChangeNext($event)"></nz-date-picker>
</div>
</div>
</div>
</ng-template>
<div nz-row [nzGutter]="64">
<div nz-col class="gutter-row" [nzSpan]="12">
<div class="title">
<div class="box" style="background-color: #3ba1ff;"></div> 环比(%)
</div>
<!-- <g2-custom delay="100" (render)="render($event)"></g2-custom> -->
<!-- <app-busitable-curve></app-busitable-curve> -->
<app-busitable-curve #curve [chartData]="chartData.chainRatio"></app-busitable-curve>
</div>
<div nz-col class="gutter-row" [nzSpan]="12">
<div class="title">
<div class="box" style="background-color: #f59a23;"></div> 业绩量(元)
</div>
<app-busitable-pillar #pillar [chartData]="chartData.performance"></app-busitable-pillar>
</div>
</div>
</nz-card>

View File

@ -0,0 +1,21 @@
.chooseBox{
display: flex;
}
.timeBox{
display: flex;
margin: 0 0 0 10px;
}
.dateBox{
display: inline-block;
margin: 0 0 0 10px;
}
.title{
display: flex;
align-items: center;
.box{
width: 8px;
height: 8px;
margin-right: 10px;
border-radius: 100px;
}
}

View File

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

View File

@ -0,0 +1,138 @@
import { Component, OnInit, ViewChild, NgZone } from '@angular/core';
import { STColumn, STComponent } from '@delon/abc/st';
import { DatePipe, _HttpClient } from '@delon/theme';
import { differenceInCalendarDays } from 'date-fns';
import { DataService } from '../../../services/data.service';
import { BusitablePillarComponent } from '../pillar/pillar.component';
import { BusitableCurveComponent } from './curve/curve.component';
@Component({
selector: 'app-datatable-busiindex',
templateUrl: './busiindex.component.html',
styleUrls: ['./busiindex.component.less'],
providers: [DatePipe]
})
export class DatatableBusiindexComponent implements OnInit {
@ViewChild('st') private readonly st!: STComponent;
@ViewChild('curve') private readonly curve!: BusitableCurveComponent;
@ViewChild('pillar') private readonly pillar!: BusitablePillarComponent;
type = 1;
mode = 'year';
date: any = null;
time: any = ['2022-01-01 00:00:00']
defineDate = [];
dateNext: any = null;
modeNext = 'year';
timeNext: any = ['2022-01-01 00:00:00']
dateFormat = 'yyyy';
today = new Date();
chartData: any = {}
columns: STColumn[] = [
{ title: '运营主体', index: 'networkTransporterName', className: 'text-center' },
{ title: '合伙人数', index: 'partnerNumber', className: 'text-center' },
{ title: '客户数', index: 'enterpriseNumbe', className: 'text-center' },
{ title: '订单数', index: 'zsl', className: 'text-center' },
{ title: '客户预存款', index: 'czcgje', className: 'text-right', type: 'widget', widget: { type: 'currency-chy', params: ({ record }) => ({ value: record.czcgje }) } },
{ title: '业绩量', index: 'yisje', className: 'text-center' },
{ title: '已收附加费', index: 'yisfjf', className: 'text-right', type: 'widget', widget: { type: 'currency-chy', params: ({ record }) => ({ value: record.yisfjf }) } },
{ title: '平均附加费率', index: 'fjfl', className: 'text-center',format: (item)=> {
return item.fjfl + '%'
} },
{ title: '已开票金额', index: 'ykpje', className: 'text-right', type: 'widget', widget: { type: 'currency-chy', params: ({ record }) => ({ value: record.ykpje }) } },
];
/**
* 查询参数
*/
get reqParams() {
if(this.mode === 'year') {
this.type = 1
} else if(this.mode === 'month') {
this.type = 2
} else if(this.mode === 'date') {
this.type = 3
} else {
this.type = 4
}
let params: any = {
time: this.time,
type: this.type
};
delete params._$expand;
return { ...params };
}
constructor(public service: DataService, private datePipe: DatePipe, private ngZone: NgZone) { }
ngOnInit(): void {
this.initData()
}
initData(flag?: boolean){
let type = 1
if(this.mode === 'year') {
type = 1
} else if(this.mode === 'month') {
type = 2
}
const params: any = {
time: this.timeNext,
type
};
this.service.request(this.service.$api_performanceReportHistogram, params).subscribe(res => {
if (res) {
this.chartData = res
if(flag) {
this.pillar.reRender()
this.curve.reRender()
}
}
})
}
changeData(){
if(this.mode === 'year') {
this.dateFormat = 'yyyy'
} else if(this.mode === 'month') {
this.dateFormat = 'yyyy-MM'
} else {
this.dateFormat = 'yyyy-MM-dd'
}
}
onChange(result: any) {
if(this.mode === 'year') {
this.time = [this.datePipe.transform(this.date, 'yyyy') + '-01-01 00:00:00']
} else if(this.mode === 'month') {
this.time = [this.datePipe.transform(this.date, 'yyyy-MM') + '-01 00:00:00']
} else if(this.mode === 'date') {
this.time = [this.datePipe.transform(this.date, 'yyyy-MM-dd') + ' 00:00:00']
} else{
this.time = [this.datePipe.transform(this.defineDate[0], 'yyyy-MM-dd') + '00:00:00', this.datePipe.transform(this.defineDate[1], 'yyyy-MM-dd') + ' 00:00:00']
}
this.st.reload({ ...this.reqParams });
}
changeDataNext() {
if(this.mode === 'year') {
this.dateFormat = 'yyyy'
} else if(this.mode === 'month') {
this.dateFormat = 'yyyy-MM'
}
}
onChangeNext(result: any) {
if(result === null) {
return
}
if(this.mode === 'year') {
this.timeNext = [this.datePipe.transform(this.dateNext, 'yyyy') + '-01-01 00:00:00']
} else if(this.mode === 'month') {
this.timeNext = [this.datePipe.transform(this.dateNext, 'yyyy-MM') + '-01 00:00:00']
}
this.initData(true)
}
disabledDate = (current: Date): boolean =>
// Can not select days before today and today
differenceInCalendarDays(current, this.today) > 0;
exportFun(){
}
}

View File

@ -0,0 +1 @@
<g2-custom delay="200" (render)="render($event)"></g2-custom>

View File

@ -0,0 +1,68 @@
import { Component, ElementRef, Input, NgZone, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
import { Chart } from '@antv/g2';
import { DataService } from 'src/app/routes/datatable/services/data.service';
@Component({
selector: 'app-busitable-curve',
templateUrl: './curve.component.html',
styleUrls: ['./curve.component.less']
})
export class BusitableCurveComponent implements OnInit, OnChanges {
el: any;
@Input() chartData: any;
chart: any;
constructor(private service: DataService, private ngZone: NgZone) {
}
ngOnChanges(changes: SimpleChanges): void {
if (this.chartData) {
// setTimeout(()=>{
// this.chart.render(true)
// }, 1000)
}
}
ngOnInit(): void {
}
reRender() {
this.chart.data(this.chartData);
this.chart.render();
}
render(el: ElementRef<HTMLDivElement>): void {
this.el = el.nativeElement
setTimeout(() => {
this.ngZone.runOutsideAngular(() => this.init(this.el));
}, 500)
}
private init(el: HTMLElement): void {
this.chart = new Chart({
container: el,
autoFit: true,
height: 500,
});
this.chart.data(this.chartData);
this.chart.scale({
year: {
range: [0, 1],
},
value: {
min: 0,
nice: true,
},
});
this.chart.tooltip({
showCrosshairs: true, // 展示 Tooltip 辅助线
shared: true,
});
this.chart.line().position('time*value').label('value');
this.chart.point().position('time*value');
this.chart.render();
}
}

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