态势增加
This commit is contained in:
@ -41,16 +41,16 @@ export default defineConfig({
|
||||
plugins: [{name: 'removeAttrs', params: {attrs: ['fill', 'stroke', 'stroke-width']}}]
|
||||
}
|
||||
})
|
||||
]
|
||||
// server: {
|
||||
// port: 8848,
|
||||
// proxy: {
|
||||
// '/api': {
|
||||
// target: localStorage.getItem('ip') || 'http://127.0.0.1:8848',
|
||||
// changeOrigin: true,
|
||||
// rewrite: (path) => path.replace(/^\/api/, '')
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
],
|
||||
/*server: {
|
||||
port: 8848,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: localStorage.getItem('ip') || 'http://127.0.0.1:8848',
|
||||
changeOrigin: true,
|
||||
rewrite: (path) => path.replace(/^\/api/, '')
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
})
|
||||
|
||||
100
package-lock.json
generated
100
package-lock.json
generated
@ -9,6 +9,7 @@
|
||||
"version": "1.0.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"@electron/remote": "^2.1.3",
|
||||
@ -20,6 +21,7 @@
|
||||
"electron-updater": "^6.3.9",
|
||||
"element-plus": "^2.10.4",
|
||||
"express": "^5.1.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"mitt": "^3.0.1",
|
||||
"moment": "^2.30.1",
|
||||
"pinia": "^3.0.3",
|
||||
@ -30,7 +32,8 @@
|
||||
"vue-clipboard3": "^2.0.0",
|
||||
"vue-i18n": "^9.14.5",
|
||||
"vue-router": "^4.5.1",
|
||||
"vuedraggable": "^2.24.3"
|
||||
"vuedraggable": "^2.24.3",
|
||||
"xlsx": "^0.18.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config-prettier": "3.0.0",
|
||||
@ -60,6 +63,11 @@
|
||||
"vue-tsc": "^3.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@amap/amap-jsapi-loader": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
|
||||
"integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
|
||||
@ -3471,6 +3479,14 @@
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/adler-32": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/adler-32/-/adler-32-1.3.1.tgz",
|
||||
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-7.1.4.tgz",
|
||||
@ -4561,6 +4577,18 @@
|
||||
],
|
||||
"license": "CC-BY-4.0"
|
||||
},
|
||||
"node_modules/cfb": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/cfb/-/cfb-1.2.2.tgz",
|
||||
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||
"dependencies": {
|
||||
"adler-32": "~1.3.0",
|
||||
"crc-32": "~1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
|
||||
@ -4782,6 +4810,14 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/codepage": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmmirror.com/codepage/-/codepage-1.15.0.tgz",
|
||||
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/collection-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||
@ -5080,9 +5116,7 @@
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz",
|
||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"crc32": "bin/crc32.njs"
|
||||
},
|
||||
@ -6971,6 +7005,11 @@
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/file-saver": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz",
|
||||
"integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
|
||||
},
|
||||
"node_modules/filelist": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/filelist/-/filelist-1.0.4.tgz",
|
||||
@ -7173,6 +7212,14 @@
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/frac": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/frac/-/frac-1.1.2.tgz",
|
||||
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/fragment-cache": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmmirror.com/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||
@ -12056,6 +12103,17 @@
|
||||
"devOptional": true,
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/ssf": {
|
||||
"version": "0.11.2",
|
||||
"resolved": "https://registry.npmmirror.com/ssf/-/ssf-0.11.2.tgz",
|
||||
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||
"dependencies": {
|
||||
"frac": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/ssri": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/ssri/-/ssri-9.0.1.tgz",
|
||||
@ -14318,6 +14376,22 @@
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
},
|
||||
"node_modules/wmf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/wmf/-/wmf-1.0.2.tgz",
|
||||
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/word": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/word/-/word-0.3.0.tgz",
|
||||
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||
@ -14371,6 +14445,26 @@
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/xlsx": {
|
||||
"version": "0.18.5",
|
||||
"resolved": "https://registry.npmmirror.com/xlsx/-/xlsx-0.18.5.tgz",
|
||||
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||
"dependencies": {
|
||||
"adler-32": "~1.3.0",
|
||||
"cfb": "~1.2.1",
|
||||
"codepage": "~1.15.0",
|
||||
"crc-32": "~1.2.1",
|
||||
"ssf": "~0.11.2",
|
||||
"wmf": "~1.0.1",
|
||||
"word": "~0.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"xlsx": "bin/xlsx.njs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/xml-name-validator": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
server:
|
||||
host: 192.168.110.25
|
||||
host: 127.0.0.1
|
||||
port: 8848
|
||||
sdk:
|
||||
port: 8888
|
||||
@ -11,7 +11,8 @@ spring:
|
||||
active: sqlite
|
||||
mysql:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://192.168.110.65:6975/yjearth?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
url: >-
|
||||
jdbc:mysql://192.168.110.65:6975/yjearth?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||
username: yjearth
|
||||
password: kNGxrsSSYMexZ2t4
|
||||
servlet:
|
||||
|
||||
@ -1 +1 @@
|
||||
41b/ujShRZRf9Aa433FD3uyIZuxWSSqXWXlc2dyQfJ75ED0HNbadcdsPF5CaMuJ6K2c3U/eBcWiXXw090/O7M5mJze/MavZ4dhk4dZIukMhEma6Itmejr90pn+gFvssT+K8dBcDoUM+RDY1LtwJQK1Q7xhv64OC8hJEz9SZwU6fZUtqT1yBvSl/eVexWpCiXlWycIXbMRGZlcnP79n+JFfbgQ9cOYdBaVOBJnQkRxNy3PEo7PUvWgPQrpixYxT9ynjLJChAg7DYvIou8Zy16Ag==
|
||||
41b/ujShRZRf9Aa433FD3uyIZuxWSSqXWXlc2dyQfJ75ED0HNbadcdsPF5CaMuJ624E+iLBfS14muki3Kp1qv3N0KPVdc0TjJDyrO+AVfwE3xW3RZy00SBFwUgG/tIU6bBTw4XijzGn57R1nl7djDeP1sx04fzNeWSLujfPS4hzwLryTr1ScTPGegLiv1C+rXsbkAxFf47uMIGGK0M2VBZTA9+UoajQ1PHwDUdI7Sfo2JRzkCFW8v6WI1jCNPaFyLypkZtybW+yeNEhnp/jeYw==
|
||||
Binary file not shown.
Binary file not shown.
@ -36,4 +36,4 @@ for %%J in (!TARGET_JARS!) do (
|
||||
:: 清理临时文件
|
||||
del "!TEMP_FILE!" >nul 2>&1
|
||||
echo. && echo 操作完成
|
||||
endlocal && pause
|
||||
endlocal
|
||||
4
src/renderer/components.d.ts
vendored
4
src/renderer/components.d.ts
vendored
@ -12,6 +12,7 @@ declare module 'vue' {
|
||||
Directory: typeof import('./src/components/dialog/directory.vue')['default']
|
||||
DirectoryEdit: typeof import('./src/components/dialog/directoryEdit.vue')['default']
|
||||
ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer']
|
||||
ElBotton: typeof import('element-plus/es')['ElBotton']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElCard: typeof import('element-plus/es')['ElCard']
|
||||
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||
@ -26,6 +27,8 @@ declare module 'vue' {
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElOption: typeof import('element-plus/es')['ElOption']
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||
ElSlider: typeof import('element-plus/es')['ElSlider']
|
||||
@ -35,6 +38,7 @@ declare module 'vue' {
|
||||
ElTableV2: typeof import('element-plus/es')['ElTableV2']
|
||||
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
||||
ElTree: typeof import('element-plus/es')['ElTree']
|
||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||
Index_b: typeof import('./src/components/SvgIcon/index_b.vue')['default']
|
||||
|
||||
BIN
src/renderer/src/assets/img/tour.png
Normal file
BIN
src/renderer/src/assets/img/tour.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 973 B |
@ -14,8 +14,8 @@ if (window && window.process && window.process.type === 'renderer') {
|
||||
baseURL = localStorage.getItem('ip') || 'http://127.0.0.1:8848'
|
||||
// baseURL = 'http://127.0.0.1:8848'
|
||||
} else {
|
||||
localStorage.setItem('ip', 'http://192.168.110.25:8848')
|
||||
baseURL = 'http://192.168.110.25:8848'
|
||||
localStorage.setItem('ip', 'http://192.168.110.71:8848')
|
||||
baseURL = 'http://192.168.110.71:8848'
|
||||
}
|
||||
// localStorage.setItem('service', baseURL)
|
||||
|
||||
@ -75,7 +75,7 @@ service.interceptors.response.use(
|
||||
(response: AxiosResponse) => {
|
||||
const key = getRequestKey(response.config)
|
||||
pendingRequests.delete(key)
|
||||
console.log(response);
|
||||
// console.log(response);
|
||||
|
||||
// 统一处理HTTP状态码
|
||||
if (response.status === 200) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import {TreeApi} from '@/api/tree'
|
||||
import {useTreeNode} from '../views/components/tree/hooks/treeNode'
|
||||
import {initMapData} from './initMapData'
|
||||
|
||||
export const addMapSource = async ({type, id, sourceName = '未命名对象', opt = {}}) => {
|
||||
const {cusAddNodes} = useTreeNode()
|
||||
if (!id) {
|
||||
@ -13,8 +14,7 @@ export const addMapSource = async ({ type, id, sourceName = '未命名对象', o
|
||||
if (node) {
|
||||
if (node.sourceType === 'directory') {
|
||||
parentId = node.id
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parentId = node.parentId
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {leftClick, rightClick} from '../../src/views/components/tree/entityClick'
|
||||
import {renderVector} from '../views/components/tree/components/hooks/renderVector'
|
||||
|
||||
export const initMapData = async (type, data, cd) => {
|
||||
let entityObject
|
||||
let options
|
||||
@ -49,7 +50,8 @@ export const initMapData = async (type, data, cd) => {
|
||||
case 'military':
|
||||
console.log('data', data)
|
||||
entityObject = new YJ.Obj.GroundSvg(window.earth, data)
|
||||
entityObject.load(() => { })
|
||||
entityObject.load(() => {
|
||||
})
|
||||
break
|
||||
case 'terrain':
|
||||
data.host = baseURL
|
||||
@ -108,7 +110,8 @@ export const initMapData = async (type, data, cd) => {
|
||||
entityObject = new YJ.Obj.RadarScanStereoscopic(window.earth, data)
|
||||
break
|
||||
case 'textBox':
|
||||
entityObject = new YJ.Obj.TextBox(window.earth, data, () => { })
|
||||
entityObject = new YJ.Obj.TextBox(window.earth, data, () => {
|
||||
})
|
||||
break
|
||||
case 'polyhedronObject':
|
||||
entityObject = new YJ.Obj.PolyhedronObject(window.earth, data)
|
||||
@ -165,6 +168,7 @@ export const initMapData = async (type, data, cd) => {
|
||||
}
|
||||
return opt
|
||||
}
|
||||
|
||||
options = getOptions()
|
||||
console.log('--------------------onClick')
|
||||
//鼠标左键点击事件
|
||||
|
||||
@ -75,6 +75,7 @@ if (!localStorage.getItem("AMapKey")) {
|
||||
// 注册全局指令
|
||||
(window as any)._winMap = new Map();
|
||||
(window as any)._entityMap = new Map();
|
||||
(window as any).did_ts_Arr = [];
|
||||
const setApp = createApp(App)
|
||||
// 定义全局方法
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ const routes = [
|
||||
component: () => import('@/views/login/index.vue'),
|
||||
hidden: true
|
||||
},
|
||||
{path: '/ts', component: () => import('@/views/TS/index.vue'), hidden: true},
|
||||
{path: '/tsEdit', component: () => import('@/views/TS/edit.vue'), hidden: true},
|
||||
{path: '/ts', component: () => import('@/views/TS/list.vue'), hidden: true},
|
||||
{path: '/tsEdit', name: 'tsEdit', component: () => import('@/views/TS/edit.vue'), hidden: true},
|
||||
{path: '/404', component: () => import('@/views/404.vue'), hidden: true},
|
||||
|
||||
{
|
||||
|
||||
@ -12,15 +12,102 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="treeBox">
|
||||
<ul id="treeDemos" class="ztree" :setting="setting"></ul>
|
||||
<ul id="treeDemos" class="ztree"></ul>
|
||||
<rightMenuTs ref="rightMenuRef" class="absolute zIndex99"></rightMenuTs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {onMounted, ref} from 'vue'
|
||||
import {onMounted, ref, nextTick} from 'vue'
|
||||
import {Search} from '@element-plus/icons-vue'
|
||||
import rightMenuTs from './components/rightMenuTs.vue'
|
||||
import {useTreeNode} from "../components/tree/hooks/treeNode";
|
||||
import {$changeComponentShow} from "../../utils/communication";
|
||||
|
||||
const {getSelectedNodes, cusSelectNode, getSameLevel, cusNodeIcon, nodeType} = useTreeNode()
|
||||
import {showRightMenuTs} from "./tree"
|
||||
|
||||
const rightMenuRef: any = ref()
|
||||
const treeObj = ref() //树形的实例
|
||||
const nodes: any = ref([])
|
||||
let input2 = ref('')
|
||||
onMounted(() => {
|
||||
let data = [
|
||||
{
|
||||
name: "88",
|
||||
sourceType: "directory"
|
||||
}
|
||||
]
|
||||
treeObj.value = $.fn.zTree.init($(`#treeDemos`), setting, data)
|
||||
window.treeObj = treeObj.value
|
||||
})
|
||||
const onClick = (event: MouseEvent, treeId: string, treeNode: any) => {
|
||||
console.log('selectNode', treeNode)
|
||||
|
||||
let isShift = event.shiftKey
|
||||
let isCtrl = event.ctrlKey
|
||||
if (!isCtrl || !isShift) {
|
||||
let source_ids: any = [];
|
||||
// 判断是否是图层文件
|
||||
if (treeNode.sourceType == "directory") {
|
||||
// 获取treeNode下面的所有souer_id
|
||||
if (treeNode.children) {
|
||||
treeNode.children.forEach((item) => {
|
||||
source_ids.push(item.id);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
source_ids.push(treeNode.id);
|
||||
}
|
||||
// YJ.Global.splitScreen.setActiveId(source_ids);
|
||||
}
|
||||
}
|
||||
const onMouseDown = (event: MouseEvent, treeId: string, treeNode: any) => {
|
||||
console.log("onMouseDown")
|
||||
let isShift = event.shiftKey
|
||||
let isCtrl = event.ctrlKey
|
||||
if ((!isShift && !isCtrl) || !treeNode) {
|
||||
nodes.value = []
|
||||
}
|
||||
if (treeNode) {
|
||||
//判断是否是图层文件
|
||||
if (isCtrl) {
|
||||
let isSelected = treeObj.value
|
||||
.getSelectedNodes()
|
||||
.some((node: any) => node.id === treeNode.id)
|
||||
if (isSelected) {
|
||||
// 如果节点已选中,则取消选中
|
||||
nodes.value = nodes.value.filter((node: any) => node.id !== treeNode.id)
|
||||
} else {
|
||||
// 如果节点未选中,则添加到选中列表
|
||||
nodes.value.push(treeNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
treeObj.value.cancelSelectedNode()
|
||||
$changeComponentShow('.rightMenuTs', false)
|
||||
}
|
||||
}
|
||||
let rightClick = (event: MouseEvent, treeId: string, treeNode: any) => {
|
||||
let selectNodes = getSelectedNodes(treeObj.value)
|
||||
let isnewSelect = true //是否为新选中
|
||||
selectNodes.forEach((item: any) => {
|
||||
if (treeNode && item.id == treeNode.id) isnewSelect = false
|
||||
})
|
||||
if (!event.ctrlKey && (selectNodes.length < 2 || isnewSelect))
|
||||
cusSelectNode(treeObj.value, treeNode)
|
||||
const menus = showRightMenuTs(event, treeObj.value, getSelectedNodes(treeObj.value), nodeType)
|
||||
console.log('menus', menus)
|
||||
if (menus.length == 0) {
|
||||
// $changeComponentShow('.rightMenu', false)
|
||||
return
|
||||
}
|
||||
nextTick(() => {
|
||||
rightMenuRef.value.initMenus(menus, treeNode)
|
||||
})
|
||||
console.log("树形节点右键点击", treeNode)
|
||||
}
|
||||
const setting = {
|
||||
edit: {
|
||||
enable: true,
|
||||
@ -55,7 +142,10 @@ const setting = {
|
||||
},
|
||||
},
|
||||
callback: {
|
||||
/*onRightClick: this.rightClick,
|
||||
onMouseDown: onMouseDown,
|
||||
onRightClick: rightClick,
|
||||
onClick: onClick,
|
||||
/*
|
||||
onClick: this.onClick,
|
||||
onDblClick: this.onDblClick,
|
||||
onCheck: this.onCheck,
|
||||
@ -74,13 +164,6 @@ const setting = {
|
||||
},
|
||||
}
|
||||
|
||||
let input2 = ref('')
|
||||
onMounted(() => {
|
||||
let data = [
|
||||
{name: "88"}
|
||||
]
|
||||
$.fn.zTree.init($(`#treeDemos`), setting, data)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -88,7 +171,7 @@ onMounted(() => {
|
||||
width: 16.3vw;
|
||||
height: 59.6vh;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
z-index: 999;
|
||||
top: 13.4259259259vh;
|
||||
right: 1.5625vw;
|
||||
border: 0.078125vw solid rgb(0, 255, 255);
|
||||
@ -101,6 +184,10 @@ onMounted(() => {
|
||||
.treeBox {
|
||||
border: 1px solid red;
|
||||
flex: auto;
|
||||
|
||||
.ztree {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
118
src/renderer/src/views/TS/components/chart.vue
Normal file
118
src/renderer/src/views/TS/components/chart.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<div class="chart" @scroll="scroll">
|
||||
<div class="area">
|
||||
<!-- 给 hr 和 row 增加 key,确保更新时重新渲染 -->
|
||||
<template v-for="(_,index) in hr" :key="index">
|
||||
<hr :style="hrStyle(index)">
|
||||
</template>
|
||||
<template v-for="(event,index) in eventList" :key="index">
|
||||
<div class="row" :style="getStyle">
|
||||
<div class="bar" :style="progressStyle(event)">{{ event.name + event.duration_time }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {computed, ref, watchEffect} from "vue";
|
||||
|
||||
const props = defineProps(['eventList', 'hr', 'originHrOffset', 'scrollLeft'])
|
||||
|
||||
// 1. 定义响应式变量,用于强制更新
|
||||
const refreshKey = ref(0)
|
||||
|
||||
// 2. 监听 preSecondPx 变化,触发更新
|
||||
// 注意:如果 preSecondPx 变化时没有触发此函数,需要在修改 preSecondPx 的地方手动调用 refresh()
|
||||
watchEffect(() => {
|
||||
// 访问外部变量,建立依赖关联
|
||||
const currentPreSecondPx = window['tsObj']._Store._scales.preSecondPx
|
||||
// 打印日志验证是否监听到变化(测试用)
|
||||
console.log('当前 preSecondPx:', currentPreSecondPx)
|
||||
})
|
||||
|
||||
// 3. 手动刷新函数(如果 watchEffect 不生效,需要在修改 preSecondPx 的地方调用此函数)
|
||||
const refresh = () => {
|
||||
refreshKey.value++ // 修改响应式变量,触发依赖更新
|
||||
}
|
||||
// 暴露给全局,方便外部调用(如果 preSecondPx 在外部修改)
|
||||
window['refreshChart'] = refresh
|
||||
|
||||
let scroll = (e) => {
|
||||
console.log("ssss")
|
||||
let scrollLeft = e.srcElement.scrollLeft
|
||||
let scrollTop = e.srcElement.scrollTop
|
||||
window['tsAction']({
|
||||
action: "scroll-chart",
|
||||
obj: {
|
||||
top: scrollTop,
|
||||
left: scrollLeft,
|
||||
deltaX: e.deltaX,
|
||||
deltaY: e.deltaY,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 4. 让 getStyle 依赖 refreshKey
|
||||
let getStyle = computed(() => {
|
||||
refreshKey.value // 加入依赖,确保 refreshKey 变化时重新计算
|
||||
let height = window['tsObj']._Store._scales.cellHeight
|
||||
return `height:${height}px;line-height:${height}px;`
|
||||
})
|
||||
|
||||
let hrStyle = (index) => {
|
||||
let cellHeight = window['tsObj']._Store._scales.cellHeight
|
||||
let top = (index + 1) * cellHeight
|
||||
return `top:${top + props.originHrOffset}px;left:${props.scrollLeft}px`
|
||||
}
|
||||
|
||||
// 5. 让 getWidth 依赖 refreshKey
|
||||
let getWidth = (durationTime) => {
|
||||
refreshKey.value // 加入依赖
|
||||
let width = (durationTime * window['tsObj']._Store._scales.preSecondPx) / 1000;
|
||||
return width;
|
||||
}
|
||||
|
||||
// 6. 让 progressStyle 间接依赖 refreshKey(通过 getWidth)
|
||||
let progressStyle = (task) => {
|
||||
let taskLeft = task.start_time - window['tsObj']._Store._startTimestamp;
|
||||
return {
|
||||
width: getWidth(task.duration_time) * 1000 + "px",
|
||||
left: getWidth(taskLeft) + "px",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 样式不变 */
|
||||
.chart {
|
||||
flex: 1 1 auto;
|
||||
overflow: auto;
|
||||
|
||||
.area {
|
||||
position: relative;
|
||||
|
||||
.row {
|
||||
position: relative;
|
||||
|
||||
.bar {
|
||||
position: absolute;
|
||||
background: rgba(0, 255, 255, 0.5);
|
||||
color: #FFF;
|
||||
height: calc(100% - 1.1px);
|
||||
overflow: hidden;
|
||||
top: 1.1px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
border: none;
|
||||
background: rgba(0, 255, 255, 0.28);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
116
src/renderer/src/views/TS/components/chart1.vue
Normal file
116
src/renderer/src/views/TS/components/chart1.vue
Normal file
@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<div class="chart" @scroll="scroll">
|
||||
<div class="area">
|
||||
<template v-for="(_,index) in hr">
|
||||
<hr :style="hrStyle(index)">
|
||||
</template>
|
||||
<template v-for="(event,index) in eventList">
|
||||
<div class="row" :style="getStyle">
|
||||
<div class="bar" :style="progressStyle(event)">{{ event.name + event.duration_time }}</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {computed, ref, watchEffect, reactive} from "vue";
|
||||
|
||||
// const scales = reactive(window['tsObj']._Store._scales);
|
||||
const props = defineProps(['eventList', 'hr', 'originHrOffset', 'scrollLeft'])
|
||||
// 定义一个响应式变量,用于强制更新
|
||||
// const forceUpdate = ref(0);
|
||||
// // 监听 preSecondPx 变化,触发组件更新
|
||||
// watchEffect(() => {
|
||||
// console.log("访问外部变量,让 watchEffect 捕获依赖", window['tsObj']._Store._scales.preSecondPx)
|
||||
// // 访问外部变量,让 watchEffect 捕获依赖
|
||||
// window['tsObj']._Store._scales.preSecondPx;
|
||||
// // 强制组件重新渲染(通过修改一个响应式变量触发)
|
||||
// forceUpdate.value++;
|
||||
// });
|
||||
|
||||
let scroll = (e) => {
|
||||
console.log("ssss")
|
||||
let scrollLeft = e.srcElement.scrollLeft
|
||||
let scrollTop = e.srcElement.scrollTop
|
||||
window['tsAction']({
|
||||
action: "scroll-chart",
|
||||
obj: {
|
||||
top: scrollTop,
|
||||
left: scrollLeft,
|
||||
deltaX: e.deltaX,
|
||||
deltaY: e.deltaY,
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
let getStyle = computed(() => {
|
||||
let height = window['tsObj']._Store._scales.cellHeight
|
||||
return `height:${height}px;line-height:${height}px;`
|
||||
})
|
||||
let hrStyle = (index) => {
|
||||
|
||||
let cellHeight = window['tsObj']._Store._scales.cellHeight
|
||||
let top = (index + 1) * cellHeight
|
||||
|
||||
// top+scrollTop-scrollTop%cellHeight
|
||||
return `top:${top + props.originHrOffset}px;left:${props.scrollLeft}px`
|
||||
}
|
||||
let getWidth = (durationTime) => {
|
||||
// console.log("durationTime", durationTime)
|
||||
let width = (durationTime * window['tsObj']._Store._scales.preSecondPx) / 1000;
|
||||
//左偏移量中 竖线所占宽度
|
||||
// let widthOfTiny = Math.floor(width / this.Store.scales.distanceOfTicTiny)
|
||||
return width;
|
||||
}
|
||||
let progressStyle = (task) => {
|
||||
// console.log("task", task)
|
||||
|
||||
let taskLeft = task.start_time - window['tsObj']._Store._startTimestamp;
|
||||
/*console.log("task", {
|
||||
width: getWidth(task.duration_time) * 1000 + "px",
|
||||
left: getWidth(taskLeft) + "px",
|
||||
})*/
|
||||
return {
|
||||
width: getWidth(task.duration_time) * 1000 + "px",
|
||||
left: getWidth(taskLeft) + "px",
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chart {
|
||||
flex: 1 1 auto;
|
||||
//background: #5fa5a97d;
|
||||
overflow: auto;
|
||||
|
||||
.area {
|
||||
position: relative;
|
||||
|
||||
.row {
|
||||
//border-bottom: 1px solid rgba(0, 255, 255, 0.28);
|
||||
position: relative;
|
||||
|
||||
.bar {
|
||||
position: absolute;
|
||||
background: rgba(0, 255, 255, 0.5);
|
||||
color: #FFF;
|
||||
height: calc(100% - 1.1px);
|
||||
overflow: hidden;
|
||||
top: 1.1px;
|
||||
}
|
||||
}
|
||||
|
||||
hr {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
//left: 50px;
|
||||
height: 1px;
|
||||
border: none;
|
||||
background: rgba(0, 255, 255, 0.28);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
36
src/renderer/src/views/TS/components/eventParams.vue
Normal file
36
src/renderer/src/views/TS/components/eventParams.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<div class="eventParams">
|
||||
<template v-if="isNoEvent">
|
||||
<div class="tourBox">
|
||||
<img src="../../../assets/img/tour.png">
|
||||
<p>选中事件调整属性</p>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref} from 'vue'
|
||||
|
||||
let isNoEvent = ref(true)
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.eventParams {
|
||||
width: 20%;
|
||||
|
||||
.tourBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
img {
|
||||
width: 71.2px;
|
||||
height: 48.1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
91
src/renderer/src/views/TS/components/grid.vue
Normal file
91
src/renderer/src/views/TS/components/grid.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<div class="grid">
|
||||
<div class="grid-header row">
|
||||
<div v-for="item in columns" :style="item.style">{{ item.name }}</div>
|
||||
</div>
|
||||
<div class="grid-body">
|
||||
<div class="row" :style="getStyle" v-for="(event) in eventList">
|
||||
<span v-for="item in columns" :class="item.key" :style="item.style">{{
|
||||
format(item.key, event[item.key])
|
||||
}}</span>
|
||||
</div>
|
||||
<div :style="style">
|
||||
<!--aa-->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {computed, onMounted, ref} from "vue"
|
||||
|
||||
let columns = ref([{name: '事件名称', key: "name", style: "flex:auto"},
|
||||
{name: '开始时间', key: "start_time", style: "width:120px"},
|
||||
{name: '持续时间', key: "duration_time", style: "width:70px"}])
|
||||
let eventList = ref([])
|
||||
let style = ref({})
|
||||
eventList.value = window['tsObj']._Store._tasks
|
||||
// 格式化时间
|
||||
let format = (key, val) => {
|
||||
if ('start_time' == key) {
|
||||
return window['tsObj'].parseTime(val, "{m}-{d} {h}:{i}:{s}")
|
||||
}
|
||||
return val
|
||||
}
|
||||
let getStyle = computed(() => {
|
||||
return "height:" + window['tsObj']._Store._scales.cellHeight + "px"
|
||||
})
|
||||
onMounted(() => {
|
||||
/* let doms = document.getElementsByClassName("start_time")
|
||||
for (let i = 0; i < doms.length; i++) {
|
||||
doms[i].style.lineHeight = "19px"
|
||||
}*/
|
||||
let panelHeight = window['tsObj']._Store.getDomElement(".chart", 0).getBoundingClientRect().height
|
||||
|
||||
// 转为字符串并按 "." 分割
|
||||
const [whole, decimalStr] = String(panelHeight).split('.');
|
||||
let rest = whole % window['tsObj']._Store.getScale('cellHeight')
|
||||
// 若有小数部分,拼接为 "0.xxx" 后转为数字;否则为 0
|
||||
const decimalPart = decimalStr ? Number(`${rest}.${decimalStr}`) : 0;
|
||||
style.value = {
|
||||
height: `${decimalPart + 10}px`,
|
||||
// opacity: 0
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.grid {
|
||||
width: 400px;
|
||||
border-right: 1px solid rgba(238, 238, 238, 0.5);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.grid-header {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
& > div {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
border-bottom: 1px solid rgba(0, 255, 255, 0.28);
|
||||
align-items: center;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-body {
|
||||
position: relative;
|
||||
overflow-y: inherit;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
134
src/renderer/src/views/TS/components/rightMenuTs.vue
Normal file
134
src/renderer/src/views/TS/components/rightMenuTs.vue
Normal file
@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="rightMenuTs" id="rMenuTs">
|
||||
<div class="menuItem custom_scroll_bar">
|
||||
<div v-if="menus.length > 0">
|
||||
<!--@click="itemClick(item, eventBus)"-->
|
||||
<!--@mouseup="$changeComponentShow('#rMenu', false)"-->
|
||||
<div
|
||||
v-for="item in menus"
|
||||
class="itemBox"
|
||||
@click="itemClick(item, eventBus)"
|
||||
>
|
||||
<div class="itemIcon">
|
||||
<svg-icon :name="item.key" :size="14"></svg-icon>
|
||||
</div>
|
||||
<div class="itemText">
|
||||
{{ t(`rightMenu.${item.key}`) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="itemBox">
|
||||
<div class="itemText">无操作权限</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {useI18n} from 'vue-i18n'
|
||||
import {ref} from 'vue'
|
||||
import {useRightOperate} from "./rightOperate";
|
||||
import {useRightMenu} from "../../components/tree/components/hooks/rightMenu";
|
||||
|
||||
const {t} = useI18n()
|
||||
const {rightMenus} = useRightOperate()
|
||||
const menus: any = ref([]) //右侧菜单
|
||||
const rightClickTreeNode: any = ref()
|
||||
const {itemClick} = useRightMenu()
|
||||
const initMenus = (arr: any, treeNode: any) => {
|
||||
let rightMenu: any = []
|
||||
console.log('rightMenu2222', rightMenu)
|
||||
if (treeNode) {
|
||||
rightClickTreeNode.value = treeNode
|
||||
arr.forEach((menuId: any) => {
|
||||
/*if (menuId == 'addResource' || menuId == 'addBIM') {
|
||||
if (['127.0.0.1', 'localhost'].includes(new URL(getIP()!).hostname)) {
|
||||
rightMenu.push(rightMenus[menuId])
|
||||
}
|
||||
} else {*/
|
||||
rightMenu.push(rightMenus[menuId])
|
||||
// }
|
||||
})
|
||||
} else rightMenu = [rightMenus.addDirectory]
|
||||
console.log('rightMenu', rightMenu)
|
||||
menus.value = rightMenu
|
||||
}
|
||||
// 暴露方法给父组件
|
||||
defineExpose({
|
||||
initMenus
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.rightMenuTs {
|
||||
user-select: none;
|
||||
width: 8.5vw;
|
||||
height: 23vh;
|
||||
border: 1px solid red;
|
||||
visibility: hidden;
|
||||
|
||||
.menuItem {
|
||||
//padding: 1vh .5vw;
|
||||
font-size: 12px;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
// margin-top: 16px;
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
//span{
|
||||
line-height: 20px;
|
||||
|
||||
.itemBox {
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
padding: 5px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* 默认文字颜色 */
|
||||
color: #fff;
|
||||
// transition: all 0.2s ease; /* 添加过渡动画使效果更平滑 */
|
||||
}
|
||||
|
||||
.itemBox:hover {
|
||||
width: 100%;
|
||||
background: rgba(0, 255, 255, 0.2);
|
||||
/* 悬停时的文字颜色 */
|
||||
color: rgba(0, 255, 255, 1);
|
||||
}
|
||||
|
||||
.itemText {
|
||||
text-align: left;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.itemIcon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
/* 关键:通过currentColor继承父元素的文字颜色 */
|
||||
.itemIcon svg {
|
||||
color: inherit; /* 继承itemIcon的颜色 */
|
||||
}
|
||||
|
||||
/* 确保SVG图标正确继承颜色 */
|
||||
.svg-icon {
|
||||
fill: currentColor !important;
|
||||
stroke: currentColor !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
38
src/renderer/src/views/TS/components/rightOperate.ts
Normal file
38
src/renderer/src/views/TS/components/rightOperate.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export const useRightOperate = () => {
|
||||
const addDirectory = () => {
|
||||
// $changeComponentPop('.adddirectoryBox', true)
|
||||
console.log("addDirectory")
|
||||
}
|
||||
const addResource = () => {
|
||||
console.log("addResource")
|
||||
}
|
||||
const addEvent = () => {
|
||||
$(".newEvent")[0].style.display = "block"
|
||||
}
|
||||
const rightMenus: any = reactive({
|
||||
addDirectory: {
|
||||
key: 'addDirectory',
|
||||
callback: addDirectory
|
||||
},
|
||||
addResource: {
|
||||
key: 'addResource',
|
||||
callback: addResource
|
||||
},
|
||||
edit: {
|
||||
key: 'edit',
|
||||
callback: addResource
|
||||
},
|
||||
del: {
|
||||
key: 'del',
|
||||
callback: addResource
|
||||
},
|
||||
addEvent: {
|
||||
key: 'addEvent',
|
||||
callback: addEvent
|
||||
}
|
||||
|
||||
})
|
||||
return {
|
||||
rightMenus
|
||||
}
|
||||
}
|
||||
78
src/renderer/src/views/TS/components/timeScale.vue
Normal file
78
src/renderer/src/views/TS/components/timeScale.vue
Normal file
@ -0,0 +1,78 @@
|
||||
<!--:style="'left:'+(index*Store.scales.distanceOfTicTiny+Store.scales.originOffset)+'px'"-->
|
||||
<template>
|
||||
<div class="timeScale">
|
||||
<!-- 循环数组,确保key唯一 -->
|
||||
<template v-for="(_, index) in ticTiny" :key="index">
|
||||
<span
|
||||
:style="{ left: `${index * distanceOfTicTiny+originOffset}px` }"
|
||||
class="timeline-ticTiny"
|
||||
></span>
|
||||
</template>
|
||||
<template v-for="(item, index) in ticMain">
|
||||
<span class="timeline-ticMain"
|
||||
:style="{ left: `${index * distanceOfTicMain+originMainOffset}px` }"></span>
|
||||
<span class="timeline-ticLabel"
|
||||
:style="{ left: `${index * distanceOfTicMain+originMainOffset}px` }">
|
||||
{{ ticLabel(index) }}
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, watchEffect} from 'vue'
|
||||
|
||||
const props = defineProps(['ticTiny', 'ticMain', 'distanceOfTicTiny', 'distanceOfTicMain', 'originOffset', 'originMainOffset'])
|
||||
|
||||
|
||||
let ticLabel = (val) => {
|
||||
let timeLabels = []
|
||||
/* console.log("timeLabels", this.Store.scales.ticMain)
|
||||
for (let i = 0; i < this.Store.scales.ticMain; i++) {
|
||||
// console.log("timeLabels", this.Store.scales.ticMain)
|
||||
}*/
|
||||
|
||||
// let stamp = this.Store.startTimestamp + val * this.Store.scales.preMains[this.Store.scales.preMainIndex] * 1000// this.Store.scales.preMains[this.Store.scales.preMainIndex] * 1000
|
||||
// return
|
||||
|
||||
// return this.Clock.makeLabel(this.Store.scales.timeLabels[val], "{y}-{m}-{d} {h}:{i}:{s}");
|
||||
return window['tsObj'].parseTime(window['tsObj']._Store.getScale("timeLabels")[val], '{h}:{i}:{s}')
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 样式不变 */
|
||||
.timeScale {
|
||||
height: 30px;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
|
||||
.timeline-ticTiny {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
height: 25%;
|
||||
background: #888;
|
||||
}
|
||||
|
||||
.timeline-ticMain {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 1px;
|
||||
height: 50%;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.timeline-ticLabel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
white-space: nowrap;
|
||||
font-size: 80%;
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
266
src/renderer/src/views/TS/deduction.vue
Normal file
266
src/renderer/src/views/TS/deduction.vue
Normal file
@ -0,0 +1,266 @@
|
||||
<template>
|
||||
<div class="deduction">
|
||||
<!--左侧元素事件面板-->
|
||||
<div class="layoutBox">
|
||||
<div class="control">
|
||||
<span>{{ formatTime(currentStamp) }}</span>
|
||||
<el-icon :size="20" @click="play">
|
||||
<ZoomOut/>
|
||||
</el-icon>
|
||||
<el-icon :size="20" @click="stop">
|
||||
<ZoomIn/>
|
||||
</el-icon>
|
||||
<span class="title">{{ TSOBJ.name }}</span>
|
||||
<span class="zoom">
|
||||
<el-icon :size="20" @click="add(-1)">
|
||||
<ZoomOut/>
|
||||
</el-icon>
|
||||
<el-slider :disabled="true" :max="maxLevel" :min="minLevel" v-model="level" :show-tooltip="false"
|
||||
style="width:80%;padding-right: 8px;"/>
|
||||
<el-icon :size="20" @click="add(1)">
|
||||
<ZoomIn/>
|
||||
</el-icon>
|
||||
</span>
|
||||
</div>
|
||||
<div class="layoutBoxs">
|
||||
<div class="layout">
|
||||
<!-- 左侧事件列表 -->
|
||||
<grid></grid>
|
||||
<!--右侧时间轴容器-->
|
||||
<div class="TLContainer">
|
||||
<div class="timelineCursorBox" :style="{ left: `${cursorLeft || 0}px` }">
|
||||
<!--@mousedown="mousedown" :style="cursorStyle"-->
|
||||
<!--@mouseup="mouseup"-->
|
||||
<!--@mousemove="mousemove"-->
|
||||
<!--<span class="timeline-icon16" v-drags="timing"></span>-->
|
||||
</div>
|
||||
<!-- 时间轴刻度线 -->
|
||||
<timeScale
|
||||
:ticTiny="ticTiny"
|
||||
:ticMain="ticMain"
|
||||
:distanceOfTicTiny="distanceOfTicTiny"
|
||||
:distanceOfTicMain="distanceOfTicMain"
|
||||
:originOffset="originOffset"
|
||||
:originMainOffset="originMainOffset"
|
||||
></timeScale>
|
||||
<!-- 事件色块 -->
|
||||
<chart :eventList="TSOBJ._Store._tasks" :hr="hr" :originHrOffset="originHrOffset"
|
||||
:scrollLeft="scrollLeft"></chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--右侧事件属性面板-->
|
||||
<eventParams></eventParams>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ZoomIn, ZoomOut} from '@element-plus/icons-vue'
|
||||
|
||||
import EventParams from "./components/eventParams.vue"
|
||||
import Grid from "./components/grid.vue"
|
||||
import TimeScale from "./components/timeScale.vue"
|
||||
import Chart from "./components/chart.vue"
|
||||
import {ref, onBeforeUnmount} from "vue"
|
||||
|
||||
let currentStamp = ref(window['tsObj']._Store._startTimestamp)
|
||||
let maxLevel = ref(24)
|
||||
let minLevel = ref(1)
|
||||
let hr = ref(0)
|
||||
let originHrOffset = ref(0)
|
||||
let scrollLeft = ref(0)
|
||||
let cursorLeft = ref(0)
|
||||
let ticTiny = ref(10)
|
||||
let ticMain = ref(10)
|
||||
let distanceOfTicTiny = ref(5)
|
||||
let distanceOfTicMain = ref(5)
|
||||
let originOffset = ref(0)
|
||||
let originMainOffset = ref(0)
|
||||
distanceOfTicMain.value = window['tsObj']._Store.getScale('numOfMain') * distanceOfTicTiny.value
|
||||
const propsMap = {
|
||||
ticTiny,
|
||||
distanceOfTicTiny,
|
||||
ticMain,
|
||||
distanceOfTicMain,
|
||||
originOffset,
|
||||
originMainOffset,
|
||||
hr,
|
||||
scrollLeft,
|
||||
cursorLeft,
|
||||
originHrOffset,
|
||||
currentStamp
|
||||
}
|
||||
// 更新数值触发视图更新
|
||||
window['updateProp'] = (key: string, val: any) => {
|
||||
if (propsMap[key])
|
||||
propsMap[key].value = val
|
||||
}
|
||||
|
||||
|
||||
const level = ref(20)
|
||||
const props = defineProps(['TSOBJ'])
|
||||
console.log(props.TSOBJ)
|
||||
let formatTime = (timeStamp) => {
|
||||
return props.TSOBJ.parseTime(timeStamp)
|
||||
}
|
||||
let play = () => {
|
||||
props.TSOBJ._Clock.animation(props.TSOBJ._Store, eventCallback)
|
||||
}
|
||||
let stop = () => {
|
||||
props.TSOBJ._Clock.stopAnimation()
|
||||
}
|
||||
|
||||
function todoEvent(timeId: number, res: any, isEnd: boolean) {
|
||||
// console.log("todoEvent", res)
|
||||
if (res) {
|
||||
|
||||
if (res.detail && typeof res.detail == "string") {
|
||||
res.detail = JSON.parse(res.detail);
|
||||
}
|
||||
console.log("执行事件对象", res, '1111111111111111111111111111');
|
||||
window['did_ts_Arr'].push(res.id)
|
||||
switch (res.callback) {
|
||||
case 'flicker':
|
||||
let tsEntity = window['earth_ts'].entityMap.get(res.source_id);
|
||||
tsEntity.flyTo()
|
||||
tsEntity.flicker(1000, 10)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let eventCallback = () => {
|
||||
// 将当前时间戳四舍五入掉毫秒部分
|
||||
let timeId = Math.round(props.TSOBJ._Store._currentTimestamp / 1000);
|
||||
timeId *= 1000;
|
||||
// console.log(timeId)
|
||||
let taskIds = [];
|
||||
let dataMap = props.TSOBJ._Store.dealData("start_time");
|
||||
console.log(dataMap)
|
||||
|
||||
let fun = (map, isEnd = false) => {
|
||||
let keys = Array.from(map.keys());
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
let timestamp = keys[i].split("_")[0]
|
||||
|
||||
let event = Array.from(map.values())[i]
|
||||
let flag = props.TSOBJ._Store._currentTimestamp > timestamp && !window.did_ts_Arr.includes(event.id)
|
||||
if (String(keys[i]).indexOf(String(timeId)) > -1 || flag) {
|
||||
taskIds.push(keys[i]);
|
||||
}
|
||||
}
|
||||
taskIds.forEach((item) => {
|
||||
let res = map.get(item);
|
||||
todoEvent(timeId, res, isEnd);
|
||||
});
|
||||
}
|
||||
fun(dataMap)
|
||||
}
|
||||
let add = (num) => {
|
||||
// 大格12个取值,小格间距3个取值,level,8-1
|
||||
|
||||
let res = level.value + num
|
||||
if (res <= maxLevel.value && res >= minLevel.value) {
|
||||
level.value += num
|
||||
window['tsAction']({
|
||||
action: "wheel-timeLine",
|
||||
num: level.value
|
||||
})
|
||||
|
||||
window['refreshChart']()
|
||||
}
|
||||
}
|
||||
onBeforeUnmount(() => {
|
||||
// props.TSOBJ._Clock.stopAnimation()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.deduction {
|
||||
//border: 1px solid red;
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
bottom: 5px;
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
height: 24.5vh;
|
||||
display: flex;
|
||||
background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%), rgba(0, 0, 0, 0.6);
|
||||
backdrop-filter: blur(3.47px);
|
||||
|
||||
.layoutBox {
|
||||
width: 80%;
|
||||
border-right: 1px solid rgba(238, 238, 238, 0.5);
|
||||
|
||||
.control {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
|
||||
.title {
|
||||
left: 62.5%;
|
||||
position: absolute;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.zoom {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.el-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.layoutBoxs {
|
||||
height: calc(100% - 30px);
|
||||
position: relative;
|
||||
border-top: 1px solid rgba(238, 238, 238, 0.5);
|
||||
|
||||
.layout {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.TLContainer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.timelineCursorBox {
|
||||
position: absolute;
|
||||
border-right: 0.5px red solid;
|
||||
height: calc(100% - 16px);
|
||||
z-index: 9;
|
||||
//left: 10px;
|
||||
top: 16px;
|
||||
transition: transform 0.001s ease-in-out;
|
||||
|
||||
.timeline-icon16 {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
//width: vw(16);
|
||||
//height: vw(16);
|
||||
transform: translate(-50%, -16px);
|
||||
background: url("../../assets/img/indicator.png") no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -1,24 +1,78 @@
|
||||
<template>
|
||||
<div class="edit">
|
||||
<div class="edit ts-zyl ">
|
||||
<svg class="icon icon-tuichu" @click="closeSituationEdit" aria-hidden="true">
|
||||
<use xlink:href="#icon-tuichu"></use>
|
||||
</svg>
|
||||
<div id="earthContainer" class="fullSize"></div>
|
||||
<cabin></cabin>
|
||||
<element></element>
|
||||
<deduction :TSOBJ="tsOBJ"></deduction>
|
||||
<newEvent></newEvent>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, onMounted} from "vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import cabin from "./cabin.vue"
|
||||
import element from "./element.vue"
|
||||
import {ref, reactive, onMounted, nextTick} from "vue";
|
||||
import {useRouter, useRoute} from "vue-router";
|
||||
import Cabin from "./cabin.vue"
|
||||
import Element from "./element.vue"
|
||||
import NewEvent from "./newEvent.vue"
|
||||
import Deduction from "./deduction.vue";
|
||||
import {TS} from "./sdk";
|
||||
import * as domain from "domain";
|
||||
|
||||
let tsOBJ = reactive({})
|
||||
const router = useRouter()
|
||||
const closeSituationEdit = () => {
|
||||
router.back()
|
||||
const route = useRoute()
|
||||
let params = {}
|
||||
// 将由列表页面传递过来的参数,数字化
|
||||
for (const routeQueryKey in route.query) {
|
||||
params[routeQueryKey] = route.query[routeQueryKey]
|
||||
if (Number(route.query[routeQueryKey])) {
|
||||
params[routeQueryKey] = Number(route.query[routeQueryKey])
|
||||
}
|
||||
}
|
||||
console.log("params", params)
|
||||
|
||||
// 通过planID获取方案包含的所有事件
|
||||
let getEventList = () => {
|
||||
let events = []
|
||||
for (let i = 0; i < 1; i++) {
|
||||
events.push({
|
||||
id: "task" + i,
|
||||
source_id: "777",
|
||||
name: "闪烁" + i,
|
||||
callback: "flicker",
|
||||
detail: JSON.stringify({}),
|
||||
start_time: params.start_time + (5 * i * (i - 1) / 2 + 10 * i) * 1000,
|
||||
duration_time: (i * 5 + 10)
|
||||
})
|
||||
}
|
||||
newTS(params, events)
|
||||
}
|
||||
// 新建态势推演对象
|
||||
let newTS = (params, events) => {
|
||||
|
||||
window['tsObj'] = new TS({name: params.name, tasks: events, startTimestamp: params.start_time})
|
||||
tsOBJ = window['tsObj']
|
||||
window['tsAction'] = window['tsObj'].initAction()
|
||||
|
||||
console.log("window['tsObj']", window['tsObj'])
|
||||
nextTick(() => {
|
||||
// dom加载完成后,通过宽度和间隔来计算出刻度线的数量
|
||||
window['tsObj']._Store.init()
|
||||
window['tsObj'].renderLabel({left: 0})
|
||||
})
|
||||
}
|
||||
getEventList()
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
let baseURL = localStorage.getItem('service')
|
||||
// getAuthInfo()
|
||||
await YJ.on({host: baseURL})
|
||||
createEarth()
|
||||
})
|
||||
const createEarth = async () => {
|
||||
window.earth_ts = await new YJ.YJEarth('earthContainer', {navigationHelpButton: false})
|
||||
YJ.Global.CesiumContainer(earth_ts, {compass: false, legend: false});
|
||||
@ -26,12 +80,9 @@ const createEarth = async () => {
|
||||
new YJ.Tools(window.earth_ts).flyHome()
|
||||
}, 1000)
|
||||
}
|
||||
onMounted(async () => {
|
||||
let baseURL = localStorage.getItem('service')
|
||||
// getAuthInfo()
|
||||
await YJ.on({host: baseURL})
|
||||
createEarth()
|
||||
})
|
||||
const closeSituationEdit = () => {
|
||||
router.back()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@ -18,23 +18,32 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="treeOrList">
|
||||
<div class="treeOrList" :style="currentTypeId!=''?'height: calc(100% - 300px);':''">
|
||||
<template v-if="dataType=='tree'">
|
||||
<el-tree
|
||||
:data="data"
|
||||
:data="treeData"
|
||||
:props="defaultProps"
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</template>
|
||||
<template v-if="dataType=='list'">
|
||||
<div v-for="item in lists">
|
||||
<div v-for="item in lists" @click="addMarker(item)" class="markerItem">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="list" v-if="showList">
|
||||
<div class="list" v-if="currentTypeId!=''">
|
||||
<div v-for="item in elementList" class="itemBox">
|
||||
<div class="imgbg">
|
||||
<img :src="service + (item.posterDataUrl||item.militaryDataUrl)"/>
|
||||
</div>
|
||||
<!--fit="contain"-->
|
||||
|
||||
<div class="label">
|
||||
{{ item.modelName || item.militaryName }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -42,114 +51,120 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref} from "vue";
|
||||
import {ref, onMounted} from "vue";
|
||||
import {Search} from '@element-plus/icons-vue'
|
||||
import {ModelApi} from "../../api/model";
|
||||
import {GraphApi} from "../../api/graphLabel";
|
||||
import {addMapSource} from "./entity";
|
||||
|
||||
const service = ref(localStorage.getItem('ip'))
|
||||
|
||||
interface Tree {
|
||||
label: string
|
||||
name: string
|
||||
children?: Tree[]
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'name',
|
||||
}
|
||||
|
||||
const activIndex = ref(0)
|
||||
const tabs = [
|
||||
{name: "人工模型", dataType: 'tree',},
|
||||
{name: "军事标绘", dataType: 'tree',},
|
||||
{name: "人工模型", dataType: 'tree', key: "model"},
|
||||
{name: "军事标绘", dataType: 'tree', key: "graph"},
|
||||
{
|
||||
name: "基础标绘", dataType: 'list', children:
|
||||
[
|
||||
{name: "点"},
|
||||
{name: "线"},
|
||||
{name: "面"},
|
||||
{name: "圆"}
|
||||
{name: "点", source_name: "点标注", funName: 'DrawPoint', type: "point"},
|
||||
{name: "线", source_name: "", funName: 'DrawPolyline', type: ""},
|
||||
{name: "面", source_name: "", funName: 'DrawPolygon', type: ""},
|
||||
{name: "圆", source_name: "", funName: 'DrawCircle', type: ""},
|
||||
{name: "攻击箭头", source_name: "", funName: 'DrawAttackArrow', type: ""},
|
||||
{name: "钳形箭头", source_name: "", funName: 'DrawPincerArrow', type: ""}
|
||||
]
|
||||
},
|
||||
{name: "特效", dataType: 'list', children: [{name: "火焰"}]},
|
||||
]
|
||||
let treeData = ref<Tree[]>([])
|
||||
// 模型类型
|
||||
let modelTypes = ref<Tree[]>([])
|
||||
// 军标类型
|
||||
let graphTypes = ref<Tree[]>([])
|
||||
|
||||
|
||||
const data: Tree[] = [
|
||||
{
|
||||
label: 'Level one 1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 1-1',
|
||||
children: [
|
||||
|
||||
{
|
||||
label: 'Level three 1-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level one 2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 2-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level two 2-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 2-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level one 3',
|
||||
children: [
|
||||
{
|
||||
label: 'Level two 3-1',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-1-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Level two 3-2',
|
||||
children: [
|
||||
{
|
||||
label: 'Level three 3-2-1',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
}
|
||||
const lists = ref([])
|
||||
const elementList = ref([])
|
||||
let input2 = ref('')
|
||||
// 显示某类型下的元素
|
||||
const showList = ref(false)
|
||||
// 当前选择类型的Id
|
||||
const currentTypeId = ref('')
|
||||
// 是否为树结构
|
||||
const dataType = ref('tree')
|
||||
// 树形结构节点点击
|
||||
const handleTabClick = (item, index) => {
|
||||
activIndex.value = index
|
||||
currentTypeId.value = ""
|
||||
elementList.value = []
|
||||
|
||||
console.log(item)
|
||||
dataType.value = item.dataType
|
||||
if (item.children) {
|
||||
if (item.key == 'model') {
|
||||
treeData.value = modelTypes.value
|
||||
} else if (item.key == 'graph') {
|
||||
treeData.value = graphTypes.value
|
||||
} else if (item.children) {
|
||||
lists.value = item.children
|
||||
}
|
||||
}
|
||||
const handleNodeClick = (data: Tree) => {
|
||||
console.log(data)
|
||||
showList.value = true
|
||||
const handleNodeClick = (data) => {
|
||||
// console.log(data)
|
||||
currentTypeId.value = currentTypeId.value == data.id ? '' : data.id
|
||||
elementList.value = []
|
||||
if (currentTypeId.value)
|
||||
getModelListByType(currentTypeId.value)
|
||||
}
|
||||
onMounted(async () => {
|
||||
await getModelTypeList()
|
||||
await getGraphTypeList()
|
||||
// console.log("modelTypes.value", modelTypes.value)
|
||||
treeData.value = modelTypes.value
|
||||
})
|
||||
// 根据类型获取模型列表
|
||||
const getModelListByType = (id) => {
|
||||
let formData = new FormData()
|
||||
if (activIndex.value == 0) {
|
||||
formData.append('modelTypeId', id)
|
||||
ModelApi.showModelByType(formData).then((res) => {
|
||||
elementList.value = res.data
|
||||
})
|
||||
} else {
|
||||
formData.append('militaryTypeId', id)
|
||||
GraphApi.showModelByType(formData).then((res) => {
|
||||
elementList.value = res.data
|
||||
})
|
||||
}
|
||||
}
|
||||
// 获取模型类型列表
|
||||
let getModelTypeList = async () => {
|
||||
let res = await ModelApi.modelTypeList()
|
||||
if (res.code == 200) {
|
||||
modelTypes.value = res.data
|
||||
}
|
||||
}
|
||||
let getGraphTypeList = async () => {
|
||||
let res = await GraphApi.modelTypeList()
|
||||
if (res.code == 200) {
|
||||
graphTypes.value = res.data
|
||||
}
|
||||
}
|
||||
// 添加标绘
|
||||
let addMarker = (item) => {
|
||||
console.log("绘制" + item.name)
|
||||
window.draw = new YJ.Draw[item.funName](earth_ts)
|
||||
window.draw.start((a, position) => {
|
||||
console.log(position)
|
||||
addMapSource({id: 777, type: item.type, name: item.source_name, position})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@ -204,12 +219,22 @@ const handleNodeClick = (data: Tree) => {
|
||||
|
||||
.treeOrList {
|
||||
//flex: auto;
|
||||
height: calc(100% - 300px);
|
||||
|
||||
overflow-y: auto;
|
||||
|
||||
.el-tree {
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.markerItem {
|
||||
cursor: pointer;
|
||||
padding-left: 4px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 255, 255, 0.38);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -217,6 +242,34 @@ const handleNodeClick = (data: Tree) => {
|
||||
border: 1px solid #eee;
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
|
||||
.itemBox {
|
||||
//border: 1px solid red;
|
||||
text-align: center;
|
||||
max-width: 100%;
|
||||
white-space: normal; /* 允许文本换行(默认值,但需确保未被覆盖) */
|
||||
word-break: break-all;
|
||||
|
||||
.imgbg {
|
||||
width: 80px;
|
||||
height: 79px;
|
||||
margin: 0 auto;
|
||||
background: url("../../assets/images/model-bg.png") no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -231,6 +284,10 @@ const handleNodeClick = (data: Tree) => {
|
||||
//border: 1px solid #0ff;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content>.el-tree-node__expand-icon) {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content:hover ) {
|
||||
--el-tree-node-hover-bg-color: rgba(0, 255, 255, 0.38);
|
||||
//--el-tree-node-hover-bg-color: linear-gradient(90deg, rgba(0, 255, 255, 0.5) 0%, rgba(0, 255, 255, 0) 100%) !important;
|
||||
|
||||
28
src/renderer/src/views/TS/entity.ts
Normal file
28
src/renderer/src/views/TS/entity.ts
Normal file
@ -0,0 +1,28 @@
|
||||
export function addMapSource(option) {
|
||||
console.log("添加到地球上", option)
|
||||
let id = option.id || new YJ.Tools().randomString()
|
||||
let name = option.name
|
||||
let entityObject
|
||||
let options
|
||||
let baseURL = localStorage.getItem('ip')
|
||||
switch (option.type) {
|
||||
case 'point':
|
||||
console.log({id, name, position: option.position})
|
||||
entityObject = new YJ.Obj.BillboardObject(window['earth_ts'], {id, name, position: option.position})
|
||||
console.log("添加dian")
|
||||
break;
|
||||
}
|
||||
|
||||
if (entityObject) {
|
||||
function getOptions() {
|
||||
let opt = structuredClone(entityObject.options)
|
||||
delete opt.host
|
||||
return opt
|
||||
}
|
||||
|
||||
options = getOptions()
|
||||
}
|
||||
console.log('options', options)
|
||||
// 进数据库
|
||||
// 上树
|
||||
}
|
||||
@ -58,7 +58,7 @@
|
||||
<el-table-column align="center" prop="date" label="创建日期" sortable/>
|
||||
<el-table-column align="center" label="操作">
|
||||
<template #default="scope">
|
||||
<el-button text size="small" type="primary" :icon="Edit" @click="toTSEdit">编辑</el-button>
|
||||
<el-button text size="small" type="primary" :icon="Edit" @click="toTSEdit(scope.row)">编辑</el-button>
|
||||
<el-button text size="small" type="primary" :icon="Delete">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@ -155,8 +155,13 @@ const search = () => {
|
||||
const reset = () => {
|
||||
searchParams.value = {name: "", create_by: "", datetime: ""}
|
||||
}
|
||||
const toTSEdit = () => {
|
||||
router.push({path: '/tsEdit'})
|
||||
const toTSEdit = (row) => {
|
||||
// router.push({path: '/tsEdit'})
|
||||
console.log("当前推演方案", row)
|
||||
router.push({
|
||||
name: 'tsEdit', // 必须用 name 匹配路由,不能用 path
|
||||
query: {id: 123, name: "战时推演", start_time: 946684800000}
|
||||
})
|
||||
}
|
||||
/*
|
||||
const generateData = (
|
||||
325
src/renderer/src/views/TS/newEvent.vue
Normal file
325
src/renderer/src/views/TS/newEvent.vue
Normal file
@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="newEvent">
|
||||
<el-dialog v-model="isShowPup" :modal="true" draggable :close-on-click-modal="false">
|
||||
<template #header>
|
||||
<div class="set_pup_header">
|
||||
<div class="system_title">
|
||||
<!--{{ t('model.title') }}-->
|
||||
态势事件
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="set_detail">
|
||||
<div class="sort">
|
||||
<el-tree
|
||||
ref="treeRef"
|
||||
style="max-width: 600px"
|
||||
:data="eventTree"
|
||||
:props="defaultProps"
|
||||
node-key="id"
|
||||
:check-on-click-node="true"
|
||||
@node-click="handleNodeClick"
|
||||
:default-expanded-keys="['normal']"
|
||||
:current-node-key="currentKey"
|
||||
:class="{'custom-tree': true}"
|
||||
/>
|
||||
</div>
|
||||
<div class="eventDetail">
|
||||
<template v-if="currentKey&¤tKey!='normal'">
|
||||
<el-form label-width="auto" :model="form" style="max-width: 600px">
|
||||
<el-form-item label="事件名称">
|
||||
<el-input v-model="form.name"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="开始时间">
|
||||
<el-date-picker
|
||||
v-model="form.datetime"
|
||||
type="datetime"
|
||||
placeholder="Select date and time"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="持续时间">
|
||||
<div class="duration">
|
||||
<span>
|
||||
<el-input v-model="hour"/>时
|
||||
</span>
|
||||
<span>
|
||||
<el-input v-model="minute"/>分
|
||||
</span><span>
|
||||
<el-input v-model="second"/>秒
|
||||
</span>
|
||||
|
||||
|
||||
</div>
|
||||
</el-form-item>
|
||||
<template v-if="currentKey=='flicker'">
|
||||
<el-form-item label="闪烁间隔">
|
||||
<div class="duration">
|
||||
<span>
|
||||
<el-input v-model="times"/>秒
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</el-form-item>
|
||||
<el-form-item label="闪烁次数">
|
||||
<div class="duration">
|
||||
<span>
|
||||
<el-input v-model="numbers"/>次
|
||||
</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</template>
|
||||
<template v-if="currentKey=='move'">
|
||||
<el-form-item label="路径是否包含元素点位" label-width="160">
|
||||
<el-switch v-model="isContainModelPosition"/>
|
||||
</el-form-item>
|
||||
<el-button>绘制路径</el-button>
|
||||
</template>
|
||||
|
||||
|
||||
<el-form-item>
|
||||
<div class="optionbtn">
|
||||
<el-button>确定</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div class="placeholder"></div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {ref, reactive} from "vue";
|
||||
import type {RenderContentContext, TreeInstance} from 'element-plus'
|
||||
|
||||
const treeRef = ref<TreeInstance>()
|
||||
// 存储当前需要高亮的节点 key(初始为空)
|
||||
const currentKey = ref<number | null>(1);
|
||||
|
||||
interface Tree {
|
||||
label: string
|
||||
children?: Tree[]
|
||||
}
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
})
|
||||
const hour = ref(0)
|
||||
const minute = ref(0)
|
||||
const second = ref(0)
|
||||
const times = ref(0)//闪烁间隔
|
||||
const numbers = ref(0)//闪烁次数
|
||||
const isContainModelPosition = ref(true)
|
||||
|
||||
form['datetime'] = new Date(2000, 1, 1, 12, 0, 0)
|
||||
const isShowPup = ref(true)
|
||||
const eventTree: { children: ({ label: string } | { label: string })[]; id: string; label: string }[] = [
|
||||
{
|
||||
id: "normal",
|
||||
label: '常用推演事件',
|
||||
children: [
|
||||
{
|
||||
id: "flicker",
|
||||
label: '闪烁事件',
|
||||
},
|
||||
{
|
||||
id: "move",
|
||||
label: '机动事件',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const defaultProps = {
|
||||
children: 'children',
|
||||
label: 'label',
|
||||
}
|
||||
const handleNodeClick = (data: Tree, node, TreeNode, event) => {
|
||||
currentKey.value = data.id; // data.id 为节点的唯一 key(需与 tree 的 node-key 对应)
|
||||
form.name = data.label
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.newEvent {
|
||||
position: absolute;
|
||||
z-index: 99;
|
||||
//bottom: 200px;
|
||||
//left: 50%;
|
||||
//width: 40vw;
|
||||
//height: 50vh;
|
||||
display: none;
|
||||
|
||||
.set_detail {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
||||
.sort {
|
||||
height: 100%;
|
||||
//width: 8vw;
|
||||
width: 150px;
|
||||
overflow-y: auto;
|
||||
|
||||
.el-tree {
|
||||
background: transparent !important;
|
||||
--el-tree-node-hover-bg-color: rgba(var(--color-sdk-base-rgb), 0.2) !important;
|
||||
color: rgba(255, 255, 255, 1) !important;
|
||||
/* font-size: 12px !important; */
|
||||
//width: 130px;
|
||||
float: left;
|
||||
margin-left: 10px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.eventDetail {
|
||||
//flex: auto;
|
||||
width: calc(100% - 170px);
|
||||
overflow-y: auto;
|
||||
|
||||
:deep(.el-input ) {
|
||||
--el-date-editor-width: 100%;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-button:not(.is-text)) {
|
||||
border: 1px solid #0ff;
|
||||
background: rgba(0, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
:deep(.el-button:hover) {
|
||||
color: #0ff;
|
||||
//background-color: transparent !important;
|
||||
background: rgba(0, 255, 255, 0.2) !important;
|
||||
}
|
||||
|
||||
.duration {
|
||||
display: flex;
|
||||
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
color: #fff;
|
||||
|
||||
.el-input {
|
||||
width: 75%;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.optionbtn {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dialog) {
|
||||
background: linear-gradient(180deg, rgba(0, 255, 255, 0.2) 0%, rgba(0, 255, 255, 0) 100%),
|
||||
rgba(0, 0, 0, 0.6);
|
||||
border: 1px solid #00c9ff;
|
||||
padding: 0 !important;
|
||||
width: 30vw;
|
||||
height: 30vh;
|
||||
|
||||
width: 570px;
|
||||
height: 323px;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 0 !important;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
|
||||
:deep(.el-dialog__headerbtn) {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
border-bottom-left-radius: 80%;
|
||||
background-color: #008989;
|
||||
|
||||
&:hover {
|
||||
background-color: #00ffff;
|
||||
|
||||
.el-dialog__close {
|
||||
color: rgba(0, 66, 66, 1); // 悬停时改变关闭图标为红色
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dialog__headerbtn .el-dialog__close) {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.set_pup_header {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// background-color: #00ffff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
//padding-bottom: 20px;
|
||||
|
||||
.system_title {
|
||||
background: url('@/assets/images/titlebg.png') no-repeat;
|
||||
background-size: 100% 100%;
|
||||
width: 229px;
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
text-align: center;
|
||||
font-family: 'alimamashuheiti';
|
||||
font-size: 18px;
|
||||
color: #fff;
|
||||
//font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper), :deep(.el-input__inner ) {
|
||||
background: transparent;
|
||||
--el-input-placeholder-color: #fff;
|
||||
color: #fff;
|
||||
//border: 1px solid #0ff;
|
||||
}
|
||||
|
||||
/*
|
||||
:deep(.el-tree-node__children .is-checked) {
|
||||
background: red;
|
||||
}
|
||||
*/
|
||||
/* 自定义高亮样式(替代默认的高亮) */
|
||||
.custom-tree {
|
||||
&:deep(.el-tree-node.is-current > .el-tree-node__content) {
|
||||
//background-color: #e6f7ff; /* 浅蓝色高亮,可自定义 */
|
||||
|
||||
}
|
||||
|
||||
&:deep(.el-tree-node.is-current > .el-tree-node__content>.el-tree-node__label ) {
|
||||
//background-color: #e6f7ff; /* 浅蓝色高亮,可自定义 */
|
||||
--el-text-color: #0ff !important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
:deep(.el-text ) {
|
||||
--el-text-color: #fff !important;
|
||||
}
|
||||
|
||||
:deep(.el-form-item__label) {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
60
src/renderer/src/views/TS/sdk/Clock.ts
Normal file
60
src/renderer/src/views/TS/sdk/Clock.ts
Normal file
@ -0,0 +1,60 @@
|
||||
export class Clock {
|
||||
_timer1
|
||||
_timer
|
||||
|
||||
constructor() {
|
||||
this._timer1 = null//
|
||||
this._timer = null//
|
||||
}
|
||||
|
||||
animation(store, eventCallback) {
|
||||
let multiplier = 1
|
||||
console.log("开始播放推演")
|
||||
//点击播放按钮时的时间戳
|
||||
let nowTime = Date.now()
|
||||
//每次循环的时间戳差异
|
||||
let diff = 0
|
||||
let timeStamp = 0
|
||||
eventCallback()//立即执行一次回调
|
||||
// 默认每秒执行一次回调(受倍数播放影响)
|
||||
this._timer1 = setInterval((function run() {
|
||||
setTimeout(() => {
|
||||
eventCallback()
|
||||
}, 1000 / multiplier)
|
||||
return run
|
||||
})(), 1000 / multiplier)
|
||||
//每毫米执行,
|
||||
this._timer = setInterval(() => {
|
||||
let now = Date.now()
|
||||
diff = (now - nowTime) * multiplier
|
||||
store._currentTimestamp += diff
|
||||
// 更新UI层的当前时间戳变量
|
||||
window['updateProp']('currentStamp', store._currentTimestamp)
|
||||
nowTime = now
|
||||
// 设置时间指示器位置
|
||||
store.setCursorLeft(store._currentTimestamp)
|
||||
|
||||
/*let now = Date.now()
|
||||
// a+=now-upTime
|
||||
diff = (now - nowTime) * multiplier
|
||||
|
||||
let num = (currentTimestamp += diff)
|
||||
for (let i = 0; i < (now - nowTime) * multiplier; i++) {
|
||||
timeStamp += 1
|
||||
}
|
||||
|
||||
// console.log((now-upTime)*multiplier)
|
||||
nowTime = now
|
||||
// cb(num, diff, timeStamp)*/
|
||||
|
||||
}, 1)
|
||||
}
|
||||
|
||||
stopAnimation() {
|
||||
// this.status=timeStatus.STOP
|
||||
|
||||
this._timer1 && clearInterval(this._timer1)
|
||||
|
||||
this._timer && clearInterval(this._timer)
|
||||
}
|
||||
}
|
||||
156
src/renderer/src/views/TS/sdk/Store.ts
Normal file
156
src/renderer/src/views/TS/sdk/Store.ts
Normal file
@ -0,0 +1,156 @@
|
||||
type ScaleKey = keyof Store['_scales']; // 提取_scales的属性键类型
|
||||
export class Store {
|
||||
|
||||
_scales = {
|
||||
fullWidth: 0,//总宽度
|
||||
fullHeight: 0,//总高度
|
||||
cellHeight: 32,//行高度
|
||||
scrollTop: 0,//面板竖向滚动位置
|
||||
scrollLeft: 0,//面板横向滚动位置
|
||||
cursorLeft: 0,//时间指示器
|
||||
ticTiny: 10,//小格数量
|
||||
distanceOfTicTinyRange: [6, 4, 5],//单个小格子的宽度可选值
|
||||
distanceOfTicTiny: 5, //单个小格子的宽度
|
||||
preMains: this.getPreMains(),// 时间线上大格之间的时间跨度的可选值
|
||||
preMainIndex: 6,//即为60s
|
||||
|
||||
ticMain: 10,//大格数量
|
||||
numOfMain: 30,// 多少小格为一大格子
|
||||
distanceOfTicMain: 30 * 5,//大格之间的距离
|
||||
|
||||
originMainOffset: 0,//起始大格偏移量
|
||||
originOffset: 0,//起始小格偏移量
|
||||
preSecondPx: 0,//一秒所占的宽度
|
||||
timeLabels: [], // 时间
|
||||
//竖向横线的数量,由面板高度和行高度决定
|
||||
hr: 0,
|
||||
//竖向横线的偏移量
|
||||
originHrOffset: 0,
|
||||
};
|
||||
_startTimestamp
|
||||
_currentTimestamp
|
||||
_tasks
|
||||
private _panelWidth //面板宽度
|
||||
|
||||
constructor(option) {
|
||||
this._panelWidth = option.panelWidth
|
||||
this._tasks = option.tasks
|
||||
this._startTimestamp = option.startTimestamp
|
||||
this._currentTimestamp = option.currentTimestamp || option.startTimestamp
|
||||
this._scales = {...this._scales, ...option.scales}
|
||||
let num = this.getScale("distanceOfTicMain") / this.getScale("preMains")[this.getScale("preMainIndex")]
|
||||
console.log(num)
|
||||
this._scales.preSecondPx = num
|
||||
// this.setScale("preSecondPx", num)
|
||||
}
|
||||
|
||||
init() {
|
||||
console.log("初始化:必要dom加载完成后,才能计算出某些值(刻度数量)")
|
||||
let dom = this.getDomElement(".timeScale", 0)
|
||||
if (dom instanceof Element) { // 缩小类型范围
|
||||
let panel = dom.getBoundingClientRect();// 安全调用
|
||||
// console.log(dom.getBoundingClientRect())
|
||||
this._panelWidth = Math.floor(panel.width);
|
||||
dom['style'].width = this._panelWidth + "px"
|
||||
this.setScale("ticTiny", this.ceil(this._panelWidth / this.getScale("distanceOfTicTiny")))
|
||||
this.setScale("ticMain", this.ceil(this._panelWidth / this.getScale("distanceOfTicMain")) + 1)
|
||||
|
||||
|
||||
// this.getMinTimeOfPanel()
|
||||
}
|
||||
let doms = this.getDomElement(".chart", 0)
|
||||
if (doms instanceof Element) {
|
||||
let height = doms.getBoundingClientRect().height
|
||||
this.setScale("hr", Math.floor(height / this._scales.cellHeight))
|
||||
}
|
||||
}
|
||||
|
||||
// 封装对_scales属性的访问器(getter)
|
||||
getScale(key: ScaleKey): any {
|
||||
return this._scales[key];
|
||||
}
|
||||
|
||||
// 封装对_scales属性的修改器(setter),在此处触发监听 tsObj._Store.setScale('ticTiny', 10);
|
||||
setScale(key: ScaleKey, value: any) {
|
||||
const oldValue = this._scales[key];
|
||||
if (oldValue === value) return; // 值未变化则不触发
|
||||
this._scales[key] = value;
|
||||
// 触发回调通知变化
|
||||
// console.log(`属性 ${key} 变化:${oldValue} → ${value}`);
|
||||
let val = value
|
||||
switch (key) {
|
||||
case "distanceOfTicMain":
|
||||
this.setScale("ticMain", this.ceil(this._panelWidth / val))
|
||||
break
|
||||
case "distanceOfTicTiny":
|
||||
// val = Math.ceil(this._panelWidth / value)
|
||||
// window['updateProp'](key, val)
|
||||
this.setScale("distanceOfTicMain", this._scales.numOfMain * this._scales.distanceOfTicTiny)
|
||||
this.setScale("ticTiny", this.ceil(this._panelWidth / val))
|
||||
window['tsObj'].renderLabel({left: this._scales.scrollLeft})
|
||||
break
|
||||
case "ticTiny":
|
||||
val = value
|
||||
|
||||
break
|
||||
case "ticMain":
|
||||
this._scales.timeLabels = this._scales.timeLabels.slice(0, this._scales.ticMain)
|
||||
break
|
||||
}
|
||||
window['updateProp'](key, val)
|
||||
}
|
||||
|
||||
getDomElement(selector, index = -1) {
|
||||
let selectors = '.ts-zyl ' + selector
|
||||
let doms = document.querySelectorAll(selectors)
|
||||
return index == -1 ? doms : doms[index]
|
||||
}
|
||||
|
||||
//面板占满所表示终点时间
|
||||
getMinTimeOfPanel() {
|
||||
// minTime=width*每秒所占宽度
|
||||
console.log(this._panelWidth / this._scales.preSecondPx)
|
||||
// return this._startTimestamp + parseInt(this._panelWidth / this._scales.preSecondPx) * 3000
|
||||
}
|
||||
|
||||
getPreMains() {
|
||||
let s = 1//一秒
|
||||
let m = 60 * s//一分
|
||||
let h = 60 * m//一小时
|
||||
let d = 24 * h//一天
|
||||
return [30 * s, 1 * m, 2 * m, 5 * m, 10 * m, 1 * h, 2 * h, 5 * h/*, 10 * h, 1 * d, 2 * d, 5 * d*/].reverse()
|
||||
}
|
||||
|
||||
ceil(num) {
|
||||
return Math.ceil(num)
|
||||
}
|
||||
|
||||
// 通过时间戳来设置位置
|
||||
setCursorLeft(stamp) {
|
||||
let newLeft = ((stamp - this._startTimestamp) / 1000) * this._scales.preSecondPx - this._scales.scrollLeft
|
||||
this.setScale('cursorLeft', newLeft)
|
||||
// console.log("newLeft", newLeft)
|
||||
}
|
||||
|
||||
dealData(key = "start_time", value = []) {
|
||||
let map = new Map()
|
||||
for (let j = 0; j < this._tasks.length; j++) {
|
||||
|
||||
let obj;
|
||||
if (value.length == 0) {
|
||||
obj = this._tasks[j]
|
||||
} else {
|
||||
let o = {}
|
||||
let key;
|
||||
value.forEach(item => {
|
||||
key = item
|
||||
o[key] = this._tasks[j][item]
|
||||
})
|
||||
obj = o
|
||||
}
|
||||
map.set(this._tasks[j][key] + "_" + this._tasks[j].id, obj)
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
}
|
||||
48
src/renderer/src/views/TS/sdk/Tools.ts
Normal file
48
src/renderer/src/views/TS/sdk/Tools.ts
Normal file
@ -0,0 +1,48 @@
|
||||
export class Tools {
|
||||
// 将时间戳转换为字符串
|
||||
parseTime(time, cFormat = '') {
|
||||
if (arguments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const format = cFormat || "{y}-{m}-{d} {h}:{i}:{s}.{M}";
|
||||
let date;
|
||||
if (typeof time === "object") {
|
||||
date = time;
|
||||
} else {
|
||||
if (("" + time).length === 10)
|
||||
time = parseInt(time) * 1000;
|
||||
date = new Date(time);
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
M: date.getMilliseconds(),
|
||||
a: date.getDay()
|
||||
};
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|M|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key];
|
||||
if (key === "a")
|
||||
return ["一", "二", "三", "四", "五", "六", "日"][value - 1];
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = "0" + value;
|
||||
}
|
||||
if (key === "M") {
|
||||
let letters = ""
|
||||
for (let i = 0; i < 3 - ("" + value).length; i++) {
|
||||
letters += "0";
|
||||
}
|
||||
value = letters + value;
|
||||
}
|
||||
return value || 0;
|
||||
});
|
||||
return time_str;
|
||||
}
|
||||
|
||||
test() {
|
||||
console.log("测试方法")
|
||||
}
|
||||
}
|
||||
74
src/renderer/src/views/TS/sdk/index.ts
Normal file
74
src/renderer/src/views/TS/sdk/index.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import {Tools} from "./Tools";
|
||||
|
||||
import {Store} from "./Store"
|
||||
import {Clock} from "./Clock"
|
||||
|
||||
export class TS extends Tools {
|
||||
private _Store: Store;
|
||||
private _Clock: Clock;
|
||||
private name;
|
||||
|
||||
constructor(option) {
|
||||
super();
|
||||
this._Store = new Store(option)
|
||||
this._Clock = new Clock()
|
||||
this.name = option.name
|
||||
this._Store._scales.fullHeight = this._Store._tasks.length * this._Store._scales.cellHeight
|
||||
|
||||
}
|
||||
|
||||
tuningLine() {
|
||||
let a = this._Store._scales.scrollLeft * -1
|
||||
this._Store.setScale("originMainOffset", a % this._Store._scales.distanceOfTicMain)
|
||||
this._Store.setScale("originOffset", a % this._Store._scales.distanceOfTicTiny)
|
||||
}
|
||||
|
||||
// 根据大格最大数,算出所有时间label
|
||||
renderLabel(obj) {
|
||||
let nums = Math.floor(obj.left / this._Store.getScale('distanceOfTicMain'))
|
||||
let all = this._Store.getScale('ticMain') + nums + 1
|
||||
console.log("renderLabel", nums)
|
||||
let allTimeLabels = []
|
||||
for (let i = 0; i < all; i++) {
|
||||
let timeOfMain = this._Store.getScale('preMains')[this._Store.getScale('preMainIndex')]
|
||||
// @ts-ignore
|
||||
allTimeLabels.push(i * timeOfMain * 1000 + this._Store._startTimestamp)
|
||||
}
|
||||
allTimeLabels.splice(0, nums)
|
||||
this._Store.setScale('timeLabels', allTimeLabels)
|
||||
}
|
||||
|
||||
initAction() {
|
||||
return (l) => {
|
||||
console.log("action的参数", l)
|
||||
const {action, obj, cb} = l
|
||||
switch (action) {
|
||||
|
||||
case "wheel-timeLine":
|
||||
const value = l.num
|
||||
// 第几个大格,小标-=1
|
||||
let num = Math.ceil(value / 3)
|
||||
// 小格宽度的选值,【3,5,8】
|
||||
let index = value % 3
|
||||
this._Store.setScale('preMainIndex', num - 1)
|
||||
this._Store.setScale('distanceOfTicTiny', this._Store.getScale("distanceOfTicTinyRange")[index])
|
||||
this._Store.setScale('preSecondPx', this._Store.getScale("distanceOfTicMain") / this._Store.getScale("preMains")[this._Store.getScale("preMainIndex")])
|
||||
|
||||
break;
|
||||
case "scroll-chart":
|
||||
this._Store._scales.scrollTop = obj.top
|
||||
this._Store.setScale('scrollLeft', obj.left)
|
||||
this.renderLabel(obj)
|
||||
if (obj.deltaX != 0) {
|
||||
this.tuningLine()
|
||||
}
|
||||
if (obj.deltaY != 0) {
|
||||
let cellHeight = this._Store._scales.cellHeight
|
||||
document.getElementsByClassName("grid-body")[0].scrollTop = obj.top
|
||||
this._Store.setScale('originHrOffset', obj.top - obj.top % cellHeight)
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
src/renderer/src/views/TS/tree.ts
Normal file
57
src/renderer/src/views/TS/tree.ts
Normal file
@ -0,0 +1,57 @@
|
||||
export const showRightMenuTs = (event: any, treeObj: any, selectedNodes, nodeType) => {
|
||||
console.log("selectNodes", selectedNodes)
|
||||
let arr: any = []
|
||||
let rightMenuHeight = window.getComputedStyle($('#rMenuTs')[0]).getPropertyValue('height')
|
||||
let rightMenuWidth = window.getComputedStyle($('#rMenuTs')[0]).getPropertyValue('width')
|
||||
console.log("selectNodes", rightMenuHeight)
|
||||
console.log("selectNodes", rightMenuWidth)
|
||||
// 切割取得数字部分
|
||||
let getNumber = (string: any) => {
|
||||
return Number(string.replace('px', ''))
|
||||
}
|
||||
let x = Math.abs(event.clientX - $('.cabin')[0].getBoundingClientRect().left)
|
||||
let y = Math.abs(event.clientY - $('.cabin')[0].getBoundingClientRect().top)
|
||||
y += document.body.scrollTop + 20
|
||||
x += document.body.scrollLeft + 40
|
||||
const bodyWidth = $('body')?.width() || 0
|
||||
const bodyHeight = $('body')?.height() || 0
|
||||
if (event.screenX + getNumber(rightMenuWidth) + 40 > bodyWidth) {
|
||||
x =
|
||||
bodyWidth -
|
||||
getNumber(rightMenuWidth) -
|
||||
$('.cabin')[0].getBoundingClientRect().left
|
||||
}
|
||||
if (event.screenY + getNumber(rightMenuHeight) + 20 > bodyHeight) {
|
||||
y = (bodyHeight - $('.cabin')[0].getBoundingClientRect().top) / 2
|
||||
}
|
||||
|
||||
$('#rMenuTs').css({
|
||||
top: y + 'px',
|
||||
left: x + 'px',
|
||||
visibility: 'visible'
|
||||
})
|
||||
if (
|
||||
Object.prototype.toString.call(selectedNodes) === '[object Array]' &&
|
||||
selectedNodes.length > 1
|
||||
) {
|
||||
arr = ['del']
|
||||
} else {
|
||||
if (selectedNodes.length == 0) arr = ['addDirectory']
|
||||
else {
|
||||
try {
|
||||
arr = [...nodeType[selectedNodes[0].sourceType].rightMenus]
|
||||
console.log("rightMenus", nodeType[selectedNodes[0].sourceType].rightMenus)
|
||||
arr.push('addEvent')
|
||||
} catch (e) {
|
||||
console.log('e', e, selectedNodes[0].sourceType)
|
||||
arr = []
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let i = arr.length - 1; i >= 0; i--) {
|
||||
if (['pictureLocation', 'importPanorama'].includes(arr[i])) {
|
||||
arr.splice(i, 1); // 从索引 i 开始删除 1 个元素
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
@ -7,6 +7,7 @@ import { GisApi } from '@/api/gisApi'
|
||||
import {addMapSource} from '@/common/addMapSource'
|
||||
import {getNamefromPath} from '@/utils/index'
|
||||
import {renderVector} from './renderVector'
|
||||
|
||||
const {cusAddNodes} = useTreeNode()
|
||||
|
||||
export const useRightOperate = () => {
|
||||
@ -32,8 +33,7 @@ export const useRightOperate = () => {
|
||||
if (node) {
|
||||
if (node.sourceType === 'directory') {
|
||||
parentId = node.id
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parentId = node.parentId
|
||||
}
|
||||
}
|
||||
@ -49,10 +49,6 @@ export const useRightOperate = () => {
|
||||
if (typeof filePaths[0] !== 'string' || filePaths[0].trim() === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
let item = filePaths[0]
|
||||
|
||||
//@ts-ignore
|
||||
@ -103,8 +99,7 @@ export const useRightOperate = () => {
|
||||
cusAddNodes(window.treeObj, params.parentId, [params])
|
||||
let entityObject = renderVector(params, true);
|
||||
(window as any)._entityMap.set(id, entityObject)
|
||||
}
|
||||
else if (["geojson"].includes(sourceType)) {
|
||||
} else if (["geojson"].includes(sourceType)) {
|
||||
let baseURL = localStorage.getItem('ip')
|
||||
await addMapSource({
|
||||
type: 'geojson',
|
||||
@ -119,8 +114,7 @@ export const useRightOperate = () => {
|
||||
color: "rgb(239, 6, 6, 1)",
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// 获取最后一个点的位置
|
||||
const lastDotIndex = filePaths[0].lastIndexOf('.');
|
||||
|
||||
@ -170,7 +164,8 @@ export const useRightOperate = () => {
|
||||
await initMapData(res.data.sourceType, mapParams, (entity) => {
|
||||
entity.flyTo()
|
||||
})
|
||||
if (res.data.sourceType) { }
|
||||
if (res.data.sourceType) {
|
||||
}
|
||||
|
||||
res.data.params = JSON.stringify(res.data.params)
|
||||
res.data.detail = JSON.stringify(res.data.detail)
|
||||
@ -188,8 +183,7 @@ export const useRightOperate = () => {
|
||||
if (node) {
|
||||
if (node.sourceType === 'directory') {
|
||||
parentId = node.id
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parentId = node.parentId
|
||||
}
|
||||
}
|
||||
@ -211,8 +205,7 @@ export const useRightOperate = () => {
|
||||
const files = await Promise.all(fileHandles.map(fileHandle => fileHandle.getFile()));
|
||||
const dataTransfer = new DataTransfer();
|
||||
handleFileImgInput(files, parentId, 'vrImage')
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = '.jpg'
|
||||
@ -232,8 +225,7 @@ export const useRightOperate = () => {
|
||||
if (node) {
|
||||
if (node.sourceType === 'directory') {
|
||||
parentId = node.id
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
parentId = node.parentId
|
||||
}
|
||||
}
|
||||
@ -255,8 +247,7 @@ export const useRightOperate = () => {
|
||||
const files = await Promise.all(fileHandles.map(fileHandle => fileHandle.getFile()));
|
||||
const dataTransfer = new DataTransfer();
|
||||
handleFileImgInput(files, parentId, 'linkImage')
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
let input = document.createElement('input')
|
||||
input.type = 'file'
|
||||
input.accept = '.jpg'
|
||||
@ -318,9 +309,11 @@ export const useRightOperate = () => {
|
||||
});
|
||||
}
|
||||
//导入模型
|
||||
const addXlsxs = () => { }
|
||||
const addXlsxs = () => {
|
||||
}
|
||||
//导入模型
|
||||
const addTrajectory = () => { }
|
||||
const addTrajectory = () => {
|
||||
}
|
||||
//编辑
|
||||
const editNode = (eventBus, node) => {
|
||||
if (!node) {
|
||||
@ -372,11 +365,14 @@ export const useRightOperate = () => {
|
||||
})
|
||||
}
|
||||
//添加BIM
|
||||
const addBIM = () => { }
|
||||
const addBIM = () => {
|
||||
}
|
||||
//重置透视
|
||||
const resetPerspective = () => { }
|
||||
const resetPerspective = () => {
|
||||
}
|
||||
|
||||
const pressModel = () => { }
|
||||
const pressModel = () => {
|
||||
}
|
||||
|
||||
//设置视图
|
||||
const setView = () => {
|
||||
@ -445,7 +441,8 @@ export const useRightOperate = () => {
|
||||
layerIndex("layerToBottom");
|
||||
}
|
||||
//切片
|
||||
const tilesetClipping = () => { }
|
||||
const tilesetClipping = () => {
|
||||
}
|
||||
const rightMenus: any = reactive({
|
||||
addDirectory: {
|
||||
key: 'addDirectory',
|
||||
@ -668,7 +665,6 @@ export const useRightOperate = () => {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getLastPathComponent(path, extensionsToRemove = []) {
|
||||
// 处理路径分隔符
|
||||
const normalizedPath = path.replace(/\\/g, '/');
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {renderMethods} from "./renderTreeNode";
|
||||
|
||||
const {ipcRenderer, BrowserWindow} = require('electron')
|
||||
export const useTreeNode = () => {
|
||||
//定义树形节点的属性
|
||||
@ -457,8 +458,7 @@ export const useTreeNode = () => {
|
||||
// 提取后缀并转换为小写进行比较
|
||||
const extension = path.slice(lastDotIndex + 1).toLowerCase();
|
||||
type = extension
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
type = node.sourceType || node.type;
|
||||
}
|
||||
console.log("----------", type);
|
||||
@ -635,6 +635,7 @@ export const useTreeNode = () => {
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
function findParentId(treeObj: any) {
|
||||
if (!treeObj) {
|
||||
return -1;
|
||||
@ -652,6 +653,7 @@ export const useTreeNode = () => {
|
||||
}
|
||||
return selectedNode.id;
|
||||
}
|
||||
|
||||
function findTreeIndex(treeObj: any) {
|
||||
if (!treeObj) {
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user