Compare commits

...

8 Commits

Author SHA1 Message Date
0e8793f01d 工具 2025-09-10 10:31:32 +08:00
zh
a1f5a61252 提交 2025-09-09 10:06:18 +08:00
zh
47fa66ce6b 合并 2025-09-08 17:26:59 +08:00
zh
50ef8e1f05 合并 2025-09-08 09:10:10 +08:00
zh
6629775367 Merge branch 'zyl' of http://xny.yj-3d.com:3000/zhouyulong/electron-4 into zyl 2025-09-05 19:45:55 +08:00
zh
41bffc2e83 合并 2025-09-05 19:45:46 +08:00
a33fbb1cbe Merge branch 'zyl' of http://xny.yj-3d.com:3000/zhouyulong/electron-4 into zyl 2025-09-05 19:42:13 +08:00
39dc98401d 修改 2025-09-05 19:42:09 +08:00
40 changed files with 1810 additions and 234 deletions

86
package-lock.json generated
View File

@ -13,9 +13,11 @@
"@electron-toolkit/utils": "^4.0.0",
"@ztree/ztree_v3": "^3.5.48",
"axios": "^1.11.0",
"clipboard": "^2.0.11",
"dayjs": "^1.11.18",
"echarts": "^6.0.0",
"electron-updater": "^6.3.9",
"element-plus": "^2.10.4",
"js-md5": "^0.8.3",
"mitt": "^3.0.1",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.4.1",
@ -30,7 +32,7 @@
"@electron-toolkit/eslint-config-ts": "^3.0.0",
"@electron-toolkit/tsconfig": "^1.0.1",
"@types/jquery": "^3.5.32",
"@types/node": "^22.16.5",
"@types/node": "^22.18.1",
"@types/plist": "^3.0.5",
"@types/verror": "^1.10.11",
"@types/vue-i18n": "^6.1.3",
@ -2649,9 +2651,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "22.16.5",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.16.5.tgz",
"integrity": "sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ==",
"version": "22.18.1",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-22.18.1.tgz",
"integrity": "sha512-rzSDyhn4cYznVG+PCzGe1lwuMYJrcBS1fc3JqSa2PvtABwWo+dZ1ij5OVok3tqfpEBCBoaR4d7upFJk73HRJDw==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
@ -4647,6 +4649,17 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/clipboard": {
"version": "2.0.11",
"resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
"integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
"license": "MIT",
"dependencies": {
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^2.0.0"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz",
@ -5196,9 +5209,9 @@
}
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"version": "1.11.18",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.18.tgz",
"integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==",
"license": "MIT"
},
"node_modules/de-indent": {
@ -5361,6 +5374,12 @@
"node": ">=0.4.0"
}
},
"node_modules/delegate": {
"version": "3.2.0",
"resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
"integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==",
"license": "MIT"
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delegates/-/delegates-1.0.0.tgz",
@ -5610,6 +5629,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/echarts": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz",
"integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "2.3.0",
"zrender": "6.0.0"
}
},
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmmirror.com/ejs/-/ejs-3.1.10.tgz",
@ -7248,6 +7277,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/good-listener": {
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
"integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
"license": "MIT",
"dependencies": {
"delegate": "^3.1.2"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
@ -8453,11 +8491,6 @@
"dev": true,
"license": "BSD-3-Clause"
},
"node_modules/js-md5": {
"version": "0.8.3",
"resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz",
"integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
@ -10986,6 +11019,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/select": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
"integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==",
"license": "MIT"
},
"node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
@ -12243,6 +12282,12 @@
"node": ">= 10.0.0"
}
},
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
"license": "MIT"
},
"node_modules/tiny-typed-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmmirror.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz",
@ -12461,6 +12506,12 @@
"typescript": ">=4.8.4"
}
},
"node_modules/tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
"license": "0BSD"
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz",
@ -13886,6 +13937,15 @@
"engines": {
"node": ">= 10"
}
},
"node_modules/zrender": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz",
"integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==",
"license": "BSD-3-Clause",
"dependencies": {
"tslib": "2.3.0"
}
}
}
}

View File

@ -25,6 +25,8 @@
"@electron-toolkit/utils": "^4.0.0",
"@ztree/ztree_v3": "^3.5.48",
"axios": "^1.11.0",
"clipboard": "^2.0.11",
"dayjs": "^1.11.18",
"echarts": "^6.0.0",
"electron-updater": "^6.3.9",
"element-plus": "^2.10.4",
@ -42,7 +44,7 @@
"@electron-toolkit/eslint-config-ts": "^3.0.0",
"@electron-toolkit/tsconfig": "^1.0.1",
"@types/jquery": "^3.5.32",
"@types/node": "^22.16.5",
"@types/node": "^22.18.1",
"@types/plist": "^3.0.5",
"@types/verror": "^1.10.11",
"@types/vue-i18n": "^6.1.3",

View File

@ -4,6 +4,8 @@ import { electronApp, optimizer, is } from '@electron-toolkit/utils'
import icon from '../../resources/earth.png?asset'
import fs from 'fs'
const { exec } = require('child_process');
// 开发环境路径处理 - 确保添加正确的file协议
const devSplashPath = path.resolve(
app.getAppPath(),

View File

@ -25,7 +25,6 @@ declare module 'vue' {
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs']
ElTag: typeof import('element-plus/es')['ElTag']
ElUpload: typeof import('element-plus/es')['ElUpload']
Index_b: typeof import('./src/components/SvgIcon/index_b.vue')['default']
Pagination: typeof import('./src/components/Pagination/index.vue')['default']

View File

@ -49,7 +49,7 @@ body {
background: var(--color-background);
line-height: 1.6;
font-family:
Inter,
SourceHanSans,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',

View File

@ -32,10 +32,15 @@
@font-face {
font-family: 'sy-boldface';
src: url('../fonts/sy-boldface.otf') format('opentype');
src: url('../iconfont/sy-boldface.otf') format('opentype');
}
@font-face {
font-family: 'Ali-mother-counts-bold';
src: url('../fonts/Ali-mother-counts-bold.ttf') format('truetype');
src: url('../iconfont/Ali-mother-counts-bold.ttf') format('truetype');
}
@font-face {
font-family: 'SourceHanSans';
src: url('../iconfont/SourceHanSansCN-Medium.otf') format('opentype');
}

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path d="M3.06995 0.0336822C3.30345 -0.0134909 3.72175 0.0203715 4.04432 0.0203715L8.80938 0.0203715C9.40915 0.0203715 10.1307 -0.0457695 10.6647 0.0603036C11.1902 0.1647 11.5443 0.463472 11.7725 0.858946C12.0226 1.29218 11.9994 1.8259 11.9994 2.52278L11.9994 10.1232C11.9994 11.3662 11.3459 12 10.0774 12L3.41699 12C3.05145 12 2.7978 11.9615 2.78966 11.6805C2.77859 11.2992 3.13767 11.3345 3.59051 11.3345L9.62358 11.3345C9.9666 11.3345 10.3532 11.3732 10.5979 11.3078C10.9435 11.2156 11.2516 10.9028 11.3187 10.5225C11.3785 10.1841 11.3321 9.80816 11.3321 9.41772L11.3321 2.70913C11.3321 2.34708 11.3626 1.95707 11.3321 1.59103C11.2915 1.1051 10.9141 0.772719 10.5312 0.699218C10.2419 0.643685 9.88335 0.685907 9.54349 0.685907L3.55046 0.685907C3.25907 0.685907 2.87412 0.72524 2.803 0.446314C2.74999 0.238375 2.86113 0.0758638 3.06995 0.0336822ZM4.9653 7.34125L2.00215 7.34125C1.65943 7.34125 1.32269 7.37425 1.04113 7.31463C0.477442 7.19527 0.00413877 6.69706 2.77496e-05 6.02349C-0.00437695 5.30309 0.516243 4.73537 1.24135 4.67911C1.82735 4.63364 2.47369 4.67911 3.11 4.67911L4.9653 4.67911C5.01246 4.16292 4.79863 2.94146 5.29899 2.94872C5.53703 2.95217 5.7177 3.11918 5.87293 3.24155C6.7027 3.89572 7.45568 4.47287 8.31552 5.11836C8.57959 5.3166 9.11366 5.62915 9.10303 6.05011C9.09247 6.46816 8.55953 6.78468 8.30218 6.98186C7.46283 7.62495 6.69288 8.19646 5.84623 8.83205C5.69609 8.94478 5.46648 9.11088 5.2456 9.05833C4.76802 8.9447 5.0393 7.88096 4.9653 7.34125Z" fill="#FFFFFF" >
</path>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,138 @@
export function processBase64Images(base64Data1, base64Data2, callback) {
if (!base64Data1 || !base64Data2) {
alert("请输入两个Base64图像数据");
return;
}
// 创建Image对象并加载第一个Base64图像
const img1 = new Image();
img1.onload = function () {
// 创建Image对象并加载第二个Base64图像
const img2 = new Image();
img2.onload = function () {
// 计算拼接后的Canvas尺寸这里示例为水平拼接垂直拼接可调整计算方式
const totalWidth = img1.width + img2.width;
const maxHeight = Math.max(img1.height, img2.height);
console.log("maxHeight", maxHeight);
const resultCanvas = document.createElement("canvas");
// 设置结果Canvas的尺寸
resultCanvas.width = totalWidth;
resultCanvas.height = maxHeight;
// 获取Canvas绘图上下文
const ctx = resultCanvas.getContext("2d");
// 绘制第一个图像(左上角开始)
ctx.drawImage(img1, 0, 0);
// 绘制第二个图像(第一个图像右侧)
ctx.drawImage(img2, img1.width, 0);
// 获取拼接后的Base64结果默认为PNG格式可指定其他格式如JPEG
const resultBase64Data = resultCanvas.toDataURL("image/png");
callback(resultBase64Data);
console.log("图像拼接完成Base64结果已生成");
};
img2.src = base64Data1;
};
img1.src = base64Data2;
}
/**
* 拼接两个Base64图像并返回新的Base64
* @param {string} base641 第一个Base64图像数据
* @param {number} width1 第一个图像要截取的宽度
* @param {string} base642 第二个Base64图像数据
* @param {number} width2 第二个图像要截取的宽度
* @param {string} [format='image/png'] 输出图像格式
* @param {number} [quality=1.0] 输出图像质量(0-1),仅对支持的格式有效
* @returns {Promise<string>} 拼接后的Base64图像数据
*/
export function combineBase64Images(
base641,
width1,
base642,
width2,
format = "image/png",
quality = 1.0
) {
return new Promise((resolve, reject) => {
// 创建canvas元素
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// 设置canvas宽度和高度
canvas.width = width1 + width2;
canvas.height = 0; // 高度将在图像加载后确定
// 创建图像对象
const img1 = new Image();
const img2 = new Image();
// 错误处理
function handleError(error) {
reject(new Error(`图像处理错误: ${error.message}`));
}
// 监听两个图像都加载完成
let loadedCount = 0;
function checkAllLoaded() {
loadedCount++;
if (loadedCount === 2) {
drawAndResolve();
}
}
// 图像1加载事件
img1.onload = function () {
checkAllLoaded();
};
// 图像2加载事件
img2.onload = function () {
checkAllLoaded();
};
// 图像加载错误事件
img1.onerror = img2.onerror = handleError;
// 加载图像
img1.src = base641;
img2.src = base642;
// 绘制图像并解析为Base64
function drawAndResolve() {
try {
// 确定canvas高度为两个图像高度的最大值
const height1 = img1.height;
const height2 = img2.height;
canvas.height = Math.max(height1, height2);
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制第一个图像的左侧部分 (从左往右截取width1)
ctx.drawImage(img1, 0, 0, width1, height1, 0, 0, width1, canvas.height);
// 绘制第二个图像的右侧部分 (从右往左截取width2)
// 计算在原图上的截取起点 (从右侧开始)
const sourceX = img2.width - width2;
ctx.drawImage(
img2,
sourceX,
0,
width2,
height2,
width1,
0,
width2,
canvas.height
);
// 将canvas内容转换为Base64
const resultBase64 = canvas.toDataURL(format, quality);
resolve(resultBase64);
} catch (error) {
handleError(error);
}
}
});
}

View File

@ -1,63 +0,0 @@
import { ipcRenderer, remote } from "electron";
import Vue from "vue";
import { Loading } from "element-ui";
let bus = new Vue();
// let bus = window.$root_home;
let $sendChanel = (chanel, arg = {}) => {
// let bus = new Vue();
bus.$emit(chanel, arg);
};
let $recvChanel = (chanel, cb) => {
bus.$on(chanel, cb);
};
let $offChanel = (chanel, cb) => {
bus.$off(chanel);
};
let $removeChanel = (chanel) => {
bus.$off(chanel);
};
let $sendElectronChanel = (chanel, arg = null) => {
ipcRenderer.send(chanel, arg);
};
let $removeElectronChanel = (chanel, cb) => {
ipcRenderer.removeListener(chanel, cb);
};
let $recvElectronChanel = (chanel, cb) => {
ipcRenderer.once(chanel, cb);
};
let $changeComponentShow = (selector, state, styleStr = false) => {
$(selector).css({ display: state ? "block" : "none" });
if (styleStr) {
console.log(123);
let str = styleStr.split(":");
if (str[0] === "top") $(selector).css({ top: str[1] });
if (str[0] === "z-index") $(selector).css({ zIndex: str[1] });
}
};
let openLoading = (
text = "拼命加载中...",
option = {
fullscreen: true,
background: "rgba(0,0,0,0.63)",
lock: true,
// spinner: 'el-icon-loading'
}
) => {
option.text = text;
let loadingInstance = Loading.service(option);
return loadingInstance;
};
let $remote = remote;
export {
openLoading,
$sendElectronChanel,
$removeElectronChanel,
$recvElectronChanel,
$sendChanel,
$recvChanel,
$offChanel,
$removeChanel,
$changeComponentShow,
$remote,
};

View File

@ -1,3 +1,4 @@
const { ipcRenderer } = require('electron')
export const $changeComponentShow = (selector: any, state: any, styleStr: any = false) => {
$(selector).css({ visibility: state ? 'visible' : 'hidden' })
if (styleStr) {
@ -17,3 +18,13 @@ export const $changeComponentPop = (selector: any, state: any, styleStr: any = f
if (str[0] === 'z-index') $(selector).css({ zIndex: str[1] })
}
}
export const $sendElectronChanel = (chanel: any, arg: any = null) => {
console.log('发送给electron', chanel, arg);
ipcRenderer.send(chanel, arg);
};
export const $recvElectronChanel = (chanel: any, cb: any) => {
console.log('接收来自electron', chanel);
ipcRenderer.once(chanel, cb);
};

View File

@ -1,13 +1,8 @@
<template>
<div class="bottomMenuBox zIndex9">
<div class="animate__animated bottomMenu">
<div
class="bottom_box"
v-for="(item, i) of bottomMenuList"
:key="i"
:title="t('bottomMenu.' + item.sourceType)"
@click="addMarker(item)"
>
<div class="bottom_box" v-for="(item, i) of bottomMenuList" :key="i" :title="t('bottomMenu.' + item.sourceType)"
@click="addMarker(item)">
<svg-icon :name="item.sourceType" :size="20" color="rgba(0, 255, 255, 1)"></svg-icon>
<div class="span">
{{ t('bottomMenu.' + item.sourceType) }}
@ -23,6 +18,8 @@ import { useI18n } from 'vue-i18n'
import { inject } from 'vue'
import { TreeApi } from '@/api/tree'
import { initMapData } from '../tree/initMapData'
import { useTreeNode } from '../tree/hooks/treeNode'
const { cusAddNodes } = useTreeNode()
const { t } = useI18n()
const eventBus: any = inject('bus')
@ -84,6 +81,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'point',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -92,6 +90,7 @@ const bottomMenuList = ref([
params: options
}
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -120,6 +119,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'line',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -128,6 +128,7 @@ const bottomMenuList = ref([
params: options
}
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -154,6 +155,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'curve',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -162,6 +164,7 @@ const bottomMenuList = ref([
params: options
}
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -194,6 +197,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'panel',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -202,8 +206,8 @@ const bottomMenuList = ref([
params: options
}
console.log(params)
// eventBus.emit("openDialog", 'panel');
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -215,8 +219,7 @@ const bottomMenuList = ref([
fun: () => {
let Draw = new YJ.Draw.DrawCircle(window.earth)
Draw.start(async (a, opt) => {
// let id = new YJ.Tools().randomString()
let id = 'aaa'
let id = new YJ.Tools().randomString()
let name = '圆'
let options: any = await initMapData('circle', {
id: id,
@ -224,18 +227,24 @@ const bottomMenuList = ref([
center: opt.center, radius: opt.radius
})
delete options.host
console.log('options', options)
let selectedNodes = window.treeObj.getSelectedNodes()
let params = {
"id": id,
"sourceName": name,
"sourceType": "circle",
"parentId": (selectedNodes && selectedNodes[selectedNodes.length - 1]) ? selectedNodes[selectedNodes.length - 1].id : undefined,
id: id,
sourceName: name,
sourceType: "circle",
// isShow: 1,
parentId: (selectedNodes && selectedNodes[selectedNodes.length - 1]) ? selectedNodes[selectedNodes.length - 1].id : undefined,
// "treeIndex": 0,
"params": options
params: options
}
console.log(params)
// eventBus.emit("openDialog", 'circle');
TreeApi.addOtherSource(params)
// TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -268,6 +277,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'rectangle',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -278,6 +288,7 @@ const bottomMenuList = ref([
console.log(params)
// eventBus.emit("openDialog", 'panel');
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -312,6 +323,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'rendezvous',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -322,6 +334,7 @@ const bottomMenuList = ref([
console.log(params)
// eventBus.emit("openDialog", 'panel');
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -356,6 +369,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'attackArrow',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -366,6 +380,7 @@ const bottomMenuList = ref([
console.log(params)
// eventBus.emit("openDialog", 'panel');
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
},
@ -401,6 +416,7 @@ const bottomMenuList = ref([
id: id,
sourceName: name,
sourceType: 'pincerArrow',
// isShow: 1,
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
@ -410,6 +426,7 @@ const bottomMenuList = ref([
}
// eventBus.emit("openDialog", 'panel');
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
}
@ -511,7 +528,7 @@ const addMarker = (item: any) => {
transform: scale(0.8);
}
> .span {
>.span {
color: #fff;
font-family: 黑体;
font-size: 1rem;

View File

@ -39,8 +39,8 @@ import { bus } from '@/utils/bus'
import leftSideSecond from '@/views/components/leftSide/leftSideSecond.vue'
const { t } = useI18n()
const eventBus = inject('bus')
const menuList = ref([
const eventBus: any = inject('bus')
const menuList: any = ref([
// 方案推演
{
name: 'situation',
@ -128,28 +128,28 @@ const menuList = ref([
// fun: this.showSecondMenu,
key: 'tool',
children: [
// 'routePlan',
// 'clearRoute',
// 'graffiti',
// // stopGraffiti: "结束涂鸦",
// 'clearGraffiti',
// 'path',
// 'coorLocation',
// 'mouseLocation',
// 'annotationAggregation',
// 'annotation',
// 'screenShot',
// 'highQuality',
// 'videoRecord',
// 'pressModel',
// 'terrainDig',
// 'tilesetClipping',
// 'clearTilesetClipping',
// 'projConvert',
// 'projectionConvert',
// 'gdbImport',
// 'circleStatistics',
// 'polygonStatistics'
'routePlan',
'clearRoute',
'graffiti',
// stopGraffiti: "结束涂鸦",
'clearGraffiti',
'path',
'coorLocation',
'mouseLocation',
'annotationAggregation',
'annotation',
'screenShot',
'highQuality',
'videoRecord',
'pressModel',
'terrainDig',
'tilesetClipping',
'clearTilesetClipping',
'projConvert',
'projectionConvert',
'gdbImport',
'circleStatistics',
'polygonStatistics'
]
},
{

View File

@ -22,9 +22,14 @@ import { ref, reactive, getCurrentInstance } from 'vue'
import { useTreeNode } from '../tree/hooks/treeNode'
import { TreeApi } from '@/api/tree'
import { renderMethods } from '../tree/hooks/renderTreeNode'
import { processBase64Images, combineBase64Images } from '@/utils/HighDefinitionScreenshot'
import { $sendElectronChanel, $recvElectronChanel } from '@/utils/communication'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs'
import fs from 'fs'
const { proxy } = getCurrentInstance()
const { t } = useI18n()
const { findParentId, findTreeIndex } = useTreeNode()
const { findParentId, findTreeIndex, cusAddNodes } = useTreeNode()
const obj = ref(null)
const isclick = ref(false)
const eventBus = inject('bus')
@ -42,6 +47,13 @@ eventBus.on('graffitiObj', (data) => {
graffitiObjArr.push(data)
})
const methodMap = {
// 轨迹运动
trajectoryMotion: () => {
// let draw = new YJ.Draw.DrawPolyline(window.earth)
// draw.start((err, positions) => {
// if (positions.length > 1) {}
// })
},
// 电子围墙
electronicFence: () => {
let draw = new YJ.Draw.DrawPolyline(window.earth)
@ -51,7 +63,8 @@ const methodMap = {
positions.forEach((item) => {
if (item.alt < alt) alt = item.alt
})
let id = proxy.$md5(new Date().getTime() + '围墙')
// let id = new YJ.Tools().randomString()
let id = 'aaa'
let params = {
sourceName: '电子围墙',
id,
@ -71,10 +84,11 @@ const methodMap = {
// 渲染电子围墙
renderMethods.renderWallStereoscopic(params)
// 存入数据库
let res = TreeApi.addOtherSource(params)
console.log('addOtherSource', res)
// let res = TreeApi.addOtherSource(params)
// console.log('addOtherSource', res)
// 上树
cusAddNodes(window.treeObj, params.parentId, [params])
eventBus.emit('openDialog', 'wallStereoscopic')
}
})
},
@ -214,14 +228,70 @@ const methodMap = {
//卷帘对比
annotation() {
clickChange.annotation = !clickChange.annotation
// if (clickChange.annotation) {
// YJ.Global.splitScreen.on(window.earth)
// } else {
// YJ.Global.splitScreen.off()
// }
if (clickChange.annotation) {
YJ.Global.splitScreen.on(window.earth)
} else {
YJ.Global.splitScreen.off()
}
},
//屏幕截图
screenShot() {},
async screenShot() {
function downloadScreen(res) {
let base64 = res.replace(/^data:image\/\w+;base64,/, '')
console.log('base64', base64)
let dataBuffer = new Buffer(base64, 'base64')
$sendElectronChanel('saveFile', {
title: '保存图片',
filename: dayjs().format('YYYYMMDDHHmmss') + '截图',
filters: [{ name: '保存图片', extensions: ['jpg'] }]
})
$recvElectronChanel('selectedFileItem', (e, path) => {
console.log('path', fs.writeFile)
fs.writeFile(path, dataBuffer, (res) => {
console.log(res)
})
})
}
if (window.splitScreen || window.multiViewportMode) {
let res = ''
let res2 = ''
let sdk
if (window.splitScreen) {
sdk = YJ.Global.splitScreen.getSdk()
} else {
sdk = YJ.Global.multiViewportMode.getSdk()
}
await new YJ.Global.ScreenShot(sdk.sdkD, (data) => {
res = data
})
await new YJ.Global.ScreenShot(sdk.sdkP, (data) => {
res2 = data
})
if (window.multiViewportMode) {
processBase64Images(res, res2, (mergedBase64) => {
downloadScreen(mergedBase64)
// window.multiViewportMode = false;
})
} else {
let doms = document.querySelectorAll('.cesium-widget')
let leftWidth = doms[0].offsetWidth
let rightWidth = doms[1].offsetWidth
combineBase64Images(res2, leftWidth, res, rightWidth)
.then((result) => {
downloadScreen(result)
// window.splitScreen = false;
})
.catch((err) => console.error('拼接失败:', err))
}
} else {
let res = ''
await new YJ.Global.ScreenShot(window.earth, (data) => {
res = data
})
downloadScreen(res)
}
},
//高清出图
highQuality() {
// eventBus.emit('screenShotDialog')
@ -230,27 +300,130 @@ const methodMap = {
//视频录制
videoRecord() {
clickChange.videoRecord = !clickChange.videoRecord
let time = 3
this.$changeComponentShow('#secondMenu', false)
// const onKeyDown = (e) => {
// if (e.keyCode === 27) {
// item.status = !item.status;
// $sendElectronChanel("endRecoder");
// document.removeEventListener("keydown", onKeyDown);
// }
// };
if (clickChange.videoRecord) {
// document.addEventListener("keydown", onKeyDown);
let loading = $root_home.openLoading(time, {
background: 'rgba(0,0,0,0)',
fullscreen: false,
customClass: 'timer'
})
let timer = ''
const p = document.createElement('p')
p.style.color = '#fff'
p.innerHTML = '再次点击录制结束'
document.getElementsByClassName('el-loading-spinner')[0].appendChild(p)
let func = () => {
loading.setText(time--)
if (time == -1) {
clearInterval(timer)
loading.close()
console.log('开始了')
p.remove()
$sendElectronChanel('startRecoder')
}
}
func()
timer = setInterval(func, 1000)
} else {
$sendElectronChanel('endRecoder')
// document.removeEventListener("keydown", onKeyDown);
}
},
//压模
pressModel() {},
//地形开挖
terrainDig() {
// if (window.checkAuthIsValid) {
// new YJ.Analysis.TerrainExcavation(window.Earth1);
eventBus.emit('terrainExcavationDialog')
// } else {
// this.$message({
// message: '您没有该功能的权限',
// type: 'warning'
// })
// }
},
//剖切
tilesetClipping() {},
tilesetClipping() {
// if (window.checkAuthIsValid) {
let selectedNode = window.treeObj.getSelectedNodes()
if (selectedNode.length < 1) {
ElMessage({
message: '请在图层指挥舱选中对应模型进行操作',
type: 'warning'
})
return
}
if (!(selectedNode[0].sourceType === 'tileset' || selectedNode[0].sourceType === 'bim')) {
ElMessage({
message: '选中的节点不能进行剖切',
type: 'warning'
})
return
}
let tileset = window.earth.entityMap.get(selectedNode[0].id)
let draw = new YJ.Draw.DrawPolygon(window.earth)
draw.start((err, pos) => {
let section = new YJ.Analysis.Section(window.earth, tileset.entity, {
positions: pos
})
// _entityMap.set(selectedNode.source_id + 'pouqie', section)
})
// } else {
// this.$message({
// message: '您没有该功能的权限',
// type: 'warning'
// })
// }
},
//删除剖切
clearTilesetClipping() {},
clearTilesetClipping() {
YJ.Analysis.ClearSection()
},
//度分秒
projConvert() {},
projConvert() {
eventBus.emit('projConvertDialog')
},
//投影转换
projectionConvert() {},
projectionConvert() {
eventBus.emit('ProjectionConvertDialog')
},
//GDB导入
gdbImport() {},
//圆形统计
circleStatistics() {},
circleStatistics() {
// if (window.checkAuthIsValid) {
eventBus.emit('goodsSearchCircleDialog')
// } else {
// this.$message({
// message: '您没有该功能的权限',
// type: 'warning'
// })
// }
},
//多边形统计
polygonStatistics() {}
polygonStatistics() {
// if (window.checkAuthIsValid) {
eventBus.emit('goodsSearchPolgonDialog')
// } else {
// this.$message({
// message: "您没有该功能的权限",
// type: "warning",
// });
// }
}
}
const handleClick = (value = 'projectionDistanceMeasure') => {

View File

@ -65,20 +65,20 @@
<div class="tr">
<div class="td">圆心坐标</div>
<div class="td lng align-center" @dblclick="inputDblclick($event, 1, 'lng')">
<input class="input" @blur="inputBlurCallBack($event, i, 'lng', 8)" type="number"
v-model="entityOptions.center.lng" min="-180" max="180" v-if="activeTd.index == i && activeTd.name == 'lng'">
<span style="pointer-events: none;" v-else>{{ (item.lng).toFixed(8) }}</span>
<input class="input" @blur="inputBlurCallBack($event, 1, 'lng', 8)" type="number"
v-model="entityOptions.center.lng" min="-180" max="180" v-if="activeTd.index == 1 && activeTd.name == 'lng'">
<span style="pointer-events: none;" v-else>{{ entityOptions.center.lng.toFixed(8) }}</span>
</div>
<div class="td lat align-center" @dblclick="inputDblclick($event, i, 'lat')">
<input class="input" @blur="inputBlurCallBack($event, i, 'lat', 8)" type="number"
v-model="entityOptions.center.lat" min="-180" max="180" v-if="activeTd.index == i && activeTd.name == 'lat'">
<span style="pointer-events: none;" v-else>{{ (item.lat).toFixed(8) }}</span>
<div class="td lat align-center" @dblclick="inputDblclick($event, 1, 'lat')">
<input class="input" @blur="inputBlurCallBack($event, 1, 'lat', 8)" type="number"
v-model="entityOptions.center.lat" min="-180" max="180" v-if="activeTd.index == 1 && activeTd.name == 'lat'">
<span style="pointer-events: none;" v-else>{{ entityOptions.center.lat.toFixed(8) }}</span>
</div>
<div class="td alt align-center" @dblclick="inputDblclick($event, i, 'alt')">
<input class="input" @blur="inputBlurCallBack($event, i, 'alt', 2)" type="number"
<div class="td alt align-center" @dblclick="inputDblclick($event, 1, 'alt')">
<input class="input" @blur="inputBlurCallBack($event, 1, 'alt', 2)" type="number"
v-model="entityOptions.height" min="-9999999" max="999999999"
v-if="activeTd.index == i && activeTd.name == 'alt'">
<span style="pointer-events: none;" v-else>{{ (entityOptions.height).toFixed(2) }}</span>
v-if="activeTd.index == 1 && activeTd.name == 'alt'">
<span style="pointer-events: none;" v-else>{{ entityOptions.height.toFixed(2) }}</span>
</div>
</div>
</div>
@ -182,7 +182,7 @@ let originalOptions: any
let that: any
const open = async (id: any, type: any) => {
that = window.earth.entityMap.get('aaa')
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
heightMode.value = entityOptions.value.heightMode

View File

@ -69,8 +69,8 @@ import { ref, reactive, onMounted } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const viewPointHeight: any = ref(1.8)
const precision: any = ref(20)
@ -92,7 +92,7 @@ const viewPointHeightChange = () => {
visibility.viewPointHeights = viewPointHeight.value
}
const viewPointHeightInput = () => {
let dom = document.getElementById('viewPointHeight')
let dom: any = document.getElementById('viewPointHeight')
if (viewPointHeight.value < dom.min * 1) {
viewPointHeight.value = dom.min * 1
} else if (viewPointHeight.value > dom.max * 1) {

View File

@ -13,7 +13,7 @@
<div class="row" style="align-items: flex-start">
<div class="col" style="flex: 0 0 120px">
<span class="label">等高线</span>
<input class="btn-switch show" type="checkbox" />
<input class="btn-switch show" type="checkbox" v-model="show" />
</div>
</div>
</div>
@ -145,6 +145,7 @@
</div>
</template>
<template #footer>
<button @click="sure">确定</button>
<button @click="close">取消</button>
</template>
</Dialog>
@ -155,19 +156,27 @@ import { ref, reactive, onMounted } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var show: any = ref(true)
eventBus.on('contourDialog', () => {
baseDialog.value?.open()
setTimeout(() => {
YJ.Global.Contour(window.earth)
})
})
const closeCallBack = (e) => {}
const closeCallBack = (e) => {
YJ.Global.ContourReset()
show.value = true
}
const close = (e) => {
baseDialog.value?.close()
}
const sure = (e) => {
YJ.Global.ContourStartDraw(window.earth, show.value)
baseDialog.value?.close()
}
</script>
<style scoped lang="scss"></style>

View File

@ -5,6 +5,7 @@
title="坐标定位"
left="180px"
top="100px"
width="418px"
:closeCallback="closeCallBack"
>
<template #content>
@ -117,8 +118,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const activeName = ref('first')
@ -135,6 +136,7 @@ eventBus.on('coorLocationDialog', () => {
baseDialog.value?.open()
})
// @ts-ignore (define in dts)
const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event)
longitude.value = null
@ -160,9 +162,13 @@ const flyto = (e) => {
})
break
case 'second':
// @ts-ignore (define in dts)
var lng = Math.abs(longitude.value) + Math.abs(lngMin.value) / 60
// @ts-ignore (define in dts)
var lat = Math.abs(latitude.value) + Math.abs(latMin.value) / 60
// @ts-ignore (define in dts)
lng = longitude.value < 0 ? -lng : lng
// @ts-ignore (define in dts)
lat = latitude.value < 0 ? -lat : lat
var position = { lng, lat, alt: 100 }
@ -172,11 +178,15 @@ const flyto = (e) => {
break
case 'third':
var lng =
// @ts-ignore (define in dts)
Math.abs(longitude.value) + Math.abs(lngMin.value) / 60 + Math.abs(lngSec.value) / 3600
var lat =
// @ts-ignore (define in dts)
Math.abs(latitude.value) + Math.abs(latMin.value) / 60 + Math.abs(latSec.value) / 3600
// @ts-ignore (define in dts)
lng = longitude.value < 0 ? -lng : lng
// @ts-ignore (define in dts)
lat = latitude.value < 0 ? -lat : lat
var position = { lng, lat, alt: 100 }

View File

@ -112,8 +112,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var height: any = ref(70)
var precision: any = ref(125)
@ -135,7 +135,7 @@ eventBus.on('cutFillDialog', () => {
})
const heightInput = () => {
let dom = document.getElementById('height')
let dom: any = document.getElementById('height')
if (height.value < dom.min * 1) {
height.value = dom.min * 1
} else if (height.value > dom.max * 1) {

View File

@ -1,4 +1,4 @@
<template>
<!-- <template>
<Dialog
ref="baseDialog"
class="fly-roam"
@ -121,8 +121,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var show: any = ref(false)
var flyRoam: any = reactive([])
@ -154,4 +154,4 @@ const close = (e) => {
}
</script>
<style scoped lang="scss"></style>
<style scoped lang="scss"></style> -->

View File

@ -0,0 +1,340 @@
<template>
<Dialog
v-if="show"
ref="baseDialog"
title="物质统计"
left="180px"
top="100px"
:closeCallback="closeCallBack"
>
<template #content>
<div id="goodSearchEchart" style="width: 100%; height: 100%"></div>
</template>
<template #footer>
<button>绘制</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { inject } from 'vue'
import { nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const shpTotalDict: any = reactive({
shlwz_jzzp: '救灾帐篷',
mb: '棉被',
mymdy: '棉衣、棉大衣',
mjb: '毛巾被',
mt: '毛毯',
dgnsd: '睡袋',
zdc: '折叠床',
jycs: '简易厕所',
xpct: '橡皮船(艇)',
cfz: '冲锋舟',
jsc: '救生船',
jsy: '救生衣',
jsq: '救生圈',
bzd: '编织袋',
md: '麻袋',
csb: '抽水泵',
fdj: '发电机',
yjd: '应急灯',
jzzp: '救灾帐篷',
jzyb: '救灾衣被',
jygj: '救援工具'
})
var draw: any = reactive([])
var show: any = ref(false)
eventBus.on('goodsSearchCircleDialog', () => {
console.log('kkkkkk')
// baseDialog.value?.open()
draw = new YJ.Draw.DrawCircle(window.earth)
draw.start((err, positions) => {
console.log('err, positions', err, positions)
if (!err && positions.center.lng) {
show.value = true
let nodes = booleanOverlaps(positions)
console.log('goodsSearchCircle', nodes)
renderCanvas(nodes)
}
})
})
function booleanOverlaps(positions1, flag = 'circle') {
let cross = undefined
function set3Array(positions) {
let arr = []
positions.forEach((item) => {
arr.push([item.lng, item.lat])
})
arr.push(arr[0])
return arr
}
let getNode = (types) => {
let treeObj = window.treeObj
let res = []
types.forEach((type) => {
let nodes = treeObj.getNodesByParam('sourceType', type, null)
// console.log("nodes",nodes)
res = res.concat(nodes)
})
return res
}
//绘制的区域
// console.log("[set3Array(positions1)]", [set3Array(positions1)])
// 获取物资处(特定的标注类型)
let allNodes = getNode(['point', 'vr', 'picture', 'Feature'])
console.log('allNodes', allNodes)
let itemInArea = [] //区域内的类型符合的标注
for (let i = 0; i < allNodes.length; i++) {
let item = allNodes[i]
let getAllItemInArea = (lng, lat) => {
if (flag == 'circle') {
let { center, radius } = positions1
let distance = new YJ.Tools().randomString(center, { lng, lat })
distance < radius && itemInArea.push(item)
} else {
let polygon1 = turf.polygon([set3Array(positions1)])
let pt = turf.point([lng, lat])
turf.booleanPointInPolygon(pt, polygon1) && itemInArea.push(item)
}
}
console.log(item, item.sourceType, 'ooooo')
switch (item.sourceType) {
case 'point':
case 'vr':
case 'picture':
let params = JSON.parse(item.params)
console.log('params', params)
let lng = params.position.lng
let lat = params.position.lat
getAllItemInArea(lng, lat)
break
case 'Feature':
if (item.detail.geometry.type == 'Point') {
lng = item.detail.geometry.coordinates[0]
lat = item.detail.geometry.coordinates[1]
getAllItemInArea(lng, lat)
}
break
}
}
return itemInArea
}
function renderCanvas(nodes) {
console.log('nodes', nodes)
let x: any = []
let y: any = []
nodes.forEach((item) => {
// shp物资统计
if (item.sourceType == 'Feature') {
let obj = JSON.parse(JSON.stringify(item.detail.properties))
for (const key in obj) {
let name = key
if (shpTotalDict[key]) {
name = shpTotalDict[key]
// 把相同名称的物资数量相加,名称相同时,累加数据
let index = x.findIndex((item) => item === name)
if (index !== -1) {
y[index] = y[index] + Number(obj[key])
} else {
x.push(name)
y.push(Number(obj[key]))
}
}
}
}
let params = JSON.parse(item.params)
if (params.attribute && params.attribute.goods) {
let goods = params.attribute.goods.content
console.log('goods', goods)
if (goods.length) {
// $root_home_index.goodSearchDialog = false;
goods.forEach((good) => {
// 把相同名称的物资数量相加,名称相同时,累加数据
let index = x.findIndex((item) => item === good.name)
if (index !== -1) {
y[index] = y[index] + Number(good.cnt)
} else {
x.push(good.name)
y.push(Number(good.cnt))
}
})
}
}
})
console.log('x,y')
console.log(x)
console.log(y)
let notZeroX = []
let notZeroY = []
for (let i = 0; i < y.length; i++) {
if (y[i] != 0) {
notZeroX.push(x[i])
notZeroY.push(y[i])
}
}
console.log(notZeroX)
console.log(notZeroY)
x = notZeroX
y = notZeroY
if (!x.length) show.value = false
if (show.value) {
nextTick(() => {
let option = {
grid: {
top: '20%',
left: '5%',
right: '5%',
bottom: '8%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
label: {
show: true
}
},
formatter(params) {
var data = ''
for (var i = 0; i < params.length; i++) {
if (params[i].seriesName == '随访率') {
data += params[i].seriesName + ': ' + params[i].value + '%'
} else {
data += params[i].seriesName + ': ' + params[i].value + '<br/>'
}
}
return data
}
},
legend: {
data: ['总量'],
top: '5%',
left: '5%',
right: '5%',
bottom: '5%',
textStyle: {
color: '#fff'
}
},
xAxis: {
// type: "category",
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
width: 40, //将内容的宽度固定
overflow: 'truncate', //超出的部分截断
truncate: '...', //截断的部分用...代替
rotate: 30,
interval: 0,
textStyle: {
color: '#fff' //X轴文字颜色
}
}
},
yAxis: [
{
type: 'value',
name: '(数量)',
nameTextStyle: {
color: '#fff'
},
splitLine: {
show: true,
lineStyle: {
color: '#eeeeee'
}
},
axisTick: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: true,
textStyle: {
color: '#fff'
}
}
},
{
type: 'value',
gridIndex: 0,
min: 50,
max: 100,
splitNumber: 8,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
splitArea: {
show: false,
areaStyle: {
color: ['rgba(250,250,250,0.0)', 'rgba(250,250,250,0.05)']
}
}
}
],
series: [
{
name: '数量',
type: 'bar',
label: {
show: true,
position: 'top'
},
barWidth: 15,
itemStyle: {
normal: {
color: '#fdcb6c'
}
}
}
]
}
var dom = document.getElementById('goodSearchEchart')
var myChart = (window as any).echarts.init(dom)
option.xAxis.data = x
option.series[0].data = y
myChart.setOption(option)
})
} else {
ElMessage({
message: '该区域没有物资',
type: 'warning'
})
}
}
const closeCallBack = (e) => {}
</script>
<style scoped lang="scss"></style>

View File

@ -0,0 +1,328 @@
<template>
<Dialog
v-if="show"
ref="baseDialog"
title="物质统计"
left="180px"
top="100px"
:closeCallback="closeCallBack"
>
<template #content>
<div id="goodSearchEchart2" style="width: 100%; height: 100%"></div>
</template>
<template #footer>
<button>绘制</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { inject } from 'vue'
import { nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const shpTotalDict: any = reactive({
shlwz_jzzp: '救灾帐篷',
mb: '棉被',
mymdy: '棉衣、棉大衣',
mjb: '毛巾被',
mt: '毛毯',
dgnsd: '睡袋',
zdc: '折叠床',
jycs: '简易厕所',
xpct: '橡皮船(艇)',
cfz: '冲锋舟',
jsc: '救生船',
jsy: '救生衣',
jsq: '救生圈',
bzd: '编织袋',
md: '麻袋',
csb: '抽水泵',
fdj: '发电机',
yjd: '应急灯',
jzzp: '救灾帐篷',
jzyb: '救灾衣被',
jygj: '救援工具'
})
var draw: any = reactive([])
var show: any = ref(false)
eventBus.on('goodsSearchPolgonDialog', () => {
draw = new YJ.Draw.DrawPolygon(window.earth)
draw.start((err, params) => {
if (!err && params.length > 2) {
show.value = true
let nodes = booleanOverlaps(params, 'polygon')
renderCanvas(nodes)
}
})
})
function booleanOverlaps(positions1, flag = 'circle') {
let cross = undefined
function set3Array(positions) {
let arr = []
positions.forEach((item) => {
arr.push([item.lng, item.lat])
})
arr.push(arr[0])
return arr
}
let getNode = (types) => {
let treeObj = window.treeObj
let res = []
types.forEach((type) => {
let nodes = treeObj.getNodesByParam('sourceType', type, null)
res = res.concat(nodes)
})
return res
}
//绘制的区域
// 获取物资处(特定的标注类型)
let allNodes = getNode(['point', 'vr', 'picture', 'Feature'])
let itemInArea = [] //区域内的类型符合的标注
for (let i = 0; i < allNodes.length; i++) {
let item = allNodes[i]
let getAllItemInArea = (lng, lat) => {
if (flag == 'circle') {
let { center, radius } = positions1
let distance = new YJ.Tools().randomString(center, { lng, lat })
distance < radius && itemInArea.push(item)
} else {
let polygon1 = turf.polygon([set3Array(positions1)])
let pt = turf.point([lng, lat])
turf.booleanPointInPolygon(pt, polygon1) && itemInArea.push(item)
}
}
switch (item.sourceType) {
case 'point':
case 'vr':
case 'picture':
let params = JSON.parse(item.params)
let lng = params.position.lng
let lat = params.position.lat
getAllItemInArea(lng, lat)
break
case 'Feature':
if (item.detail.geometry.type == 'Point') {
lng = item.detail.geometry.coordinates[0]
lat = item.detail.geometry.coordinates[1]
getAllItemInArea(lng, lat)
}
break
}
}
return itemInArea
}
function renderCanvas(nodes) {
let x: any = []
let y: any = []
nodes.forEach((item) => {
// shp物资统计
if (item.sourceType == 'Feature') {
let obj = JSON.parse(JSON.stringify(item.detail.properties))
for (const key in obj) {
let name = key
if (shpTotalDict[key]) {
name = shpTotalDict[key]
// 把相同名称的物资数量相加,名称相同时,累加数据
let index = x.findIndex((item) => item === name)
if (index !== -1) {
y[index] = y[index] + Number(obj[key])
} else {
x.push(name)
y.push(Number(obj[key]))
}
}
}
}
let params = JSON.parse(item.params)
if (params.attribute && params.attribute.goods) {
let goods = params.attribute.goods.content
if (goods.length) {
// $root_home_index.goodSearchDialog = false;
goods.forEach((good) => {
// 把相同名称的物资数量相加,名称相同时,累加数据
let index = x.findIndex((item) => item === good.name)
if (index !== -1) {
y[index] = y[index] + Number(good.cnt)
} else {
x.push(good.name)
y.push(Number(good.cnt))
}
})
}
}
})
console.log('x,y')
console.log(x)
console.log(y)
let notZeroX = []
let notZeroY = []
for (let i = 0; i < y.length; i++) {
if (y[i] != 0) {
notZeroX.push(x[i])
notZeroY.push(y[i])
}
}
console.log(notZeroX)
console.log(notZeroY)
x = notZeroX
y = notZeroY
if (!x.length) show.value = false
if (show.value) {
nextTick(() => {
let option = {
grid: {
top: '20%',
left: '5%',
right: '5%',
bottom: '8%',
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow',
label: {
show: true
}
},
formatter(params) {
var data = ''
for (var i = 0; i < params.length; i++) {
if (params[i].seriesName == '随访率') {
data += params[i].seriesName + ': ' + params[i].value + '%'
} else {
data += params[i].seriesName + ': ' + params[i].value + '<br/>'
}
}
return data
}
},
legend: {
data: ['总量'],
top: '5%',
left: '5%',
right: '5%',
bottom: '5%',
textStyle: {
color: '#fff'
}
},
xAxis: {
// type: "category",
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: true,
width: 40, //将内容的宽度固定
overflow: 'truncate', //超出的部分截断
truncate: '...', //截断的部分用...代替
rotate: 30,
interval: 0,
textStyle: {
color: '#fff' //X轴文字颜色
}
}
},
yAxis: [
{
type: 'value',
name: '(数量)',
nameTextStyle: {
color: '#fff'
},
splitLine: {
show: true,
lineStyle: {
color: '#eeeeee'
}
},
axisTick: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: true,
textStyle: {
color: '#fff'
}
}
},
{
type: 'value',
gridIndex: 0,
min: 50,
max: 100,
splitNumber: 8,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
splitArea: {
show: false,
areaStyle: {
color: ['rgba(250,250,250,0.0)', 'rgba(250,250,250,0.05)']
}
}
}
],
series: [
{
name: '数量',
type: 'bar',
label: {
show: true,
position: 'top'
},
barWidth: 15,
itemStyle: {
normal: {
color: '#fdcb6c'
}
}
}
]
}
var dom = document.getElementById('goodSearchEchart2')
var myChart = (window as any).echarts.init(dom)
option.xAxis.data = x
option.series[0].data = y
myChart.setOption(option)
})
} else {
ElMessage({
message: '该区域没有物资',
type: 'warning'
})
}
}
const closeCallBack = (e) => {}
</script>
<style scoped lang="scss"></style>

View File

@ -48,8 +48,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var width: any = ref(1)
var graffiti: any = reactive([])
@ -59,12 +59,12 @@ eventBus.on('graffitiDialog', () => {
graffiti = new YJ.Obj.Graffiti(window.earth, {
width: width.value
})
}, 0)
}, 10)
})
const closeCallBack = (e) => {}
const widthInput = () => {
let dom = document.getElementById('width')
let dom: any = document.getElementById('width')
if (width.value < dom.min * 1) {
width.value = dom.min * 1
} else if (width.value > dom.max * 1) {

View File

@ -25,8 +25,8 @@ import { ref, reactive, onMounted } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
//属性
var profile: any = reactive([])
var echartsObject: any = reactive({})
@ -50,6 +50,7 @@ function close() {
baseDialog.value?.close()
}
const draw = (e) => {
// @ts-ignore (define in dts)
initEcharts()
profile.reDraw()
}
@ -68,12 +69,14 @@ function initEcharts(points) {
continue
}
const curData = [element.distance.toFixed(2), element.position.height.toFixed(2)]
// @ts-ignore (define in dts)
datas.push(curData)
const curCoords = [element.position.lng, element.position.lat]
// @ts-ignore (define in dts)
coords.push(curCoords)
}
const ele = document.getElementsByClassName('profile-echarts')[0]
echartsObject = echarts.init(ele)
echartsObject = (window as any).echarts.init(ele)
option = {
tooltip: {
trigger: 'axis',
@ -81,7 +84,7 @@ function initEcharts(points) {
align: 'left'
},
formatter(params) {
const xy = coords[params[0].dataIndex]
const xy: any = coords[params[0].dataIndex]
const tipData = params[0]['data']
profile.formatter(xy, tipData)
return (
@ -174,7 +177,7 @@ function initEcharts(points) {
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
color: new (window as any).echarts.graphic.LinearGradient(
0,
0,
0,
@ -222,7 +225,7 @@ function initEcharts(points) {
}
} else {
const ele = document.getElementsByClassName('profile-echarts')[0]
echartsObject = echarts.init(ele)
echartsObject = (window as any).echarts.init(ele)
option = {
tooltip: {
trigger: 'axis',
@ -305,7 +308,7 @@ function initEcharts(points) {
},
areaStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
color: new (window as any).echarts.graphic.LinearGradient(
0,
0,
0,

View File

@ -0,0 +1,283 @@
<template>
<Dialog
ref="baseDialog"
class="proj-convert"
title="度分秒格式转换"
left="180px"
top="100px"
width="515px"
:closeCallback="closeCallBack"
>
<template #content v-if="status1">
<span class="custom-divider"></span>
<div class="div-item">
<div class="row">
<div class="col input-select-box">
<span class="label" style="flex: 0 0 60px">输入格式</span>
<div class="input-select"></div>
</div>
</div>
</div>
<div class="div-item item" data-type="0">
<span class="custom-divider"></span>
<p style="font-size: 16px; padding-bottom: 6px; margin-top: 10px; margin-bottom: 5px">
<span style="margin-right: 10px"></span>
<span style="font-size: 12px; margin-bottom: 5px; color: #f16c55">例如116.6°, 39.9°</span>
</p>
<div class="row">
<div class="col">
<span class="label" style="flex: auto">经度</span>
<input class="input lng" type="number" min="-180" max="180" value="0" title="" />
</div>
<div class="col" style="margin: 0">
<span class="label">纬度</span>
<input class="input lat" type="number" min="-90" max="90" value="0" title="" />
</div>
<div class="col" style="flex: 0 0 24px">
<i
class="icon-copy-box"
title="复制"
data-clipboard-action="copy"
data-clipboard-target=".input"
style="cursor: pointer"
>
<svg class="icon-copy" style="margin: 4px; margin-bottom: 0px">
<use xlink:href="#yj-icon-copy"></use>
</svg>
</i>
<button class="convert" style="margin-left: 10px"> </button>
</div>
</div>
</div>
<div class="div-item item" data-type="1">
<span class="custom-divider"></span>
<p style="font-size: 16px; padding-bottom: 6px; margin-top: 10px; margin-bottom: 5px">
<span style="margin-right: 10px">度分</span>
<span style="font-size: 12px; margin-bottom: 5px; color: #f16c55"
>例如95°10.1702', 49°12.4015'</span
>
</p>
<div class="row">
<div class="col" style="flex-direction: column">
<div class="row" style="margin-bottom: 15px">
<span class="label">经度</span>
<input
class="input lng-dm-d"
style="flex: 1"
type="number"
min="-180"
max="180"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px"></span>
<input
class="input lng-dm-m"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px"></span>
<span class="top-line"></span>
</div>
<div class="row">
<span class="label">纬度</span>
<input
class="input lat-dm-d"
style="flex: 1"
type="number"
min="-90"
max="90"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px"></span>
<input
class="input lat-dm-m"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px"></span>
<span class="bottom-line"></span>
</div>
</div>
<div class="col" style="flex: 0 0 24px; margin: 0">
<i
class="icon-copy-box"
title="复制"
data-clipboard-action="copy"
data-clipboard-target=".input"
style="cursor: pointer; position: relative; left: -30px"
>
<svg class="icon-copy" style="margin: 4px; margin-bottom: 0px">
<use xlink:href="#yj-icon-copy"></use>
</svg>
</i>
<button class="convert" style="margin-left: 10px"> </button>
</div>
</div>
</div>
<div class="div-item item" data-type="2">
<span class="custom-divider"></span>
<p style="font-size: 16px; padding-bottom: 6px; margin-top: 10px; margin-bottom: 5px">
<span style="margin-right: 10px">度分秒</span>
<span style="font-size: 12px; margin-bottom: 5px; color: #f16c55"
>例如11°18'54.37", 39°13'46.57"</span
>
</p>
<div class="row">
<div class="col" style="flex-direction: column">
<div class="row" style="margin-bottom: 15px">
<span class="label">经度</span>
<input
class="input lng-dms-d"
style="flex: 1"
type="number"
min="-180"
max="180"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">度</span>
<input
class="input lng-dms-m"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">分</span>
<input
class="input lng-dms-s"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">秒</span>
<span class="top-line"></span>
</div>
<div class="row">
<span class="label">纬度</span>
<input
class="input lat-dms-d"
style="flex: 1"
type="number"
min="-90"
max="90"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">度</span>
<input
class="input lat-dms-m"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">分</span>
<input
class="input lat-dms-s"
style="flex: 1"
type="number"
min="0"
max="60"
value="0"
title=""
/>
<span class="label" style="flex: 0 0 14px; margin: 0 10px">秒</span>
<span class="bottom-line"></span>
</div>
</div>
<div class="col" style="flex: 0 0 24px; margin: 0">
<i
class="icon-copy-box"
title="复制"
data-clipboard-action="copy"
data-clipboard-target=".input"
style="cursor: pointer; position: relative; left: -30px"
>
<svg class="icon-copy" style="margin: 4px; margin-bottom: 0px">
<use xlink:href="#yj-icon-copy"></use>
</svg>
</i>
<button class="convert" style="margin-left: 10px">转 换</button>
</div>
</div>
</div>
<span class="custom-divider" style="order: 10; margin-top: 12px"></span>
</template>
<template #footer>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
import Clipboard from 'clipboard'
import { ElMessage } from 'element-plus'
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var status1: any = ref(false)
var tools: any = reactive([])
eventBus.on('projConvertDialog', () => {
baseDialog.value?.open()
if (status1.value) {
reset()
status1.value = false
}
status1.value = !status1.value
setTimeout(() => {
tools = new YJ.Tools(window.earth)
tools.projConvert(status1.value, () => {
status1.value = false
})
}, 100)
})
const closeCallBack = (e) => {
status1.value = false
}
const reset = () => {
let contentElm = document
.getElementsByClassName('proj-convert')[0]
.getElementsByClassName('content')[0]
contentElm.getElementsByClassName('lng-dms-d')[0].value = null
contentElm.getElementsByClassName('lng-dms-m')[0].value = null
contentElm.getElementsByClassName('lng-dms-s')[0].value = null
contentElm.getElementsByClassName('lat-dms-d')[0].value = null
contentElm.getElementsByClassName('lat-dms-m')[0].value = null
contentElm.getElementsByClassName('lat-dms-s')[0].value = null
contentElm.getElementsByClassName('lng')[0].value = null
contentElm.getElementsByClassName('lat')[0].value = null
}
const close = (e) => {
baseDialog.value?.close()
}
</script>
<style scoped lang="scss">
::v-deep .content > div {
display: flex !important;
flex-direction: column !important;
}
</style>

View File

@ -0,0 +1,171 @@
<template>
<Dialog
ref="baseDialog"
class="projection-convert"
title="投影转换"
left="180px"
top="100px"
width="634px"
:closeCallback="closeCallBack"
>
<template #content v-if="status1">
<span class="custom-divider"></span>
<div style="width: 585px; display: flex">
<div class="row left" style="flex: 1; margin-bottom: 0">
<div
style="
margin: 10px 0;
flex: 1;
display: flex;
align-items: center;
flex: 1;
justify-content: space-between;
"
>
<span class="lable-left-line">源坐标</span>
<button class="btn pick" style="margin-left: 15px">
<svg class="icon-edit"><use xlink:href="#yj-icon-edit"></use></svg>坐标拾取
</button>
<button
class="btn sourceCopy"
data-clipboard-action="copy"
data-clipboard-target=".input"
style="margin-left: 5px"
>
<svg class="icon-copy"><use xlink:href="#yj-icon-copy"></use></svg>复制
</button>
</div>
<div>
<div style="display: flex; margin-bottom: 12px; align-items: center">
<span class="label" style="flex: 0 0 60px">椭圆基准</span>
<div class="datalist_left"></div>
</div>
<div style="display: flex; margin-bottom: 12px; align-items: center">
<span class="label" style="flex: 0 0 60px">经度(x)</span>
<input class="input left-x" type="number" title="" />
</div>
<div style="display: flex; margin-bottom: 10px; align-items: center">
<span class="label" style="flex: 0 0 60px">纬度(y)</span>
<input class="input left-y" type="number" title="" />
</div>
</div>
</div>
<div
style="
display: flex;
flex-direction: column;
justify-content: center;
margin: 28px 15px 0 15px;
"
>
<button class="btn convert">
<svg-icon name="turn" :size="11" color="rgba(255, 255, 255, 1)"></svg-icon>
转换
</button>
</div>
<div class="row right" style="flex: 1; margin-bottom: 0">
<div
style="
margin: 10px 0;
height: 32px;
display: flex;
align-items: center;
flex: 1;
justify-content: space-between;
"
>
<span class="lable-left-line">目标坐标</span>
<button
class="btn copy"
data-clipboard-action="copy"
data-clipboard-target=".input"
style="margin-left: 20px"
>
<svg class="icon-copy"><use xlink:href="#yj-icon-copy"></use></svg>复制
</button>
</div>
<div>
<div style="display: flex; margin-bottom: 12px; align-items: center">
<span class="label" style="flex: 0 0 60px">椭圆基准</span>
<div class="datalist_right"></div>
</div>
<div style="display: flex; margin-bottom: 12px; align-items: center">
<span class="label" style="flex: 0 0 60px">经度(x)</span>
<input class="input right-x" readonly="readonly" />
</div>
<div style="display: flex; margin-bottom: 10px; align-items: center">
<span class="label" style="flex: 0 0 60px">纬度(y)</span>
<input class="input right-y" readonly="readonly" />
</div>
</div>
</div>
</div>
<span class="custom-divider"></span>
</template>
<template #footer>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
import Clipboard from 'clipboard'
import { ElMessage } from 'element-plus'
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var status1: any = ref(false)
var tools: any = reactive([])
eventBus.on('ProjectionConvertDialog', () => {
baseDialog.value?.open()
if (status1.value) {
reset()
status1.value = false
tools && tools.projectionConvert(status1.value, () => {})
}
status1.value = !status1.value
setTimeout(() => {
tools = new YJ.Tools(window.earth)
tools.projectionConvert(status1.value, () => {
status1.value = false
})
}, 100)
})
const closeCallBack = (e) => {
status1.value = false
tools && tools.projectionConvert(status1.value, () => {})
}
const reset = () => {
let contentElm = document
.getElementsByClassName('projection-convert')[0]
.getElementsByClassName('content')[0]
contentElm.getElementsByClassName('left-x')[0].value = null
contentElm.getElementsByClassName('left-y')[0].value = null
contentElm.getElementsByClassName('right-x')[0].value = null
contentElm.getElementsByClassName('right-y')[0].value = null
}
const close = (e) => {
baseDialog.value?.close()
}
</script>
<style scoped lang="scss">
::v-deep .content > div {
display: flex !important;
flex-direction: column !important;
}
::v-deep .content .cy_datalist input {
background: rgba(var(--color-sdk-base-rgb), 0.2) !important;
border: unset;
}
::v-deep .content input[type='number'] {
font-size: 16px !important;
// font-weight: 700 !important;
color: var(--color-sdk-auxiliary-public) !important;
}
</style>

View File

@ -29,8 +29,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
//属性
var startLng: any = ref(null)

View File

@ -128,8 +128,8 @@ import { ref, reactive, onMounted } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var selectType: any = ref('first')
var scale: any = ref(1)
var radio: any = ref('1:500')

View File

@ -184,8 +184,8 @@ import { ref, reactive, onMounted } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
// 属性
var minWaterLevel: any = ref(0)
var maxWaterLevel: any = ref(0)
@ -261,7 +261,7 @@ function analog() {
}
function minWaterLevelInput() {
let dom = document.getElementById('minWaterLevel')
let dom: any = document.getElementById('minWaterLevel')
if (minWaterLevel.value != '.') {
if (minWaterLevel.value < dom.min * 1) {
minWaterLevel.value = dom.min * 1
@ -277,7 +277,7 @@ function minWaterLevelInput() {
}
}
function maxWaterLevelInput() {
let dom = document.getElementById('maxWaterLevel')
let dom: any = document.getElementById('maxWaterLevel')
if (minWaterLevel.value != '.') {
if (maxWaterLevel.value < dom.min * 1) {
maxWaterLevel.value = dom.min * 1
@ -299,7 +299,7 @@ function maxWaterLevelInput() {
}
}
function areaInput() {
let dom = document.getElementById('area')
let dom: any = document.getElementById('area')
if (minWaterLevel.value != '.') {
if (area.value < dom.min * 1) {
area.value = dom.min * 1
@ -315,7 +315,7 @@ function areaInput() {
}
}
function waterVolumeInput() {
let dom = document.getElementById('waterVolume')
let dom: any = document.getElementById('waterVolume')
if (waterVolume.value < dom.min * 1) {
waterVolume.value = dom.min * 1
} else if (waterVolume.value > dom.max * 1) {
@ -331,7 +331,7 @@ function waterVolumeInput() {
}
}
function risingSpeedInput() {
let dom = document.getElementById('risingSpeed')
let dom: any = document.getElementById('risingSpeed')
if (risingSpeed.value != '.') {
if (risingSpeed.value < dom.min * 1) {
risingSpeed.value = dom.min * 1

View File

@ -43,7 +43,7 @@
</div>
</template>
<template #footer>
<button @click="close">取消</button>
<button @click="close">关闭</button>
</template>
</Dialog>
</template>
@ -53,8 +53,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
var height: any = ref(10)
@ -62,7 +62,7 @@ var excavation: any = reactive([])
eventBus.on('terrainExcavationDialog', () => {
baseDialog.value?.open()
excavation = new YJ.Analysis.TerrainExcavation(this.sdk, { height: 10 })
excavation = new (window as any).YJ.Analysis.TerrainExcavation(window.earth, { height: 10 })
})
const changeHeight = () => {
@ -76,7 +76,9 @@ const heightInput = () => {
height.value = dom.max * 1
}
}
const closeCallBack = (e) => {}
const closeCallBack = (e) => {
height.value = 10
}
const close = (e) => {
baseDialog.value?.close()
}

View File

@ -87,8 +87,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const viewPointHeight: any = ref(1.8)
var horizontalViewAngle: any = ref(90)
@ -98,13 +98,13 @@ var timeout: any = reactive([])
eventBus.on('viewShedDialog', () => {
baseDialog.value?.open()
viewShed && viewShed.destroy && viewShed.destroy()
viewShed = new YJ.Analysis.ViewShed(window.earth)
viewShed = new (window as any).YJ.Analysis.ViewShed((window as any).earth)
setTimeout(() => {
let contentElm = document.getElementsByClassName('view-shed')[0]
let e_horizontalViewAngle = contentElm.querySelector("input[name='horizontalViewAngle']")
let rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
let e_horizontalViewAngle:any = contentElm.querySelector("input[name='horizontalViewAngle']")
let rangeNodeActive:any = contentElm.getElementsByClassName('range-node-active')[0]
let rangeNodeActiveText = rangeNodeActive.getElementsByClassName('range-node-active-text')[0]
let rangeProcess = contentElm.getElementsByClassName('range-process')[0]
let rangeProcess:any = contentElm.getElementsByClassName('range-process')[0]
let percentage = (horizontalViewAngle.value / 180) * 100
rangeNodeActive.style.left = percentage + '%'
rangeProcess.style.width = percentage + '%'
@ -113,13 +113,13 @@ eventBus.on('viewShedDialog', () => {
e_horizontalViewAngle.removeEventListener('change', changeFun)
e_horizontalViewAngle.addEventListener('input', inputFun)
e_horizontalViewAngle.addEventListener('change', changeFun)
})
}, 10)
})
function inputFun() {
let contentElm = document.getElementsByClassName('view-shed')[0]
let rangeNodeActive = contentElm.getElementsByClassName('range-node-active')[0]
let rangeNodeActiveText = rangeNodeActive.getElementsByClassName('range-node-active-text')[0]
let rangeProcess = contentElm.getElementsByClassName('range-process')[0]
let rangeNodeActive:any = contentElm.getElementsByClassName('range-node-active')[0]
let rangeNodeActiveText:any = rangeNodeActive.getElementsByClassName('range-node-active-text')[0]
let rangeProcess:any = contentElm.getElementsByClassName('range-process')[0]
let percentage = (horizontalViewAngle.value / 180) * 100
rangeNodeActive.style.left = percentage + '%'
rangeProcess.style.width = percentage + '%'
@ -138,7 +138,7 @@ const closeCallBack = (e) => {
horizontalViewAngle.value = 90
}
function viewPointHeightInput(e) {
let dom = document.getElementById('viewPointHeight')
let dom:any = document.getElementById('viewPointHeight')
if (viewPointHeight.value != '.') {
if (viewPointHeight.value < dom.min * 1) {
viewPointHeight.value = dom.min * 1

View File

@ -43,8 +43,8 @@ import { ref, reactive } from 'vue'
import { inject } from 'vue'
import Dialog from '@/components/dialog/baseDialog.vue'
const baseDialog = ref(null)
const eventBus = inject('bus')
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
const viewPointHeight: any = ref(1.8)
var visibility: any = reactive([])
eventBus.on('analysisDialog', () => {
@ -53,7 +53,7 @@ eventBus.on('analysisDialog', () => {
const clangeViewPointHeight = () => {}
const viewPointHeightInput = () => {
let dom = document.getElementById('viewPointHeight')
let dom: any = document.getElementById('viewPointHeight')
if (viewPointHeight.value < dom.min * 1) {
viewPointHeight.value = dom.min * 1
} else if (viewPointHeight.value > dom.max * 1) {
@ -61,16 +61,16 @@ const viewPointHeightInput = () => {
}
}
const closeCallBack = (e) => {
viewPointHeight.value = 1.8
YJ.Measure.SetMeasureStatus(false)
viewPointHeight.value = 1.8;
(window as any).YJ.Measure.SetMeasureStatus(false)
// visibility && visibility.end()
}
const draw = (e) => {
visibility && visibility.end && visibility.end()
visibility = new YJ.Analysis.Visibility(window.earth, { viewPointHeight: viewPointHeight.value })
// visibility.create(this)
!window.analysisArr && (window.analysisArr = [])
window.analysisArr.push(visibility)
!(window as any).analysisArr && ((window as any).analysisArr = []);
(window as any).analysisArr.push(visibility);
baseDialog.value?.close()
}
</script>

View File

@ -15,6 +15,9 @@ import { inject } from 'vue'
import { TreeApi } from '@/api/tree'
import Dialog from '@/components/dialog/baseDialog.vue'
import { initMapData } from '../tree/initMapData'
import { useTreeNode } from '../tree/hooks/treeNode'
const { cusAddNodes } = useTreeNode()
const baseDialog: any = ref(null)
const eventBus: any = inject('bus')
@ -37,10 +40,12 @@ const confirm = () => {
let id = new YJ.Tools().randomString()
let options: any = await initMapData('groundText', {
id: id,
name: name,
text: name,
positions: positions
})
delete options.host
delete options.positions
console.log('options', options)
let selectedNodes = window.treeObj.getSelectedNodes()
let params = {
id: id,
@ -54,6 +59,7 @@ const confirm = () => {
params: options
}
TreeApi.addOtherSource(params)
cusAddNodes(window.treeObj, params.parentId, [params])
})
}
defineExpose({

View File

@ -41,19 +41,20 @@ const confirm = () => {
positions: positions
})
delete options.host
let selectedNodes = window.treeObj.getSelectedNodes()
let params = {
id: id,
sourceName: name,
sourceType: 'standText',
parentId:
selectedNodes && selectedNodes[selectedNodes.length - 1]
? selectedNodes[selectedNodes.length - 1].id
: undefined,
// "treeIndex": 0,
params: options
}
TreeApi.addOtherSource(params)
console.log('options', options)
// let selectedNodes = window.treeObj.getSelectedNodes()
// let params = {
// id: id,
// sourceName: name,
// sourceType: 'standText',
// parentId:
// selectedNodes && selectedNodes[selectedNodes.length - 1]
// ? selectedNodes[selectedNodes.length - 1].id
// : undefined,
// // "treeIndex": 0,
// params: options
// }
// TreeApi.addOtherSource(params)
})
}
defineExpose({

View File

@ -102,6 +102,7 @@ let originalOptions: any
let that: any
const colorRef = ref(null)
const open = async (id: any) => {
console.log('id', id)
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that
@ -131,12 +132,12 @@ const confirm = () => {
delete params.name
let params2 = {
"id": params.id,
"sourceName": params.name,
"sourceName": params.text,
"params": params,
"isShow": params.show ? 1 : 0,
}
TreeApi.updateDirectoryInfo(params2)
cusUpdateNode({ "id": params.id, "sourceName": params.name, "params": JSON.stringify(params) })
cusUpdateNode({ "id": params.id, "sourceName": params.text, "params": JSON.stringify(params) })
}
const close = () => {
baseDialog.value?.close()

View File

@ -61,6 +61,7 @@ let originalOptions: any
let that: any
const colorRef = ref(null)
const open = async (id: any) => {
id = (window as any).standTextid
that = window.earth.entityMap.get(id)
originalOptions = structuredClone(that.options)
entityOptions.value = that

View File

@ -28,6 +28,7 @@ export const useRightOperate = () => {
const editNode = (eventBus) => {
let selectNodes = getSelectedNodes(window.treeObj);
if (selectNodes && selectNodes[selectNodes.length - 1]) {
console.log('------------------',selectNodes[selectNodes.length - 1].params)
let params = JSON.parse(selectNodes[selectNodes.length - 1].params)
eventBus.emit("openDialog", selectNodes[selectNodes.length - 1].sourceType, params.id);
}
@ -73,6 +74,13 @@ export const useRightOperate = () => {
if (selectNodes && selectNodes[selectNodes.length - 1]) {
let node = selectNodes[selectNodes.length - 1]
let params = JSON.parse(node.params)
if(!params) {
params = {
name: node.sourceName,
show: node.isShow,
id: node.id,
}
}
let entityObject = window.earth.entityMap.get(params.id)
entityObject.setCustomView()
params.customView = entityObject.customView
@ -83,7 +91,7 @@ export const useRightOperate = () => {
"parentId": node.parentId,
"treeIndex": node.treeIndex,
"params": params,
"isShow": node.isShow ? 1 : 0,
"isShow": node.isShow ? 1 : 0 ? 1 : 0,
}
TreeApi.updateDirectoryInfo(params2)
}

View File

@ -435,8 +435,22 @@ export const useTree = () => {
for (let i = 0; i < zNodes.value.length; i++) {
if (zNodes.value[i].params) {
let params = JSON.parse(zNodes.value[i].params)
if (!params.id) {
params.id = zNodes.value[i].id
}
initMapData(zNodes.value[i].sourceType, params)
}
else {
//@ts-ignore
if (zNodes.value[i].detail) {
//@ts-ignore
let detail = JSON.parse(zNodes.value[i].detail)
if (!detail.id) {
detail.id = zNodes.value[i].id
}
initMapData(zNodes.value[i].sourceType, detail)
}
}
}
}
}

View File

@ -1,6 +1,7 @@
export const initMapData = async (type, data) => {
let entityObject
let options
console.log('data', type, data)
switch (type) {
case 'groundText':
entityObject = new YJ.Obj.GroundText(window.earth, data)
@ -39,6 +40,18 @@ export const initMapData = async (type, data) => {
case 'model':
entityObject = new YJ.Obj.ModelObject(window.earth, data)
break
case 'terrain':
data.host = 'http://192.168.110.25:8848'
entityObject = new YJ.Obj.Terrain(window.earth, data)
break
case 'layer':
data.host = 'http://192.168.110.25:8848'
entityObject = new YJ.Obj.Layer(window.earth, data)
break
case 'tileset':
data.host = 'http://192.168.110.25:8848'
entityObject = new YJ.Obj.Tileset(window.earth, data)
break
default:
return
break

View File

@ -18,6 +18,25 @@
accept=".jpeg,.png,.jpg,.mp4,.pdf"
@input="uploadFile"
/>
<!-- 多点视线分析 -->
<Visibility ref="visibility"></Visibility>
<CircleViewShed ref="CircleViewShed"></CircleViewShed>
<Submerge ref="Submerge"></Submerge>
<Profile ref="Profile"></Profile>
<ViewShed ref="ViewShed"></ViewShed>
<CutFill ref="CutFill"></CutFill>
<Contour ref="Contour"></Contour>
<RoutePlanning ref="RoutePlanning"></RoutePlanning>
<Graffiti ref="Graffiti"></Graffiti>
<!-- <FlyRoam ref="FlyRoam"></FlyRoam> -->
<CoorLocation ref="CoorLocation"></CoorLocation>
<ScreenShot ref="ScreenShot"></ScreenShot>
<TerrainExcavation ref="TerrainExcavation"></TerrainExcavation>
<ProjConvert ref="ProjConvert"></ProjConvert>
<ProjectionConvert ref="ProjectionConvert"></ProjectionConvert>
<GoodsSearchCircle ref="GoodsSearchCircle"></GoodsSearchCircle>
<GoodsSearchPolgon ref="GoodsSearchPolgon"></GoodsSearchPolgon>
</template>
<script setup lang="ts">
@ -34,9 +53,28 @@ import attackArrow from '../components/propertyBox/attackArrow.vue'
import richText from '../components/propertyBox/richText.vue'
import groundText from '../components/propertyBox/groundText.vue'
import standText from '../components/propertyBox/standText.vue'
import circleObject from '../components/propertyBox/circleObject.vue'
import addDirectory from '@/components/dialog/directory.vue'
import firstMenu from '@/views/components/leftSide/leftSideFirst.vue'
import bottomMenu from '@/views/components/bottomSide/bottomSide.vue'
import Visibility from '../components/propertyBox/Visibility.vue'
import CircleViewShed from '../components/propertyBox/CircleViewShed.vue'
import Submerge from '../components/propertyBox/Submerge.vue'
import Profile from '../components/propertyBox/Profile.vue'
import ViewShed from '../components/propertyBox/ViewShed.vue'
import CutFill from '../components/propertyBox/CutFill.vue'
import Contour from '../components/propertyBox/Contour.vue'
import RoutePlanning from '../components/propertyBox/RoutePlanning.vue'
import Graffiti from '../components/propertyBox/Graffiti.vue'
import FlyRoam from '../components/propertyBox/FlyRoam.vue'
import CoorLocation from '../components/propertyBox/CoorLocation.vue'
import ScreenShot from '../components/propertyBox/ScreenShot.vue'
import TerrainExcavation from '../components/propertyBox/TerrainExcavation.vue'
import ProjConvert from '../components/propertyBox/ProjConvert.vue'
import ProjectionConvert from '../components/propertyBox/ProjectionConvert.vue'
import GoodsSearchCircle from '../components/propertyBox/GoodsSearchCircle.vue'
import GoodsSearchPolgon from '../components/propertyBox/GoodsSearchPolgon.vue'
import { GisApi } from '@/api/gisApi'
const firstMenuRef = ref(null)
@ -56,7 +94,7 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
case 'groundText':
currentComponent.value = groundText
await nextTick()
dynamicComponentRef.value?.open()
dynamicComponentRef.value?.open(id)
break
case 'addStandText':
currentComponent.value = addStandText
@ -66,7 +104,7 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
case 'standText':
currentComponent.value = standText
await nextTick()
dynamicComponentRef.value?.open()
dynamicComponentRef.value?.open(id)
break
case 'point':
currentComponent.value = billboardObject
@ -90,17 +128,17 @@ eventBus.on('openDialog', async (sourceType: any, id: any) => {
dynamicComponentRef.value?.open(id)
break
case 'circle':
currentComponent.value = polygonObject
currentComponent.value = circleObject
await nextTick()
dynamicComponentRef.value?.open(id, 'circle')
break;
break
case 'rectangle':
currentComponent.value = polygonObject
await nextTick()
dynamicComponentRef.value?.open(id, 'rectangle')
break
case 'rendezvous':
currentComponent.value = rendezvous
currentComponent.value = polygonObject
await nextTick()
dynamicComponentRef.value?.open(id, 'rendezvous')
break