feat:新增了gantt,新增天气显示,header组件

This commit is contained in:
严争鸣 2024-12-19 14:48:14 +08:00
parent 167b49ea00
commit f7e20bca6a
24 changed files with 4132 additions and 709 deletions

View File

@ -7,13 +7,13 @@
<!-- <script src="baseConfig.js"></script> -->
<!-- <script src="GV/thirdParty/thirdParty.js"></script> -->
<!-- <script src="GV/GEOVIS.web.js"></script> -->
<script src="baseConfig.js"></script>
<script src="/baseConfig.js"></script>
<!-- <link href="GV/thirdParty/CesiumManager/Widgets/widgets.css" /> -->
<script src="js/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="js/Cesium/Widgets/widgets.css" />
<script src="/js/Cesium/Cesium.js"></script>
<link rel="stylesheet" href="/js/Cesium/Widgets/widgets.css" />
<script src="js/cesium-sensor-volumes.js"></script>
<script src="/js/cesium-sensor-volumes.js"></script>
<title>Vite App</title>
</head>

3086
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,8 @@
"@cesium-extends/heat": "^1.0.3",
"@cesium-extends/subscriber": "^1.1.0",
"@turf/turf": "^7.1.0",
"@visactor/vtable": "^1.13.2",
"@visactor/vtable-gantt": "^1.13.2",
"@vueuse/core": "^9.9.0",
"@wenrenfangge/cesium-draw": "^1.0.4",
"axios": "^1.2.1",
@ -42,6 +44,7 @@
"@vicons/tabler": "^0.12.0",
"@vitejs/plugin-legacy": "^4.0.1",
"@vitejs/plugin-vue": "^4.0.0",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/eslint-config-typescript": "^11.0.0",
"@vue/tsconfig": "^0.1.3",

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

346
src/api/Gantt/index.js Normal file
View File

@ -0,0 +1,346 @@
const main = [
{
id: 0,
name: '任务-1',
start: '2024-11-15',
end: '2024-11-21',
children: [
{
id: 1,
name: '事件-1-1',
start: '2024-11-15',
end: '2024-11-17',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
{
id: 2,
name: '事件-1-2',
start: '2024-11-17',
end: '2024-11-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 3,
name: '事件-1-3',
start: '2024-11-19',
end: '2024-11-20',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 4,
name: '事件-1-4',
start: '2024-11-18',
end: '2024-11-19',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
],
},
{
id: 300,
name: '任务-2',
children: [
{
id: 5,
name: '事件-2-1',
start: '2024-11-18',
end: '2024-11-21',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
},
],
},
{
name: '任务-3',
children: [
{
id: 6,
name: '事件-3-1',
start: '2024-11-21',
end: '2024-11-22',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
},
{
id: 7,
name: '事件-3-2',
start: '2024-11-18',
end: '2024-11-19',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
},
],
},
{
name: '任务-4',
children: [
{
id: 8,
name: '事件-4-1',
start: '2024-11-20',
end: '2024-11-21',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 9,
name: '事件-4-2',
start: '2024-11-25',
end: '2024-11-26',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
{
id: 10,
name: '事件-4-3',
start: '2024-11-17',
end: '2024-11-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 11,
name: '事件-4-4',
start: '2024-11-22',
end: '2024-11-25',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
{
id: 12,
name: '事件-4-5',
start: '2024-11-23',
end: '2024-11-24',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
],
},
{
name: '任务-5',
children: [
{
id: 13,
name: '事件-5-1',
start: '2024-11-22',
end: '2024-11-25',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
},
{
id: 14,
name: '事件-5-2',
start: '2024-11-27',
end: '2024-11-30',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
},
{
id: 15,
name: '事件-5-3',
start: '2024-12-10',
end: '2024-12-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
},
],
},
{
name: '任务-6',
children: [
{
id: 16,
name: '事件-6-1',
start: '2024-11-20',
end: '2024-11-30',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 17,
name: '事件-6-2',
start: '2024-12-02',
end: '2024-12-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
],
},
{
name: '任务-7',
children: [
{
id: 18,
name: '事件-7-1',
start: '2024-12-22',
end: '2024-12-28',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
},
],
},
{
name: '任务-8',
children: [
{
id: 19,
name: '事件-8-1',
start: '2024-11-25',
end: '2024-11-30',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
},
{
id: 20,
name: '事件-8-2',
start: '2024-12-01',
end: '2024-12-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
},
],
},
]
const sub = [
{
id: 0,
name: 'DD',
start: '2024-11-15',
end: '2024-11-21',
children: [
{
id: 1,
name: '发射',
start: '2024-11-15',
end: '2024-11-17',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
{
id: 2,
name: '脱离-1',
start: '2024-11-17',
end: '2024-11-18',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 3,
name: '脱落-2',
start: '2024-11-19',
end: '2024-11-20',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 4,
name: '落地-3',
start: '2024-11-18',
end: '2024-11-19',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
],
},
{
id: 300,
name: '飞机',
children: [
{
id: 5,
name: '起飞',
start: '2024-11-18',
end: '2024-11-21',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
},
],
},
{
name: '舰船',
children: [
{
id: 6,
name: '停留',
start: '2024-11-21',
end: '2024-11-22',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
},
{
id: 7,
name: '扫描',
start: '2024-11-18',
end: '2024-11-19',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
},
],
},
{
name: '航J',
children: [
{
id: 8,
name: '航J事件',
start: '2024-11-20',
end: '2024-11-21',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
},
{
id: 9,
name: '航J事件-2',
start: '2024-11-25',
end: '2024-11-26',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
},
],
},
{
name: 'xx',
children: [
{
id: 13,
name: 'xx-事件-1',
start: '2024-11-22',
end: '2024-11-25',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
},
{
id: 14,
name: 'xx-事件-2',
start: '2024-11-27',
end: '2024-11-30',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
},
],
},
]
export function getMainGantt(data = {}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(main)
}, 1000)
})
}
export function getSubGantt(subId) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(sub)
}, 1000)
})
}

View File

@ -54,6 +54,8 @@
#08ffff77,
#71ffff77
);
--color-bg: #1a222966;
}
@media (prefers-color-scheme: dark) {

View File

@ -37,12 +37,12 @@ const props = defineProps({
<polygon
id="polygon1"
points="6,66 6,18 12,12 18,12 24,6 27,6 30,9 36,9 39,6 84,6 81,9 75,9 73.2,7 40.8,7 37.8,10.2 24,10.2 12,21 12,24 9,27 9,51 7.8,54 7.8,63"
fill="#4284aa"
fill="#3F91C1"
>
<!-- #3f79b0#235fa7;#4fd2dd#4b5f87 -->
<animate
attributeName="fill"
values="#4fd2dd;#3f79b0;#4284aa;#3f79b0;#4fd2dd;"
values="#4fd2dd;#3f79b0;#3F91C1;#3f79b0;#4fd2dd;"
dur="3s"
begin="0s"
repeatCount="indefinite"
@ -51,14 +51,14 @@ const props = defineProps({
<polygon
id="polygon2"
points="27.599999999999998,4.8 38.4,4.8 35.4,7.8 30.599999999999998,7.8"
fill="#4284aa"
fill="#3F91C1"
></polygon>
<!-- #235fa7 4fd2dd -->
<polygon
id="polygon3"
points="9,54 9,63 7.199999999999999,66 7.199999999999999,75 7.8,78 7.8,110 8.4,110 8.4,66 9.6,66 9.6,54"
fill="#4284aa"
fill="#3F91C1"
></polygon>
</g>
</defs>
@ -102,8 +102,10 @@ $radius: 2rem;
height: calc(100% - 1rem + 2px);
}
.warp-bg {
background-color: #1a222966;
background-color: var(--color-bg);
// background-color: #fff55;
border-radius: $radius;
// backdrop-filter: blur(10px);
}
.border-content {
// z-index: 10;
@ -114,11 +116,11 @@ $radius: 2rem;
// width: calc(100% - 1rem);
// height: calc(100% - 1rem + 2px);
box-shadow: inset 0 0 15px 2px #40c8ee4d;
box-shadow: inset 0 0 15px 2px #40c8ee77;
.content-title {
@apply h-9 px-5 leading-9 tracking-[5px];
border-radius: $radius $radius 0 0;
background: linear-gradient(to right, #4fd2dd33, #4b877400);
background: linear-gradient(to right, #4fd2dd55, #4b877400);
.title-text {
@apply font-bold italic;
color: transparent;

View File

@ -13,20 +13,27 @@ class SatelliteEntity {
this.tleLine2 = tleLine2.trim()
this.satrec = twoline2satrec(this.tleLine1, this.tleLine2)
this.totalSeconds = 86400 // 24小时
this.totalSeconds = 7 * 86400 // 24小时
this.stepSeconds = 100
this.leadTime = parseInt((24 * 3600) / circle)
this.trailTime = 0
this.sensor = false
this.entity = null
this.sensorType = 'rectangle'
}
get sensor() {
return this.sensor
}
set sensor(showSensor) {
console.log(showSensor, 'showSensor')
showSensor && this.createRectangleSensor(this.entity)
if (showSensor) {
if (this.sensorType === 'conic') {
this.createConicSensor(this.entity)
} else {
this.createRectangleSensor(this.entity)
}
}
//showSensor &&
}
_checkTle(tle) {
@ -104,7 +111,7 @@ class SatelliteEntity {
// material: color,
material: new Cesium.PolylineTrailLinkMaterialProperty({
color,
duration: 8640,
duration: 86400 * 1000,
}),
}),
label: {
@ -284,6 +291,38 @@ class SatelliteEntity {
)
}
createConicSensor(satellite) {
let position = Cesium.Property.getValueOrUndefined(
satellite.position,
viewer.clock.currentTime,
new Cesium.Cartesian3()
)
// const conicSensor = new CesiumSensorVolumes.ConicSensorGraphics()
// conicSensor.radius = 20000000.0
// conicSensor.modelMatrix = this.getModelMatrix(position)
// conicSensor.intersectionColor = new Cesium.ConstantProperty(
// new Cesium.Color(0.1, 0.2, 0.3, 0.4)
// )
const customSensor = new CesiumSensorVolumes.CustomSensorVolume()
customSensor.modelMatrix = this.getModelMatrix(position)
customSensor.radius = 20000000.0
// customSensor.directions = directions;
viewer.scene.primitives.add(customSensor)
viewer.scene.preRender.addEventListener((scene, time) => {
customSensor.show = false
let position = Cesium.Property.getValueOrUndefined(
satellite.position,
time,
new Cesium.Cartesian3()
)
customSensor.modelMatrix = this.getModelMatrix(position)
customSensor.show = true
})
viewer.scene.primitives.add(customSensor)
}
// createSensor(satellite) {
// // let sensor = new Sensor({
// // position: satellite.position,

View File

@ -8,6 +8,24 @@ const router = createRouter({
name: 'Home',
component: () => import('@/views/Home/index.vue'),
},
{
path: '/gantt',
name: 'Gantt',
component: () => import('@/views/Gantt'),
redirect: '/gantt/main',
children: [
{
path: 'main',
name: 'MainGantt',
component: () => import('@/views/Gantt/components/MainGantt'),
},
{
path: 'sub/:subId',
name: 'SubGantt',
component: () => import('@/views/Gantt/components/SubGantt'),
},
],
},
],
})

View File

@ -78,7 +78,7 @@
<stop offset="0.5" style="stop-color:#29baf1" />
<stop offset="1" style="stop-color:#29baf1;stop-opacity:0.3" />
</linearGradient>
<path id="polygon" style="fill:rgba(26, 34, 41, 0.4);" d="
<path id="polygon" style="fill:#1a222966;" d="
M0,28.4c0,0,538.6,3.2,575.7,3.2c30.5,0,25.5,43.3,70.1,43.3c21.4,0,596.3,0,629.4,0c44.9,0,33.1-43.3,75.1-43.3
c36.2,0,569.7-3.2,569.7-3.2" />
<path id="line" style="fill:none;stroke:url(#line_00000023994454057530153110000010704537899013655470_);stroke-width:3;stroke-miterlimit:10;" d="

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,74 @@
<script lang="ts" setup>
const worldTime = ref('')
const getTime = () => {
worldTime.value = new Date().toLocaleString()
requestAnimationFrame(getTime)
}
onMounted(() => {
getTime()
})
</script>
<template>
<div class="header-bg absolute z-20 h-[100px] w-full"></div>
<div
class="time-bg z-20 mb-1 flex h-[30px] w-full items-center justify-between px-5 text-2xl"
>
<div class="time-container">
<div class="time-title">世界时</div>
<div class="bgc-animation">
{{ worldTime }}
</div>
</div>
<div class="time-container bgc-animation">
<div class="bgc-animation">{{ worldTime }}</div>
<div class="time-title">作战时</div>
</div>
</div>
<div class="title-container bgc-animation">xxxxx平台</div>
</template>
<style type="scss" scoped>
.time-bg {
background-color: var(--color-bg);
.time-container {
@apply flex items-center justify-center gap-2;
font-family: Digital;
.time-title {
@apply h-6 border border-[#29baf1] px-2 text-sm leading-5 text-[#29baf1];
}
}
}
.bgc-animation {
background: var(--gradient-bg);
background-size: 200% 200%;
animation: gradientAnimation 3s ease infinite alternate;
background-clip: text;
color: transparent;
}
@keyframes gradientAnimation {
0% {
background-position: 200% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.header-bg {
background: url('./header.svg') no-repeat;
background-size: 100% 100%;
}
.title-container {
@apply absolute left-[50%] top-3 z-20 h-20 text-5xl font-bold tracking-[18px];
transform: translateX(-50%);
}
</style>

View File

@ -1,5 +1,6 @@
<script setup>
import { RepeatSharp } from '@vicons/ionicons5'
import HeaderCom from './components/Header/index.vue'
import Panel from '@/components/Panel/index.vue'
// import Header from './components/Header.vue'
import Satellite from '../Satellite/index.vue'
@ -17,6 +18,7 @@ import HeatMap from '../Mubiao/components/HeatMap/index.vue'
import { useTextReport } from '../TextReport/hooks/text'
import { useHisImage } from '../BaseMB/components/HisImages/hooks/hisImage'
import { useMBTrajectory } from '../Mubiao/components/HisTrajectory/hooks/mbTraj'
import { useWeather } from '../Weather/hooks/weather'
import DetailsModal from './components/DetailsModal/index.vue'
const { getTextConfigs, initWebSocket } = useTextReport()
@ -49,20 +51,21 @@ const types = [
const showPanelName = ref('ss')
const worldTime = ref('')
const getTime = () => {
worldTime.value = new Date().toLocaleString()
requestAnimationFrame(getTime)
}
onMounted(() => {
getTime()
})
// const worldTime = ref('')
// const getTime = () => {
// worldTime.value = new Date().toLocaleString()
// requestAnimationFrame(getTime)
// }
// onMounted(() => {
// getTime()
// })
const { showWeather } = useWeather()
</script>
<template>
<div class="flex flex-col w-h-full">
<!-- <div class="absolute z-20 h-8 w-full bg-[#1a222988]"></div> -->
<div class="header-bg absolute z-20 h-[100px] w-full"></div>
<header-com />
<!-- <div class="header-bg absolute z-20 h-[100px] w-full"></div>
<div
class="time-bg z-20 mb-1 flex h-[30px] w-full items-center justify-between px-5 text-2xl"
>
@ -77,9 +80,9 @@ onMounted(() => {
<div class="time-title">作战时</div>
</div>
</div>
<div class="title-container bgc-animation">xxxxx平台</div>
<div class="title-container bgc-animation">xxxxx平台</div> -->
<div class="grid flex-1 grid-cols-[1.5fr_3fr_1.5fr] grid-rows-1 gap-1 p-2">
<div class="grid flex-1 grid-cols-[1.3fr_3fr_1.3fr] grid-rows-1 gap-1 p-2">
<div class="left-panel pl-8">
<div
class="radio-group absolute top-[50%] -left-7 z-30 flex w-14 translate-y-[-50%] transform flex-col"
@ -162,6 +165,14 @@ onMounted(() => {
</transition>
</div>
<div class="flex h-full flex-col justify-end">
<div class="absolute top-2 z-30 flex w-full justify-between">
<div class="btn-class left"></div>
<div
class="btn-class right"
:class="{ checked: showWeather }"
@click="showWeather = !showWeather"
></div>
</div>
<!-- <his-images
class="transition-duration-1000 z-20 row-start-5 transition-all"
></his-images> -->
@ -258,4 +269,86 @@ onMounted(() => {
transform: translateX(-120%) scale(0.8);
filter: blur(4px);
}
.btn-class {
@apply h-[28px] w-[110px];
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
letter-spacing: 4px;
color: #a7cae0;
cursor: pointer;
background: linear-gradient(
90deg,
rgba(47, 255, 255, 0.4) 0%,
rgba(8, 77, 126, 0.4) 25%,
rgba(8, 77, 126, 0.4) 70%,
rgba(47, 255, 255, 0.4) 100%
);
filter: drop-shadow(inset 0 0 0 2px red);
clip-path: polygon(
0% 0%,
71.67% 0%,
79.33% 6%,
84% 15.33%,
88% 28%,
91% 41.67%,
94.33% 59.33%,
97% 74%,
99% 88%,
100% 100%,
0% 100%
);
border-radius: 5px;
&:hover {
background: linear-gradient(
180deg,
rgba(8, 77, 126, 0.2) 0%,
rgba(8, 77, 126, 0.42) 100%
),
rgba(47, 255, 255, 0.4);
box-shadow: inset 0 0 12px rgba(151, 200, 255, 0.44);
}
&::after {
content: '显示天气';
width: 100%;
height: 100%;
display: block;
position: absolute;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
// color: '#a7cae0';
// background: var(--gradient-bg);
// background-clip: text;
}
}
.checked {
color: #f2f7fb;
background: linear-gradient(
180deg,
rgba(8, 77, 126, 0.2) 0%,
rgba(8, 77, 126, 0.42) 100%
),
rgba(47, 255, 255, 0.4);
box-shadow: inset 0 0 12px rgba(151, 200, 255, 0.44);
}
.left {
&::after {
content: '热力图';
}
}
.right {
transform: rotateY(180deg);
&::after {
transform: rotateY(-180deg);
}
}
</style>

View File

@ -16,7 +16,9 @@ onMounted(() => {
fullscreenButton: false,
homeButton: false,
imageryProvider: new Cesium.UrlTemplateImageryProvider({
url: 'GV/resources/theme/earthTheme/{z}/{x}/{y}.jpg',
url: 'http://192.168.10.201:2022/api/maptilecache/service/tms/1.0.0/img_globle1to9-PNG-4326@EPSG:4326@png/{z}/{x}/{reverseY}.png',
// url: 'js/Cesium/Assets/Textures/NaturalEarthII/{z}/{x}/{reverseY}.jpg',
// url: 'GV/resources/theme/earthTheme/{z}/{x}/{y}.jpg',
tilingScheme: new Cesium.GeographicTilingScheme(),
}),
@ -36,7 +38,16 @@ onMounted(() => {
// 齿
viewer.scene.postProcessStages.fxaa.enabled = true
// viewer.scene.skyBox = GV.SkyboxTheme.getSkyBox('GV/resources/theme/skyBox/{z}/{x}/{y}.jpg',false,'jpg')
viewer.scene.skyBox = new Cesium.SkyBox({
sources: {
positiveX: 'GV/resources/theme/skyBox/PositiveX.jpg',
negativeX: 'GV/resources/theme/skyBox/NegativeX.jpg',
positiveY: 'GV/resources/theme/skyBox/PositiveY.jpg',
negativeY: 'GV/resources/theme/skyBox/NegativeY.jpg',
positiveZ: 'GV/resources/theme/skyBox/PositiveZ.jpg',
negativeZ: 'GV/resources/theme/skyBox/NegativeZ.jpg',
},
})
// viewer.scene.globe.depthTestAgainstTerrain = true
// addBaseFacilities()

View File

@ -0,0 +1,334 @@
import { Group, Image, Text, CheckBox, Rect } from '@visactor/vtable/es/vrender'
import { Gantt, tools, TYPES } from '@visactor/vtable-gantt'
import { getMainGantt, getSubGantt } from '@/api/Gantt'
type GanttParams = {
route?: any
router?: any
}
let ganttInstance: null | Gantt = null
const bgColor = '#1c202c'
const headerBgColor = '#33566f22'
const textColor = '#65c5e7'
const textColorWithOp = '#75fbfd22'
const useGantt = ({ router, route }: GanttParams) => {
const { subId } = route.params
const records = ref([])
onMounted(() => {
getGanttData(subId)
})
async function getGanttData(subId: string) {
if (subId) {
const res = await getSubGantt(subId)
records.value = res
ganttInstance?.setRecords(records.value)
} else {
const res = await getMainGantt()
// console.log(res, '----')
records.value = res
ganttInstance?.setRecords(records.value)
}
}
function renderMainTask(dom: HTMLElement) {
const option = getOption()
ganttInstance = new Gantt(dom, option)
// window['ganttInstance'] = ganttInstance
console.log(ganttInstance)
}
function getOption(): TYPES.GanttConstructorOptions {
const option = {
records: records.value,
taskListTable: renderTaskListTable(),
tasksShowMode: TYPES.TasksShowMode.Sub_Tasks_Arrange,
frame: {
outerFrameStyle: {
borderLineWidth: 2,
borderColor: textColor,
cornerRadius: 3,
},
// verticalSplitLineHighlight: {
// lineColor: 'green',
// lineWidth: 3
// }
},
grid: {
// backgroundColor: bgColor,
horizontalLine: {
lineWidth: 1,
lineColor: textColorWithOp,
},
verticalLine: {
lineWidth: 1,
lineColor: textColorWithOp,
lineDash: [4, 8],
},
},
taskList: {
// backgroundColor: bgColor,
headerStyle: {
borderColor: '#e1e4e8',
borderLineWidth: 0,
fontSize: 18,
fontWeight: 'bold',
color: 'red',
},
},
headerRowHeight: 59,
rowHeight: subId ? 200 : 100,
taskBar: renderTaskBar(subId),
timelineHeader: {
backgroundColor: headerBgColor,
colWidth: 100,
verticalLine: {
lineColor: textColorWithOp,
lineWidth: 1,
lineDash: [4, 2],
},
horizontalLine: {
lineColor: textColorWithOp,
lineWidth: 1,
lineDash: [4, 2],
},
scales: getTimeScales('day'),
},
minDate: '2024-11-14',
maxDate: '2024-12-30',
scrollStyle: {
scrollRailColor: 'RGBA(246,246,246,0)',
visible: 'focus',
width: 6,
scrollSliderCornerRadius: 2,
scrollSliderColor: 'rgba(255,255,255,0.25)',
},
underlayBackgroundColor: bgColor,
}
return option as TYPES.GanttConstructorOptions
}
function renderColumn() {
const columns = [
{
field: 'name',
title: '类型',
width: '120',
mergeCell: true,
},
]
if (subId) {
columns.unshift({
field: 'isCheck',
title: '',
width: '60',
headerType: 'checkbox',
cellType: 'checkbox',
})
}
return columns
}
function renderTaskListTable() {
const taskListTable = {
columns: renderColumn(),
// tableWidth: 'auto',
theme: {
underlayBackgroundColor: bgColor,
headerStyle: {
borderColor: textColorWithOp,
borderLineWidth: 1,
fontWeight: 'bold',
color: textColor,
bgColor: headerBgColor,
textAlign: 'center',
fontSize: 20,
hover: {
cellBgColor: 'transparent',
},
},
bodyStyle: {
borderColor: textColorWithOp,
textAlign: 'center',
borderLineWidth: 1,
autoWrapText: true,
fontSize: 16,
color: textColor,
bgColor: bgColor,
hover: {
cellBgColor: textColorWithOp,
},
},
},
}
return taskListTable
}
function renderTaskBar(subId: string) {
const taskBar = {
resizable: false,
moveable: false,
startDateField: 'start',
endDateField: 'end',
// progressField: 'progress',
barStyle: { width: subId ? 180 : 60 },
customLayout: args => {
const { width, height, startDate, endDate, taskRecord } = args
const container = new Group({
width,
height,
fill: 'transparent',
// stroke:true,
// stroke: textColor,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
})
if (!subId) {
container.addEventListener('click', event => {
router.push({
path: `/gantt/sub/${taskRecord.id}`,
})
})
}
if (subId) {
const image = new Image({
image: taskRecord.avatar,
width: 100,
height: 100,
x: 10,
y: 10,
boundsPadding: [0, 0, 10, 0],
})
container.add(image)
}
// const checkbox = new CheckBox({
// width: 20,
// height: 20,
// checked: false,
// })
// container.add(checkbox)
// checkbox.addEventListener('click', event => {
// console.log(event, 'event')
// })
const name = new Text({
text: taskRecord.name,
fontSize: 16,
fontFamily: 'sans-serif',
fill: textColor,
fontWeight: 'bold',
maxLineWidth: width,
textAlign: 'center',
// boundsPadding: [10, 0, 0, 0],
})
container.add(name)
const days = new Text({
text: `${startDate.toLocaleDateString()} ~ ${endDate.toLocaleDateString()}`,
fontSize: 13,
fontFamily: 'sans-serif',
fill: textColor,
boundsPadding: [10, 0, 0, 0],
})
container.add(days)
const rect = new Rect({
width: width,
height: 7,
fill: {
gradient: 'linear',
x0: 0,
y0: 0,
x1: 1,
y1: 0,
stops: [
{
offset: 0,
color: textColor,
},
{
offset: 1,
color: textColorWithOp,
},
],
},
boundsPadding: [10, 0, 0, 0],
})
container.add(rect)
return {
rootContainer: container,
}
},
hoverBarStyle: {
cornerRadius: 2,
barOverlayColor: textColorWithOp,
},
selectedBarStyle: {
// cornerRadius: 2,
borderColor: textColorWithOp,
borderLineWidth: 2,
},
}
return taskBar
}
function renderGroup(opt: IGroupGraphicAttribute) {
return new Group(opt)
}
function renderText(opt: ITextGraphicAttribute) {
return new Text(opt)
}
function renderImage(opt: IImageGraphicAttribute) {
return new Image(opt)
}
function changeTimeScales(scale: TYPES.ITimelineScale['unit']) {
const scales = getTimeScales(scale)
ganttInstance && ganttInstance.updateScales(scales)
}
function getTimeScales(
scale: TYPES.ITimelineScale['unit']
): TYPES.ITimelineScale[] {
return [
{
unit: scale,
step: 1,
customLayout: args => {
const { width, height, startDate } = args
const container = new Group({
width,
height,
display: 'flex',
flexDirection: 'row',
flexWrap: 'nowrap',
})
const day = new Text({
text:
scale === 'day'
? startDate.toLocaleDateString()
: startDate.toLocaleTimeString(),
fontSize: 14,
fontWeight: 'bold',
fontFamily: 'sans-serif',
fill: textColor,
textAlign: 'right',
maxLineWidth: width,
boundsPadding: [25, 12, 10, 12],
})
container.add(day)
return {
rootContainer: container,
}
},
},
]
}
return { renderMainTask, changeTimeScales }
}
export default useGantt

View File

@ -0,0 +1,29 @@
import useGantt from './hooks/gantt'
import { useRouter, useRoute } from 'vue-router'
export default defineComponent({
props: {
scale: {
type: String,
default: 'day',
},
},
setup(props) {
const router = useRouter()
const route = useRoute()
const { renderMainTask, changeTimeScales } = useGantt({ route, router })
onMounted(() => {
nextTick(() => {
renderMainTask(document.querySelector('#tableContainer'))
})
})
watch(
() => props.scale,
val => {
changeTimeScales(val)
}
)
return () => <div id="tableContainer" class="bg-[#1c202c] w-h-full"></div>
},
})

View File

@ -0,0 +1,21 @@
import { NDatePicker, NRadioButton, NRadioGroup } from 'naive-ui'
import GanttCom from '../Gantt'
export default defineComponent({
setup() {
const range = ref()
const value = ref('day')
return () => (
<>
<div class="flex gap-2">
<NDatePicker v-model:value={range.value} type="daterange" clearable />
<NRadioGroup v-model:value={value.value} name="radiobuttongroup">
<NRadioButton value="hour" label="日" />
<NRadioButton value="day" label="月" />
</NRadioGroup>
</div>
<GanttCom scale={value.value} />
</>
)
},
})

View File

@ -0,0 +1,17 @@
import { NButton } from 'naive-ui'
import GanttCom from '../Gantt'
export default defineComponent({
setup() {
const value = ref('day')
return () => (
<>
<div class="flex gap-2">
<NButton>态势展示</NButton>
<NButton>返回</NButton>
</div>
<GanttCom scale={value.value} />
</>
)
},
})

View File

@ -0,0 +1,531 @@
<script setup>
import HeaderCom from '../Content/components/Header/index.vue'
import { Gantt, tools } from '@visactor/vtable-gantt'
// import * as VTableGantt from '@visactor/vtable-gantt';
import * as VRender from '@visactor/vtable/es/vrender'
const checked = ref({
id: 'test',
width: 20,
height: 20,
checked: false,
})
let ganttInstance
const barColors0 = [
'#aecde6',
'#c6a49a',
'#ffb582',
'#eec1de',
'#b3d9b3',
'#cccccc',
'#e59a9c',
'#d9d1a5',
'#c9bede',
]
const barColors = [
'#1f77b4',
'#8c564b',
'#ff7f0e',
'#e377c2',
'#2ca02c',
'#7f7f7f',
'#d62728',
'#bcbd22',
'#9467bd',
]
const records = [
{
id: 1,
title: 'Project Task 1',
developer: 'bear.xiong',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bear.jpg',
start: '2024-07-24',
end: '2024-07-26',
progress: 31,
priority: 'P0',
},
{
id: 2,
title: 'Project Task 2',
developer: 'wolf.lang',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/wolf.jpg',
start: '07/25/2024',
end: '07/28/2024',
progress: 60,
priority: 'P0',
},
{
id: 3,
title: 'Project Task 3',
developer: 'rabbit.tu',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/rabbit.jpg',
start: '2024-07-28',
end: '2024-08-01',
progress: 100,
priority: 'P1',
},
{
id: 1,
title: 'Project Task 4',
developer: 'cat.mao',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/cat.jpg',
start: '2024-07-31',
end: '2024-08-03',
progress: 31,
priority: 'P0',
},
{
id: 2,
title: 'Project Task 5',
developer: 'bird.niao',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg',
start: '2024-08-02',
end: '2024-08-04',
progress: 60,
priority: 'P0',
},
{
id: 6,
title: 'Project Task 5',
developer: 'bird.niao',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/bird.jpeg',
start: '2024-08-02',
end: '2024-08-04',
progress: 60,
priority: 'P0',
},
{
id: 3,
title: 'Project Task 6',
developer: 'flower.hua',
avatar:
'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/VTable/custom-render/flower.jpg',
start: '2024-08-03',
end: '2024-08-10',
progress: 100,
priority: 'P1',
},
]
const columns = [
{
field: 'title',
title: 'TASK',
width: '200',
mergeCell: true,
headerStyle: {
textAlign: 'center',
fontSize: 20,
fontWeight: 'bold',
color: 'white',
bgColor: '#1c202c',
},
style: {
bgColor: '#1c202c',
},
customLayout: args => {
const { table, row, col, rect } = args
const taskRecord = table.getCellOriginRecord(col, row)
const { height, width } = rect ?? table.getCellRect(col, row)
const container = new VRender.Group({
y: 10,
x: 20,
height: height - 20,
width: width - 40,
fill: 'white',
display: 'flex',
flexDirection: 'column',
cornerRadius: 30,
})
const developer = new VRender.Text({
text: taskRecord.developer,
fontSize: 16,
fontFamily: 'sans-serif',
fill: barColors[args.row],
fontWeight: 'bold',
maxLineWidth: width - 120,
boundsPadding: [10, 0, 0, 0],
alignSelf: 'center',
})
container.add(developer)
const days = new VRender.Text({
text: `${tools.formatDate(
new Date(taskRecord.start),
'mm/dd'
)}-${tools.formatDate(new Date(taskRecord.end), 'mm/dd')}`,
fontSize: 12,
fontFamily: 'sans-serif',
fontWeight: 'bold',
fill: 'black',
boundsPadding: [10, 0, 0, 0],
alignSelf: 'center',
})
container.add(days)
return {
rootContainer: container,
expectedWidth: 160,
}
},
},
]
const option = {
records,
taskListTable: {
columns,
tableWidth: 'auto',
theme: {
underlayBackgroundColor: '#1c202c',
headerStyle: {
borderColor: '#e1e4e8',
borderLineWidth: 0,
fontSize: 18,
fontWeight: 'bold',
color: 'red',
// bgColor: '#EEF1F5'
},
bodyStyle: {
borderColor: '#e1e4e8',
borderLineWidth: 0,
fontSize: 16,
color: '#4D4D4D',
bgColor: '#FFF',
},
},
},
frame: {
outerFrameStyle: {
borderLineWidth: 0,
borderColor: 'red',
cornerRadius: 0,
},
// verticalSplitLineHighlight: {
// lineColor: 'green',
// lineWidth: 3
// }
},
grid: {
backgroundColor: '#1c202c',
// horizontalLine: {
// lineWidth: 2,
// lineColor: '#d5d9ee',
// },
verticalLine: {
lineWidth: 1,
lineColor: '#d5d9ee',
lineDash: [8, 4],
},
},
taskList: {
backgroundColor: '#1c202c',
headerStyle: {
borderColor: '#e1e4e8',
borderLineWidth: 0,
fontSize: 18,
fontWeight: 'bold',
color: 'red',
},
},
headerRowHeight: 60,
rowHeight: 100,
taskBar: {
resizable: false,
moveable: false,
startDateField: 'start',
endDateField: 'end',
progressField: 'progress',
barStyle: { width: 60 },
customLayout: args => {
const colorLength = barColors.length
const {
width,
height,
index,
startDate,
endDate,
taskDays,
progress,
taskRecord,
ganttInstance,
} = args
const container = new VRender.Group({
width,
height,
// cornerRadius: 30,
fill: {
gradient: 'linear',
x0: 0,
y0: 0,
x1: 1,
y1: 0,
stops: [
{
offset: 0,
color: barColors0[index % colorLength],
},
{
offset: 0.5,
color: barColors[index % colorLength],
},
{
offset: 1,
color: barColors0[index % colorLength],
},
],
},
display: 'flex',
// flexDirection: 'column',
flexWrap: 'nowrap',
})
const containerLeft = new VRender.Group({
height: 60,
width: 60,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around',
// fill: 'red'
})
container.add(containerLeft)
const avatar = new VRender.Image({
width: 50,
height: 50,
image: taskRecord.avatar,
cornerRadius: 25,
})
containerLeft.add(avatar)
const containerCenter = new VRender.Group({
height: 60,
width: width - (width >= 120 ? 120 : 60),
display: 'flex',
// flexDirection: 'column',
// alignItems: 'left'
})
container.add(containerCenter)
const checkbox = new VRender.CheckBox(checked.value)
container.add(checkbox)
checkbox.addEventListener('click', event => {
console.log(event, checkbox, 'event')
})
const developer = new VRender.Text({
text: taskRecord.developer,
fontSize: 16,
fontFamily: 'sans-serif',
fill: 'white',
fontWeight: 'bold',
maxLineWidth: width - (width >= 120 ? 120 : 60),
boundsPadding: [10, 0, 0, 0],
})
containerCenter.add(developer)
const days = new VRender.Text({
text: `${taskDays}`,
fontSize: 13,
fontFamily: 'sans-serif',
fill: 'white',
boundsPadding: [10, 0, 0, 0],
})
containerCenter.add(days)
if (width >= 120) {
const containerRight = new VRender.Group({
cornerRadius: 20,
fill: 'white',
height: 40,
width: 40,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center', //
boundsPadding: [10, 0, 0, 0],
})
container.add(containerRight)
const progressText = new VRender.Text({
text: `${progress}%`,
fontSize: 12,
fontFamily: 'sans-serif',
fill: 'black',
alignSelf: 'center',
fontWeight: 'bold',
maxLineWidth: (width - 60) / 2,
boundsPadding: [0, 0, 0, 0],
})
containerRight.add(progressText)
}
return {
rootContainer: container,
// renderDefaultBar: true
// renderDefaultText: true
}
},
hoverBarStyle: {
cornerRadius: 0,
barOverlayColor: '#f0f0',
},
},
timelineHeader: {
backgroundColor: '#1c202c',
colWidth: 100,
// verticalLine: {
// lineColor: 'red',
// lineWidth: 1,
// lineDash: [4, 2]
// },
// horizontalLine: {
// lineColor: 'green',
// lineWidth: 1,
// lineDash: [4, 2]
// },
scales: [
{
unit: 'day',
step: 1,
format(date) {
return date.dateIndex.toString()
},
customLayout: args => {
const colorLength = barColors.length
const {
width,
height,
index,
startDate,
endDate,
days,
dateIndex,
title,
ganttInstance,
} = args
console.log(width, height, 'height')
const container = new VRender.Group({
width,
height,
fill: '#1c202c',
display: 'flex',
flexDirection: 'row',
flexWrap: 'nowrap',
})
const containerLeft = new VRender.Group({
height,
width: 30,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around',
// fill: 'red'
})
container.add(containerLeft)
const avatar = new VRender.Image({
width: 20,
height: 30,
image:
'<svg t="1724675965803" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4299" width="200" height="200"><path d="M53.085678 141.319468C23.790257 141.319468 0 165.035326 0 194.34775L0 918.084273C0 947.295126 23.796789 971.112572 53.085678 971.112572L970.914322 971.112572C1000.209743 971.112572 1024 947.396696 1024 918.084273L1024 194.34775C1024 165.136896 1000.203211 141.319468 970.914322 141.319468L776.827586 141.319468 812.137931 176.629813 812.137931 88.275862C812.137931 68.774506 796.328942 52.965517 776.827586 52.965517 757.32623 52.965517 741.517241 68.774506 741.517241 88.275862L741.517241 176.629813 741.517241 211.940158 776.827586 211.940158 970.914322 211.940158C961.186763 211.940158 953.37931 204.125926 953.37931 194.34775L953.37931 918.084273C953.37931 908.344373 961.25643 900.491882 970.914322 900.491882L53.085678 900.491882C62.813237 900.491882 70.62069 908.306097 70.62069 918.084273L70.62069 194.34775C70.62069 204.087649 62.74357 211.940158 53.085678 211.940158L247.172414 211.940158C266.67377 211.940158 282.482759 196.131169 282.482759 176.629813 282.482759 157.128439 266.67377 141.319468 247.172414 141.319468L53.085678 141.319468ZM211.862069 176.629813C211.862069 196.131169 227.671058 211.940158 247.172414 211.940158 266.67377 211.940158 282.482759 196.131169 282.482759 176.629813L282.482759 88.275862C282.482759 68.774506 266.67377 52.965517 247.172414 52.965517 227.671058 52.965517 211.862069 68.774506 211.862069 88.275862L211.862069 176.629813ZM1024 353.181537 1024 317.871192 988.689655 317.871192 35.310345 317.871192 0 317.871192 0 353.181537 0 441.457399C0 460.958755 15.808989 476.767744 35.310345 476.767744 54.811701 476.767744 70.62069 460.958755 70.62069 441.457399L70.62069 353.181537 35.310345 388.491882 988.689655 388.491882 953.37931 353.181537 953.37931 441.457399C953.37931 460.958755 969.188299 476.767744 988.689655 476.767744 1008.191011 476.767744 1024 460.958755 1024 441.457399L1024 353.181537ZM776.937913 582.62069C796.439287 582.62069 812.248258 566.811701 812.248258 547.310345 812.248258 527.808989 796.439287 512 776.937913 512L247.172414 512C227.671058 512 211.862069 527.808989 211.862069 547.310345 211.862069 566.811701 227.671058 582.62069 247.172414 582.62069L776.937913 582.62069ZM247.172414 688.551724C227.671058 688.551724 211.862069 704.360713 211.862069 723.862069 211.862069 743.363425 227.671058 759.172414 247.172414 759.172414L600.386189 759.172414C619.887563 759.172414 635.696534 743.363425 635.696534 723.862069 635.696534 704.360713 619.887563 688.551724 600.386189 688.551724L247.172414 688.551724ZM776.827586 211.940158 741.517241 176.629813 741.517241 247.328574C741.517241 266.829948 757.32623 282.638919 776.827586 282.638919 796.328942 282.638919 812.137931 266.829948 812.137931 247.328574L812.137931 176.629813 812.137931 141.319468 776.827586 141.319468 247.172414 141.319468C227.671058 141.319468 211.862069 157.128439 211.862069 176.629813 211.862069 196.131169 227.671058 211.940158 247.172414 211.940158L776.827586 211.940158ZM282.482759 176.629813C282.482759 157.128439 266.67377 141.319468 247.172414 141.319468 227.671058 141.319468 211.862069 157.128439 211.862069 176.629813L211.862069 247.328574C211.862069 266.829948 227.671058 282.638919 247.172414 282.638919 266.67377 282.638919 282.482759 266.829948 282.482759 247.328574L282.482759 176.629813Z" fill="#389BFF" p-id="4300"></path></svg>',
})
containerLeft.add(avatar)
const containerCenter = new VRender.Group({
height,
width: width - 30,
display: 'flex',
flexDirection: 'column',
// alignItems: 'left'
})
container.add(containerCenter)
const dayNumber = new VRender.Text({
text: String(dateIndex).padStart(2, '0'),
fontSize: 20,
fontWeight: 'bold',
fontFamily: 'sans-serif',
fill: 'white',
textAlign: 'right',
maxLineWidth: width - 30,
boundsPadding: [15, 0, 0, 0],
})
containerCenter.add(dayNumber)
const weekDay = new VRender.Text({
text: tools.getWeekday(startDate, 'short').toLocaleUpperCase(),
fontSize: 12,
fontFamily: 'sans-serif',
fill: 'white',
boundsPadding: [0, 0, 0, 0],
})
containerCenter.add(weekDay)
return {
rootContainer: container,
//renderDefaultText: true
}
},
},
],
},
minDate: '2024-07-20',
maxDate: '2024-08-30',
markLine: [
{
date: '2024-07-29',
style: {
lineWidth: 1,
lineColor: 'blue',
lineDash: [8, 4],
},
},
{
date: '2024-08-17',
style: {
lineWidth: 2,
lineColor: 'red',
lineDash: [8, 4],
},
},
],
scrollStyle: {
scrollRailColor: 'RGBA(246,246,246,0)',
visible: 'focus',
width: 6,
scrollSliderCornerRadius: 2,
scrollSliderColor: 'rgba(255,255,255,0.25)',
},
underlayBackgroundColor: '#1c202c',
}
const range = ref()
const value = ref('month')
onMounted(() => {
nextTick(() => {
ganttInstance = new Gantt(document.getElementById('tableContainer'), option)
window['ganttInstance'] = ganttInstance
})
})
</script>
<template>
<div class="flex flex-col bg-[#1c202c] w-h-full">
<div class="relative h-[60px]">
<header-com />
</div>
<div class="z-30 flex flex-1 flex-col gap-2 p-5">
<div class="flex gap-2">
<n-date-picker v-model:value="range" type="daterange" clearable />
<n-radio-group v-model:value="value" name="radiobuttongroup">
<n-radio-button value="day" label="日" />
<n-radio-button value="month" label="月" />
</n-radio-group>
</div>
<div id="tableContainer" class="bg-[#1c202c] w-h-full"></div>
</div>
</div>
</template>

17
src/views/Gantt/index.jsx Normal file
View File

@ -0,0 +1,17 @@
import { RouterView } from 'vue-router'
import HeaderCom from '../Content/components/Header/index.vue'
export default defineComponent({
setup() {
return () => (
<div class="flex flex-col bg-[#1c202c] w-h-full">
<div class="relative h-[60px]">
<HeaderCom />
</div>
<div class="z-30 flex flex-1 flex-col gap-4 p-5">
<RouterView />
</div>
</div>
)
},
})

View File

@ -0,0 +1,7 @@
<script setup>
import TestJsx from './index.jsx'
</script>
<template>
<test-jsx />
</template>

View File

@ -47,7 +47,7 @@ export function useSatellite() {
// setTimeout(() => {
// satellite.sensor = true
// }, 10000)
// }, 2000)
// viewer.clock.multiplier = 100
return cesiumSateEntity

View File

@ -0,0 +1,98 @@
import { ref, nextTick } from 'vue'
import { parseWKT } from '@/utils/parseWKT'
import Subscriber from '@cesium-extends/subscriber'
import { useWeatherPopup } from './weatherPopup'
const { popupMap, createPopup } = useWeatherPopup()
let subscriber: Subscriber | null = null
const weatherMap = new Map()
const weatherList = [
{
id: '10',
createTime: null,
updateTime: null,
geom: 'POINT (121.9 29.02)',
type: 'weather',
name: '晴天',
description: null,
},
]
const useWeather = () => {
const showWeather = ref(true)
nextTick(() => {
watch(
showWeather,
newVal => {
newVal ? showWeatherPoints() : hideWeatherPoints()
},
{
immediate: true,
}
)
})
return {
showWeather,
}
}
function showWeatherPoints() {
subscriber = new Subscriber(viewer, {
pickResult: {
enable: true,
},
})
weatherList.forEach(data => {
const entity = createWeatherPoint(data)
addEventSub(data.id, entity, data)
weatherMap.set(data.id, entity)
})
}
function hideWeatherPoints() {
subscriber && subscriber.destroy()
weatherMap.keys().forEach(key => {
viewer.entities.remove(weatherMap.get(key))
weatherMap.delete(key)
if (popupMap.has(key)) {
popupMap.get(key).windowClose()
popupMap.delete(key)
}
})
}
function createWeatherPoint(data) {
const { name, geom } = data
const pos = parseWKT(geom).coordinates
const entity = viewer.entities.add({
name,
position: Cesium.Cartesian3.fromDegrees(...pos),
billboard: {
image: '/images/icons/base/weather.png',
width: 30,
height: 30,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
})
return entity
}
function addEventSub(
id: string | number,
entity: Cesium.Entity,
data: Record<string, any>
) {
subscriber &&
subscriber.add(
entity,
(movement, entity) => {
console.log(movement, entity, 'move')
createPopup(id, entity.position, data)
},
'LEFT_CLICK'
)
// console.log(subscriber, '-------')
}
export { useWeather }

View File

@ -0,0 +1,39 @@
import Popup from '@/views/Earth/components/Popup'
const popupMap: Map<string | number, any> = new Map()
export const useWeatherPopup = () => {
return {
popupMap,
createPopup,
}
}
function createPopup(id: string | number, position: Cesium.Cartesian3, data) {
if (popupMap.has(id)) {
return
}
const opts = {
viewer,
position,
title: '天气信息',
slotContent: generateContent(data),
// slotFooter: generateFooter(data),
closeEvent: function () {
if (popupMap.has(id)) {
popupMap.get(id).windowClose()
popupMap.delete(id)
}
},
}
const popup = new Popup(opts)
popupMap.set(id, popup)
}
function generateContent(data: TBaseNode) {
return h(
'div',
{},
Object.keys(data).map(key => h('div', {}, `${key}${data[key]}`))
)
}

View File

@ -4,6 +4,7 @@ import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import WindiCSS from 'vite-plugin-windicss'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
@ -11,17 +12,18 @@ import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'
// https://vitejs.dev/config/
export default defineConfig({
define: {
// enable hydration mismatch details in production build
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'true',
},
// define: {
// // enable hydration mismatch details in production build
// __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'true',
// },
base: '/',
plugins: [
vue({
script: {
defineModel: true,
},
}),
vueJsx(),
WindiCSS(),
AutoImport({
imports: [