邵佳豪 3 years ago
parent
commit
808850a01b
  1. 24
      src/app/babylon/controller/data-manager.ts
  2. 12
      src/app/babylon/controller/mode-manager.ts
  3. 2
      src/app/babylon/controller/scene-manager.ts
  4. 15
      src/app/babylon/controller/serve-manager.ts
  5. 27
      src/app/babylon/controller/status/login-status.ts
  6. 5
      src/app/babylon/model/data/institution/institution-data.ts
  7. 6
      src/app/babylon/tool/babylon-tool.ts
  8. 1
      src/app/babylon/view/building-window/building-window.ts
  9. 2
      src/app/babylon/view/indoor-window/indoor-window.ts
  10. 22
      src/app/http-interceptors/base-interceptor.ts
  11. 4
      src/app/pages/pages.module.ts
  12. 34
      src/app/pages/plan/plan.component.html
  13. 67
      src/app/pages/plan/plan.component.scss
  14. 80
      src/app/pages/plan/plan.component.ts
  15. 30
      src/app/pages/plan/publicPop.scss
  16. 4
      src/app/service/babylon/building-basic-infos.service.ts
  17. 87
      src/app/service/babylon/objects.service.ts
  18. 80
      src/app/service/objects.service.ts
  19. BIN
      src/assets/skybox/default/default_ny.jpg
  20. BIN
      src/assets/skybox/default/default_py.jpg

24
src/app/babylon/controller/data-manager.ts

@ -142,7 +142,6 @@ export class DataManager {
DataManager.institutionData.normalData.key.toLowerCase(), DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.environmentDatas[0].normalData.key.toLocaleLowerCase(), DataManager.institutionData.environmentDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Environment, BuildingPosType.Environment,
'modelEn001'
); );
DataManager.institutionData.environmentDatas[0].outdoorData.modelData = new ModelData_building( DataManager.institutionData.environmentDatas[0].outdoorData.modelData = new ModelData_building(
'modelEn001', 'modelEn001',
@ -200,7 +199,6 @@ export class DataManager {
DataManager.institutionData.normalData.key.toLowerCase(), DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(), DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.OutDoor, BuildingPosType.OutDoor,
'modelOut001'
); );
DataManager.institutionData.normalBuildingDatas[0].outdoorData.modelData = new ModelData_building( DataManager.institutionData.normalBuildingDatas[0].outdoorData.modelData = new ModelData_building(
'modelOut001', 'modelOut001',
@ -221,7 +219,6 @@ export class DataManager {
let resPath_inDoor1 = DataManager.getResPath_building( let resPath_inDoor1 = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(), DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(), DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Indoor,
'nei1' 'nei1'
); );
indoorData1.modelData = new ModelData_building( indoorData1.modelData = new ModelData_building(
@ -241,7 +238,6 @@ export class DataManager {
let resPath_inDoor2 = DataManager.getResPath_building( let resPath_inDoor2 = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(), DataManager.institutionData.normalData.key.toLowerCase(),
DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(), DataManager.institutionData.normalBuildingDatas[0].normalData.key.toLocaleLowerCase(),
BuildingPosType.Indoor,
'nei2' 'nei2'
); );
indoorData2.modelData = new ModelData_building( indoorData2.modelData = new ModelData_building(
@ -274,21 +270,25 @@ export class DataManager {
//获取建筑资源完整路径
/**
* (ObjectsService.baseUrl)
* @param institutionKey
* @param buildingKey
* @param key
*/
static getResPath_building( static getResPath_building(
institutionKey: string, institutionKey: string,
buildingKey: string, buildingKey: string,
buildingPosType: BuildingPosType,
key: string key: string
): string { ): string {
let result = let result =
ConfigManager.c_resPath_institutionsRoot + institutionKey.toLocaleLowerCase()
institutionKey.toLocaleLowerCase() + '/' +
ServeManager.ngAssetsPath +
'/' + '/' +
buildingKey.toLocaleLowerCase() + buildingKey.toLocaleLowerCase() +
'/' + '/' +
buildingPosType +
'/' +
key + key +
'/'; '/';
return result; return result;
@ -299,9 +299,10 @@ export class DataManager {
buildingKey: string, facilityType: FacilityType, facilityKey: string, key: string) { buildingKey: string, facilityType: FacilityType, facilityKey: string, key: string) {
let result = let result =
ConfigManager.c_resPath_institutionsRoot +
institutionKey.toLocaleLowerCase() + institutionKey.toLocaleLowerCase() +
'/' + '/' +
ServeManager.ngAssetsPath +
'/' +
buildingKey.toLocaleLowerCase() + buildingKey.toLocaleLowerCase() +
'/' + '/' +
ConfigManager.c_reaPath_facilityProperty + ConfigManager.c_reaPath_facilityProperty +
@ -311,7 +312,6 @@ export class DataManager {
facilityKey.toLocaleLowerCase() + facilityKey.toLocaleLowerCase() +
"/"; "/";
return result; return result;
} }

12
src/app/babylon/controller/mode-manager.ts

@ -15,20 +15,22 @@ export enum ModeType {
export class ModeManager { export class ModeManager {
/** /**
* *
* 使 currentMode 访
*/ */
private static s_currentMode: ModeType = ModeType.Edit; private static s_currentMode: ModeType = ModeType.Edit;
/**
*
*/
public static highPower = true;
/** /**
* *
*/ */
public static isDebug = true; public static isDebug = true;
/**
*
*/
public static isEditor = true;
//#region 演示单单位 //#region 演示单单位

2
src/app/babylon/controller/scene-manager.ts

@ -133,7 +133,7 @@ export class SceneManager {
this.scene //定义摄像机所属的场景 this.scene //定义摄像机所属的场景
); );
camera.maxZ = 6000; //摄像机拍摄的最远距离 camera.maxZ = 6000; //摄像机拍摄的最远距离
camera.upperBetaLimit = 1.5; //beta方向上的旋转限制(防止看到模型底面) // camera.upperBetaLimit = 1.5; //beta方向上的旋转限制(防止看到模型底面)
camera.lowerRadiusLimit = 3; //相机距离拍摄目标的最小距离(防止穿插) camera.lowerRadiusLimit = 3; //相机距离拍摄目标的最小距离(防止穿插)
camera.setTarget(Vector3.Zero()); //设置拍摄目标 camera.setTarget(Vector3.Zero()); //设置拍摄目标
camera.attachControl(this.canvas, true); //把相机连接到画布 camera.attachControl(this.canvas, true); //把相机连接到画布

15
src/app/babylon/controller/serve-manager.ts

@ -1,7 +1,7 @@
import { HttpErrorResponse } from "@angular/common/http"; import { HttpErrorResponse } from "@angular/common/http";
import { classToPlain } from "class-transformer"; import { classToPlain } from "class-transformer";
import { BuildingBasicInfosService } from "src/app/service/babylon/building-basic-infos.service"; import { BuildingBasicInfosService } from "src/app/service/babylon/building-basic-infos.service";
import { ObjectsService } from "src/app/service/babylon/objects.service"; import { ObjectsService } from "src/app/service/objects.service";
import { InsitutionDataSimple } from "../model/data/institution/institution-data-simple"; import { InsitutionDataSimple } from "../model/data/institution/institution-data-simple";
import { AllMarkPlanData } from "../model/data/mark/mark-plan-data"; import { AllMarkPlanData } from "../model/data/mark/mark-plan-data";
import { ModeManager } from "./mode-manager"; import { ModeManager } from "./mode-manager";
@ -51,7 +51,7 @@ export class ServeManager {
) => void, onError?: (key: string, error: string) => void) { ) => void, onError?: (key: string, error: string) => void) {
let data = classToPlain(institutionData); let data = classToPlain(institutionData);
console.log(data); console.log("保存单位", data);
this.buildingBISrv.postBuildingBasicInfos(key, data) this.buildingBISrv.postBuildingBasicInfos(key, data)
.subscribe(data => { .subscribe(data => {
ModeManager.log("保存单位成功:" + key); ModeManager.log("保存单位成功:" + key);
@ -192,12 +192,12 @@ export class ServeManager {
async postFile(file: File) { async postFile(file: File) {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
ServeManager.instance.objectsSrv.postFile(ServeManager.ngAssetsPath + this.postFilePath, file).subscribe(data => { ServeManager.instance.objectsSrv.postFile(this.postFilePath, file).subscribe(data => {
let dataObj = data as any; let dataObj = data as any;
let fileName = dataObj.fileName; let fileName = dataObj.fileName;
let filePath: string = dataObj.objectName; let filePath: string = dataObj.objectName;//此路径不全,前面缺少ObjectsService.baseUrl,这部分不可序列化,要在运行时拼接
filePath = filePath.replace(fileName, ""); filePath = filePath.replace(fileName, "");//去掉结尾的文件名
filePath = ObjectsService.baseUrl + filePath; //filePath = ObjectsService.baseUrl + filePath;
ServeManager.instance.onGetPostFileResult(fileName, filePath, file); ServeManager.instance.onGetPostFileResult(fileName, filePath, file);
resolve('success') resolve('success')
}); });
@ -211,8 +211,6 @@ export class ServeManager {
* @param file * @param file
*/ */
onGetPostFileResult(fileName: string, filePath: string, file: File) { onGetPostFileResult(fileName: string, filePath: string, file: File) {
if (ServeManager.instance.onPostFileSuccess) { if (ServeManager.instance.onPostFileSuccess) {
ServeManager.instance.onPostFileSuccess(fileName, filePath, file); ServeManager.instance.onPostFileSuccess(fileName, filePath, file);
} }
@ -226,6 +224,7 @@ export class ServeManager {
postFileByMul(file: File) { postFileByMul(file: File) {
ServeManager.instance.objectsSrv.postFile_MultipartUpload(ServeManager.ngAssetsPath + this.postFilePath, file).then((value) => { ServeManager.instance.objectsSrv.postFile_MultipartUpload(ServeManager.ngAssetsPath + this.postFilePath, file).then((value) => {
let dataObj = value as any; let dataObj = value as any;
dataObj.filePath = dataObj.filePath.replace(dataObj.name, ""); //去掉结尾的文件名
ServeManager.instance.onGetPostFileResult(dataObj.fileName, dataObj.filePath, file); ServeManager.instance.onGetPostFileResult(dataObj.fileName, dataObj.filePath, file);
}); });

27
src/app/babylon/controller/status/login-status.ts

@ -38,6 +38,7 @@ export class LoginSatus extends StatusBase {
console.error("创建单位key为null"); console.error("创建单位key为null");
return; return;
} }
console.log("创建单位");
let insData = new InstitutionData(); let insData = new InstitutionData();
insData.normalData = new NormalData(key, name); insData.normalData = new NormalData(key, name);
@ -78,6 +79,7 @@ export class LoginSatus extends StatusBase {
console.log("新建数据列表"); console.log("新建数据列表");
} }
else { else {
console.log("单纯报错", error instanceof HttpErrorResponse, error.status === 404)
if (onFail) { if (onFail) {
onFail(error); onFail(error);
} }
@ -122,19 +124,23 @@ export class LoginSatus extends StatusBase {
console.log("进入 logins"); console.log("进入 logins");
BabylonTool.importMeshSync("", "assets/mesh/outdoor/ZhuTi/ZhuTi.gltf", undefined, undefined, undefined, (meshes) => { //测试
console.log("加载完成", meshes); // BabylonTool.importMeshSync("", "assets/mesh/outdoor/ZhuTi/ZhuTi.gltf", undefined, undefined, undefined, (meshes) => {
}); // console.log("加载完成", meshes);
// });
// let l_xy = 100;
// let result = [new Vector3(l_xy, l_xy), new Vector3(l_xy, -l_xy), new Vector3(-l_xy, -l_xy), new Vector3(-l_xy, l_xy)];
// let poly_tri = new PolygonMeshBuilder("polytri", result, SceneManager.Instance.scene);
// let mesh = poly_tri.build(true, 0);
// mesh.position.y = -10;
// console.log(poly_tri);
let l_xy = 100;
let result = [new Vector3(l_xy, l_xy), new Vector3(l_xy, -l_xy), new Vector3(-l_xy, -l_xy), new Vector3(-l_xy, l_xy)];
let poly_tri = new PolygonMeshBuilder("polytri", result, SceneManager.Instance.scene);
let mesh = poly_tri.build(true, 0);
mesh.position.y = -10;
console.log(poly_tri); UIManager.open<TopbarWindow>(TopbarWindow);
//UIManager.open<TopbarWindow>(TopbarWindow);
// this.openSelectWindow();//可以开启选择、新建单位 // this.openSelectWindow();//可以开启选择、新建单位
@ -217,6 +223,7 @@ export class LoginSatus extends StatusBase {
//保存新单位信息至服务器 //保存新单位信息至服务器
saveNewIns(status: LoginSatus, insData: InstitutionData, key: string, onSuccess?: (insDataSimple: InsitutionDataSimple) => void) { saveNewIns(status: LoginSatus, insData: InstitutionData, key: string, onSuccess?: (insDataSimple: InsitutionDataSimple) => void) {
console.log("准备保存新单位");
ServeManager.instance.saveInstitutionData(insData, key, (key, result) => { ServeManager.instance.saveInstitutionData(insData, key, (key, result) => {
console.log("在服务器新建单位" + key); console.log("在服务器新建单位" + key);
let insDataSimple = new InsitutionDataSimple(); let insDataSimple = new InsitutionDataSimple();

5
src/app/babylon/model/data/institution/institution-data.ts

@ -5,6 +5,11 @@ import { BuildingData_ChemicalPlant, BuildingData_Environment, BuildingData_Norm
//单位信息 //单位信息
export class InstitutionData { export class InstitutionData {
/**
*
*/
version: string = "1.0";
@Type(() => NormalData) @Type(() => NormalData)
normalData: NormalData = null;//常规信息 normalData: NormalData = null;//常规信息

6
src/app/babylon/tool/babylon-tool.ts

@ -31,6 +31,7 @@ import {
StackPanel, StackPanel,
TextBlock, TextBlock,
} from '@babylonjs/gui'; } from '@babylonjs/gui';
import { ObjectsService } from 'src/app/service/objects.service';
import { ConfigManager } from '../controller/config-manager'; import { ConfigManager } from '../controller/config-manager';
import { ModeManager } from '../controller/mode-manager'; import { ModeManager } from '../controller/mode-manager';
import { UIManager } from '../controller/ui-manager'; import { UIManager } from '../controller/ui-manager';
@ -124,9 +125,12 @@ export class BabylonTool {
if (path == null) { if (path == null) {
return null; return null;
} }
if (path.indexOf(ConfigManager.c_resPath_assetsRoot) == -1) { if (path.indexOf(ConfigManager.c_resPath_assetsRoot) == -1) { //本地资源
path = ConfigManager.c_resPath_assetsRoot + rootUrl; path = ConfigManager.c_resPath_assetsRoot + rootUrl;
} }
else {
path = ObjectsService.baseUrl + path; //根据环境,动态改变桶名
}
console.log("异步加载模型" + path + sceneFilename); console.log("异步加载模型" + path + sceneFilename);
let modelPath = path + sceneFilename; let modelPath = path + sceneFilename;

1
src/app/babylon/view/building-window/building-window.ts

@ -97,7 +97,6 @@ export class BuildingWindow extends UIBase {
let resPath_out = DataManager.getResPath_building( let resPath_out = DataManager.getResPath_building(
DataManager.institutionData.normalData.key.toLowerCase(), DataManager.institutionData.normalData.key.toLowerCase(),
normalData.key.toLocaleLowerCase(), normalData.key.toLocaleLowerCase(),
BuildingPosType.OutDoor,
buildingData.normalData.key buildingData.normalData.key
); );
// console.log("新资源路径" + resPath_out); // console.log("新资源路径" + resPath_out);

2
src/app/babylon/view/indoor-window/indoor-window.ts

@ -77,7 +77,7 @@ export class IndoorWindow extends UIBase {
let institutionKey = DataManager.institutionData.normalData.key; let institutionKey = DataManager.institutionData.normalData.key;
let indoorData = modelEditData; let indoorData = modelEditData;
let buildingKey = StatusManager.getStatus<IndoorStatus>(IndoorStatus).buildingInfo.buildingData.normalData.key; let buildingKey = StatusManager.getStatus<IndoorStatus>(IndoorStatus).buildingInfo.buildingData.normalData.key;
let path = DataManager.getResPath_building(institutionKey, buildingKey, BuildingPosType.Indoor, indoorData.modelData.key); let path = DataManager.getResPath_building(institutionKey, buildingKey, indoorData.modelData.key);
// console.log("模型路径" + path); // console.log("模型路径" + path);
let instance = this; let instance = this;

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

@ -5,8 +5,8 @@ import {
} from '@angular/common/http'; } from '@angular/common/http';
import { throwError } from 'rxjs' import { throwError } from 'rxjs'
import { catchError, retry } from 'rxjs/operators'; import { catchError, retry } from 'rxjs/operators';
import { Router,ActivatedRoute } from '@angular/router' import { Router, ActivatedRoute } from '@angular/router'
import {CacheTokenService} from '../service/cache-token.service' import { CacheTokenService } from '../service/cache-token.service'
import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar'; import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar';
import { CookieService } from 'ngx-cookie-service'; import { CookieService } from 'ngx-cookie-service';
@ -16,20 +16,20 @@ import { CookieService } from 'ngx-cookie-service';
@Injectable() @Injectable()
export class BaseInterceptor implements HttpInterceptor { export class BaseInterceptor implements HttpInterceptor {
constructor(private http:HttpClient,private router:Router,private route:ActivatedRoute,public token:CacheTokenService, constructor(private http: HttpClient, private router: Router, private route: ActivatedRoute, public token: CacheTokenService,
public snackBar: MatSnackBar,private cookieService: CookieService) {} public snackBar: MatSnackBar, private cookieService: CookieService) { }
intercept(req, next: HttpHandler) { intercept(req, next: HttpHandler) {
let newReq = req.clone({ let newReq = req.clone({
url: req.hadBaseurl ? `${req.url}` : `${req.url}`, url: req.hadBaseurl ? `${req.url}` : `${req.url}`,
}); });
if(!req.cancelToken) { if (!req.cancelToken) {
/*获取token*/ /*获取token*/
let token = this.cookieService.get("token") let token = this.cookieService.get("token")
/*此处设置额外请求头,token令牌*/ /*此处设置额外请求头,token令牌*/
newReq.headers = newReq.headers =
newReq.headers.set('Authorization', `Bearer ${token}`) newReq.headers.set('Authorization', `Bearer ${token}`)
} }
// 携带请求头发送下一次请求 // 携带请求头发送下一次请求
@ -45,12 +45,12 @@ export class BaseInterceptor implements HttpInterceptor {
private handleError(error: HttpErrorResponse) { private handleError(error: HttpErrorResponse) {
// 用户认证失败返回登录页 // 用户认证失败返回登录页
if (error.status === 401||error.status === 614) { if (error.status === 401 || error.status === 614) {
this.token.delete() this.token.delete()
sessionStorage.clear() sessionStorage.clear()
window.localStorage.clear() window.localStorage.clear()
this.cookieService.set("token",'',new Date(new Date().getTime() + 1),'/') this.cookieService.set("token", '', new Date(new Date().getTime() + 1), '/')
this.cookieService.set("refreshToken",'',new Date(new Date().getTime() + 1),'/') this.cookieService.set("refreshToken", '', new Date(new Date().getTime() + 1), '/')
this.snackBar.open('用户认证信息过期,请重新登录', '确定', { this.snackBar.open('用户认证信息过期,请重新登录', '确定', {
duration: 3000 duration: 3000
}); });
@ -65,7 +65,7 @@ export class BaseInterceptor implements HttpInterceptor {
const config = new MatSnackBarConfig(); const config = new MatSnackBarConfig();
config.verticalPosition = 'top'; config.verticalPosition = 'top';
config.duration = 3000 config.duration = 3000
this.snackBar.open('请核对您的输入格式是否正确','确定',config); this.snackBar.open('请核对您的输入格式是否正确', '确定', config);
} }
if (error.error instanceof ErrorEvent) { if (error.error instanceof ErrorEvent) {
@ -80,6 +80,6 @@ export class BaseInterceptor implements HttpInterceptor {
} }
// 返回带有面向用户的错误信息 // 返回带有面向用户的错误信息
return throwError( return throwError(
error.error); error);
}; };
} }

4
src/app/pages/pages.module.ts

@ -12,8 +12,6 @@ import { RouterModule } from '@angular/router';
import { LoginComponent } from './login/login.component'; import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component'; import { RegisterComponent } from './register/register.component';
import { HomeComponent } from './home/home.component'; import { HomeComponent } from './home/home.component';
import { NzFormModule } from 'ng-zorro-antd/form'; import { NzFormModule } from 'ng-zorro-antd/form';
import { NzInputModule } from 'ng-zorro-antd/input'; import { NzInputModule } from 'ng-zorro-antd/input';
import { UiModule } from '../ui/ui.module'; import { UiModule } from '../ui/ui.module';
@ -22,12 +20,12 @@ import { PlanComponent } from './plan/plan.component';
import { PagesRoutingModule } from './pages-routing.module'; import { PagesRoutingModule } from './pages-routing.module';
import { TodayWarningComponent } from './today-warning/today-warning.component'; import { TodayWarningComponent } from './today-warning/today-warning.component';
import { CriminalRecordsComponent } from './criminal-records/criminal-records.component'; import { CriminalRecordsComponent } from './criminal-records/criminal-records.component';
import { NzSelectModule } from 'ng-zorro-antd/select'; import { NzSelectModule } from 'ng-zorro-antd/select';
import { NzDatePickerModule } from 'ng-zorro-antd/date-picker'; import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzIconModule } from 'ng-zorro-antd/icon';
import { NzGridModule } from 'ng-zorro-antd/grid'; import { NzGridModule } from 'ng-zorro-antd/grid';
import { NzModalModule } from 'ng-zorro-antd/modal'; import { NzModalModule } from 'ng-zorro-antd/modal';
@NgModule({ @NgModule({
declarations: [LoginComponent, RegisterComponent, HomeComponent, PlanComponent, TodayWarningComponent, CriminalRecordsComponent,], declarations: [LoginComponent, RegisterComponent, HomeComponent, PlanComponent, TodayWarningComponent, CriminalRecordsComponent,],
imports: [ imports: [

34
src/app/pages/plan/plan.component.html

@ -1,3 +1,37 @@
<div class="content"> <div class="content">
<canvas id="center"></canvas> <canvas id="center"></canvas>
<!-- 左侧建筑 -->
<div class="showLeftBuilding" title="显示" *ngIf="!isShowLeftBuilding" (click)="toggleLeftBuilding(true)"><i nz-icon nzType="right" nzTheme="outline"></i></div>
<div class="leftBuilding" [ngClass]="{'isShowLeftBuilding': isShowLeftBuilding === false}">
<div class="hideLeft"><i nz-icon nzType="close" nzTheme="outline" title="隐藏" (click)="toggleLeftBuilding(false)"></i></div>
<div class="leftHeader">
<h1><label>模型列表</label></h1>
<button nz-button nzType="primary" (click)="isShowBuildingPop = true">新建</button>
</div>
<div class="leftCenter">
<div class="everyBuilding" *ngFor="let item of buildingUIItems" (click)='selectLeftBuilding(item)' [ngClass]="{'selectLeftBuilding': beforeOneBuildingID == item.getBuildingID()}">
<label style="flex: 1;" class="overflowText modelTitle">{{item.getBuildingName()}}</label>
<label style="width: 95px; overflow: hidden;">
<i nz-icon nzType="edit" nzTheme="outline" title="编辑" (click)="editModelBuilding($event,item)"></i>
<i nz-icon nzType="delete" nzTheme="outline" title="删除" (click)="deleteModelBuilding($event,item)"></i>
</label>
</div>
</div>
</div>
<!-- 左侧建筑 -->
<!-- 新增/编辑左侧建筑弹窗 -->
<nz-modal [(nzVisible)]="isShowBuildingPop" nzTitle="创建/编辑建筑" (nzOnCancel)="isShowBuildingPop = false" (nzOnOk)="addModelBuilding()">
<form nz-form>
<nz-form-item>
<nz-form-label [nzSpan]="5">名称</nz-form-label>
<nz-form-control [nzSpan]="12" nzErrorTip="请输入必填项">
<input nz-input ngModel name="name" required/>
</nz-form-control>
</nz-form-item>
</form>
</nz-modal>
<!-- 新增/编辑左侧建筑弹窗 -->
</div> </div>

67
src/app/pages/plan/plan.component.scss

@ -4,4 +4,71 @@
overflow: hidden; overflow: hidden;
position: relative; position: relative;
canvas{ width: 100%; height: 100%; border: none; outline: none; } canvas{ width: 100%; height: 100%; border: none; outline: none; }
}
//文本溢出
.overflowText{
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
//左侧建筑
.showLeftBuilding{
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
position: absolute;
left: 1px;
top: 50%;
margin-top: -15px;
color: #48A5FF;
background: rgba(0,17,33,0.7);
border-radius: 0px 50% 50% 0px;
}
.leftBuilding{
width: 230px;
height: 70%;
position: absolute;
left: 1px;
top: 0;
bottom: 0;
margin: auto;/*这行代码是关键*/
background: rgba(0,17,33,0.7);
border-radius: 0px 10px 10px 0px;
margin-left: 0;
transition: margin-left 0.5s;
display: flex;
flex-direction: column;
.hideLeft { text-align: right; color: #fff; padding: 3px 5px; z-index: 10; }
.leftHeader {
overflow: hidden;
text-align: center;
margin-top: -15px;
h1 { font-size: 18px; color: #fff; margin-bottom: 10px; }
button { width: 90%; }
}
.leftCenter{
flex: 1;
overflow-x: hidden;
overflow-y: auto;
.everyBuilding {
height: 30px;
line-height: 30px;
margin-top: 5px;
box-sizing: border-box;
padding-left: 5px;
color: #fff;
font-size: 16px;
display: flex;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
.modelTitle { font-size: 14px; }
label { display: block; }
}
.selectLeftBuilding { background-color: #2196f3; } //选中样式
}
}
.isShowLeftBuilding{ //隐藏 动态效果
margin-left: -300px;
transition: margin-left 0.5s;
} }

80
src/app/pages/plan/plan.component.ts

@ -1,28 +1,104 @@
import { Component, ElementRef, OnInit } from '@angular/core'; import { Component, ElementRef, OnInit } from '@angular/core';
import { Game } from 'src/app/babylon/game'; import { Game } from 'src/app/babylon/game';
import { LoginSatus } from 'src/app/babylon/controller/status/login-status';
import { StatusManager } from 'src/app/babylon/controller/status/status-manager';
import { InsitutionDataSimple } from 'src/app/babylon/model/data/institution/institution-data-simple';
import { ModeManager } from 'src/app/babylon/controller/mode-manager';
import { ServeManager } from 'src/app/babylon/controller/serve-manager';
import { BuildingBasicInfosService } from 'src/app/service/babylon/building-basic-infos.service';
import { ObjectsService } from 'src/app/service/objects.service';
@Component({ @Component({
selector: 'app-plan', selector: 'app-plan',
templateUrl: './plan.component.html', templateUrl: './plan.component.html',
styleUrls: ['./plan.component.scss'] styleUrls: ['./plan.component.scss','./publicPop.scss']
}) })
export class PlanComponent implements OnInit { export class PlanComponent implements OnInit {
constructor(private element: ElementRef,) { } constructor(private element: ElementRef, private buildingBISrv: BuildingBasicInfosService, private objectsSrv: ObjectsService) { }
static instance: PlanComponent; static instance: PlanComponent;
public game: Game = new Game(); public game: Game = new Game();
public beforeOneSatus; //当前 satus
public canvas: HTMLCanvasElement; //canvas 实例 public canvas: HTMLCanvasElement; //canvas 实例
ngOnInit(): void { ngOnInit(): void {
PlanComponent.instance = this; PlanComponent.instance = this;
ServeManager.Init(this.buildingBISrv, this.objectsSrv);
this.canvas = this.element.nativeElement.querySelector('#center') as HTMLCanvasElement; this.canvas = this.element.nativeElement.querySelector('#center') as HTMLCanvasElement;
this.game.init(this.canvas); this.game.init(this.canvas);
} }
ngAfterViewInit(): void {
let loginStatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
loginStatus.getInstitutionListFromServe((result: InsitutionDataSimple[], data: any) => {
if (ModeManager.institutionDemoKey == ModeManager.c_demoKey_null) { //无指定测试单位,则为正式启动,根据当前单位key寻找
let key = 'ceshi';
let find = data.find(item => { return item.key === key })
if (find) { //如果在data中找到了对应的单位key,则表示已经有三维数据,直接进入
console.log("找到已有单位" + key);
this.beforeOneSatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
this.beforeOneSatus.onSelectInsSuccess(find)
} else { //如果没有找到对应的单位key,则调用新建单位
let name = 'ceshi';
console.log("没找到单位,新建" + key);
loginStatus.createInsitution(key, name);
}
} else {
let find = data.find(item => { return item.key === ModeManager.institutionDemoKey })
if (find) {
sessionStorage.setItem('unitId', find.key)
this.beforeOneSatus = StatusManager.getStatus<LoginSatus>(LoginSatus);
this.beforeOneSatus.onSelectInsSuccess(find)
} else {
this.modelInit(data) //开发模式 选择单位 弹窗
}
}
});
}
ngOnDestroy(): void { //组件销毁前 销毁canvas ngOnDestroy(): void { //组件销毁前 销毁canvas
this.game.dispose(); this.game.dispose();
this.game = null; this.game = null;
} }
//开发模式 选择单位 弹窗
modelInit(InsList) {
console.log(InsList)
}
buildingUIItems: any[] = []; //左侧 建筑list
beforeOneBuildingID: string = null; //选中 左侧建筑ID
isShowBuildingPop: boolean = false; //显隐 新增/编辑左侧建筑弹窗
isShowLeftBuilding: boolean = true; //显隐 建筑
toggleLeftBuilding(e) { this.isShowLeftBuilding = e }; //显隐 建筑
//选择建筑
selectLeftBuilding(e) {
}
//创建建筑
addModelBuilding() {
console.log('add')
}
//编辑建筑
editModelBuilding(event, e) {
event.stopPropagation()
}
//删除建筑
deleteModelBuilding(event, e) {
event.stopPropagation()
let isTrue = confirm('您确定要删除吗')
if (isTrue) {
}
}
} }

30
src/app/pages/plan/publicPop.scss

@ -0,0 +1,30 @@
.keyMargin {
width: 100%;
margin-bottom: 10px;
text-align: center;
.mat-form-field { width: 100%; }
//上传CAD弹窗 inputfile
.uploadBackGround {
width: 125px;
padding: 0 25px;
height: 30px;
line-height: 30px;
position: relative;
cursor: pointer;
color: #0275e7;
font-size: 14px;
background: #fafafa;
border: 1px solid #0275e7;
border-radius: 5px;
overflow: hidden;
display: inline-block;
}
.uploadBackGround input {
position: absolute;
width: 100%;
right: 0;
top: 0;
opacity: 0;
cursor: pointer
}
}

4
src/app/service/babylon/building-basic-infos.service.ts

@ -8,12 +8,12 @@ import { catchError, retry } from 'rxjs/operators';
}) })
export class BuildingBasicInfosService { export class BuildingBasicInfosService {
//获取单位信息的api //获取单位信息的api
baseUrl = 'api/v2/BuildingBasicInfos'; baseUrl = 'api/Services/3D/BuildingBasicInfo';
/** /**
* ()api * ()api
*/ */
markUrl = "api/v2/Sandboxie"; markUrl = "api/Services/3D/Sandboxie";
constructor( constructor(

87
src/app/service/babylon/objects.service.ts

@ -1,87 +0,0 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ObjectsService {
static readonly c_apiRoot = "/api/";//普通上传的API根路径
static readonly c_apiRoot_Multipart = "/api/";//分块上传的API根路径
// static testPath = "f1/f2";//测试路径
constructor(private http: HttpClient) { }
//普通上传,单个文件上限5M
static baseUrl = ObjectsService.c_apiRoot + 'Objects/WebPlan/';
postFile(extensionPath: string, file: File): Observable<Object> {
let formData = new FormData()
//console.log(file.name + file.type);
formData.append("file", file, file.name)
let data = { keepOriginalName: 'true' }
return this.http.post(ObjectsService.baseUrl + extensionPath, formData, { params: data });
}
//分块上传
static baseUrl_MultipartUpload = ObjectsService.c_apiRoot_Multipart + 'NewMultipartUpload/WebPlan/';
// {
// "objectName": "string",
// "uploadId": "string"
// }
postFile_MultipartUpload(extensionPath: string, file: File): Promise<Object> {
// let formData = new FormData()
// formData.append("file", file, file.name)
// return this.http.post(ObjectsService.baseUrl + extensionPath, formData);
let data = { keepOriginalName: 'true', filename: file.name }
return new Promise((resolve, reject) => {
this.http.post(ObjectsService.baseUrl_MultipartUpload + extensionPath, {}, { params: data }).subscribe(async (data: any) => { //初始化分段上传
let objectName = data.objectName
let uploadId = data.uploadId
let PartNumberETag = []; //每次返回需要保存的信息
//分块 处理
let fileSize = file.size || null //上传文件的总大小
let shardSize = 5 * 1024 * 1024 //5MB一个分片
let allSlice = Math.ceil(fileSize / shardSize) //总文件/5MB===共分多少段
for (let i = 0; i < allSlice; i++) { //循环分段上传
let start = i * shardSize //切割文件开始位置
let end = Math.min(fileSize, start + shardSize); //切割文件结束位置
let formData = new FormData()
formData.append("file", file.slice(start, end))
//同步写法实现异步调用
let result = await new Promise((resolve, reject) => {
// await 需要后面返回一个 promise 对象
this.http.post(ObjectsService.c_apiRoot_Multipart + `MultipartUpload/WebPlan/${objectName}?uploadId=${uploadId}&partNumber=${i + 1}`, formData).subscribe((data: any) => {
let msg = { "partNumber": data.partNumber || null, "eTag": data.eTag || null }
resolve(msg) // 调用 promise 内置方法处理成功
})
});
PartNumberETag.push(result)
if (PartNumberETag.length === allSlice) { //分块上传完成
let data = PartNumberETag
let paramsData = { uploadId: uploadId };
let path = ObjectsService.c_apiRoot_Multipart + 'CompleteMultipartUpload/WebPlan/' + objectName;
this.http.post(path, data, { params: paramsData }).subscribe(data => {
let objData: any = new Object();
objData.fileName = file.name;
objData.filePath = (ObjectsService.baseUrl + objectName).replace(file.name, "");
resolve(objData)
})
}
}//for循环
//分块 处理
})
})
}
}

80
src/app/service/objects.service.ts

@ -2,22 +2,72 @@ import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
/**
*
*/
enum EnvironmentType {
/**
*
*/
DevelopEditor,
/**
*
*/
Test,
/**
*
*/
Production,
}
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class ObjectsService { export class ObjectsService {
static readonly c_apiRoot = "/api/";//普通上传的API根路径 static readonly c_apiRoot = "/api/Objects/";//普通上传的API根路径
static readonly c_apiRoot_Multipart = "/api/";//分块上传的API根路径 static apiRoot_Multipart = "/api/";//分块上传的API根路径
/**
*
*/
static currentEnvironmentType: EnvironmentType = EnvironmentType.DevelopEditor;
/**
* +
*/
static baseUrl;
/**
*
*/
obsRootByEnv = new Map<EnvironmentType, string>([
[EnvironmentType.DevelopEditor, "sinochemweb/"], //开发与编辑
[EnvironmentType.Test, "sinochem3d/"],//测试
[EnvironmentType.Production, "prod/"],//生产环境(根据需要设置)
]);
// static testPath = "f1/f2";//测试路径
constructor(private http: HttpClient) { } constructor(private http: HttpClient) {
let bucketName = this.getBucketName();
ObjectsService.baseUrl = ObjectsService.c_apiRoot + bucketName;
}
/**
*
*/
getBucketName() {
return this.obsRootByEnv.get(ObjectsService.currentEnvironmentType);
}
//普通上传,单个文件上限5M /**
static baseUrl = ObjectsService.c_apiRoot + 'Objects/PlanPlatform/'; * 5M
*/
postFile(extensionPath: string, file: File): Observable<Object> { postFile(extensionPath: string, file: File): Observable<Object> {
let formData = new FormData() let formData = new FormData()
formData.append("file", file, file.name) formData.append("file", file, file.name)
@ -29,18 +79,14 @@ export class ObjectsService {
//分块上传 //分块上传
static baseUrl_MultipartUpload = ObjectsService.c_apiRoot_Multipart + 'NewMultipartUpload/PlanPlatform/';
// {
// "objectName": "string",
// "uploadId": "string"
// }
postFile_MultipartUpload(extensionPath: string, file: File): Promise<Object> { postFile_MultipartUpload(extensionPath: string, file: File): Promise<Object> {
// let formData = new FormData() // let formData = new FormData()
// formData.append("file", file, file.name) // formData.append("file", file, file.name)
// return this.http.post(ObjectsService.baseUrl + extensionPath, formData); // return this.http.post(ObjectsService.baseUrl + extensionPath, formData);
let data = { keepOriginalName: 'true', filename: file.name } let data = { keepOriginalName: 'true', filename: file.name }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.http.post(ObjectsService.baseUrl_MultipartUpload + extensionPath, {}, { params: data }).subscribe(async (data: any) => { //初始化分段上传 this.http.post(ObjectsService.apiRoot_Multipart + "NewMultipartUpload/" + this.getBucketName() + extensionPath, {}, { params: data }).subscribe(async (data: any) => { //初始化分段上传
let instance = this;
let objectName = data.objectName let objectName = data.objectName
let uploadId = data.uploadId let uploadId = data.uploadId
let PartNumberETag = []; //每次返回需要保存的信息 let PartNumberETag = []; //每次返回需要保存的信息
@ -58,7 +104,7 @@ export class ObjectsService {
//同步写法实现异步调用 //同步写法实现异步调用
let result = await new Promise((resolve, reject) => { let result = await new Promise((resolve, reject) => {
// await 需要后面返回一个 promise 对象 // await 需要后面返回一个 promise 对象
this.http.post(ObjectsService.c_apiRoot_Multipart + `MultipartUpload/PlanPlatform/${objectName}?uploadId=${uploadId}&partNumber=${i + 1}`, formData).subscribe((data: any) => { this.http.post(ObjectsService.apiRoot_Multipart + `MultipartUpload/${instance.getBucketName()}${objectName}?uploadId=${uploadId}&partNumber=${i + 1}`, formData).subscribe((data: any) => {
let msg = { "partNumber": data.partNumber || null, "eTag": data.eTag || null } let msg = { "partNumber": data.partNumber || null, "eTag": data.eTag || null }
resolve(msg) // 调用 promise 内置方法处理成功 resolve(msg) // 调用 promise 内置方法处理成功
}) })
@ -68,11 +114,12 @@ export class ObjectsService {
if (PartNumberETag.length === allSlice) { //分块上传完成 if (PartNumberETag.length === allSlice) { //分块上传完成
let data = PartNumberETag let data = PartNumberETag
let paramsData = { uploadId: uploadId }; let paramsData = { uploadId: uploadId };
let path = ObjectsService.c_apiRoot_Multipart + 'CompleteMultipartUpload/PlanPlatform/' + objectName; let path = ObjectsService.apiRoot_Multipart + `CompleteMultipartUpload/${instance.getBucketName()}` + objectName;
this.http.post(path, data, { params: paramsData }).subscribe(data => { this.http.post(path, data, { params: paramsData }).subscribe(data => {
let objData: any = new Object(); let objData: any = new Object();
objData.fileName = file.name; objData.fileName = file.name;
objData.filePath = (ObjectsService.baseUrl + objectName).replace(file.name, ""); // objData.filePath = (ObjectsService.baseUrl + objectName).replace(file.name, "");//桶名要根据当前环境动态组装
objData.filePath = objectName;//此路径不全,前面缺少ObjectsService.baseUrl,这部分不可序列化,要在运行时拼接
resolve(objData) resolve(objData)
}) })
} }
@ -83,3 +130,6 @@ export class ObjectsService {
}) })
} }
} }

BIN
src/assets/skybox/default/default_ny.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 963 KiB

BIN
src/assets/skybox/default/default_py.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

Loading…
Cancel
Save