This commit is contained in:
2025-09-25 16:24:08 +08:00
99 changed files with 1684 additions and 283 deletions

View File

@ -12,7 +12,7 @@
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false", "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
"typecheck": "npm run typecheck:node && npm run typecheck:web", "typecheck": "npm run typecheck:node && npm run typecheck:web",
"start": "electron-vite preview", "start": "electron-vite preview",
"dev": "electron-vite dev", "dev": "chcp 65001 && electron-vite dev",
"build": "npm run typecheck && electron-vite build", "build": "npm run typecheck && electron-vite build",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir", "build:unpack": "npm run build && electron-builder --dir",
@ -37,6 +37,7 @@
"pinia": "^3.0.3", "pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.4.1", "pinia-plugin-persistedstate": "^4.4.1",
"scss": "^0.2.4", "scss": "^0.2.4",
"three": "^0.180.0",
"verror": "^1.10.1", "verror": "^1.10.1",
"vue-clipboard3": "^2.0.0", "vue-clipboard3": "^2.0.0",
"vue-i18n": "^9.14.5", "vue-i18n": "^9.14.5",

Binary file not shown.

View File

@ -12,11 +12,11 @@ let SERVER_PORTS = 55110;
* @param port * @param port
* @param cb * @param cb
*/ */
let server
function portIsOccupied(port, cb) { function portIsOccupied(port, cb) {
// 创建服务并监听该端口 // 创建服务并监听该端口
port = Number(port); port = Number(port);
let server = net.createServer().listen(port); server = net.createServer().listen(port);
server.on("listening", function() { server.on("listening", function() {
// 执行这块代码说明端口未被占用 // 执行这块代码说明端口未被占用
@ -61,14 +61,17 @@ function start() {
createApp(); createApp();
portIsOccupied(SERVER_PORTS, (port) => { portIsOccupied(SERVER_PORTS, (port) => {
// avilablePort挂载全局 // avilablePort挂载全局
// console.log(apps);
apps.listen(port); server = apps.listen(port);
availablePort = port; availablePort = port;
// console.log("global.sharedObject", global.avilablePort); // console.log("global.sharedObject", global.avilablePort);
global.sharedObject.availablePort = port; global.sharedObject.availablePort = port;
// ipcRenderer.invoke("set-global-variable", "avilablePort", avilablePort); // ipcRenderer.invoke("set-global-variable", "avilablePort", avilablePort);
}); });
} }
function getServer() {
return server
}
//获取项目根目录 //获取项目根目录
// function GetHomeDir() { // function GetHomeDir() {
// let HOME_DIR = process.cwd() // let HOME_DIR = process.cwd()
@ -85,4 +88,4 @@ ipcMain.handle('get-available-port', () => {
return availablePort; return availablePort;
}); });
export { apps, start }; export { apps, start, getServer };

View File

@ -7,7 +7,7 @@ import fs from 'fs'
import { exec } from 'child_process' import { exec } from 'child_process'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { GetHomeDir } from './config' import { GetHomeDir } from './config'
import { start } from "./app"; import { start, getServer } from "./app";
// 开发环境路径处理 - 确保添加正确的file协议 // 开发环境路径处理 - 确保添加正确的file协议
@ -57,9 +57,9 @@ if (prodSplashPath) {
// 最终的启动页URL // 最终的启动页URL
const splashURL = process.env.NODE_ENV === 'development' ? devSplashURL : prodSplashURL const splashURL = process.env.NODE_ENV === 'development' ? devSplashURL : prodSplashURL
let startBatPath = path.join(process.resourcesPath, 'app.asar.unpacked', 'resources', 'java', 'start.bat') let startBatPath = process.env.NODE_ENV === 'development' ? path.resolve(app.getAppPath(), 'resources', 'java', 'start.bat') : path.join(process.resourcesPath, 'app.asar.unpacked', 'resources', 'java', 'start.bat')
startBatPath = process.platform === 'win32' ? startBatPath.replace(/^(\w:)/, '/$1') : startBatPath startBatPath = process.platform === 'win32' ? startBatPath.replace(/^(\w:)/, '/$1') : startBatPath
let stopBatPath = path.join(process.resourcesPath, 'app.asar.unpacked', 'resources', 'java', 'stop.bat') let stopBatPath = process.env.NODE_ENV === 'development' ? path.resolve(app.getAppPath(), 'resources', 'java', 'stop.bat') : path.join(process.resourcesPath, 'app.asar.unpacked', 'resources', 'java', 'stop.bat')
stopBatPath = process.platform === 'win32' ? stopBatPath.replace(/^(\w:)/, '/$1') : stopBatPath stopBatPath = process.platform === 'win32' ? stopBatPath.replace(/^(\w:)/, '/$1') : stopBatPath
// const splashURL = // const splashURL =
@ -126,7 +126,7 @@ function createWindow(): void {
}, 1000) }, 1000)
}) })
ipcMain.on('quit-app', () => { ipcMain.on('quit-app', () => {
app.quit() windowAllClosed()
}) })
ipcMain.on('renderNode', () => { ipcMain.on('renderNode', () => {
// 获取所有窗口并转发消息 // 获取所有窗口并转发消息
@ -332,36 +332,89 @@ app.whenReady().then(() => {
// Quit when all windows are closed, except on macOS. There, it's common // Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits // for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q. // explicitly with Cmd + Q.
app.on('window-all-closed', () => { // app.on('window-all-closed', () => {
console.log('=================================================111111111', process.platform) // if (process.platform !== 'darwin') {
if (process.platform !== 'darwin') { // getServer().close(() => {
app.quit() // // 关闭后台服务
} // exec(stopBatPath.substring(1, 200), () => {
}) // app.quit()
// });
// })
// }
// })
// 退出时注销所有快捷键 // 退出时注销所有快捷键
app.on('will-quit', () => { app.on('will-quit', () => {
console.log('222222222222222222222')
// 关闭后台服务
exec(stopBatPath.substring(1, 200), (error, stdout, stderr) => {
dialog.showMessageBox({
type: 'info',
title: '信息1',
message: 'process.platform',
buttons: ['确定']
})
if (error) {
console.error(`执行错误: ${error.message}`);
return;
}
if (stderr) {
console.error(`错误输出: ${stderr}`);
return;
}
console.log(`批处理输出: ${stdout}`);
});
globalShortcut.unregisterAll() globalShortcut.unregisterAll()
}) })
// 用于跟踪是否正在执行退出流程
let isQuitting = false;
app.on('window-all-closed', () => {
windowAllClosed()
});
function windowAllClosed() {
// 防止重复触发退出流程
if (isQuitting) return;
isQuitting = true;
// macOS特殊处理保持应用活跃
if (process.platform === 'darwin') {
return;
}
console.log('所有窗口已关闭,执行清理脚本...');
getServer().close(() => {
// 执行批处理文件
const cleanupProcess = exec(stopBatPath.substring(1, 200), (error, stdout, stderr) => {
if (error) {
console.error(`清理脚本执行失败: ${error.message}`);
}
if (stderr) {
console.error(`清理脚本错误输出: ${stderr}`);
}
if (stdout) {
console.log(`清理脚本输出: ${stdout}`);
}
// 脚本执行完成后强制退出
forceQuit();
});
// 监听子进程退出事件(确保即使脚本出错也能退出)
cleanupProcess.on('exit', (code) => {
console.log(`清理脚本退出,代码: ${code}`);
if (isQuitting) {
forceQuit();
}
});
// 超时保护:防止脚本卡住导致应用无法退出
setTimeout(() => {
if (isQuitting) {
console.log('清理脚本执行超时,强制退出');
cleanupProcess.kill(); // 终止卡住的脚本
forceQuit();
}
}, 2000); // 2秒超时
})
}
// 强制退出应用的辅助函数
function forceQuit() {
// 终止所有剩余的子进程
if (process.platform === 'win32') {
// Windows系统特殊处理
exec('taskkill /F /T /PID ' + process.pid, (error) => {
if (error) console.error('强制终止失败:', error);
});
} else {
// 其他系统
process.exit(0);
}
}
console.log('=================================================') console.log('=================================================')
global.sharedObject = { global.sharedObject = {
hasService: false, hasService: false,

View File

@ -2495,7 +2495,7 @@
} }
.el-select-dropdown__item { .el-select-dropdown__item {
font-size: 14px; font-size: 12px;
padding: 0 20px; padding: 0 20px;
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 597 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 550 B

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 422 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 593 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 277 B

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

After

Width:  |  Height:  |  Size: 272 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

File diff suppressed because one or more lines are too long

View File

@ -753,15 +753,13 @@
} }
.YJ-custom-base-dialog>.content input[type=number] { .YJ-custom-base-dialog>.content input[type=number] {
/* padding: 0 16px 0 10px; /* padding: 0 16px 0 10px; */
font-weight: 700;
font-family: 'D-Din-Bold'; font-family: 'D-Din-Bold';
font-size: 18px; */ font-size: 18px;
font-size: 12px;
font-weight: 400; font-weight: 400;
letter-spacing: 0px; letter-spacing: 0px;
line-height: 24px; line-height: 24px;
color: rgba(204, 204, 204, 1); color: #ffffff;
text-align: left; text-align: left;
vertical-align: top; vertical-align: top;
} }
@ -2212,6 +2210,7 @@
.YJ-custom-base-dialog.cut-fill>.content>div .div-item:last-child .row .unit { .YJ-custom-base-dialog.cut-fill>.content>div .div-item:last-child .row .unit {
margin-left: 5px; margin-left: 5px;
} }
.YJ-custom-base-dialog.cut-fill>.content .firstTip { .YJ-custom-base-dialog.cut-fill>.content .firstTip {
position: absolute; position: absolute;
left: 340px; left: 340px;
@ -2276,6 +2275,7 @@
flex: 0 0 60px; flex: 0 0 60px;
justify-content: center; justify-content: center;
} }
.YJ-custom-base-dialog.submerge>.content .rangeWords { .YJ-custom-base-dialog.submerge>.content .rangeWords {
font-size: 14px; font-size: 14px;
font-weight: 500; font-weight: 500;
@ -2437,6 +2437,7 @@
.YJ-custom-base-dialog.circle-view-shed>.content { .YJ-custom-base-dialog.circle-view-shed>.content {
width: 290px; width: 290px;
} }
.YJ-custom-base-dialog.circle-view-shed>.content .firstTip { .YJ-custom-base-dialog.circle-view-shed>.content .firstTip {
font-size: 14px; font-size: 14px;
font-weight: 700; font-weight: 700;
@ -3198,6 +3199,7 @@
background-size: 100% 100%; background-size: 100% 100%;
padding: 5px 5px 0px 5px; padding: 5px 5px 0px 5px;
} }
.popup-textarea textarea { .popup-textarea textarea {
width: 158px; width: 158px;
height: 95px; height: 95px;
@ -3205,6 +3207,7 @@
border: unset !important; border: unset !important;
color: #fff; color: #fff;
} }
.popup-textarea textarea::-webkit-scrollbar { .popup-textarea textarea::-webkit-scrollbar {
width: 8px !important; width: 8px !important;
/* height: 8px!important; */ /* height: 8px!important; */
@ -3811,12 +3814,16 @@
border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5); border: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
border-right: none; border-right: none;
} }
.billboard-attribute-box .table .tr .th, .billboard-attribute-box .table .tr .td {
.billboard-attribute-box .table .tr .th,
.billboard-attribute-box .table .tr .td {
border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.5); border-right: 1px solid rgba(var(--color-sdk-base-rgb), 0.5);
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
.billboard-attribute-box .table .tr .th:last-child, .billboard-attribute-box .table .tr .td:last-child {
.billboard-attribute-box .table .tr .th:last-child,
.billboard-attribute-box .table .tr .td:last-child {
border-right: none; border-right: none;
} }
@ -3865,6 +3872,7 @@
background-color: #f0f9eb; background-color: #f0f9eb;
color: rgb(82, 196, 26); color: rgb(82, 196, 26);
} }
#YJ-custom-message.warning { #YJ-custom-message.warning {
background-color: #fdf6ec; background-color: #fdf6ec;
color: #e6a23c; color: #e6a23c;
@ -3889,8 +3897,8 @@
.yj-custom-icon { .yj-custom-icon {
display: inline-block; display: inline-block;
width: 22px; width: 40px;
height: 10px; height: 20px;
margin-right: 5px; margin-right: 5px;
} }
@ -3964,3 +3972,33 @@
background: url(../../img/arrow/6.png) 100% 100% no-repeat; background: url(../../img/arrow/6.png) 100% 100% no-repeat;
background-size: 100% 100%; background-size: 100% 100%;
} }
.yj-custom-icon.icon-wall {
background: url(../img/icon-wall.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-gradient {
background: url(../img/icon-wall-gradient.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-arrow {
background: url(../../img/material/arrow.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-warn {
background: url(../../img/material/warn.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-brick1 {
background: url(../../img/material/brick1.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-brick2 {
background: url(../../img/material/brick2.png) 100% 100% no-repeat;
background-size: 100% 100%;
}
.yj-custom-icon.icon-wall-brick3 {
background: url(../../img/material/brick3.png) 100% 100% no-repeat;
background-size: 100% 100%;
}

Binary file not shown.

View File

@ -68,20 +68,20 @@ export default {
}, },
effect: { effect: {
trajectoryMotion: "轨迹运动", trajectoryMotion: "轨迹运动",
electronicFence: "电子围墙", wallStereoscopic: "电子围墙",
// nightVision: '实体墙', entityWall: '实体墙',
radarLightWave: "扩散光波", diffuseScan: "扩散光波",
diffusedLightWave: "雷达光波", radarScan: "雷达光波",
scanStereoscopic: "立体雷达", scanStereoscopic: "立体雷达",
multilateralBody: "多边体", polyhedronObject: "多边体",
waterSurface: "水面", water: "水面",
fountain: '喷泉', fountain: '喷泉',
waterL: '水柱', waterL: '水柱',
fire: "火焰", fire: "火焰",
explosion: "爆炸", explosion: "爆炸",
smoke: "烟雾", smoke: "烟雾",
nightVision: '夜视', nightVision: '夜视',
// nightVision: '飞线', flyLine: '飞线',
}, },
analysis: { analysis: {
inundationAnalysis: "淹没分析", inundationAnalysis: "淹没分析",
@ -115,7 +115,7 @@ export default {
graffiti: "涂鸦", graffiti: "涂鸦",
// stopGraffiti: "结束涂鸦", // stopGraffiti: "结束涂鸦",
clearGraffiti: "清除涂鸦", clearGraffiti: "清除涂鸦",
path: "飞行漫游", roam: "飞行漫游",
coorLocation: "坐标定位", coorLocation: "坐标定位",
mouseLocation: "鼠标定位", mouseLocation: "鼠标定位",
annotationAggregation: "标注点聚合", annotationAggregation: "标注点聚合",

View File

@ -68,7 +68,7 @@ export default {
pressModel: 'press Model', pressModel: 'press Model',
terrainDig: 'terrainDig', terrainDig: 'terrainDig',
pictureLocation: 'pictureLocation', pictureLocation: 'pictureLocation',
path: 'path', roam: 'roam',
annotationAggregation: 'MarkPoint', annotationAggregation: 'MarkPoint',
mouseLocation: 'mouseLocation', mouseLocation: 'mouseLocation',
mouseOver: 'mouseOver', mouseOver: 'mouseOver',
@ -83,13 +83,13 @@ export default {
fire: 'fire', fire: 'fire',
smoke: 'smoke', smoke: 'smoke',
explosion: 'explosion', explosion: 'explosion',
waterSurface: 'waterSurface', water: 'waterSurface',
radarLightWave: 'radar', diffuseScan: 'radar',
diffusedLightWave: 'diffused', radarScan: 'diffused',
scanStereoscopic: 'scanStereoscopic', scanStereoscopic: 'scanStereoscopic',
electronicFence: 'elecFence', wallStereoscopic: 'elecFence',
entityWall: 'entityWall', entityWall: 'entityWall',
multilateralBody: 'multilateral', polyhedronObject: 'multilateral',
clearTrajectoryMotion: 'clearTrajectoryMotion', clearTrajectoryMotion: 'clearTrajectoryMotion',
cube: 'cube', cube: 'cube',
trajectoryMotion: 'trackMotion', trajectoryMotion: 'trackMotion',
@ -112,12 +112,12 @@ export default {
standText: 'StandText', standText: 'StandText',
// fire: "fire", // fire: "fire",
// waterSurface: "waterSurface", // water: "waterSurface",
// annotationAggregation: "annotationAggregation", // annotationAggregation: "annotationAggregation",
// radarLightWave: "radarLightWave", // diffuseScan: "radarLightWave",
// diffusedLightWave: "diffusedLightWave", // radarScan: "diffusedLightWave",
// electronicFence: "electronicFence", // wallStereoscopic: "electronicFence",
// multilateralBody: "multilateralBody", // polyhedronObject: "multilateralBody",
// cube: "cube", // cube: "cube",
// trajectoryMotion: "trajectoryMotion", // trajectoryMotion: "trajectoryMotion",
// roadDraw: "roadDraw", // roadDraw: "roadDraw",

View File

@ -61,7 +61,7 @@ export default {
terrainDig: '地形開挖', terrainDig: '地形開挖',
pictureLocation: '照片定位', pictureLocation: '照片定位',
importPanorama: '全景導入', importPanorama: '全景導入',
path: '飛行漫遊', roam: '飛行漫遊',
annotationAggregation: '標註點聚合', annotationAggregation: '標註點聚合',
mouseLocation: '鼠標定位', mouseLocation: '鼠標定位',
mouseOver: '結束定位', mouseOver: '結束定位',
@ -75,14 +75,14 @@ export default {
fire: '火焰', fire: '火焰',
smoke: '烟霧', smoke: '烟霧',
explosion: '爆炸', explosion: '爆炸',
waterSurface: '水面', water: '水面',
radarLightWave: '擴散光波', diffuseScan: '擴散光波',
diffusedLightWave: '雷達光波', radarScan: '雷達光波',
clearTrajectoryMotion: '清除軌跡', clearTrajectoryMotion: '清除軌跡',
scanStereoscopic: '立體雷達', scanStereoscopic: '立體雷達',
electronicFence: '電子圍墻', wallStereoscopic: '電子圍墻',
entityWall: '物體牆', entityWall: '物體牆',
multilateralBody: '多邊體', polyhedronObject: '多邊體',
cube: '立方體', cube: '立方體',
trajectoryMotion: '軌跡運動', trajectoryMotion: '軌跡運動',
roadDraw: '道路繪製', roadDraw: '道路繪製',

View File

@ -9,6 +9,9 @@ export const TreeApi = {
}, },
// 新增资源 /source/addModelSource // 新增资源 /source/addModelSource
addModelSource: async (data: any) => { addModelSource: async (data: any) => {
if (!data.treeIndex) {
data.treeIndex = getTreeIndex()
}
return await request.post({ return await request.post({
url: `/source/addModelSource`, url: `/source/addModelSource`,
data data
@ -16,6 +19,9 @@ export const TreeApi = {
}, },
// 新增其他资源 /source/addOtherSource // 新增其他资源 /source/addOtherSource
addOtherSource: async (data: any) => { addOtherSource: async (data: any) => {
if (!data.treeIndex) {
data.treeIndex = getTreeIndex()
}
return await request.post({ return await request.post({
url: `/source/addOtherSource`, url: `/source/addOtherSource`,
data data
@ -29,6 +35,9 @@ export const TreeApi = {
//新增目录 //新增目录
addDirectory: async (data: any) => { addDirectory: async (data: any) => {
if (!data.treeIndex) {
data.treeIndex = getTreeIndex()
}
return await request.post({ return await request.post({
url: `/source/addDirectory`, url: `/source/addDirectory`,
data data
@ -68,3 +77,44 @@ export const TreeApi = {
}) })
} }
} }
const getTreeIndex = () => {
let nodes = window.treeObj.getSelectedNodes();
// 获取最大tree_index的辅助函数
const getMaxTreeIndex = (items: any = []) => items.reduce((max, item) => Math.max(max, item.treeIndex || 0), 0);
if (nodes.length > 0) {
// 检查当前节点是否有子节点
let children = nodes[0].children;
if (children && children.length > 0) {
// 从子节点中获取最大tree_index
return getMaxTreeIndex(children) + 1;
} else {
// 获取父节点
let parentNode = nodes[0].getParentNode();
if (parentNode) {
// 从父节点的子节点中获取最大tree_index
return getMaxTreeIndex(parentNode.children) + 1;
} else {
// 没有父节点,获取根节点列表
let nodes = window.treeObj.getNodes();
if (nodes.length > 0) {
return getMaxTreeIndex(nodes) + 1;
} else {
return nodes.length + 1;
}
}
}
} else {
// 没有选中节点,获取根节点列表
// 获取根节点列表,处理可能为undefined的情况
const nodes = window.treeObj.getNodes() || [];
let max
if (nodes.length > 0) {
max = getMaxTreeIndex(nodes)
} else {
max = nodes.length
}
return max + 1;
}
}

View File

@ -72,7 +72,7 @@ module.exports = {
pressModel: "press Model", pressModel: "press Model",
terrainDig: "terrainDig", terrainDig: "terrainDig",
pictureLocation: "pictureLocation", pictureLocation: "pictureLocation",
path: "path", roam: "roam",
annotationAggregation: "MarkPoint", annotationAggregation: "MarkPoint",
mouseLocation: "mouseLocation", mouseLocation: "mouseLocation",
mouseOver: "mouseOver", mouseOver: "mouseOver",
@ -87,13 +87,13 @@ module.exports = {
fire: "fire", fire: "fire",
smoke: "smoke", smoke: "smoke",
explosion: "explosion", explosion: "explosion",
waterSurface: "waterSurface", water: "waterSurface",
radarLightWave: "radar", diffuseScan: "radar",
diffusedLightWave: "diffused", radarScan: "diffused",
scanStereoscopic: "scanStereoscopic", scanStereoscopic: "scanStereoscopic",
electronicFence: "elecFence", wallStereoscopic: "elecFence",
entityWall: "entityWall", entityWall: "entityWall",
multilateralBody: "multilateral", polyhedronObject: "multilateral",
clearTrajectoryMotion: "clearTrajectoryMotion", clearTrajectoryMotion: "clearTrajectoryMotion",
cube: "cube", cube: "cube",
trajectoryMotion: "trackMotion", trajectoryMotion: "trackMotion",
@ -116,12 +116,12 @@ module.exports = {
standText: "StandText", standText: "StandText",
// fire: "fire", // fire: "fire",
// waterSurface: "waterSurface", // water: "waterSurface",
// annotationAggregation: "annotationAggregation", // annotationAggregation: "annotationAggregation",
// radarLightWave: "radarLightWave", // diffuseScan: "radarLightWave",
// diffusedLightWave: "diffusedLightWave", // radarScan: "diffusedLightWave",
// electronicFence: "electronicFence", // wallStereoscopic: "electronicFence",
// multilateralBody: "multilateralBody", // polyhedronObject: "multilateralBody",
// cube: "cube", // cube: "cube",
// trajectoryMotion: "trajectoryMotion", // trajectoryMotion: "trajectoryMotion",
// roadDraw: "roadDraw", // roadDraw: "roadDraw",

View File

@ -65,7 +65,7 @@ module.exports = {
terrainDig: "地形開挖", terrainDig: "地形開挖",
pictureLocation: "照片定位", pictureLocation: "照片定位",
importPanorama: "全景導入", importPanorama: "全景導入",
path: "飛行漫遊", roam: "飛行漫遊",
annotationAggregation: "標註點聚合", annotationAggregation: "標註點聚合",
mouseLocation: "鼠標定位", mouseLocation: "鼠標定位",
mouseOver: "結束定位", mouseOver: "結束定位",
@ -79,14 +79,14 @@ module.exports = {
fire: "火焰", fire: "火焰",
smoke: "烟霧", smoke: "烟霧",
explosion: "爆炸", explosion: "爆炸",
waterSurface: "水面", water: "水面",
radarLightWave: "擴散光波", diffuseScan: "擴散光波",
diffusedLightWave: "雷達光波", radarScan: "雷達光波",
clearTrajectoryMotion: "清除軌跡", clearTrajectoryMotion: "清除軌跡",
scanStereoscopic: "立體雷達", scanStereoscopic: "立體雷達",
electronicFence: "電子圍墻", wallStereoscopic: "電子圍墻",
entityWall: "物體牆", entityWall: "物體牆",
multilateralBody: "多邊體", polyhedronObject: "多邊體",
cube: "立方體", cube: "立方體",
trajectoryMotion: "軌跡運動", trajectoryMotion: "軌跡運動",
roadDraw: "道路繪製", roadDraw: "道路繪製",

View File

@ -69,7 +69,7 @@ module.exports = {
terrainDig: '地形开挖', terrainDig: '地形开挖',
splitScreen: '卷帘对比', splitScreen: '卷帘对比',
path: '飞行漫游', roam: '飞行漫游',
annotationAggregation: '标注点聚合', annotationAggregation: '标注点聚合',
mouseLocation: '鼠标定位', mouseLocation: '鼠标定位',
mouseOver: '结束定位', mouseOver: '结束定位',
@ -83,13 +83,13 @@ module.exports = {
fire: '火焰', fire: '火焰',
smoke: '烟雾', smoke: '烟雾',
explosion: '爆炸', explosion: '爆炸',
waterSurface: '水面', water: '水面',
radarLightWave: '扩散光波', diffuseScan: '扩散光波',
diffusedLightWave: '雷达光波', radarScan: '雷达光波',
scanStereoscopic: '立体雷达', scanStereoscopic: '立体雷达',
electronicFence: '电子围墙', wallStereoscopic: '电子围墙',
entityWall: '实体墙', entityWall: '实体墙',
multilateralBody: '多边体', polyhedronObject: '多边体',
cube: '立方体', cube: '立方体',
trajectoryMotion: '轨迹运动', trajectoryMotion: '轨迹运动',
clearTrajectoryMotion: '清除轨迹', clearTrajectoryMotion: '清除轨迹',

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

View File

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

View File

@ -28,7 +28,7 @@
linear-gradient(to right, rgba(0, 255, 255, 0.3) 0%, rgba(0, 255, 255, 0) 100%), linear-gradient(to right, rgba(0, 255, 255, 0.3) 0%, rgba(0, 255, 255, 0) 100%),
rgba(0, 0, 0, 0.8); rgba(0, 0, 0, 0.8);
--bg-color1: rgba(0, 255, 255, 0.2); --bg-color1: rgba(0, 255, 255, 0.2);
font-size: calc(10px + 0.2vw); // font-size: calc(10px + 0.2vw);
} }
@media (max-width: 768px) { @media (max-width: 768px) {
:root { :root {
@ -272,6 +272,21 @@ img {
.YJ-custom-checkbox-right { .YJ-custom-checkbox-right {
top: 6.5vw !important; top: 6.5vw !important;
} }
.YJ-custom-base-dialog .el-select__wrapper{
background-color: rgba(0, 255, 255, 0.2);
font-size: 12px;
box-shadow: none;
font-size: 12px;
}
.YJ-custom-base-dialog .el-select__wrapper.is-focused,
.YJ-custom-base-dialog .el-select__wrapper.is-hovering:not(.is-focused) {
box-shadow: none;
}
.YJ-custom-base-dialog .el-select__wrapper .el-select__placeholder, .YJ-custom-base-dialog .el-select__wrapper.is-focused .el-select__placeholder{
color: #fff;
display: flex;
align-items: center;
}
.el-select__popper.el-popper{ .el-select__popper.el-popper{
background: transparent !important; background: transparent !important;
border: none !important; /* 去除边框 */ border: none !important; /* 去除边框 */
@ -297,7 +312,7 @@ img {
.el-select-dropdown__item { .el-select-dropdown__item {
color: #fff !important; /* 文字颜色 */ color: #fff !important; /* 文字颜色 */
font-size: 12px !important;
} }
/* 修改选中项的样式 */ /* 修改选中项的样式 */
.el-select-dropdown__item.is-selected { .el-select-dropdown__item.is-selected {
@ -319,6 +334,28 @@ img {
background: transparent !important; background: transparent !important;
border: none !important; border: none !important;
} }
/* 树 */
.ztree li span.button.ico_docu {
background:url(../images/tree/folder-empty.png) 0 0 no-repeat;
background-size: 100% 100% !important;
background-position: center !important;
}
.ztree li span.button.ico_close {
background:url(../images/tree/folder-close.png) 0 0 no-repeat;
background-size: 100% 100% !important;
background-position: center !important;
}
.ztree li span.button.ico_open {
background:url(../images/tree/folder-open.png) 0 0 no-repeat;
background-size: 100% 100% !important;
background-position: center !important;
}
.ztree li span.button.ico_docu:not([style=""]) {
background-size: 90% 90% !important;
background-position: center !important;
/* margin-top: 1px; */
}
/* 提示 */ /* 提示 */
/* .el-message--info { /* .el-message--info {
background: rgba(0, 0, 0, 0.5) !important; background: rgba(0, 0, 0, 0.5) !important;

View File

@ -93,6 +93,9 @@ export const initMapData = async (type, data, cd) => {
case 'wallStereoscopic': case 'wallStereoscopic':
entityObject = new YJ.Obj.WallStereoscopic(window.earth, data) entityObject = new YJ.Obj.WallStereoscopic(window.earth, data)
break break
case 'entityWall':
entityObject = new YJ.Obj.WallRealStereoscopic(window.earth, data)
break
case 'diffuseScan': case 'diffuseScan':
entityObject = new YJ.Obj.CircleDiffuse(window.earth, data) entityObject = new YJ.Obj.CircleDiffuse(window.earth, data)
break break
@ -103,7 +106,7 @@ export const initMapData = async (type, data, cd) => {
entityObject = new YJ.Obj.RadarScanStereoscopic(window.earth, data) entityObject = new YJ.Obj.RadarScanStereoscopic(window.earth, data)
break break
case 'textBox': case 'textBox':
entityObject = new YJ.Obj.TextBox(window.earth, data) entityObject = new YJ.Obj.TextBox(window.earth, data, ()=>{})
break break
case 'polyhedronObject': case 'polyhedronObject':
entityObject = new YJ.Obj.PolyhedronObject(window.earth, data) entityObject = new YJ.Obj.PolyhedronObject(window.earth, data)
@ -111,6 +114,24 @@ export const initMapData = async (type, data, cd) => {
case 'water': case 'water':
entityObject = new YJ.Obj.WaterSurface(window.earth, data) entityObject = new YJ.Obj.WaterSurface(window.earth, data)
break break
case 'fountain':
entityObject = new YJ.Obj.Fountain(window.earth, data)
break
case 'fire':
entityObject = new YJ.Obj.Flame(window.earth, data)
break
case 'smoke':
entityObject = new YJ.Obj.Smoke(window.earth, data)
break
case 'waterL':
entityObject = new YJ.Obj.Spout(window.earth, data)
break
case 'flyLine':
entityObject = new YJ.Obj.FlowLine(window.earth, data)
break
case 'explosion':
entityObject = new YJ.Obj.Explosion(window.earth, data)
break
default: default:
break break
} }
@ -122,11 +143,19 @@ export const initMapData = async (type, data, cd) => {
case 'textBox': case 'textBox':
delete options.name delete options.name
break break
case 'fountain':
case 'fire':
case 'smoke':
case 'waterL':
delete options.url
break
default: default:
break break
} }
console.log('--------------------onClick')
//鼠标左键点击事件 //鼠标左键点击事件
entityObject.onClick = () => { entityObject.onClick = () => {
// console.log('onClick')
leftClick(options); leftClick(options);
}; };
//鼠标右键点击事件 //鼠标右键点击事件

View File

@ -4,13 +4,6 @@
:class="className" :class="className"
ref="baseDialog" ref="baseDialog"
:id="id" :id="id"
:style="{
width: width,
height: height,
top: top,
left: left,
position: fix ? 'fixed' : 'absolute'
}"
v-if="dialogVisible" v-if="dialogVisible"
v-show="dialogVisible" v-show="dialogVisible"
> >
@ -128,11 +121,18 @@ const open = (data) => {
}) })
} }
dialogVisible.value = true dialogVisible.value = true
// nextTick(() => { nextTick(() => {
// setTimeout(() => { // setTimeout(() => {
// openPosition() // openPosition()
// }, 0) // }, 0)
// }) if(baseDialog.value) {
baseDialog.value.style.width = props.width
baseDialog.value.style.height = props.height
baseDialog.value.style.top = props.top
baseDialog.value.style.left = props.left
baseDialog.value.style.position = props.fix ? 'fixed' : 'absolute'
}
})
} }
const close = () => { const close = () => {

View File

@ -75,12 +75,13 @@ const add = throttle(async () => {
let addNode = await cusAddNodes(window.treeObj, getSelectedNode(window.treeObj), [node], true) //添加节点 let addNode = await cusAddNodes(window.treeObj, getSelectedNode(window.treeObj), [node], true) //添加节点
//获取该节点下的同级节点 //获取该节点下的同级节点
const someNode: any = getSameLevel(window.treeObj, addNode[0]) const someNode: any = getSameLevel(window.treeObj, addNode[0])
console.log('someNode', someNode)
const newNode = someNode.map((item: any) => { const newNode = someNode.map((item: any) => {
let index = item.getIndex() let index = item.getIndex()
item.tree_index = index item.treeIndex = index+1
return { return {
...item, ...item,
tree_index: item.getIndex() treeIndex: item.getIndex()
} }
}) })
ElMessage({ ElMessage({
@ -101,7 +102,7 @@ const updateTree = async (newNode: any) => {
const list = newNode.map((item: any) => { const list = newNode.map((item: any) => {
return { return {
id: item.id, id: item.id,
tree_index: item.tree_index, treeIndex: item.treeIndex,
parentId: item.parentId parentId: item.parentId
} }
}) })

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -201,6 +201,7 @@ const closeDialog = () => {
modelType.value = '' modelType.value = ''
dialogVisible.value = false dialogVisible.value = false
} }
//@ts-ignore
const addType = () => { const addType = () => {
if (!modelType.value) { if (!modelType.value) {
return ElMessage.warning('请输入模型类型名称') return ElMessage.warning('请输入模型类型名称')
@ -378,7 +379,7 @@ const allowDrag = (draggingNode: Node) => {
//拖拽结束 //拖拽结束
//---------------------查看缩略图-------------------- //---------------------查看缩略图--------------------
var showImageRow = null var showImageRow:any = null
const showImage = (row: any) => { const showImage = (row: any) => {
showImageRow = row showImageRow = row
eventBus.emit('imagePopDialog', row) eventBus.emit('imagePopDialog', row)
@ -656,6 +657,7 @@ const handleDelete = (row: ModelItem) => {
ModelApi.delModel(formData).then((res) => { ModelApi.delModel(formData).then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
ElMessage.success('删除成功') ElMessage.success('删除成功')
// @ts-ignore
getModelListByType(row.modelTypeId) getModelListByType(row.modelTypeId)
} }
}) })

View File

@ -66,18 +66,20 @@ const menuList: any = ref([
key: 'effect', key: 'effect',
children: [ children: [
'trajectoryMotion', 'trajectoryMotion',
'electronicFence', 'wallStereoscopic',
'entityWall',
// "nightVision", // "nightVision",
'radarLightWave', 'diffuseScan',
'diffusedLightWave', 'radarScan',
'scanStereoscopic', 'scanStereoscopic',
'multilateralBody', 'polyhedronObject',
'waterSurface', 'water',
'fountain', 'fountain',
'waterL', 'waterL',
'fire', 'fire',
'explosion', 'explosion',
'smoke', 'smoke',
'flyLine',
'nightVision' 'nightVision'
// "nightVision", // "nightVision",
] ]
@ -134,7 +136,7 @@ const menuList: any = ref([
'graffiti', 'graffiti',
// stopGraffiti: "结束涂鸦", // stopGraffiti: "结束涂鸦",
'clearGraffiti', 'clearGraffiti',
'path', 'roam',
'coorLocation', 'coorLocation',
'mouseLocation', 'mouseLocation',
'annotationAggregation', 'annotationAggregation',

View File

@ -3,7 +3,7 @@
<div class="leftSideSecondBox"> <div class="leftSideSecondBox">
<template v-if="obj"> <template v-if="obj">
<div class="menuItem" v-for="value in obj.children" @click="handleClick(value)"> <div class="menuItem" v-for="value in obj.children" @click="handleClick(value)">
<img :src="'src/assets/images/second/' + `${value}` + '.png'" style="color: rgb(255, 0, 0)" alt="" /> <img :src="'http://localhost:'+`${availablePort}`+ '/icon/' + `${value}` + '.png'" style="color: rgb(255, 0, 0)" alt="" />
<!-- <svg-icon :name="value" :size="20" color="rgba(0, 255, 255, 1)"></svg-icon> --> <!-- <svg-icon :name="value" :size="20" color="rgba(0, 255, 255, 1)"></svg-icon> -->
<span :style="{ color: !clickChange[value] ? 'var(--color-text)' : 'rgb(255,0,0)' }">{{ <span :style="{ color: !clickChange[value] ? 'var(--color-text)' : 'rgb(255,0,0)' }">{{
t(`${obj.key}.${value}`) t(`${obj.key}.${value}`)
@ -33,6 +33,10 @@ const { ipcRenderer } = require('electron')
const { t } = useI18n() const { t } = useI18n()
const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode() const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode()
const fs = require('fs') const fs = require('fs')
const availablePort = ref(55110);
ipcRenderer.invoke('get-available-port').then((port)=>{
availablePort.value = port
})
const obj: any = ref(null) const obj: any = ref(null)
const isclick = ref(false) const isclick = ref(false)
const eventBus: any = inject('bus') const eventBus: any = inject('bus')
@ -43,7 +47,8 @@ var clickChange = reactive({
mouseLocation: false, mouseLocation: false,
annotation: false, annotation: false,
annotationAggregation: false, annotationAggregation: false,
videoRecord: false videoRecord: false,
nightVision: false
}) })
var graffitiObjArr = reactive([]) var graffitiObjArr = reactive([])
eventBus.on('graffitiObj', (data: never) => { eventBus.on('graffitiObj', (data: never) => {
@ -87,7 +92,7 @@ window.addEventListener('keydown', handleKeyDown)
const methodMap = { const methodMap = {
// 轨迹运动 // 轨迹运动
trajectoryMotion: async () => { trajectoryMotion: async () => {
let availablePort = await ipcRenderer.invoke('get-available-port'); eventBus.emit('openModel', true, (url) => {
let draw = new YJ.Draw.DrawPolyline(window.earth) let draw = new YJ.Draw.DrawPolyline(window.earth)
draw.start(async (err, positions) => { draw.start(async (err, positions) => {
if (positions && positions.length > 1) { if (positions && positions.length > 1) {
@ -102,7 +107,7 @@ const methodMap = {
name: name, name: name,
model: { model: {
show: true, show: true,
url: `http://localhost:${availablePort}/tank.glb` url: url
}, },
line: { line: {
show: true, show: true,
@ -112,9 +117,10 @@ const methodMap = {
}) })
} }
}) })
}, 'trajectoryMotion')
}, },
// 电子围墙 // 电子围墙
electronicFence: () => { wallStereoscopic: () => {
let draw = new YJ.Draw.DrawPolyline(window.earth) let draw = new YJ.Draw.DrawPolyline(window.earth)
draw.start((err, positions) => { draw.start((err, positions) => {
if (positions.length > 1) { if (positions.length > 1) {
@ -133,8 +139,28 @@ const methodMap = {
} }
}) })
}, },
// 实体墙
entityWall: () => {
let draw = new YJ.Draw.DrawPolyline(window.earth)
draw.start((err, positions) => {
if (positions.length > 1) {
let id = 'aaa'
let name = '实体墙'
addMapSource({
type: 'entityWall',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
positions: positions
}
})
}
})
},
// 扩散光波 // 扩散光波
radarLightWave: () => { diffuseScan: () => {
let draw = new YJ.Draw.DrawCircle(window.earth) let draw = new YJ.Draw.DrawCircle(window.earth)
draw.start((err, options) => { draw.start((err, options) => {
console.log('options', options) console.log('options', options)
@ -162,7 +188,7 @@ const methodMap = {
}) })
}, },
// 雷达光波 // 雷达光波
diffusedLightWave: () => { radarScan: () => {
let draw = new YJ.Draw.DrawCircle(window.earth) let draw = new YJ.Draw.DrawCircle(window.earth)
draw.start((err, options) => { draw.start((err, options) => {
console.log('options', options) console.log('options', options)
@ -208,7 +234,7 @@ const methodMap = {
}) })
}, },
// 多面体 // 多面体
multilateralBody: () => { polyhedronObject: () => {
let draw = new YJ.Draw.DrawPolygon(window.earth) let draw = new YJ.Draw.DrawPolygon(window.earth)
draw.start((err, positions) => { draw.start((err, positions) => {
if (!positions || positions.length < 3) { if (!positions || positions.length < 3) {
@ -232,7 +258,8 @@ const methodMap = {
}) })
}) })
}, },
waterSurface: () => { // 水面
water: () => {
let draw = new YJ.Draw.DrawPolygon(window.earth) let draw = new YJ.Draw.DrawPolygon(window.earth)
draw.start((err, positions) => { draw.start((err, positions) => {
if (!positions || positions.length < 3) { if (!positions || positions.length < 3) {
@ -256,6 +283,156 @@ const methodMap = {
}) })
}) })
}, },
// 喷泉
fountain: () => {
let draw = new YJ.Draw.DrawPoint(window.earth)
draw.start(async (a, position) => {
if (!position) {
return
}
let id = new YJ.Tools().randomString()
let name = '喷泉'
await addMapSource({
type: 'fountain',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
lng: position.lng,
lat: position.lat,
alt: position.alt,
}
})
})
},
// 火焰
fire: () => {
let draw = new YJ.Draw.DrawPoint(window.earth)
draw.start(async (a, position) => {
if (!position) {
return
}
let id = new YJ.Tools().randomString()
let name = '火焰'
await addMapSource({
type: 'fire',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
lng: position.lng,
lat: position.lat,
alt: position.alt,
}
})
})
},
// 烟雾
smoke: () => {
let draw = new YJ.Draw.DrawPoint(window.earth)
draw.start(async (a, position) => {
if (!position) {
return
}
let id = new YJ.Tools().randomString()
let name = '烟雾'
await addMapSource({
type: 'smoke',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
lng: position.lng,
lat: position.lat,
alt: position.alt,
}
})
})
},
// 喷射水柱
waterL: () => {
let draw = new YJ.Draw.DrawPolyline(window.earth, { number: 2 })
draw.start(async (a, positions) => {
if (!positions || positions.length < 2) {
ElMessage({
message: '至少需要绘制两个坐标!',
type: 'warning'
})
return
}
let id = new YJ.Tools().randomString()
let name = '喷射水柱'
await addMapSource({
type: 'waterL',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
start: {
...positions[0]
},
end: {
...positions[1]
}
}
})
})
},
// 飞线
flyLine: () => {
let draw = new YJ.Draw.DrawPolygon(window.earth)
draw.start((err, positions) => {
if (!positions || positions.length < 3) {
ElMessage({
message: '至少需要绘制三个坐标!',
type: 'warning'
})
return
}
let id = new YJ.Tools().randomString()
let name = '飞线'
addMapSource({
type: 'flyLine',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
positions: positions
}
})
})
},
// 爆炸
explosion: () => {
let draw = new YJ.Draw.DrawPoint(window.earth)
draw.start(async (a, position) => {
if (!position) {
return
}
let id = new YJ.Tools().randomString()
let name = '爆炸'
await addMapSource({
type: 'explosion',
id: id,
sourceName: name,
opt: {
id: id,
name: name,
position: position
}
})
})
},
// 夜视
nightVision: () => {
clickChange.nightVision = !clickChange.nightVision
YJ.Global.efflect.nightVision(window.earth, clickChange.nightVision);
},
//投影面积 //投影面积
projectionArea: () => { projectionArea: () => {
new YJ.Measure.MeasureTyArea(window.earth).start() new YJ.Measure.MeasureTyArea(window.earth).start()
@ -363,8 +540,8 @@ const methodMap = {
item.remove() item.remove()
}) })
}, },
//路径 //漫游
path() { roam() {
eventBus.emit('flyRoamDialog') eventBus.emit('flyRoamDialog')
}, },
//坐标定位 //坐标定位

View File

@ -0,0 +1,132 @@
<template>
<Dialog ref="baseDialog" title="爆炸属性" left="180px" top="100px" className="explosion"
:closeCallback="closeCallback">
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" v-model="entityOptions.name">
</div>
<div class="col" style="flex: 0 0 120px">
<span class="label">随地图缩放</span>
<input class="btn-switch" type="checkbox" v-model="entityOptions.scaleByDistance" />
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" v-model="entityOptions.lng">
</div>
<div class="col">
<span class="label">爆炸范围</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="999999" v-model="entityOptions.size">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" v-model="entityOptions.lat">
</div>
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="-9999999" max="999999999" v-model="entityOptions.alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<div style="position: absolute; left: 24px; display: flex;">
<button style="margin-left: 10px;" @click="translate"><svg class="icon-py">
<use xlink:href="#yj-icon-py"></use>
</svg>平移</button>
</div>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { inject } from 'vue'
import { TreeApi } from '@/api/tree'
import Dialog from '@/components/dialog/baseDialog.vue'
import { useTreeNode } from '../tree/hooks/treeNode'
const { cusUpdateNode } = useTreeNode()
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
eventBus.on('openStandTextAdd', () => {
baseDialog.value?.open()
})
const entityOptions: any = ref({});
let originalOptions: any
let that: any
const closeCallback = () => {
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
entityOptions.value.reset()
eventBus.emit("destroyComponent")
}
const open = async (id: any) => {
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
baseDialog.value?.open()
}
const translate = () => {
if(that.positionEditing) {
that.closePositionEditing()
}
else {
that.openPositionEditing(()=>{
entityOptions.value.lng = entityOptions.value.lng
entityOptions.value.lat = entityOptions.value.lat
entityOptions.value.alt = entityOptions.value.alt
})
}
}
const confirm = () => {
originalOptions = structuredClone(that.options)
baseDialog.value?.close()
let params = structuredClone(that.options)
delete params.host
let params2 = {
"id": params.id,
"sourceName": params.name,
"params": params,
"isShow": params.show ? 1 : 0
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
}
const close = () => {
baseDialog.value?.close()
}
const remove = () => {
that.remove()
close()
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,156 @@
<template>
<Dialog ref="baseDialog" title="飞线属性" left="180px" top="100px" className="flow-line-surface"
:closeCallback="closeCallback">
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" v-model="entityOptions.name">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="color" ref="colorRef"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">飞线数量</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="1" max="99999" v-model="entityOptions.pointNumber">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">飞线宽度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="99999" min="1" step="1" v-model="entityOptions.width">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">飞线高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="999999" step="1" v-model="entityOptions.height">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">飞线高度差</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="99999" min="0" step="1" v-model="entityOptions.heightDifference">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">单次运动时长s</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="999999999" min="1" step="1" v-model="entityOptions.duration">
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">轨迹透明度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" max="1" min="0.01" step="0.01" v-model="entityOptions.lineBackAlpha">
<span class="arrow"></span>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { inject } from 'vue'
import { TreeApi } from '@/api/tree'
import Dialog from '@/components/dialog/baseDialog.vue'
import { useTreeNode } from '../tree/hooks/treeNode'
const { cusUpdateNode } = useTreeNode()
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const colorRef = ref(null)
eventBus.on('openStandTextAdd', () => {
baseDialog.value?.open()
})
const entityOptions: any = ref({});
let originalOptions: any
let that: any
const closeCallback = () => {
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
entityOptions.value.reset()
eventBus.emit("destroyComponent")
}
const open = async (id: any) => {
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
baseDialog.value?.open()
await nextTick()
new (window as any).YJColorPicker({
el: colorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.color,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: (color) => {
entityOptions.value.color = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.color = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
}
const confirm = () => {
originalOptions = structuredClone(that.options)
baseDialog.value?.close()
let params = structuredClone(that.options)
delete params.host
let params2 = {
"id": params.id,
"sourceName": params.name,
"params": params,
"isShow": params.show ? 1 : 0
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
}
const close = () => {
baseDialog.value?.close()
}
const remove = () => {
that.remove()
close()
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss"></style>

View File

@ -59,7 +59,7 @@ eventBus.on('imagePopDialog', (data) => {
}) })
}) })
//----------------模型预览--------------- //----------------模型预览---------------
const threeCanvas = ref(null) const threeCanvas:any = ref(null)
let scene, camera, renderer, model, controls let scene, camera, renderer, model, controls
const initThreeJS = () => { const initThreeJS = () => {

View File

@ -63,6 +63,7 @@ const confirm = () => {
originalOptions = structuredClone(that.options) originalOptions = structuredClone(that.options)
baseDialog.value?.close() baseDialog.value?.close()
let params = { let params = {
layerIndex: entityOptions.value.layerIndex,
alpha: entityOptions.value.alpha, alpha: entityOptions.value.alpha,
brightness: entityOptions.value.brightness, brightness: entityOptions.value.brightness,
name: entityOptions.value.name, name: entityOptions.value.name,

View File

@ -128,7 +128,7 @@ interface Category {
} }
// 模拟数据 // 模拟数据
const categories = ref<Category[]>([]) const categories = ref<any[]>([])
const activeTab = ref('0') const activeTab = ref('0')
const galleryRef = ref<HTMLElement>() const galleryRef = ref<HTMLElement>()
@ -241,6 +241,7 @@ const toggleExpand = (row: any) => {
currentTypeId.value = row.id currentTypeId.value = row.id
// loadModelsByType(row.id) // loadModelsByType(row.id)
} }
const addType = ref('')
const handleTypeClick = (row: TypeNode) => { const handleTypeClick = (row: TypeNode) => {
getModelListByType(row.id) getModelListByType(row.id)
@ -260,6 +261,13 @@ const modelClick = (index, row) => {
// return // return
// } // }
// 轨迹运动选择模型
if(selectCallback && typeof selectCallback === 'function' && addType.value === 'trajectoryMotion'){
selectCallback('http://127.0.0.1:8848' + row.data)
close()
return
}
if (!isSetting) { if (!isSetting) {
ElMessage.warning('请先设置模型默认参数') ElMessage.warning('请先设置模型默认参数')
return return
@ -321,7 +329,7 @@ const renderModel = async (data, model) => {
} }
let Model = await new YJ.Obj.Model(window.earth, option) let Model = await new YJ.Obj.Model(window.earth, option)
let DbOption = { let DbOption:any = {
params: option, params: option,
id, id,
sourceName: model.modelName + index, sourceName: model.modelName + index,
@ -397,7 +405,9 @@ onBeforeUnmount(() => {
}) })
//end //end
eventBus.on('openModel', (data) => { eventBus.on('openModel', (data, cb, type) => {
selectCallback = cb
addType.value = type
isShowPup.value = data isShowPup.value = data
if (data) { if (data) {
getModelList() getModelList()
@ -405,6 +415,8 @@ eventBus.on('openModel', (data) => {
} }
}) })
eventBus.on('closeModelSet', (data) => { eventBus.on('closeModelSet', (data) => {
addType.value = ''
selectCallback = null
isShowPup.value = data isShowPup.value = data
if (data) { if (data) {
getSetting() getSetting()
@ -412,7 +424,7 @@ eventBus.on('closeModelSet', (data) => {
}) })
//查看是否有设置模型设置 //查看是否有设置模型设置
var isSetting = null var isSetting:any = null
const getSetting = () => { const getSetting = () => {
ModelApi.getModelSetting().then((res) => { ModelApi.getModelSetting().then((res) => {
if (res.code == 0 || res.code == 200) { if (res.code == 0 || res.code == 200) {
@ -424,13 +436,18 @@ const open = () => {
isShowPup.value = true isShowPup.value = true
} }
const close = () => { const close = () => {
addType.value = ''
selectCallback = null
isShowPup.value = false isShowPup.value = false
} }
const setting = () => { const setting = () => {
isShowPup.value = false isShowPup.value = false
// @ts-ignore
eventBus.emit('openModelSetting', (true, isSetting)) eventBus.emit('openModelSetting', (true, isSetting))
} }
let selectCallback:any = null
defineExpose({ defineExpose({
open, open,
close close

View File

@ -491,10 +491,13 @@
</template> </template>
<template #footer> <template #footer>
<div style="position: absolute; left: 24px; display: flex"> <div style="position: absolute; left: 24px; display: flex">
<button @click="nodeEdit">
<svg class="icon-edit">
<use xlink:href="#yj-icon-edit"></use></svg>二次编辑
</button>
<button style="margin-left: 10px" v-if="!moveFlag" @click="translate"> <button style="margin-left: 10px" v-if="!moveFlag" @click="translate">
<svg class="icon-py"> <svg class="icon-py">
<use xlink:href="#yj-icon-py"></use></svg <use xlink:href="#yj-icon-py"></use></svg>平移
>平移
</button> </button>
<button style="margin-left: 10px" v-if="moveFlag" @click="translate"> <button style="margin-left: 10px" v-if="moveFlag" @click="translate">
<svg class="icon-py"> <svg class="icon-py">

View File

@ -0,0 +1,334 @@
<template>
<Dialog ref="baseDialog" :title="title + '属性'" left="180px" top="100px" className="particle-effects"
:closeCallback="closeCallback">
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.name" />
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">经度</span>
<input class="input" type="number" title="" min="-180" max="180" v-model="entityOptions.lng" />
</div>
<div class="col">
<span class="label">纬度</span>
<input class="input" type="number" title="" min="-90" max="90" v-model="entityOptions.lat" />
</div>
</div>
<div class="row">
<div class="col">
<span class="label">高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" v-model="entityOptions.alt">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<div class="row">
<div class="col">
<span class="label">起始颜色</span>
<div class="start_color" ref="startColorRef"></div>
</div>
<div class="col" style="margin: 0;justify-content: flex-end;">
<span class="label">结束颜色</span>
<div class="end_color" ref="endColorRef"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item" v-if="title !== '喷射水柱'">
<div class="row">
<div class="col">
<div class="row">
<span>最小初速度</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.minimumSpeed">
</div>
</div>
<div class="col">
<div class="row">
<span>最大初速度</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.maximumSpeed">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" v-model="entityOptions.minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" v-model="entityOptions.maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" v-model="entityOptions.startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" v-model="entityOptions.endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>发射速率/</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.emissionRate">
</div>
</div>
<div class="col">
<div class="row">
<span>尺寸像素</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.particleSize">
</div>
</div>
</div>
</div>
<div class="div-item" v-else>
<div class="row">
<div class="col">
<div class="row">
<span>速度</span>
<input type="range" max="30" min="0" step="0.1" v-model="entityOptions.speed">
</div>
</div>
<div class="col">
<div class="row">
<span>发射速率/</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.emissionRate">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>最小存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" v-model="entityOptions.minimumParticleLife">
</div>
</div>
<div class="col">
<div class="row">
<span>最大存在时间</span>
<input type="range" max="100" min="0.01" step="0.1" v-model="entityOptions.maximumParticleLife">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>起始比例</span>
<input type="range" max="10" min="0" step="0.1" v-model="entityOptions.startScale">
</div>
</div>
<div class="col">
<div class="row">
<span>结束比例</span>
<input type="range" max="10" min="0" step="0.1" v-model="entityOptions.endScale">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>朝向</span>
<input type="range" max="360" min="0.1" step="0.1" v-model="entityOptions.heading">
</div>
</div>
<div class="col">
<div class="row">
<span>俯仰角度</span>
<input type="range" max="360" min="0.1" step="0.1" v-model="entityOptions.pitch">
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="row">
<span>尺寸像素</span>
<input type="range" max="100" min="0" step="1" v-model="entityOptions.particleSize">
</div>
</div>
<div class="col">
</div>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<div style="position: absolute; left: 24px; display: flex;">
<button @click="translate"><svg class="icon-py">
<use xlink:href="#yj-icon-py"></use>
</svg>平移</button>
</div>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { inject } from "vue";
import { TreeApi } from '@/api/tree'
import { ElMessage, ElMessageBox } from 'element-plus'
import Dialog from '@/components/dialog/baseDialog.vue'
import { useTreeNode } from '@/views/components/tree/hooks/treeNode'
const { cusUpdateNode, getSelectedNodes, cusRemoveNode } = useTreeNode()
const title: any = ref('喷泉')
const baseDialog: any = ref(null);
const eventBus: any = inject("bus");
eventBus.on("openStandTextAdd", () => {
baseDialog.value?.open()
});
const entityOptions: any = ref({});
let originalOptions: any
let that: any
const startColorRef = ref(null)
const endColorRef = ref(null)
const open = async (id: any, type: string) => {
if (type) {
if (type === 'fountain') {
title.value = '喷泉'
}
else if (type === 'smoke') {
title.value = '烟雾'
}
else if (type === 'flame') {
title.value = '火焰'
}
else if (type === 'waterL') {
title.value = '喷射水柱'
}
}
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
baseDialog.value?.open()
await nextTick()
new window.YJColorPicker({
el: startColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.startColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: color => {
entityOptions.value.startColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.startColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
new window.YJColorPicker({
el: endColorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.endColor,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: color => {
entityOptions.value.endColor = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.endColor = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
}
const translate = () => {
if (that.positionEditing) {
that.closePositionEditing()
}
else {
that.openPositionEditing(() => {
entityOptions.value.options.lng = structuredClone(that.options.lng)
entityOptions.value.options.lat = structuredClone(that.options.lat)
entityOptions.value.options.alt = structuredClone(that.options.alt)
})
}
}
const confirm = () => {
originalOptions = structuredClone(that.options)
baseDialog.value?.close()
let params = structuredClone(that.options)
// 删除不必要的属性
delete params.host
let params2 = {
"id": params.id,
"sourceName": params.name,
"params": params,
"isShow": params.show ? 1 : 0,
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
}
const close = () => {
baseDialog.value?.close()
}
const remove = () => {
close()
ElMessageBox.confirm('此操作将永久删除节点及所有子节点, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
let selectNodes = getSelectedNodes(window.treeObj)
let source_ids = cusRemoveNode(window.treeObj, selectNodes)
const res = await TreeApi.removeDirectory({ ids: source_ids })
if (res.code == 0 || res.code == 200) {
ElMessage({
message: '删除成功',
type: 'success'
})
that.remove()
} else {
ElMessage({
message: res.msg || '删除失败',
type: 'error'
})
}
})
.catch(() => {
// 用户点击取消,不执行任何操作
})
}
const closeCallback = () => {
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
that.reset()
eventBus?.emit("destroyComponent")
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss"></style>

View File

@ -134,7 +134,8 @@
<div class="col" style="margin: 0px;"> <div class="col" style="margin: 0px;">
<span class="label">模型动画</span> <span class="label">模型动画</span>
<div class="input input-select model-animate-select"></div> <div class="input input-select model-animate-select"></div>
<el-select class="model-animate-select" v-model="entityOptions.modelAnimate" v-if="entityOptions.model && entityOptions.model.loader && entityOptions.model.loader.components && entityOptions.model.loader.components.animations"> <el-select class="model-animate-select" v-model="entityOptions.modelAnimate"
v-if="entityOptions.model && entityOptions.model.loader && entityOptions.model.loader.components && entityOptions.model.loader.components.animations">
<el-option label="无"></el-option> <el-option label="无"></el-option>
<el-option v-for="item in entityOptions.model.loader.components.animations" :label="item.name" <el-option v-for="item in entityOptions.model.loader.components.animations" :label="item.name"
:value="item.name"></el-option> :value="item.name"></el-option>
@ -310,7 +311,11 @@ const remove = () => {
// 用户点击取消,不执行任何操作 // 用户点击取消,不执行任何操作
}) })
} }
const clickChangeModel = () => { } const clickChangeModel = () => {
eventBus.emit('openModel', true, (url) => {
that.changeModelUrl(url)
}, 'trajectoryMotion')
}
const modelRotate = () => { const modelRotate = () => {
that.modelRotate() that.modelRotate()
} }

View File

@ -0,0 +1,238 @@
<template>
<Dialog ref="baseDialog" title="实体墙属性" left="180px" top="100px" className="wall-stereoscopic"
:closeCallback="closeCallback">
<template #content>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">名称</span>
<input class="input" maxlength="40" type="text" v-model="entityOptions.name">
</div>
<div class="col">
<span class="label">颜色</span>
<div class="color" ref="colorRef"></div>
</div>
</div>
</div>
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col">
<span class="label">宽度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" data-min="0.01" min="0.01" max="999999"
v-model="entityOptions.width">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
<div class="col">
<span class="label">拉伸高度</span>
<div class="input-number input-number-unit-1">
<input class="input" type="number" title="" min="0" max="999999999"
v-model="entityOptions.extrudedHeight">
<span class="unit">m</span>
<span class="arrow"></span>
</div>
</div>
</div>
<div class="row">
<div class="col material-box">
<span class="label">拐角类型</span>
<el-select class="input input-select input-select-line-type"
v-model="entityOptions.material">
<el-option v-for="item in material" :key="item.key" :label="item.name" :value="item.key">
<i class="yj-custom-icon" :class="item.icon"></i>
{{ item.name }}
</el-option>
</el-select>
</div>
<div class="col material-box">
<span class="label">墙体样式</span>
<el-select class="input input-select input-select-line-type"
v-model="entityOptions.material">
<template #label="{ label, value }">
<i class="yj-custom-icon" :class="material[value].icon"></i>
{{ label }}
</template>
<el-option v-for="item in material" :key="item.key" :label="item.name" :value="item.key">
<div style="display: flex; align-items: center;">
<i class="yj-custom-icon" :class="item.icon"></i>
{{ item.name }}
</div>
</el-option>
</el-select>
</div>
</div>
<div class="row">
<div class="col">
<span class="label">墙体闭合</span>
<input class="btn-switch" type="checkbox" v-model="entityOptions.noseToTail">
</div>
<div class="col">
</div>
</div>
</div>
<div class="div-item">
<div class="row">
<el-tabs v-model="activeName">
<el-tab-pane label="属性信息" name="1">
<attribute :entityOptions="entityOptions"></attribute>
</el-tab-pane>
<el-tab-pane label="标签风格" name="2">
<labelStyle :entityOptions="entityOptions"></labelStyle>
</el-tab-pane>
</el-tabs>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<div style="position: absolute; left: 24px; display: flex;">
<button @click="nodeEdit">
<svg class="icon-edit">
<use xlink:href="#yj-icon-edit"></use>
</svg>二次编辑
</button>
</div>
<button @click="remove">删除</button>
<button @click="confirm">确定</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { inject } from "vue";
import { TreeApi } from '@/api/tree'
import { ElMessage, ElMessageBox } from 'element-plus'
import Dialog from '@/components/dialog/baseDialog.vue'
import attribute from './attribute.vue'
import labelStyle from './labelStyle.vue'
import { useTreeNode } from '@/views/components/tree/hooks/treeNode'
const { cusUpdateNode, getSelectedNodes, cusRemoveNode } = useTreeNode()
const baseDialog: any = ref(null);
const eventBus: any = inject("bus");
const material = ref([
{
name: '纯色墙',
value: '纯色墙',
key: 0,
icon: 'icon-wall'
},
{
name: '红砖墙',
value: '红砖墙',
key: 1,
icon: 'icon-wall-brick1'
},
{
name: '黄砖墙',
value: '黄砖墙',
key: 2,
icon: 'icon-wall-brick2'
},
{
name: '灰瓷墙',
value: '灰瓷墙',
key: 3,
icon: 'icon-wall-brick3'
}
])
eventBus.on("openStandTextAdd", () => {
baseDialog.value?.open()
});
const activeName = ref('1')
const entityOptions: any = ref({});
let originalOptions: any
let that: any
const colorRef = ref(null)
const open = async (id: any) => {
that = window.earth.entityMap.get('aaa')
originalOptions = structuredClone(that.options)
entityOptions.value = that
baseDialog.value?.open()
await nextTick()
let colorPicker = new window.YJColorPicker({
el: colorRef.value,
size: 'mini', //颜色box类型
alpha: true, //是否开启透明度
defaultColor: entityOptions.value.color,
disabled: false, //是否禁止打开颜色选择器
openPickerAni: 'opacity', //打开颜色选择器动画
sure: color => {
entityOptions.value.color = color
}, //点击确认按钮事件回调
clear: () => {
entityOptions.value.color = 'rgba(255,255,255,1)'
} //点击清空按钮事件回调
})
}
const confirm = () => {
originalOptions = structuredClone(that.options)
baseDialog.value?.close()
let params = structuredClone(that.options)
// 删除不必要的属性
delete params.host
console.log('params', params)
let params2 = {
"id": params.id,
"sourceName": params.name,
"params": params,
"isShow": params.show ? 1 : 0,
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
}
const close = () => {
baseDialog.value?.close()
}
const remove = () => {
close()
ElMessageBox.confirm('此操作将永久删除节点及所有子节点, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
let selectNodes = getSelectedNodes(window.treeObj)
let source_ids = cusRemoveNode(window.treeObj, selectNodes)
const res = await TreeApi.removeDirectory({ ids: source_ids })
if (res.code == 0 || res.code == 200) {
ElMessage({
message: '删除成功',
type: 'success'
})
entityOptions.value.remove()
} else {
ElMessage({
message: res.msg || '删除失败',
type: 'error'
})
}
})
.catch(() => {
// 用户点击取消,不执行任何操作
})
}
const nodeEdit = () => {
that.nodeEdit()
}
const closeCallback = () => {
entityOptions.value.originalOptions = structuredClone(originalOptions)
that.positionEditing = false
that.reset()
eventBus?.emit("destroyComponent")
}
defineExpose({
open,
close
})
</script>
<style scoped lang="scss"></style>

View File

@ -29,11 +29,16 @@
</div> </div>
<div class="col material-box"> <div class="col material-box">
<span class="label">材质样式</span> <span class="label">材质样式</span>
<el-select class="input input-select input-select-line-type" style="margin-left: 20px" <el-select class="input input-select input-select-line-type" v-model="entityOptions.material">
v-model="entityOptions.material"> <template #label="{ label, value }">
<i class="yj-custom-icon" :class="material[value].icon"></i>
{{ label }}
</template>
<el-option v-for="item in material" :key="item.key" :label="item.name" :value="item.key"> <el-option v-for="item in material" :key="item.key" :label="item.name" :value="item.key">
<div style="display: flex; align-items: center;">
<i class="yj-custom-icon" :class="item.icon"></i> <i class="yj-custom-icon" :class="item.icon"></i>
{{ item.name }} {{ item.name }}
</div>
</el-option> </el-option>
</el-select> </el-select>
</div> </div>

View File

@ -22,7 +22,7 @@
<span class="label">高度</span> <span class="label">高度</span>
<div class="input-number input-number-unit-1"> <div class="input-number input-number-unit-1">
<input class="input" type="number" title="" v-model="entityOptions.height"> <input class="input" type="number" title="" v-model="entityOptions.height">
<span class="unit">px</span> <span class="unit">m</span>
<span class="arrow"></span> <span class="arrow"></span>
</div> </div>
</div> </div>

View File

@ -66,6 +66,7 @@ export const useRightOperate = () => {
if (extension === 'mbtiles') { if (extension === 'mbtiles') {
params2.alpha = 1 params2.alpha = 1
params2.brightness = 1 params2.brightness = 1
params2.layerIndex = 99999
} }
if (extension === 'apk') { if (extension === 'apk') {
// params2.exaggeration = 1 // params2.exaggeration = 1
@ -312,13 +313,21 @@ export const useRightOperate = () => {
} }
} }
//提升图层 //提升图层
const layerRaise = () => { } const layerRaise = () => {
layerIndex("layerRaise");
}
//降低图层 //降低图层
const layerLower = () => { } const layerLower = () => {
layerIndex("layerLower");
}
//置顶图层 //置顶图层
const layerToTop = () => { } const layerToTop = () => {
layerIndex("layerToTop");
}
//置底图层 //置底图层
const layerToBottom = () => { } const layerToBottom = () => {
layerIndex("layerToBottom");
}
//切片 //切片
const tilesetClipping = () => { } const tilesetClipping = () => { }
const rightMenus: any = reactive({ const rightMenus: any = reactive({
@ -412,6 +421,56 @@ export const useRightOperate = () => {
} }
}) })
const layerIndex = (key) => {
let selectNodes = getSelectedNodes(window.treeObj);
if (selectNodes && selectNodes[selectNodes.length - 1]) {
let node = selectNodes[selectNodes.length - 1]
let layer = window.earth.entityMap.get(node.id);
layer[key]();
_updateLayerIndex();
}
}
const _updateLayerIndex = () => {
let nodes = window.treeObj.transformToArray(
window.treeObj.getNodes()
);
let layers:any = [];
let arr = [
"ArcgisWXImagery",
"ArcgisBLUEImagery",
"ArcgisLWImagery",
"GDLWImagery",
"GDWXImagery",
"GDSLImagery",
"layer",
];
nodes.forEach((item) => {
if (arr.includes(item.sourceType) && item.isShow) {
let entityOptions = window.earth.entityMap.get(item.id)
let layerIndex = entityOptions.layerIndex;
layers.push({ id: item.id, layerIndex });
let params = {
layerIndex: entityOptions.layerIndex,
alpha: entityOptions.alpha,
brightness: entityOptions.brightness,
name: entityOptions.name,
show: entityOptions.show,
id: item.id,
}
let params2 = {
"id": params.id,
"sourceName": params.name,
"params": params,
"isShow": params.show ? 1 : 0
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
}
});
console.log('layers', layers)
}
// 图片文件上传后续 // 图片文件上传后续
async function handleFileImgInput(files: any, parentId: string, type: string) { async function handleFileImgInput(files: any, parentId: string, type: string) {
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')

View File

@ -97,16 +97,16 @@ export const useTree = () => {
const someNode: any = getSameLevel(window.treeObj, treeNodes[0]) const someNode: any = getSameLevel(window.treeObj, treeNodes[0])
const newNode = someNode.map((item: any) => { const newNode = someNode.map((item: any) => {
let index = item.getIndex() let index = item.getIndex()
item.tree_index = index item.treeIndex = index
return { return {
...item, ...item,
tree_index: item.getIndex() treeIndex: item.getIndex()+1
} }
}) })
const list = newNode.map((item: any) => { const list = newNode.map((item: any) => {
return { return {
id: item.id, id: item.id,
tree_index: item.tree_index, treeIndex: item.treeIndex,
parentId: item.parentId parentId: item.parentId
} }
}) })
@ -500,6 +500,8 @@ export const useTree = () => {
(window as any).pressModelMap.set(res.data[i].id + "_" + obj.modelId, res.data[i]); (window as any).pressModelMap.set(res.data[i].id + "_" + obj.modelId, res.data[i]);
} }
res.data[i].icon = await cusNodeIcon(res.data[i]); res.data[i].icon = await cusNodeIcon(res.data[i]);
res.data[i].class = 'xxxx'
res.data[i].className = 'xxxx'
} }
} }
zNodes.value = res.data zNodes.value = res.data
@ -533,6 +535,16 @@ export const useTree = () => {
} }
const initTreeCallBack = () => { const initTreeCallBack = () => {
let arr = [
"ArcgisWXImagery",
"ArcgisBLUEImagery",
"ArcgisLWImagery",
"GDLWImagery",
"GDWXImagery",
"GDSLImagery",
"layer",
];
let layers:any = []
if (window.earth) { if (window.earth) {
for (let i = 0; i < zNodes.value.length; i++) { for (let i = 0; i < zNodes.value.length; i++) {
if (zNodes.value[i].sourceType === 'directory') { if (zNodes.value[i].sourceType === 'directory') {
@ -548,9 +560,25 @@ export const useTree = () => {
if (!params.name) { if (!params.name) {
params.name = zNodes.value[i].sourceName params.name = zNodes.value[i].sourceName
} }
if(arr.includes(zNodes.value[i].sourceType)) {
layers.push(
{
sourceType: zNodes.value[i].sourceType,
params: { ...detail, ...params }
}
)
}
else {
initMapData(zNodes.value[i].sourceType, { ...detail, ...params }, null) initMapData(zNodes.value[i].sourceType, { ...detail, ...params }, null)
} }
} }
layers.sort((obj1, obj2) => {
return obj1.params.layerIndex - obj2.params.layerIndex;
});
for(let i = 0; i < layers.length; i++) {
initMapData(layers[i].sourceType, layers[i].params, null)
}
}
} }

View File

@ -34,6 +34,13 @@ export const useTreeNode = () => {
// detailFun: get_detail_line, // detailFun: get_detail_line,
// allowChildren: false, // allowChildren: false,
}, },
polyhedronObject: {
rightMenus: ['edit', 'del', 'setView', 'resetView']
// render: renderBaseMarker,
// render2d: renderBaseMarker2d,
// detailFun: get_detail_line,
// allowChildren: false,
},
curve: { curve: {
rightMenus: ['edit', 'del', 'setView', 'resetView'] rightMenus: ['edit', 'del', 'setView', 'resetView']
// render: renderCurve, // render: renderCurve,
@ -94,7 +101,7 @@ export const useTreeNode = () => {
// detailFun: get_detail_groundImage, // detailFun: get_detail_groundImage,
// allowChildren: false, // allowChildren: false,
}, },
waterl: { waterL: {
rightMenus: ['edit', 'del', 'setView', 'resetView'] rightMenus: ['edit', 'del', 'setView', 'resetView']
// render: renderSpout, // render: renderSpout,
// detailFun: get_detail_waterl, // detailFun: get_detail_waterl,
@ -319,7 +326,7 @@ export const useTreeNode = () => {
}, },
fountain: { fountain: {
// render: renderFountain, // render: renderFountain,
rightMenus: ['edit', 'del'], rightMenus: ['edit', 'del', 'setView', 'resetView'],
// detailFun: get_detail_fountain, // detailFun: get_detail_fountain,
allowChildren: false allowChildren: false
}, },
@ -393,9 +400,9 @@ export const useTreeNode = () => {
flyLine: { flyLine: {
rightMenus: [ rightMenus: [
'edit', 'edit',
'del' 'del',
// "setView", 'setView',
// "resetView" /*"setView", "resetView"*/, 'resetView'
] ]
// render: renderFlyLine, // render: renderFlyLine,
// detailFun: get_detail_flyLine, // detailFun: get_detail_flyLine,
@ -589,6 +596,7 @@ export const useTreeNode = () => {
left: x + 'px', left: x + 'px',
visibility: 'visible' visibility: 'visible'
}) })
if ((window as any).checkAuthIsValid) {
if ( if (
Object.prototype.toString.call(selectedNodes) === '[object Array]' && Object.prototype.toString.call(selectedNodes) === '[object Array]' &&
selectedNodes.length > 1 selectedNodes.length > 1
@ -605,6 +613,8 @@ export const useTreeNode = () => {
} }
} }
} }
}
return arr return arr
} }

View File

@ -10,14 +10,8 @@
<firstMenu class="absolute zIndex9" ref="firstMenuRef"></firstMenu> <firstMenu class="absolute zIndex9" ref="firstMenuRef"></firstMenu>
<!--底部菜单--> <!--底部菜单-->
<bottomMenu class="absolute zIndex9" ref="bottomMenuRef"></bottomMenu> <bottomMenu class="absolute zIndex9" ref="bottomMenuRef"></bottomMenu>
<input <input type="file" id="fileInputlink" style="display: none" multiple accept=".jpeg,.png,.jpg,.mp4,.pdf"
type="file" @input="uploadFile" />
id="fileInputlink"
style="display: none"
multiple
accept=".jpeg,.png,.jpg,.mp4,.pdf"
@input="uploadFile"
/>
<!-- 多点视线分析 --> <!-- 多点视线分析 -->
<Visibility ref="visibility"></Visibility> <Visibility ref="visibility"></Visibility>
@ -91,6 +85,7 @@ import tileset from '../components/propertyBox/tileset.vue'
import layer from '../components/propertyBox/layer.vue' import layer from '../components/propertyBox/layer.vue'
import trajectoryMotion from '../components/propertyBox/trajectoryMotion.vue' import trajectoryMotion from '../components/propertyBox/trajectoryMotion.vue'
import wallStereoscopic from '../components/propertyBox/wallStereoscopic.vue' import wallStereoscopic from '../components/propertyBox/wallStereoscopic.vue'
import wallRealStereoscopic from '../components/propertyBox/wallRealStereoscopic.vue'
import circleDiffuse from '../components/propertyBox/circleDiffuse.vue' import circleDiffuse from '../components/propertyBox/circleDiffuse.vue'
import radarScan from '../components/propertyBox/radarScan.vue' import radarScan from '../components/propertyBox/radarScan.vue'
import radarScanStereoscopic from '../components/propertyBox/radarScanStereoscopic.vue' import radarScanStereoscopic from '../components/propertyBox/radarScanStereoscopic.vue'
@ -110,6 +105,11 @@ import waterSurface from '../components/propertyBox/waterSurface.vue'
import { addMapSource } from '../../common/addMapSource' import { addMapSource } from '../../common/addMapSource'
import modelSetting from '../components/propertyBox/modelSetting.vue' import modelSetting from '../components/propertyBox/modelSetting.vue'
import modelObject from '../components/propertyBox/modelObject.vue' import modelObject from '../components/propertyBox/modelObject.vue'
import particleEffects from '../components/propertyBox/particleEffects.vue'
import flyLine from '../components/propertyBox/flyLine.vue'
import explosion from '../components/propertyBox/explosion.vue'
import graphObject from '../components/propertyBox/graphObject.vue' import graphObject from '../components/propertyBox/graphObject.vue'
import graph from '../components/propertyBox/graph.vue' import graph from '../components/propertyBox/graph.vue'
import graphSetting from '../components/propertyBox/graphSetting.vue' import graphSetting from '../components/propertyBox/graphSetting.vue'
@ -223,6 +223,11 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
await nextTick() await nextTick()
dynamicComponentRef.value?.open(id) dynamicComponentRef.value?.open(id)
break break
case 'entityWall':
currentComponent.value = wallRealStereoscopic
await nextTick()
dynamicComponentRef.value?.open(id)
break
case 'diffuseScan': case 'diffuseScan':
currentComponent.value = circleDiffuse currentComponent.value = circleDiffuse
await nextTick() await nextTick()
@ -260,6 +265,24 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
await nextTick() await nextTick()
dynamicComponentRef.value?.open(id) dynamicComponentRef.value?.open(id)
break break
case 'fountain':
case 'fire':
case 'smoke':
case 'waterL':
currentComponent.value = particleEffects
await nextTick()
dynamicComponentRef.value?.open(id, sourceType)
break
case 'flyLine':
currentComponent.value = flyLine
await nextTick()
dynamicComponentRef.value?.open(id)
break
case 'explosion':
currentComponent.value = explosion
await nextTick()
dynamicComponentRef.value?.open(id)
break
default: default:
break break
} }
@ -307,17 +330,17 @@ const createEarth = async () => {
YJ.Global.rotateAround(window.earth, object.position) YJ.Global.rotateAround(window.earth, object.position)
break break
case 'textBox': case 'textBox':
// let id = new YJ.Tools().randomString() let id = new YJ.Tools().randomString()
// let name = '文本框' let name = '文本框'
// addMapSource({ addMapSource({
// type: 'textBox', type: 'textBox',
// id: id, id: id,
// sourceName: name, sourceName: name,
// opt: { opt: {
// id: id, id: id,
// position: object.position position: object.position
// } }
// }) })
break break
case 'attribute': case 'attribute':
let node = window.treeObj.getNodeByParam('id', object.id, null) let node = window.treeObj.getNodeByParam('id', object.id, null)