| @@ -42,6 +42,7 @@ | |||||
| "@microsoft/signalr": "^8.0.0", | "@microsoft/signalr": "^8.0.0", | ||||
| "@microsoft/signalr-protocol-msgpack": "^8.0.0", | "@microsoft/signalr-protocol-msgpack": "^8.0.0", | ||||
| "@types/signalr": "^2.4.3", | "@types/signalr": "^2.4.3", | ||||
| "@types/three": "^0.162.0", | |||||
| "ag-grid-angular": "^31.0.2", | "ag-grid-angular": "^31.0.2", | ||||
| "echarts": "^5.5.0", | "echarts": "^5.5.0", | ||||
| "moment": "^2.30.1", | "moment": "^2.30.1", | ||||
| @@ -50,6 +51,8 @@ | |||||
| "ngx-mqtt": "^17.0.0", | "ngx-mqtt": "^17.0.0", | ||||
| "rxjs": "~7.8.0", | "rxjs": "~7.8.0", | ||||
| "screenfull": "^6.0.2", | "screenfull": "^6.0.2", | ||||
| "three": "^0.162.0", | |||||
| "three-orbitcontrols-ts": "^0.1.2", | |||||
| "tslib": "^2.3.0", | "tslib": "^2.3.0", | ||||
| "zone.js": "~0.14.3" | "zone.js": "~0.14.3" | ||||
| }, | }, | ||||
| @@ -38,8 +38,18 @@ export class DataVNavigationComponent implements OnInit { | |||||
| }, | }, | ||||
| { | { | ||||
| code: '03', | code: '03', | ||||
| text: '3D', | |||||
| url: '/data-v/threejs' | |||||
| text: '重磅3D', | |||||
| url: '/data-v/t1' | |||||
| }, | |||||
| { | |||||
| code: '04', | |||||
| text: '煤流总览', | |||||
| url: '/data-v/t1' | |||||
| }, | |||||
| { | |||||
| code: '05', | |||||
| text: '毛重计量', | |||||
| url: '/data-v/t1' | |||||
| }, | }, | ||||
| { | { | ||||
| text: '...' | text: '...' | ||||
| @@ -5,6 +5,7 @@ import { DataVDateComponent } from './date/date.component'; | |||||
| import { DataVWorkstationComponent } from './workstation/workstation.component'; | import { DataVWorkstationComponent } from './workstation/workstation.component'; | ||||
| import { DataVS1Component } from './s1/s1.component'; | import { DataVS1Component } from './s1/s1.component'; | ||||
| import { DataVThreejsComponent } from './threejs/threejs.component'; | import { DataVThreejsComponent } from './threejs/threejs.component'; | ||||
| import { DataVT1Component } from './t1/t1.component'; | |||||
| export const routes: Routes = [ | export const routes: Routes = [ | ||||
| { | { | ||||
| @@ -12,4 +13,5 @@ export const routes: Routes = [ | |||||
| component: DataVS1Component | component: DataVS1Component | ||||
| } | } | ||||
| , | , | ||||
| { path: 'threejs', component: DataVThreejsComponent }]; | |||||
| { path: 'threejs', component: DataVThreejsComponent }, | |||||
| { path: 't1', component: DataVT1Component }]; | |||||
| @@ -66,7 +66,7 @@ | |||||
| 量热仪 | 量热仪 | ||||
| </div> | </div> | ||||
| <div nz-col nzSpan="12" class="sys-status-title"> | <div nz-col nzSpan="12" class="sys-status-title"> | ||||
| 谈情氮元素 | |||||
| 碳氢氮元素 | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -103,5 +103,4 @@ | |||||
| <div class="sys-status-title">煤样超差率:超差样量/总样量 03/16</div> | <div class="sys-status-title">煤样超差率:超差样量/总样量 03/16</div> | ||||
| <div class="sys-status-title">煤样合格率:合格样量/总样量 15/16</div> | <div class="sys-status-title">煤样合格率:合格样量/总样量 15/16</div> | ||||
| </data-v-card> --> | </data-v-card> --> | ||||
| </div> | </div> | ||||
| @@ -12,6 +12,8 @@ import { NzProgressModule } from 'ng-zorro-antd/progress'; | |||||
| import { NzBadgeModule } from 'ng-zorro-antd/badge'; | import { NzBadgeModule } from 'ng-zorro-antd/badge'; | ||||
| import { Subscription } from 'rxjs'; | import { Subscription } from 'rxjs'; | ||||
| import { IMqttMessage, MqttService } from 'ngx-mqtt'; | import { IMqttMessage, MqttService } from 'ngx-mqtt'; | ||||
| import { TitleService } from '@delon/theme'; | |||||
| @Component({ | @Component({ | ||||
| selector: 'app-data-v-s1', | selector: 'app-data-v-s1', | ||||
| standalone: true, | standalone: true, | ||||
| @@ -22,6 +24,7 @@ import { IMqttMessage, MqttService } from 'ngx-mqtt'; | |||||
| export class DataVS1Component implements OnInit { | export class DataVS1Component implements OnInit { | ||||
| private readonly http = inject(_HttpClient); | private readonly http = inject(_HttpClient); | ||||
| private readonly modal = inject(ModalHelper); | private readonly modal = inject(ModalHelper); | ||||
| private readonly titleService = inject(TitleService); | |||||
| private c1OptionC = { | private c1OptionC = { | ||||
| series: [ | series: [ | ||||
| @@ -108,6 +111,90 @@ export class DataVS1Component implements OnInit { | |||||
| } | } | ||||
| ] | ] | ||||
| }; | }; | ||||
| private c2OptionC = { | |||||
| series: [ | |||||
| { | |||||
| type: 'gauge', | |||||
| startAngle: 180, | |||||
| endAngle: 0, | |||||
| center: ['50%', '75%'], | |||||
| radius: '90%', | |||||
| min: 0, | |||||
| max: 1, | |||||
| splitNumber: 8, | |||||
| axisLine: { | |||||
| lineStyle: { | |||||
| width: 6, | |||||
| color: [ | |||||
| [0.6, '#FF6E76'], | |||||
| [0.9, '#FDDD60'], | |||||
| [1, '#7CFFB2'] | |||||
| ] | |||||
| } | |||||
| }, | |||||
| pointer: { | |||||
| icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z', | |||||
| length: '12%', | |||||
| width: 20, | |||||
| offsetCenter: [0, '-60%'], | |||||
| itemStyle: { | |||||
| color: 'auto' | |||||
| } | |||||
| }, | |||||
| axisTick: { | |||||
| length: 12, | |||||
| lineStyle: { | |||||
| color: 'auto', | |||||
| width: 2 | |||||
| } | |||||
| }, | |||||
| splitLine: { | |||||
| length: 20, | |||||
| lineStyle: { | |||||
| color: 'auto', | |||||
| width: 5 | |||||
| } | |||||
| }, | |||||
| axisLabel: { | |||||
| color: '#464646', | |||||
| fontSize: 20, | |||||
| distance: -60, | |||||
| rotate: 'tangential', | |||||
| formatter: function (value: number) { | |||||
| if (value === 0.875) { | |||||
| return ''; | |||||
| } else if (value === 0.625) { | |||||
| return ''; | |||||
| } else if (value === 0.125) { | |||||
| return ''; | |||||
| } | |||||
| return ''; | |||||
| } | |||||
| }, | |||||
| title: { | |||||
| offsetCenter: [0, '-10%'], | |||||
| fontSize: 20 | |||||
| }, | |||||
| detail: { | |||||
| fontSize: 30, | |||||
| offsetCenter: [0, '-5%'], | |||||
| valueAnimation: true, | |||||
| formatter: function (value: number) { | |||||
| return Math.round(value * 100) + ''; | |||||
| }, | |||||
| color: 'inherit' | |||||
| }, | |||||
| data: [ | |||||
| { | |||||
| value: 0.7, | |||||
| name: '' | |||||
| } | |||||
| ] | |||||
| } | |||||
| ] | |||||
| }; | |||||
| private c1Chart: any; | private c1Chart: any; | ||||
| rowData = [ | rowData = [ | ||||
| @@ -240,97 +327,12 @@ export class DataVS1Component implements OnInit { | |||||
| } | } | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| this.titleService.setTitle('化验总览'); | |||||
| var c1 = document.getElementById('c1')!; | var c1 = document.getElementById('c1')!; | ||||
| this.c1Chart = echarts.init(c1); | this.c1Chart = echarts.init(c1); | ||||
| var c2 = document.getElementById('c2')!; | var c2 = document.getElementById('c2')!; | ||||
| var c2Chart = echarts.init(c2); | var c2Chart = echarts.init(c2); | ||||
| let c2OptionC = { | |||||
| series: [ | |||||
| { | |||||
| type: 'gauge', | |||||
| startAngle: 180, | |||||
| endAngle: 0, | |||||
| center: ['50%', '75%'], | |||||
| radius: '90%', | |||||
| min: 0, | |||||
| max: 1, | |||||
| splitNumber: 8, | |||||
| axisLine: { | |||||
| lineStyle: { | |||||
| width: 6, | |||||
| color: [ | |||||
| [0.25, '#74FAFB'], | |||||
| [0.5, '#74FAFB'], | |||||
| [0.75, '#74FAFB'], | |||||
| [1, '#74FAFB'] | |||||
| ] | |||||
| } | |||||
| }, | |||||
| pointer: { | |||||
| icon: 'path://M12.8,0.7l12,40.1H0.7L12.8,0.7z', | |||||
| length: '12%', | |||||
| width: 20, | |||||
| offsetCenter: [0, '-60%'], | |||||
| itemStyle: { | |||||
| color: 'auto' | |||||
| } | |||||
| }, | |||||
| axisTick: { | |||||
| length: 12, | |||||
| lineStyle: { | |||||
| color: 'auto', | |||||
| width: 2 | |||||
| } | |||||
| }, | |||||
| splitLine: { | |||||
| length: 20, | |||||
| lineStyle: { | |||||
| color: 'auto', | |||||
| width: 5 | |||||
| } | |||||
| }, | |||||
| axisLabel: { | |||||
| color: '#464646', | |||||
| fontSize: 20, | |||||
| distance: -60, | |||||
| rotate: 'tangential', | |||||
| formatter: function (value: any) { | |||||
| if (value === 0.875) { | |||||
| return ''; | |||||
| } else if (value === 0.625) { | |||||
| return ''; | |||||
| } else if (value === 0.375) { | |||||
| return ''; | |||||
| } else if (value === 0.125) { | |||||
| return ''; | |||||
| } | |||||
| return ''; | |||||
| } | |||||
| }, | |||||
| title: { | |||||
| offsetCenter: [0, '0%'], | |||||
| fontSize: 20 | |||||
| }, | |||||
| detail: { | |||||
| fontSize: 30, | |||||
| offsetCenter: [0, '-5%'], | |||||
| valueAnimation: true, | |||||
| formatter: function (value: any) { | |||||
| return Math.round(value * 100) + ''; | |||||
| }, | |||||
| color: 'inherit' | |||||
| }, | |||||
| data: [ | |||||
| { | |||||
| value: 0.97, | |||||
| name: '' | |||||
| } | |||||
| ] | |||||
| } | |||||
| ] | |||||
| }; | |||||
| var d1 = document.getElementById('d1'); | var d1 = document.getElementById('d1'); | ||||
| var d1Chart = echarts.init(d1, 'dark'); | var d1Chart = echarts.init(d1, 'dark'); | ||||
| var d2 = document.getElementById('d2'); | var d2 = document.getElementById('d2'); | ||||
| @@ -608,7 +610,7 @@ export class DataVS1Component implements OnInit { | |||||
| optionD2 && d2Chart.setOption(optionD2); | optionD2 && d2Chart.setOption(optionD2); | ||||
| this.c1Chart.setOption(this.c1OptionC); | this.c1Chart.setOption(this.c1OptionC); | ||||
| c2Chart.setOption(c2OptionC); | |||||
| c2Chart.setOption(this.c2OptionC); | |||||
| var r1 = document.getElementById('r1'); | var r1 = document.getElementById('r1'); | ||||
| var r1Chart = echarts.init(r1, 'dark'); | var r1Chart = echarts.init(r1, 'dark'); | ||||
| @@ -0,0 +1,6 @@ | |||||
| <!-- <div #Three style="background-color: red;"></div> --> | |||||
| <div style="display: flex; flex-direction: column; height: 100vh;"> | |||||
| <div #Three style="flex-grow: 1;"></div> | |||||
| </div> | |||||
| @@ -0,0 +1,120 @@ | |||||
| import { Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; | |||||
| import { STColumn, STComponent } from '@delon/abc/st'; | |||||
| import { SFSchema } from '@delon/form'; | |||||
| import { ModalHelper, _HttpClient } from '@delon/theme'; | |||||
| import { SHARED_IMPORTS } from '@shared'; | |||||
| import * as THREE from 'three'; | |||||
| import { OrbitControls } from 'three-orbitcontrols-ts'; | |||||
| import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'; | |||||
| import { TitleService } from '@delon/theme'; | |||||
| const clock = new THREE.Clock(); | |||||
| let mixer: { update: (arg0: number) => void; }; | |||||
| @Component({ | |||||
| selector: 'app-data-v-t1', | |||||
| standalone: true, | |||||
| imports: [...SHARED_IMPORTS], | |||||
| templateUrl: './t1.component.html', | |||||
| }) | |||||
| export class DataVT1Component implements OnInit { | |||||
| private readonly http = inject(_HttpClient); | |||||
| private readonly modal = inject(ModalHelper); | |||||
| private readonly titleService = inject(TitleService); | |||||
| @ViewChild('Three', { static: true }) container!: ElementRef; | |||||
| public scene!: THREE.Scene; | |||||
| public camera!: THREE.PerspectiveCamera; | |||||
| public renderer!: THREE.WebGLRenderer; | |||||
| public cube!: THREE.Mesh; | |||||
| ngOnInit(): void { | |||||
| this.titleService.setTitle('重磅3D'); | |||||
| this.initThreeJs(); | |||||
| this.animate(); | |||||
| } | |||||
| private initThreeJs(): void { | |||||
| // 创建相机 | |||||
| this.camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 20000); | |||||
| this.camera.position.set(2200, 300, -3100); | |||||
| //创建场景 | |||||
| this.scene = new THREE.Scene(); | |||||
| this.scene.background = new THREE.Color(0x040516); | |||||
| const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 5); | |||||
| hemiLight.position.set(0, 200, 0); | |||||
| this.scene.add(hemiLight); | |||||
| const dirLight = new THREE.DirectionalLight(0xffffff, 5); | |||||
| dirLight.position.set(0, 200, 100); | |||||
| dirLight.castShadow = true; | |||||
| dirLight.shadow.camera.top = 180; | |||||
| dirLight.shadow.camera.bottom = - 100; | |||||
| dirLight.shadow.camera.left = - 120; | |||||
| dirLight.shadow.camera.right = 120; | |||||
| this.scene.add(dirLight); | |||||
| const that = this; | |||||
| const loader = new FBXLoader(); | |||||
| loader.load('assets/fbx/bb.fbx', function (object) { | |||||
| object.traverse(function (child) { | |||||
| // if (child.isMesh) { | |||||
| // child.castShadow = true; | |||||
| // child.receiveShadow = true; | |||||
| // } | |||||
| }); | |||||
| that.scene.add(object); | |||||
| }, | |||||
| (xhr) => { | |||||
| // loading progress | |||||
| }, | |||||
| (err) => { | |||||
| console.error('An error happened', err); | |||||
| }); | |||||
| this.renderer = new THREE.WebGLRenderer({ antialias: true }); | |||||
| this.renderer.setPixelRatio(window.devicePixelRatio); | |||||
| this.renderer.setSize(window.innerWidth, window.innerHeight); | |||||
| this.renderer.shadowMap.enabled = true; | |||||
| this.container.nativeElement.appendChild(this.renderer.domElement); | |||||
| const radius = 5; // 圆的半径 | |||||
| const segments = 32; // 圆的分段数 | |||||
| const geometry = new THREE.CircleGeometry(radius, segments); | |||||
| const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); // 红色材质,你可以根据需要调整颜色 | |||||
| const circle = new THREE.Mesh(geometry, material); | |||||
| circle.position.set(850, 100, -2000); // 设置圆的位置 | |||||
| this.scene.add(circle); | |||||
| const controls = new OrbitControls(this.camera, this.renderer.domElement); | |||||
| controls.target.set(850, 100, -2000); | |||||
| controls.update(); | |||||
| //const axesHelper = new THREE.AxesHelper(1000); | |||||
| //this.scene.add(axesHelper); | |||||
| window.addEventListener('resize', this.onWindowResize); | |||||
| } | |||||
| public render(): void { | |||||
| this.cube.rotation.x += 0.01; | |||||
| this.cube.rotation.y += 0.01; | |||||
| this.renderer.render(this.scene, this.camera); | |||||
| } | |||||
| onWindowResize() { | |||||
| this.camera.aspect = window.innerWidth / window.innerHeight; | |||||
| this.camera.updateProjectionMatrix(); | |||||
| this.renderer.setSize(window.innerWidth, window.innerHeight); | |||||
| } | |||||
| animate = () => { | |||||
| requestAnimationFrame(this.animate); | |||||
| const delta = clock.getDelta(); | |||||
| if (mixer) mixer.update(delta); | |||||
| this.renderer.render(this.scene, this.camera); | |||||
| }; | |||||
| } | |||||
| @@ -1,6 +1,6 @@ | |||||
| import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; | import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, inject } from '@angular/core'; | ||||
| import { ModalHelper, _HttpClient } from '@delon/theme'; | |||||
| import { ModalHelper, TitleService, _HttpClient } from '@delon/theme'; | |||||
| import { SHARED_IMPORTS } from '@shared'; | import { SHARED_IMPORTS } from '@shared'; | ||||
| import { AgGridAngular } from 'ag-grid-angular'; | import { AgGridAngular } from 'ag-grid-angular'; | ||||
| import { ColDef } from 'ag-grid-community'; | import { ColDef } from 'ag-grid-community'; | ||||
| @@ -23,6 +23,7 @@ export class DataVWorkstationComponent implements OnInit, AfterViewInit { | |||||
| private readonly http = inject(_HttpClient); | private readonly http = inject(_HttpClient); | ||||
| private readonly modal = inject(ModalHelper); | private readonly modal = inject(ModalHelper); | ||||
| private readonly elementRef = inject(ElementRef); | private readonly elementRef = inject(ElementRef); | ||||
| private readonly titleService = inject(TitleService); | |||||
| @ViewChild('myGrid') grid!: AgGridAngular; | @ViewChild('myGrid') grid!: AgGridAngular; | ||||
| public defaultColDef: ColDef = { | public defaultColDef: ColDef = { | ||||
| @@ -103,7 +104,7 @@ export class DataVWorkstationComponent implements OnInit, AfterViewInit { | |||||
| ]; | ]; | ||||
| ngOnInit(): void { | ngOnInit(): void { | ||||
| console.log('ngOnInit' + this.rowData.length); | |||||
| this.titleService.setTitle('我的工作站'); | |||||
| for (var i = 1; i < 30; i++) { | for (var i = 1; i < 30; i++) { | ||||
| this.rowData.push({ | this.rowData.push({ | ||||
| @@ -29,8 +29,6 @@ | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| <ng-template #coverTemplate> | <ng-template #coverTemplate> | ||||
| <img style="height: 100px;" alt="example" src="assets/bg2.jpg" /> | <img style="height: 100px;" alt="example" src="assets/bg2.jpg" /> | ||||
| </ng-template> | </ng-template> | ||||
| @@ -91,15 +91,20 @@ | |||||
| color: #515151; | color: #515151; | ||||
| vertical-align: middle; | vertical-align: middle; | ||||
| } | } | ||||
| } | |||||
| .color-515151 { | |||||
| color: #515151; | |||||
| } | |||||
| .color-515151 { | |||||
| color: #515151; | |||||
| } | } | ||||
| } | } | ||||
| [data-theme='dark'] { | [data-theme='dark'] { | ||||
| :host ::ng-deep { | :host ::ng-deep { | ||||
| display: block; | |||||
| width: 538px; | |||||
| margin: 0 auto; | |||||
| .icon { | .icon { | ||||
| color: rgb(255 255 255 / 20%); | color: rgb(255 255 255 / 20%); | ||||
| @@ -36,7 +36,9 @@ | |||||
| ], | ], | ||||
| "@_mock": [ | "@_mock": [ | ||||
| "_mock/index" | "_mock/index" | ||||
| ] | |||||
| ], | |||||
| "three": ["./node_modules/three/src/Three"], | |||||
| "three/*": ["./node_modules/three/*"] | |||||
| } | } | ||||
| }, | }, | ||||
| "angularCompilerOptions": { | "angularCompilerOptions": { | ||||