雨辰5日gantt
This commit is contained in:
parent
a1bf52118e
commit
a2b20d4b56
10
public/baseConfig.js
Normal file → Executable file
10
public/baseConfig.js
Normal file → Executable file
@ -83,10 +83,12 @@ window['settings'] = {
|
||||
|
||||
dd: { label: '主体' },
|
||||
|
||||
mainEvent: { label: '主事件', color: 'success' },
|
||||
eventType: { label: '事件分类', color: 'info' },
|
||||
1: { label: '主事件', color: 'success' },
|
||||
2: { label: '事件分类', color: 'info' },
|
||||
|
||||
subEvent: { label: '子事件', color: 'warning' },
|
||||
twoEvent: { label: '二级分类', color: 'warning' },
|
||||
3: { label: '二级分类', color: 'warning' },
|
||||
4: { label: '子事件', color: 'warning' },
|
||||
},
|
||||
|
||||
imgServer: 'http://minio.yc.com:29990/professional-system',
|
||||
}
|
||||
|
26
src/api/Gantt/gantt.js
Executable file
26
src/api/Gantt/gantt.js
Executable file
@ -0,0 +1,26 @@
|
||||
import { defAxios as request } from '@/utils/http'
|
||||
const baseUrl = `${window.settings.apis}/gantt`
|
||||
|
||||
|
||||
export function getDDList() {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-info/simp-list`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
export function getMainGantt(data = {}) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-info/gantt-list`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function getSubGantt(params) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/activity-event/gantt-list`,
|
||||
method: 'get',
|
||||
params,
|
||||
})
|
||||
}
|
104
src/api/Gantt/index.js
Normal file → Executable file
104
src/api/Gantt/index.js
Normal file → Executable file
@ -11,7 +11,7 @@ const sub = [
|
||||
name: '弹道DD',
|
||||
start: '2024-11-15',
|
||||
end: '2024-11-17',
|
||||
type: "twoEvent",
|
||||
type: 'twoEvent',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
@ -21,7 +21,6 @@ const sub = [
|
||||
type: 'subEvent',
|
||||
trajData: {},
|
||||
avatar: '/images/影像.jpg',
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -30,7 +29,7 @@ const sub = [
|
||||
name: '巡航DD',
|
||||
start: '2024-11-15',
|
||||
end: '2024-11-17',
|
||||
type: "twoEvent",
|
||||
type: 'twoEvent',
|
||||
children: [
|
||||
{
|
||||
id: 1,
|
||||
@ -40,12 +39,10 @@ const sub = [
|
||||
type: 'subEvent',
|
||||
trajData: {},
|
||||
avatar: '/images/影像.jpg',
|
||||
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
},
|
||||
{
|
||||
id: 300,
|
||||
@ -370,3 +367,100 @@ export function getTask() {
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
|
||||
import { defAxios as request } from '@/utils/http'
|
||||
const baseUrl = window.settings.apis + '/gantt'
|
||||
// export function getHangjing(data = {}) {
|
||||
// return request({
|
||||
// url: `${baseUrl}/hangjing/list`,
|
||||
// method: 'post',
|
||||
// data,
|
||||
// })
|
||||
// }
|
||||
|
||||
export function getSimpList() {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-info/simp-list`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
export function getSimpTreeList(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-activity/tree-list`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function addSimp(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-activity/create`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function updateSimp(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-activity/update`,
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function uploadImage(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/platform/sys/file/sync/upload`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteSimp(params) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/target-activity/delete`,
|
||||
method: 'delete',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
export function getSon(params) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/activity-event/get`,
|
||||
method: 'get',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
export function addSon(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/activity-event/create`,
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function updateSon(data) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/activity-event/update`,
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function getTwoClass(params) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/data-type/list`,
|
||||
method: 'get',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
||||
export function deleteSon(params) {
|
||||
return request({
|
||||
url: `${baseUrl}/gantt/activity-event/delete`,
|
||||
method: 'delete',
|
||||
params,
|
||||
})
|
||||
}
|
||||
|
@ -38,6 +38,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
nodeClick: {
|
||||
type: Function as (key: string) => void,
|
||||
default: undefined,
|
||||
},
|
||||
})
|
||||
|
||||
const searchValue = ref<string>('')
|
||||
@ -48,6 +52,11 @@ const updateChecked = (keys: Array<string | number>) => {
|
||||
checkedKeys.value = keys
|
||||
}
|
||||
|
||||
const updateSelected = (key: Array<string | number>) => {
|
||||
// nodeClick && nodeClick(props.data.find(item => item[props.keyField] === keys[0]))
|
||||
props.nodeClick && props.nodeClick(key)
|
||||
}
|
||||
|
||||
// watch(
|
||||
// () => props.defaultCheckedKeys,
|
||||
// val => {
|
||||
@ -86,6 +95,7 @@ const updateChecked = (keys: Array<string | number>) => {
|
||||
:node-props="nodeProps"
|
||||
:render-suffix="renderSuffix"
|
||||
:render-label="renderLabel"
|
||||
@update:selected-keys="updateSelected"
|
||||
/>
|
||||
<!-- :default-checked-keys="defaultCheckedKeys" -->
|
||||
</n-scrollbar>
|
||||
|
@ -132,8 +132,16 @@ export class Beam {
|
||||
})
|
||||
this.beamEntity = cylinder
|
||||
|
||||
// const that = this
|
||||
let currentTime = 0
|
||||
this._listener = (scene, time) => {
|
||||
const timeStamp = Cesium.JulianDate.toDate(time).getTime()
|
||||
const deltaTime = timeStamp - currentTime
|
||||
|
||||
if (deltaTime <= 100) {
|
||||
return
|
||||
}
|
||||
currentTime = timeStamp
|
||||
|
||||
if (!this.beamEntity) {
|
||||
return
|
||||
}
|
||||
@ -144,11 +152,8 @@ export class Beam {
|
||||
if (!topPosition) {
|
||||
return
|
||||
}
|
||||
// console.log(topPosition, 'topPosition')
|
||||
let bottomPosition = this.bottomEntity.position._value
|
||||
// console.log(bottomPosition, 'bottomPosition')
|
||||
this.centerPoint = this._getCenterPoint(topPosition, bottomPosition)
|
||||
// console.log(this.centerPoint, 'centerPoint')
|
||||
this.beamEntity.position = this.centerPoint
|
||||
this.distance = this._getDistance(topPosition, bottomPosition)
|
||||
this.beamEntity.cylinder.length = this.distance
|
||||
@ -156,14 +161,12 @@ export class Beam {
|
||||
const orientation = this._getOrientation(bottomPosition, topPosition)
|
||||
|
||||
this.beamEntity.orientation = orientation
|
||||
console.log('1')
|
||||
// throw new Error('TODO: Beam.js:26 Uncaught Error: TODO: Beam.js:26')
|
||||
}
|
||||
|
||||
// viewer.scene.preRender.addEventListener(this._listener)
|
||||
setInterval(() => {
|
||||
this._listener(viewer.scene, viewer.clock.currentTime)
|
||||
}, 100)
|
||||
viewer.scene.preRender.addEventListener(this._listener)
|
||||
// setInterval(() => {
|
||||
// this._listener(viewer.scene, viewer.clock.currentTime)
|
||||
// }, 100)
|
||||
}
|
||||
|
||||
_getCenterPoint(t, b) {
|
||||
|
0
src/views/Gantt/components/EventList/components/EventDdConfig.jsx
Normal file → Executable file
0
src/views/Gantt/components/EventList/components/EventDdConfig.jsx
Normal file → Executable file
82
src/views/Gantt/components/EventList/components/MainEventEdit.jsx
Normal file → Executable file
82
src/views/Gantt/components/EventList/components/MainEventEdit.jsx
Normal file → Executable file
@ -8,6 +8,7 @@ import {
|
||||
} from 'naive-ui'
|
||||
import ModalCom from '@/components/Modal/index.vue'
|
||||
import { useEvent } from '../hooks'
|
||||
import { addSimp, updateSimp, uploadImage } from '@/api/Gantt'
|
||||
export default defineComponent({
|
||||
// props: {
|
||||
// show: {
|
||||
@ -16,61 +17,110 @@ export default defineComponent({
|
||||
// },
|
||||
// },
|
||||
setup() {
|
||||
const { showMainEvent, mainEventData } = useEvent()
|
||||
const imageValue = ref()
|
||||
const {
|
||||
universalRules,
|
||||
showMainEvent,
|
||||
mainEventData,
|
||||
targetId,
|
||||
searchTreeList,
|
||||
} = useEvent()
|
||||
|
||||
const close = () => {
|
||||
showMainEvent.value = false
|
||||
}
|
||||
const changeFile = async file => {
|
||||
console.log(uploadImg)
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file.file)
|
||||
const res = await uploadImage(formData)
|
||||
imageValue.value = res.data.path
|
||||
}
|
||||
const sure = async () => {
|
||||
const data = {
|
||||
...mainEventData.value,
|
||||
targetId: targetId.value,
|
||||
fileUrl: imageValue.value,
|
||||
startTime: new Date(timeRange.value[0]).toISOString(),
|
||||
endTime: new Date(timeRange.value[0]).toISOString(),
|
||||
}
|
||||
|
||||
const res = mainEventData.value.id
|
||||
? await updateSimp(data)
|
||||
: await addSimp(data)
|
||||
if (res.code === 200) {
|
||||
showMainEvent.value = false
|
||||
searchTreeList()
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
[
|
||||
() => mainEventData.value.start,
|
||||
() => mainEventData.value.end,
|
||||
() => mainEventData.value.avatar,
|
||||
() => mainEventData.value.startTime,
|
||||
() => mainEventData.value.endTime,
|
||||
() => mainEventData.value.fileUrl,
|
||||
],
|
||||
([start, end, avatar]) => {
|
||||
timeRange.value = start ? [start, end] : null
|
||||
uploadImg.value = [
|
||||
{
|
||||
url: avatar,
|
||||
status: 'finished',
|
||||
},
|
||||
]
|
||||
([start, end, fileUrl]) => {
|
||||
timeRange.value = start
|
||||
? [new Date(start).getTime(), new Date(end).getTime()]
|
||||
: null
|
||||
if (fileUrl) {
|
||||
uploadImg.value = [
|
||||
{
|
||||
id: '1',
|
||||
name: fileUrl,
|
||||
url: `${window.settings.imgServer}${fileUrl}`,
|
||||
status: 'finished',
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const timeRange = ref(null)
|
||||
const uploadImg = ref([])
|
||||
// const desc = ref ()
|
||||
|
||||
return () => (
|
||||
<ModalCom v-model:show={showMainEvent.value} title="编辑事件">
|
||||
<ModalCom
|
||||
v-model:show={showMainEvent.value}
|
||||
title={`${mainEventData.value.id ? '编辑' : '添加'}事件`}
|
||||
>
|
||||
<NForm
|
||||
class="w-[500px]"
|
||||
model={mainEventData}
|
||||
label-placement="left"
|
||||
label-width="auto"
|
||||
rules={universalRules}
|
||||
>
|
||||
<NFormItem label="事件名称" path="name">
|
||||
<NInput v-model:value={mainEventData.value.name} />
|
||||
</NFormItem>
|
||||
<NFormItem label="事件时间" path="description">
|
||||
<NFormItem label="事件时间" path="startTime">
|
||||
<NDatePicker
|
||||
v-model:value={timeRange.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="上传图片" path="avatar">
|
||||
<NFormItem label="事件描述" path="describe">
|
||||
<NInput
|
||||
v-model:value={mainEventData.value.describe}
|
||||
type="textarea"
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="上传图片" path="fileUrl">
|
||||
<NUpload
|
||||
default-file-list={uploadImg.value}
|
||||
list-type="image-card"
|
||||
max={1}
|
||||
onChange={changeFile}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton onClick={close}>取消</NButton>
|
||||
<NButton type="primary" onClick={close}>
|
||||
<NButton type="primary" onClick={sure}>
|
||||
确认
|
||||
</NButton>
|
||||
</div>
|
||||
|
103
src/views/Gantt/components/EventList/components/SubEventEdit.jsx
Normal file → Executable file
103
src/views/Gantt/components/EventList/components/SubEventEdit.jsx
Normal file → Executable file
@ -9,6 +9,7 @@ import {
|
||||
} from 'naive-ui'
|
||||
import ModalCom from '@/components/Modal/index.vue'
|
||||
import { useEvent } from '../hooks'
|
||||
import { addSon, updateSon, uploadImage } from '@/api/gantt'
|
||||
export default defineComponent({
|
||||
// props: {
|
||||
// show: {
|
||||
@ -17,34 +18,77 @@ export default defineComponent({
|
||||
// },
|
||||
// },
|
||||
setup() {
|
||||
const { showNewEvent, eventData } = useEvent()
|
||||
|
||||
const {
|
||||
showNewEvent,
|
||||
eventData,
|
||||
sonOptions,
|
||||
oneClassData,
|
||||
searchTreeList,
|
||||
} = useEvent()
|
||||
const imageValue = ref()
|
||||
const close = () => {
|
||||
showNewEvent.value = false
|
||||
}
|
||||
const changeFile = async file => {
|
||||
const formData = new FormData()
|
||||
formData.append('file', file.file.file)
|
||||
const res = await uploadImage(formData)
|
||||
imageValue.value = res.data.path
|
||||
}
|
||||
const sure = async () => {
|
||||
const data = {
|
||||
// id: eventData.value.id ?? null,
|
||||
// activityId: oneClassData.value.activityId ?? null,
|
||||
// name: eventData.value.name,
|
||||
activityId: oneClassData.value?.pid ?? null,
|
||||
oneType: oneClassData.value?.id,
|
||||
...eventData.value,
|
||||
twoType: twoTypeId.value,
|
||||
fileUrl: imageValue.value,
|
||||
startTime: new Date(timeRange.value[0]).toISOString(),
|
||||
endTime: new Date(timeRange.value[1]).toISOString(),
|
||||
}
|
||||
// console.log(data, 'data')
|
||||
const res = eventData.value.id
|
||||
? await updateSon(data)
|
||||
: await addSon(data)
|
||||
if (res.code === 200) {
|
||||
showNewEvent.value = false
|
||||
searchTreeList()
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
[
|
||||
() => eventData.value.start,
|
||||
() => eventData.value.end,
|
||||
() => eventData.value.avatar,
|
||||
() => eventData.value.startTime,
|
||||
() => eventData.value.endTime,
|
||||
() => eventData.value.fileUrl,
|
||||
() => eventData.value.twoType,
|
||||
],
|
||||
([start, end, avatar]) => {
|
||||
timeRange.value = start ? [start, end] : null
|
||||
uploadImg.value = [
|
||||
{
|
||||
url: avatar,
|
||||
status: 'finished',
|
||||
},
|
||||
]
|
||||
([start, end, fileUrl, twoType]) => {
|
||||
timeRange.value = start
|
||||
? [new Date(start).getTime(), new Date(end).getTime()]
|
||||
: null
|
||||
if (fileUrl) {
|
||||
uploadImg.value = [
|
||||
{
|
||||
id: fileUrl,
|
||||
name: fileUrl,
|
||||
url: `${window.settings.imgServer}${fileUrl}`,
|
||||
status: 'finished',
|
||||
},
|
||||
]
|
||||
console.log(uploadImg.value)
|
||||
}
|
||||
console.log(twoType, 'twoType')
|
||||
|
||||
twoType && (twoTypeId.value = twoType)
|
||||
}
|
||||
)
|
||||
|
||||
const timeRange = ref(null)
|
||||
const uploadImg = ref([])
|
||||
const value1 = ref(null)
|
||||
const value2 = ref(null)
|
||||
const value3 = ref(null)
|
||||
const twoTypeId = ref(null)
|
||||
|
||||
return () => (
|
||||
<ModalCom
|
||||
@ -58,35 +102,50 @@ export default defineComponent({
|
||||
label-width="auto"
|
||||
>
|
||||
<NFormItem label="二级分类">
|
||||
<NSelect v-model:value={value1.value}></NSelect>
|
||||
<NSelect
|
||||
v-model:value={twoTypeId.value}
|
||||
options={sonOptions.value}
|
||||
label-field="name"
|
||||
value-field="id"
|
||||
></NSelect>
|
||||
</NFormItem>
|
||||
<NFormItem label="步骤">
|
||||
{/* <NFormItem label="步骤">
|
||||
<NSelect v-model:value={value2.value}></NSelect>
|
||||
</NFormItem>
|
||||
<NFormItem label="目标">
|
||||
<NSelect v-model:value={value3.value}></NSelect>
|
||||
</NFormItem>
|
||||
</NFormItem> */}
|
||||
<NFormItem label="事件名称" path="name">
|
||||
<NInput v-model:value={eventData.value.name} />
|
||||
</NFormItem>
|
||||
<NFormItem label="事件时间" path="description">
|
||||
<NFormItem label="事件时间" path="startTime">
|
||||
<NDatePicker
|
||||
v-model:value={timeRange.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
/>
|
||||
</NFormItem>
|
||||
<NFormItem label="上传图片" path="avatar">
|
||||
<NFormItem label="装备型号" path="equipModel">
|
||||
<NInput v-model:value={eventData.value.equipModel} />
|
||||
</NFormItem>
|
||||
<NFormItem label="上报站点" path="reportSite">
|
||||
<NInput v-model:value={eventData.value.reportSite} />
|
||||
</NFormItem>
|
||||
<NFormItem label="事件描述" path="describe">
|
||||
<NInput v-model:value={eventData.value.describe} type="textarea" />
|
||||
</NFormItem>
|
||||
<NFormItem label="上传图片" path="fileUrl">
|
||||
<NUpload
|
||||
default-file-list={uploadImg.value}
|
||||
list-type="image-card"
|
||||
onChange={changeFile}
|
||||
max={1}
|
||||
/>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
<div class="flex justify-end gap-2">
|
||||
<NButton onClick={close}>取消</NButton>
|
||||
<NButton type="primary" onClick={close}>
|
||||
<NButton type="primary" onClick={sure}>
|
||||
确认
|
||||
</NButton>
|
||||
</div>
|
||||
|
0
src/views/Gantt/components/EventList/components/useEventDdConfig.jsx
Normal file → Executable file
0
src/views/Gantt/components/EventList/components/useEventDdConfig.jsx
Normal file → Executable file
98
src/views/Gantt/components/EventList/hooks.jsx
Normal file → Executable file
98
src/views/Gantt/components/EventList/hooks.jsx
Normal file → Executable file
@ -1,30 +1,106 @@
|
||||
import { generateId } from '@/utils/id'
|
||||
import { getSimpTreeList, getTwoClass } from '@/api/Gantt'
|
||||
|
||||
const universalRules = {
|
||||
name: { required: true, message: '请输入', trigger: 'blur' },
|
||||
startTime: { required: true, message: '请输入', trigger: 'blur' },
|
||||
}
|
||||
const showMainEvent = ref(false)
|
||||
|
||||
watch(showMainEvent, show => {
|
||||
if (!show) {
|
||||
resetMainEventData()
|
||||
}
|
||||
})
|
||||
|
||||
const mainEventData = ref({
|
||||
name: '',
|
||||
start: '',
|
||||
end: '',
|
||||
type: 'mainEvent',
|
||||
avatar: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
// type: 'mainEvent',
|
||||
describe: '',
|
||||
fileUrl: '',
|
||||
})
|
||||
|
||||
function resetMainEventData() {
|
||||
mainEventData.value = ref({
|
||||
name: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
// type: 'mainEvent',
|
||||
describe: '',
|
||||
fileUrl: '',
|
||||
})
|
||||
}
|
||||
|
||||
const targetId = ref(null)
|
||||
const range = ref([new Date('2000-01-01').getTime(), Date.now()])
|
||||
|
||||
const showNewEvent = ref(false)
|
||||
|
||||
const eventData = ref({
|
||||
name: '',
|
||||
start: '',
|
||||
end: '',
|
||||
avatar: '',
|
||||
type: 'subEvent',
|
||||
watch(showNewEvent, show => {
|
||||
if (!show) {
|
||||
oneClassData.value = null
|
||||
resetEventData()
|
||||
}
|
||||
})
|
||||
|
||||
const eventData = ref({
|
||||
name: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
fileUrl: '',
|
||||
describe: '',
|
||||
equipModel: '',
|
||||
reportSite: '',
|
||||
// type: 'subEvent',
|
||||
})
|
||||
|
||||
function resetEventData() {
|
||||
eventData.value = ref({
|
||||
name: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
fileUrl: '',
|
||||
describe: '',
|
||||
equipModel: '',
|
||||
reportSite: '',
|
||||
})
|
||||
}
|
||||
|
||||
const tableData = ref([])
|
||||
|
||||
const oneClassData = ref(null)
|
||||
async function searchTreeList() {
|
||||
tableData.value = []
|
||||
|
||||
const res = await getSimpTreeList({
|
||||
targetId: targetId.value,
|
||||
startTime: new Date(range.value[0]).toISOString(),
|
||||
endTime: new Date(range.value[1]).toISOString(),
|
||||
})
|
||||
tableData.value = res.data.list
|
||||
// console.log('searchTreeList', tableData)
|
||||
}
|
||||
|
||||
const sonOptions = ref([])
|
||||
async function getTwoClassList(oneTypeId) {
|
||||
const res = await getTwoClass({ oneType: oneTypeId })
|
||||
sonOptions.value = res.data.list
|
||||
}
|
||||
// const getSonList = async()
|
||||
export const useEvent = () => {
|
||||
return {
|
||||
universalRules,
|
||||
showMainEvent,
|
||||
mainEventData,
|
||||
showNewEvent,
|
||||
eventData,
|
||||
targetId,
|
||||
searchTreeList,
|
||||
tableData,
|
||||
range,
|
||||
oneClassData,
|
||||
sonOptions,
|
||||
getTwoClassList,
|
||||
}
|
||||
}
|
||||
|
110
src/views/Gantt/components/EventList/index.jsx
Normal file → Executable file
110
src/views/Gantt/components/EventList/index.jsx
Normal file → Executable file
@ -1,5 +1,10 @@
|
||||
import { NDataTable, NIcon, NButton, useDialog, NTag } from 'naive-ui'
|
||||
import { getEventListByDDType } from '@/api/gantt'
|
||||
import {
|
||||
getEventListByDDType,
|
||||
deleteSimp,
|
||||
getTwoClass,
|
||||
deleteSon,
|
||||
} from '@/api/gantt'
|
||||
import { useTree } from '@/utils/tree'
|
||||
import {
|
||||
HelpCircleOutline,
|
||||
@ -9,6 +14,8 @@ import {
|
||||
EnterOutline,
|
||||
} from '@vicons/ionicons5'
|
||||
|
||||
import { cloneDeep } from 'es-toolkit'
|
||||
|
||||
import MainEventEdit from './components/MainEventEdit'
|
||||
import SubEventEdit from './components/SubEventEdit'
|
||||
|
||||
@ -19,18 +26,31 @@ import { useEvent } from './hooks'
|
||||
export default defineComponent({
|
||||
props: {
|
||||
dd: {
|
||||
type: String,
|
||||
type: Number,
|
||||
require: true,
|
||||
},
|
||||
tableData: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { showMainEvent, mainEventData, showNewEvent, eventData } = useEvent()
|
||||
const {
|
||||
showMainEvent,
|
||||
mainEventData,
|
||||
showNewEvent,
|
||||
eventData,
|
||||
searchTreeList,
|
||||
oneClassData,
|
||||
// sonOptions,
|
||||
getTwoClassList,
|
||||
} = useEvent()
|
||||
const dict = window.settings.gantt
|
||||
const columns = [
|
||||
{
|
||||
title: '事件名称',
|
||||
key: 'name',
|
||||
width: 'auto',
|
||||
// width: 'auto',
|
||||
render: row => {
|
||||
return (
|
||||
<div class="inline-flex items-center gap-2">
|
||||
@ -41,9 +61,9 @@ export default defineComponent({
|
||||
size="small"
|
||||
round
|
||||
bordered={false}
|
||||
type={dict[row.type].color}
|
||||
type={dict[row.level].color}
|
||||
>
|
||||
{dict[row.type].label}
|
||||
{dict[row.level].label}
|
||||
</NTag>
|
||||
{row.name}
|
||||
</div>
|
||||
@ -52,11 +72,13 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
key: 'start',
|
||||
key: 'startTime',
|
||||
width: '300',
|
||||
},
|
||||
{
|
||||
title: '结束时间',
|
||||
key: 'end',
|
||||
key: 'endTime',
|
||||
width: '300',
|
||||
},
|
||||
// {
|
||||
// title: '类型',
|
||||
@ -76,10 +98,17 @@ export default defineComponent({
|
||||
// },
|
||||
{
|
||||
title: '图片',
|
||||
key: 'avatar',
|
||||
key: 'filePath',
|
||||
width: '200',
|
||||
render(row) {
|
||||
if (row.avatar) {
|
||||
return <img src={row.avatar} width="50" alt="" />
|
||||
if (row.fileUrl) {
|
||||
return (
|
||||
<img
|
||||
src={`${window.settings.imgServer}${row.fileUrl}`}
|
||||
width="50"
|
||||
alt=""
|
||||
/>
|
||||
)
|
||||
} else {
|
||||
return <span>-</span>
|
||||
}
|
||||
@ -88,11 +117,12 @@ export default defineComponent({
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: '240',
|
||||
render(row, rowIndex) {
|
||||
// console.log(row, rowIndex)
|
||||
return (
|
||||
<div class="flex justify-end">
|
||||
{row.type === 'mainEvent' && (
|
||||
{row.level === 1 && (
|
||||
<NButton
|
||||
type="primary"
|
||||
size="small"
|
||||
@ -105,7 +135,7 @@ export default defineComponent({
|
||||
编辑事件
|
||||
</NButton>
|
||||
)}
|
||||
{row.type === 'twoEvent' ? (
|
||||
{row.level === 2 ? (
|
||||
<NButton
|
||||
type="success"
|
||||
size="small"
|
||||
@ -118,7 +148,7 @@ export default defineComponent({
|
||||
添加子事件
|
||||
</NButton>
|
||||
) : null}
|
||||
{row.type === 'isDD' && (
|
||||
{row.level === 4 && (
|
||||
<NButton
|
||||
type="primary"
|
||||
size="small"
|
||||
@ -144,7 +174,7 @@ export default defineComponent({
|
||||
编辑DD轨迹
|
||||
</NButton>
|
||||
)}
|
||||
{row.type === 'subEvent' && (
|
||||
{/* {row.level == 4 && (
|
||||
<NButton
|
||||
type="primary"
|
||||
size="small"
|
||||
@ -156,8 +186,8 @@ export default defineComponent({
|
||||
</NIcon>
|
||||
编辑子事件
|
||||
</NButton>
|
||||
)}
|
||||
{row.type !== 'eventType' ? (
|
||||
)} */}
|
||||
{![2, 3].includes(row.level) ? (
|
||||
<NButton
|
||||
type="error"
|
||||
size="small"
|
||||
@ -179,28 +209,40 @@ export default defineComponent({
|
||||
|
||||
function editMainEvent(row) {
|
||||
showMainEvent.value = true
|
||||
mainEventData.value = row
|
||||
mainEventData.value = cloneDeep(row)
|
||||
}
|
||||
|
||||
function addSubEvent(row) {
|
||||
const addSubEvent = async row => {
|
||||
console.log(row, 'row')
|
||||
oneClassData.value = row
|
||||
showNewEvent.value = true
|
||||
// eventData.value = {}
|
||||
await getTwoClassList(row.id)
|
||||
}
|
||||
|
||||
function editSubEvent(row) {
|
||||
showNewEvent.value = true
|
||||
eventData.value = row
|
||||
eventData.value = cloneDeep(row)
|
||||
getTwoClassList(row.oneType)
|
||||
console.log('子事件编辑:', row, 'onClassData', oneClassData)
|
||||
}
|
||||
|
||||
const dialog = useDialog()
|
||||
function deleteEvent(row) {
|
||||
console.log(row, 'row')
|
||||
dialog.warning({
|
||||
title: '删除事件',
|
||||
content: `确定删除事件 ${row.name} 吗?`,
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
// await deleteEventById(row.id)
|
||||
// getEventList()
|
||||
//await deleteEventById(row.id)
|
||||
if (row.level == 1) {
|
||||
await deleteSimp({ id: row.id })
|
||||
} else if (row.level == 4) {
|
||||
await deleteSon({ id: row.id })
|
||||
}
|
||||
searchTreeList()
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -220,35 +262,29 @@ export default defineComponent({
|
||||
})
|
||||
}
|
||||
|
||||
const tableData = ref([])
|
||||
onMounted(async () => {
|
||||
await getEventList()
|
||||
})
|
||||
|
||||
const { getAllKeys } = useTree()
|
||||
const expandedRowKeys = ref([])
|
||||
async function getEventList() {
|
||||
const res = await getEventListByDDType(props.dd)
|
||||
tableData.value = res.children
|
||||
expandedRowKeys.value = getAllKeys(tableData.value, 'name')
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.dd,
|
||||
async () => {
|
||||
getEventList()
|
||||
() => props.tableData,
|
||||
() => {
|
||||
expandedRowKeys.value = getAllKeys(props.tableData, 'name') || []
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<NDataTable
|
||||
remote
|
||||
class="h-full"
|
||||
flex-height
|
||||
indent={30}
|
||||
indent={20}
|
||||
v-model:expanded-row-keys={expandedRowKeys.value}
|
||||
columns={columns}
|
||||
data={tableData.value}
|
||||
data={props.tableData}
|
||||
row-key={row => row.name}
|
||||
/>
|
||||
<MainEventEdit v-model:show={showMainEvent.value} />
|
||||
|
0
src/views/Gantt/components/Gantt/components/VRender.jsx
Normal file → Executable file
0
src/views/Gantt/components/Gantt/components/VRender.jsx
Normal file → Executable file
263
src/views/Gantt/components/Gantt/hooks/gantt.ts
Normal file → Executable file
263
src/views/Gantt/components/Gantt/hooks/gantt.ts
Normal file → Executable file
@ -1,7 +1,10 @@
|
||||
import { Group, Image, Text, CheckBox, Rect } from '@visactor/vtable/es/vrender'
|
||||
|
||||
import { useDialog } from 'naive-ui'
|
||||
import { Gantt, tools, TYPES } from '@visactor/vtable-gantt'
|
||||
import { getMainGantt, getSubGantt } from '@/api/Gantt'
|
||||
import { getMainGantt, getSubGantt } from '@/api/Gantt/gantt'
|
||||
import { getSon } from '@/api/Gantt'
|
||||
import { useTree } from '@/utils/tree'
|
||||
import * as dayjs from 'dayjs'
|
||||
|
||||
type GanttParams = {
|
||||
route?: any
|
||||
@ -13,33 +16,121 @@ const headerBgColor = '#33566f22'
|
||||
const textColor = '#65c5e7'
|
||||
const textColorWithOp = '#75fbfd22'
|
||||
|
||||
const { getTimeRangeForTree } = useTree()
|
||||
|
||||
const useGantt = ({ router, route }: GanttParams) => {
|
||||
const currentImage = ref()
|
||||
const { subId } = route.params
|
||||
const records = ref([])
|
||||
onMounted(() => {
|
||||
getGanttData()
|
||||
})
|
||||
async function getGanttData() {
|
||||
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)
|
||||
const timeRange = ref([])
|
||||
// onMounted(() => {
|
||||
// getGanttData()
|
||||
// })
|
||||
async function getGanttData(params: Record<string, string>) {
|
||||
timeRange.value = [params.startTime, params.endTime]
|
||||
console.log('%csubId', 'color:red;font-size:20px', subId)
|
||||
const { code, data } = subId
|
||||
? await getSubGantt({ activityId: subId })
|
||||
: await getMainGantt(params)
|
||||
if (code === 200) {
|
||||
// records.value = data.list
|
||||
console.log(subId, ',,,,,')
|
||||
if (subId) {
|
||||
records.value = data.list
|
||||
.reduce((acc, cur) => {
|
||||
if (Array.isArray(cur.children) && cur.children.length > 0) {
|
||||
acc.push(
|
||||
cur.children.map(twoType => {
|
||||
return {
|
||||
...twoType,
|
||||
children:
|
||||
twoType.children &&
|
||||
twoType.children.map(eventItem => {
|
||||
console.log(
|
||||
eventItem.startTime,
|
||||
eventItem.endTime
|
||||
// new Date(eventItem.startTime).getMonth()
|
||||
)
|
||||
return {
|
||||
...eventItem,
|
||||
start: eventItem.startTime,
|
||||
end: eventItem.endTime,
|
||||
}
|
||||
}),
|
||||
parentName: cur.name,
|
||||
childrenLengthForParent: cur.children.length,
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
.flat()
|
||||
console.log(records.value)
|
||||
|
||||
records.value.length > 0 &&
|
||||
(timeRange.value = getTimeRangeForTree(records.value))
|
||||
} else {
|
||||
// console.log(data.list, '------')
|
||||
records.value = data.list.map(item => {
|
||||
return {
|
||||
...item,
|
||||
children:
|
||||
item.children &&
|
||||
item.children.map(mainEvent => {
|
||||
const date = new Date(mainEvent.startTime)
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth()
|
||||
const startOfMonth = new Date(year, month, 1)
|
||||
startOfMonth.setHours(0, 0, 0, 0)
|
||||
|
||||
const lastDayOfMonth = new Date(year, month + 1, 0)
|
||||
const endOfMonth = new Date(
|
||||
year,
|
||||
month,
|
||||
lastDayOfMonth.getDate()
|
||||
)
|
||||
endOfMonth.setHours(23, 59, 59, 9999)
|
||||
// new Date().toISOString()
|
||||
|
||||
// console.log(
|
||||
// mainEvent.startTime,
|
||||
// startOfMonth.toISOString(),
|
||||
// endOfMonth.toISOString()
|
||||
// )
|
||||
|
||||
return {
|
||||
...mainEvent,
|
||||
start: startOfMonth.toISOString(),
|
||||
end: endOfMonth.toISOString(),
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
records.value.length > 0 && ganttInstance?.setRecords(records.value)
|
||||
}
|
||||
}
|
||||
function renderMainTask(dom: HTMLElement) {
|
||||
async function renderMainTask(
|
||||
dom: HTMLElement,
|
||||
params: Record<string, string>
|
||||
) {
|
||||
// console.log(subId, 'renderMainTask')
|
||||
await getGanttData(params)
|
||||
const option = getOption()
|
||||
|
||||
// if (ganttInstance) {
|
||||
// ganttInstance.setRecords(records.value)
|
||||
// } else {
|
||||
if (records.value.length === 0) return
|
||||
ganttInstance && ganttInstance?.release()
|
||||
ganttInstance = new Gantt(dom, option)
|
||||
window['ganttInstance'] = ganttInstance
|
||||
// console.log(ganttInstance)
|
||||
// }
|
||||
}
|
||||
function getOption(): TYPES.GanttConstructorOptions {
|
||||
// console.log(records.value);
|
||||
const option = {
|
||||
records: records.value,
|
||||
taskListTable: renderTaskListTable(),
|
||||
@ -91,7 +182,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
taskBar: renderTaskBar(subId),
|
||||
timelineHeader: {
|
||||
backgroundColor: headerBgColor,
|
||||
colWidth: 140,
|
||||
colWidth: 150,
|
||||
// colWidth: 1040,
|
||||
// verticalLine: {
|
||||
// lineColor: textColorWithOp,
|
||||
@ -103,13 +194,13 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
lineWidth: 1,
|
||||
lineDash: [4, 2],
|
||||
},
|
||||
scales: getTimeScales('day'),
|
||||
scales: getTimeScales(subId ? 'day' : 'month'),
|
||||
},
|
||||
minDate: '2024-11-14',
|
||||
maxDate: '2024-12-30',
|
||||
minDate: timeRange.value[0],
|
||||
maxDate: timeRange.value[1],
|
||||
markLine: [
|
||||
{
|
||||
date: '2024-07-29',
|
||||
date: '2024-01-14T21:12:40',
|
||||
style: {
|
||||
lineWidth: 1,
|
||||
lineColor: 'blue',
|
||||
@ -128,7 +219,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
scrollStyle: {
|
||||
scrollRailColor: 'RGBA(246,246,246,0)',
|
||||
visible: 'focus',
|
||||
width: 6,
|
||||
width: 10,
|
||||
scrollSliderCornerRadius: 2,
|
||||
scrollSliderColor: 'rgba(255,255,255,0.25)',
|
||||
},
|
||||
@ -144,21 +235,8 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
width: '120',
|
||||
mergeCell: true,
|
||||
customLayout: args => {
|
||||
console.log(args, 'srgs')
|
||||
// console.log(args, 'srgs')
|
||||
const { table, row, col, rect, dataValue } = args
|
||||
// console.log(
|
||||
// table,
|
||||
// '1',
|
||||
// row,
|
||||
// '2',
|
||||
// col,
|
||||
// '3',
|
||||
// rect,
|
||||
// '4',
|
||||
// dataValue,
|
||||
// '5',
|
||||
// '-----------'
|
||||
// )
|
||||
const { height, width } = rect ?? table.getCellRect(col, row)
|
||||
const container = new Group({
|
||||
width,
|
||||
@ -174,17 +252,22 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
console.log(args)
|
||||
const count = table.records.find(r => dataValue === r.name)?.children
|
||||
?.length
|
||||
|
||||
// console.log('args:-----', args);
|
||||
|
||||
const count =
|
||||
table.records.find(r => dataValue === r.name)?.children?.length || 0
|
||||
const values = new Text({
|
||||
text: `${dataValue}`,
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
textAlign: 'center',
|
||||
// boundsPadding: [10, 0, 0, 0],
|
||||
maxLineWidth: width,
|
||||
whiteSpace: 'normal',
|
||||
// boundsPadding: [10, 10, 10, 10],
|
||||
})
|
||||
const counts = new Text({
|
||||
text: `( ${count} )`,
|
||||
@ -202,6 +285,12 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
},
|
||||
]
|
||||
if (subId) {
|
||||
columns.unshift({
|
||||
field: 'parentName',
|
||||
title: '事件分类',
|
||||
width: '120',
|
||||
mergeCell: true,
|
||||
})
|
||||
columns.unshift({
|
||||
field: 'isChecked',
|
||||
title: '',
|
||||
@ -248,16 +337,19 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
return taskListTable
|
||||
}
|
||||
|
||||
function renderTaskBar() {
|
||||
function renderTaskBar(subId: string | number) {
|
||||
// console.log(subId, '------');
|
||||
const taskBar = {
|
||||
resizable: false,
|
||||
moveable: false,
|
||||
startDateField: 'start',
|
||||
endDateField: 'end',
|
||||
// progressField: 'progress',
|
||||
barStyle: { width: subId ? 180 : 60 },
|
||||
barStyle: { width: subId ? 200 : 80 },
|
||||
customLayout: args => {
|
||||
// console.log(args, 'args');
|
||||
const { width, height, startDate, endDate, taskRecord } = args
|
||||
// console.log(taskRecord, 'taskRecord');
|
||||
const container = new Group({
|
||||
width,
|
||||
height,
|
||||
@ -272,18 +364,70 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
})
|
||||
if (!subId) {
|
||||
container.addEventListener('click', () => {
|
||||
console.log(taskRecord, 'ooooooo')
|
||||
|
||||
container.addEventListener('click', async () => {
|
||||
console.log(taskRecord, 'ooooooo')
|
||||
if (!subId) {
|
||||
router.push({
|
||||
path: `/gantt/sub/${taskRecord.id}`,
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
const { code, data } = await getSon({ id: taskRecord.id })
|
||||
|
||||
if (code === 200) {
|
||||
const showData = {
|
||||
事件名称: data.name,
|
||||
事件时间: `${data.startTime} - ${data.endTime}`,
|
||||
装备型号: data.equipModel,
|
||||
上报站点: data.reportSite,
|
||||
事件描述: data.describe,
|
||||
}
|
||||
window.$dialog.info({
|
||||
title: '子事件详情',
|
||||
class: '!w-[40vw]',
|
||||
content: () => {
|
||||
return h(
|
||||
'div',
|
||||
{ class: 'flex flex-col gap-4 w-full h-full' },
|
||||
[
|
||||
...Object.keys(showData).map(key => {
|
||||
return h('div', { class: 'flex w-full h-full ' }, [
|
||||
h('div', { class: 'w-[120px]' }, key),
|
||||
h(
|
||||
'div',
|
||||
{ class: 'flex-1 text-wrap' },
|
||||
showData[key]
|
||||
),
|
||||
])
|
||||
}),
|
||||
h('div', { class: 'flex w-full h-full' }, [
|
||||
h('div', { class: 'w-[120px]' }, '图片'),
|
||||
h('img', {
|
||||
src: `${window.settings.imgServer}${data.fileUrl}`,
|
||||
}),
|
||||
]),
|
||||
]
|
||||
)
|
||||
},
|
||||
positiveText: '确定',
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
// if (!subId) {
|
||||
// container.addEventListener('click', () => {
|
||||
// console.log(taskRecord, 'ooooooo')
|
||||
// router.push({
|
||||
// path: `/gantt/sub/${taskRecord.id}`,
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
|
||||
if (subId) {
|
||||
const imgUrl = `${window.settings.imgServer}${taskRecord.fileUrl}`
|
||||
// console.log(imgUrl);
|
||||
const image = new Image({
|
||||
image: taskRecord.avatar,
|
||||
image: imgUrl,
|
||||
width: 100,
|
||||
height: 100,
|
||||
x: 10,
|
||||
@ -292,8 +436,10 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
cursor: 'pointer',
|
||||
})
|
||||
container.add(image)
|
||||
image.addEventListener('click', () => {
|
||||
currentImage.value = [taskRecord.avatar, Date.now()]
|
||||
image.addEventListener('click', e => {
|
||||
e.stopPropagation()
|
||||
|
||||
currentImage.value = [imgUrl, Date.now()]
|
||||
// console.log(currentImage, 'currentImage')
|
||||
})
|
||||
}
|
||||
@ -343,14 +489,22 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
})
|
||||
nameContainer.add(name)
|
||||
|
||||
const days = new Text({
|
||||
text: `${startDate.toLocaleDateString()} ~ ${endDate.toLocaleDateString()}`,
|
||||
const start = new Text({
|
||||
text: `${taskRecord.startTime}`,
|
||||
fontSize: 13,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
container.add(days)
|
||||
container.add(start)
|
||||
const end = new Text({
|
||||
text: `${taskRecord.endTime}`,
|
||||
fontSize: 13,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
container.add(end)
|
||||
const rect = new Rect({
|
||||
width: width,
|
||||
height: 7,
|
||||
@ -389,6 +543,7 @@ const useGantt = ({ router, route }: GanttParams) => {
|
||||
borderLineWidth: 2,
|
||||
},
|
||||
}
|
||||
// console.log(taskBar, '0000000');
|
||||
return taskBar
|
||||
}
|
||||
function renderGroup(opt: IGroupGraphicAttribute) {
|
||||
|
41
src/views/Gantt/components/Gantt/index.jsx
Normal file → Executable file
41
src/views/Gantt/components/Gantt/index.jsx
Normal file → Executable file
@ -8,8 +8,16 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: 'day',
|
||||
},
|
||||
dateRange: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
types: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
setup(props, { expose }) {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const { renderMainTask, changeTimeScales, currentImage } = useGantt({
|
||||
@ -17,9 +25,38 @@ export default defineComponent({
|
||||
router,
|
||||
})
|
||||
|
||||
const refresh = ref(false)
|
||||
|
||||
expose({ refresh })
|
||||
|
||||
watch(refresh, val => {
|
||||
if (val) {
|
||||
renderMainTask(document.querySelector('#tableContainer'), {
|
||||
ids: props.types,
|
||||
startTime: props.dateRange
|
||||
? new Date(props.dateRange[0]).toISOString()
|
||||
: null,
|
||||
endTime: props.dateRange
|
||||
? new Date(props.dateRange[1]).toISOString()
|
||||
: null,
|
||||
})
|
||||
refresh.value = false
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
renderMainTask(document.querySelector('#tableContainer'))
|
||||
// console.log(props);
|
||||
renderMainTask(document.querySelector('#tableContainer'), {
|
||||
ids: props.types,
|
||||
startTime: props.dateRange
|
||||
? new Date(props.dateRange[0]).toISOString()
|
||||
: null,
|
||||
endTime: props.dateRange
|
||||
? new Date(props.dateRange[1]).toISOString()
|
||||
: null,
|
||||
})
|
||||
refresh.value = false
|
||||
})
|
||||
})
|
||||
watch(
|
||||
|
47
src/views/Gantt/components/Gantt1/components/VRender.jsx
Executable file
47
src/views/Gantt/components/Gantt1/components/VRender.jsx
Executable file
@ -0,0 +1,47 @@
|
||||
import { VImage, VGroup, VRect, VText } from '@visactor/vtable/es/vrender'
|
||||
|
||||
const textColor = '#65c5e7'
|
||||
export default defineComponent({
|
||||
props: {
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
taskRecord: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { width, height, taskRecord } = props
|
||||
return () => (
|
||||
<VGroup
|
||||
attribute={{
|
||||
width,
|
||||
height,
|
||||
fill: 'transparent',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<VText
|
||||
attribute={{
|
||||
text: 'taskRecord.name',
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
fontWeight: 'bold',
|
||||
maxLineWidth: width,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
></VText>
|
||||
</VGroup>
|
||||
)
|
||||
},
|
||||
})
|
452
src/views/Gantt/components/Gantt1/hooks/gantt.ts
Executable file
452
src/views/Gantt/components/Gantt1/hooks/gantt.ts
Executable file
@ -0,0 +1,452 @@
|
||||
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 currentImage = ref()
|
||||
const { subId } = route.params
|
||||
const records = ref([])
|
||||
onMounted(() => {
|
||||
getGanttData()
|
||||
})
|
||||
async function getGanttData() {
|
||||
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,
|
||||
// groupBy: 'name',
|
||||
// groupField: 'name',
|
||||
// widthMode: 'standard',
|
||||
// groupTitleFieldFormat: (record, col, row, table) => {
|
||||
// console.log(record, col, row, table, '----')
|
||||
// const groupData = table.getGroupData(record); // 获取分组数据
|
||||
// const count = groupData ? groupData.length : 0; // 计算分组下的记录数量
|
||||
// return `${record.name} (${count})`; // 返回格式化的分组标题
|
||||
// },
|
||||
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: 140,
|
||||
// colWidth: 1040,
|
||||
// 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',
|
||||
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: bgColor,
|
||||
}
|
||||
return option as TYPES.GanttConstructorOptions
|
||||
}
|
||||
function renderColumn() {
|
||||
const columns = [
|
||||
{
|
||||
field: 'name',
|
||||
title: subId ? '事件类型' : '事件主体',
|
||||
width: '120',
|
||||
mergeCell: true,
|
||||
customLayout: args => {
|
||||
const { table, row, col, rect, dataValue } = args
|
||||
// console.log(
|
||||
// table,
|
||||
// '1',
|
||||
// row,
|
||||
// '2',
|
||||
// col,
|
||||
// '3',
|
||||
// rect,
|
||||
// '4',
|
||||
// dataValue,
|
||||
// '5',
|
||||
// '-----------'
|
||||
// )
|
||||
const { height, width } = rect ?? table.getCellRect(col, row)
|
||||
const container = new Group({
|
||||
width,
|
||||
height,
|
||||
fill: 'transparent',
|
||||
// fill: textColor,
|
||||
// fillOpacity: 0.1,
|
||||
// stroke: textColor,
|
||||
// strokeOpacity: 0.2,
|
||||
// lineWidth: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
})
|
||||
console.log(args)
|
||||
const count = table.records.find(r => dataValue === r.name)?.children
|
||||
?.length
|
||||
const values = new Text({
|
||||
text: `${dataValue}`,
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
textAlign: 'center',
|
||||
// boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
const counts = new Text({
|
||||
text: `( ${count} )`,
|
||||
fontSize: 13,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
container.add(values)
|
||||
container.add(counts)
|
||||
return {
|
||||
rootContainer: container,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
if (subId) {
|
||||
columns.unshift({
|
||||
field: 'isChecked',
|
||||
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() {
|
||||
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',
|
||||
// fill: textColor,
|
||||
// fillOpacity: 0.1,
|
||||
// stroke: textColor,
|
||||
// strokeOpacity: 0.2,
|
||||
// lineWidth: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
})
|
||||
if (!subId) {
|
||||
container.addEventListener('click', () => {
|
||||
console.log(taskRecord, 'ooooooo')
|
||||
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],
|
||||
cursor: 'pointer',
|
||||
})
|
||||
container.add(image)
|
||||
image.addEventListener('click', () => {
|
||||
currentImage.value = [taskRecord.avatar, Date.now()]
|
||||
// console.log(currentImage, 'currentImage')
|
||||
})
|
||||
}
|
||||
// const checkbox = new CheckBox({
|
||||
// width: 20,
|
||||
// height: 20,
|
||||
// checked: false,
|
||||
// })
|
||||
// container.add(checkbox)
|
||||
|
||||
// checkbox.addEventListener('click', event => {
|
||||
// console.log(event, 'event')
|
||||
// })
|
||||
// console.log(taskRecord, 'taskRecord')
|
||||
const nameContainer = new Group({
|
||||
fill: 'transparent',
|
||||
display: 'flex',
|
||||
// flexDirection: 'column',
|
||||
// justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})
|
||||
|
||||
container.add(nameContainer)
|
||||
|
||||
if ('trajData' in taskRecord && taskRecord.trajData) {
|
||||
const taskRecordSymbol = new Image({
|
||||
width: 20,
|
||||
height: 20,
|
||||
fill: '#ff0',
|
||||
image:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8s8 3.59 8 8s-3.59 8-8 8zm0-12.5c-2.49 0-4.5 2.01-4.5 4.5s2.01 4.5 4.5 4.5s4.5-2.01 4.5-4.5s-2.01-4.5-4.5-4.5zm0 5.5c-.55 0-1-.45-1-1s.45-1 1-1s1 .45 1 1s-.45 1-1 1z" fill="#ff0"></path></svg>',
|
||||
boundsPadding: [-3, 10, 0, 0],
|
||||
cursor: 'pointer',
|
||||
})
|
||||
nameContainer.add(taskRecordSymbol)
|
||||
}
|
||||
|
||||
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],
|
||||
})
|
||||
nameContainer.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',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'nowrap',
|
||||
})
|
||||
|
||||
const day = new Text({
|
||||
text: startDate.toLocaleDateString(),
|
||||
// scale === 'day'
|
||||
// ? startDate.toLocaleDateString()
|
||||
// : startDate.toLocaleTimeString(),
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
textAlign: 'right',
|
||||
maxLineWidth: width,
|
||||
})
|
||||
container.add(day)
|
||||
return {
|
||||
rootContainer: container,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
return { renderMainTask, changeTimeScales, currentImage }
|
||||
}
|
||||
|
||||
export default useGantt
|
51
src/views/Gantt/components/Gantt1/index.jsx
Executable file
51
src/views/Gantt/components/Gantt1/index.jsx
Executable file
@ -0,0 +1,51 @@
|
||||
import { NImage } from 'naive-ui'
|
||||
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, currentImage } = useGantt({
|
||||
route,
|
||||
router,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
renderMainTask(document.querySelector('#tableContainer'))
|
||||
})
|
||||
})
|
||||
watch(
|
||||
() => props.scale,
|
||||
val => {
|
||||
changeTimeScales(val)
|
||||
}
|
||||
)
|
||||
|
||||
const imgRef = ref(null)
|
||||
watch(currentImage, imgUrl => {
|
||||
nextTick(() => {
|
||||
if (imgUrl) {
|
||||
imgRef.value.click()
|
||||
}
|
||||
})
|
||||
})
|
||||
return () => (
|
||||
<>
|
||||
<div id="tableContainer" class="bg-[#1c202c] w-h-full"></div>
|
||||
<NImage
|
||||
class="absolute h-0"
|
||||
ref={imgRef}
|
||||
src={currentImage.value?.[0]}
|
||||
></NImage>
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
47
src/views/Gantt/components/Gantt2/components/VRender.jsx
Executable file
47
src/views/Gantt/components/Gantt2/components/VRender.jsx
Executable file
@ -0,0 +1,47 @@
|
||||
import { VImage, VGroup, VRect, VText } from '@visactor/vtable/es/vrender'
|
||||
|
||||
const textColor = '#65c5e7'
|
||||
export default defineComponent({
|
||||
props: {
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
taskRecord: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { width, height, taskRecord } = props
|
||||
return () => (
|
||||
<VGroup
|
||||
attribute={{
|
||||
width,
|
||||
height,
|
||||
fill: 'transparent',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
<VText
|
||||
attribute={{
|
||||
text: 'taskRecord.name',
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
fontWeight: 'bold',
|
||||
maxLineWidth: width,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
></VText>
|
||||
</VGroup>
|
||||
)
|
||||
},
|
||||
})
|
461
src/views/Gantt/components/Gantt2/hooks/gantt.ts
Executable file
461
src/views/Gantt/components/Gantt2/hooks/gantt.ts
Executable file
@ -0,0 +1,461 @@
|
||||
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/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 currentImage = ref()
|
||||
const { subId } = route.params
|
||||
const records = ref([])
|
||||
|
||||
const timeRange = ref([])
|
||||
// onMounted(() => {
|
||||
// getGanttData()
|
||||
// })
|
||||
async function getGanttData(params: Record<string, string>) {
|
||||
timeRange.value = [params.startTime, params.endTime]
|
||||
console.log('%csubId', 'color:red;font-size:20px', subId);
|
||||
const { code, data } = subId ? await getSubGantt({ activityId: subId }) : await getMainGantt(params)
|
||||
if (code === 200) {
|
||||
records.value = data.list
|
||||
ganttInstance?.setRecords(records.value)
|
||||
|
||||
}
|
||||
}
|
||||
async function renderMainTask(dom: HTMLElement, params: Record<string, string>) {
|
||||
await getGanttData(params)
|
||||
const option = getOption()
|
||||
ganttInstance = new Gantt(dom, option)
|
||||
window['ganttInstance'] = ganttInstance
|
||||
}
|
||||
function getOption(): TYPES.GanttConstructorOptions {
|
||||
console.log(records.value);
|
||||
const option = {
|
||||
records: records.value,
|
||||
taskListTable: renderTaskListTable(),
|
||||
tasksShowMode: TYPES.TasksShowMode.Sub_Tasks_Arrange,
|
||||
// groupBy: 'name',
|
||||
// groupField: 'name',
|
||||
// widthMode: 'standard',
|
||||
// groupTitleFieldFormat: (record, col, row, table) => {
|
||||
// console.log(record, col, row, table, '----')
|
||||
// const groupData = table.getGroupData(record); // 获取分组数据
|
||||
// const count = groupData ? groupData.length : 0; // 计算分组下的记录数量
|
||||
// return `${record.name} (${count})`; // 返回格式化的分组标题
|
||||
// },
|
||||
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: 4000,
|
||||
// colWidth: 1040,
|
||||
// verticalLine: {
|
||||
// lineColor: textColorWithOp,
|
||||
// lineWidth: 1,
|
||||
// lineDash: [4, 2],
|
||||
// },
|
||||
horizontalLine: {
|
||||
lineColor: textColorWithOp,
|
||||
lineWidth: 1,
|
||||
lineDash: [4, 2],
|
||||
},
|
||||
scales: getTimeScales('month'),
|
||||
},
|
||||
minDate: timeRange.value[0],
|
||||
maxDate: timeRange.value[1],
|
||||
markLine: [
|
||||
{
|
||||
date: '2024-03-13T13:15:10',
|
||||
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: 10,
|
||||
scrollSliderCornerRadius: 2,
|
||||
scrollSliderColor: 'rgba(255,255,255,0.25)',
|
||||
},
|
||||
underlayBackgroundColor: bgColor,
|
||||
}
|
||||
return option as TYPES.GanttConstructorOptions
|
||||
}
|
||||
function renderColumn() {
|
||||
const columns = [
|
||||
{
|
||||
field: 'name',
|
||||
title: subId ? '事件类型' : '事件主体',
|
||||
width: '120',
|
||||
mergeCell: true,
|
||||
customLayout: args => {
|
||||
// console.log(args, 'srgs')
|
||||
const { table, row, col, rect, dataValue } = args
|
||||
// console.log(
|
||||
// table,
|
||||
// '1',
|
||||
// row,
|
||||
// '2',
|
||||
// col,
|
||||
// '3',
|
||||
// rect,
|
||||
// '4',
|
||||
// dataValue,
|
||||
// '5',
|
||||
// '-----------'
|
||||
// )
|
||||
const { height, width } = rect ?? table.getCellRect(col, row)
|
||||
const container = new Group({
|
||||
width,
|
||||
height,
|
||||
fill: 'transparent',
|
||||
// fill: textColor,
|
||||
// fillOpacity: 0.1,
|
||||
// stroke: textColor,
|
||||
// strokeOpacity: 0.2,
|
||||
// lineWidth: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
cursor: 'pointer',
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
// console.log('args:-----', args);
|
||||
|
||||
const count = table.records.find(r => dataValue === r.name)?.children
|
||||
?.length || 0
|
||||
const values = new Text({
|
||||
text: `${dataValue}`,
|
||||
fontSize: 16,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
textAlign: 'center',
|
||||
maxLineWidth: width,
|
||||
whiteSpace: 'normal'
|
||||
// boundsPadding: [10, 10, 10, 10],
|
||||
})
|
||||
const counts = new Text({
|
||||
text: `( ${count} )`,
|
||||
fontSize: 13,
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
boundsPadding: [10, 0, 0, 0],
|
||||
})
|
||||
container.add(values)
|
||||
container.add(counts)
|
||||
return {
|
||||
rootContainer: container,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
if (subId) {
|
||||
columns.unshift({
|
||||
field: 'isChecked',
|
||||
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 | number) {
|
||||
// console.log(subId, '------');
|
||||
const taskBar = {
|
||||
resizable: false,
|
||||
moveable: false,
|
||||
startDateField: 'startTime',
|
||||
endDateField: 'endTime',
|
||||
// progressField: 'progress',
|
||||
barStyle: { width: subId ? 180 : 60 },
|
||||
customLayout: args => {
|
||||
|
||||
const { width, height, startDate, endDate, taskRecord } = args
|
||||
// console.log(taskRecord, 'taskRecord');
|
||||
const container = new Group({
|
||||
width,
|
||||
height,
|
||||
fill: 'transparent',
|
||||
// fill: textColor,
|
||||
// fillOpacity: 0.1,
|
||||
// stroke: textColor,
|
||||
// strokeOpacity: 0.2,
|
||||
// lineWidth: 4,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
cursor: 'pointer',
|
||||
})
|
||||
if (!subId) {
|
||||
container.addEventListener('click', () => {
|
||||
console.log(taskRecord, 'ooooooo')
|
||||
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],
|
||||
cursor: 'pointer',
|
||||
})
|
||||
container.add(image)
|
||||
image.addEventListener('click', () => {
|
||||
currentImage.value = [taskRecord.avatar, Date.now()]
|
||||
// console.log(currentImage, 'currentImage')
|
||||
})
|
||||
}
|
||||
// const checkbox = new CheckBox({
|
||||
// width: 20,
|
||||
// height: 20,
|
||||
// checked: false,
|
||||
// })
|
||||
// container.add(checkbox)
|
||||
|
||||
// checkbox.addEventListener('click', event => {
|
||||
// console.log(event, 'event')
|
||||
// })
|
||||
// console.log(taskRecord, 'taskRecord')
|
||||
const nameContainer = new Group({
|
||||
fill: 'transparent',
|
||||
display: 'flex',
|
||||
// flexDirection: 'column',
|
||||
// justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
})
|
||||
|
||||
container.add(nameContainer)
|
||||
|
||||
if ('trajData' in taskRecord && taskRecord.trajData) {
|
||||
const taskRecordSymbol = new Image({
|
||||
width: 20,
|
||||
height: 20,
|
||||
fill: '#ff0',
|
||||
image:
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8s8 3.59 8 8s-3.59 8-8 8zm0-12.5c-2.49 0-4.5 2.01-4.5 4.5s2.01 4.5 4.5 4.5s4.5-2.01 4.5-4.5s-2.01-4.5-4.5-4.5zm0 5.5c-.55 0-1-.45-1-1s.45-1 1-1s1 .45 1 1s-.45 1-1 1z" fill="#ff0"></path></svg>',
|
||||
boundsPadding: [-3, 10, 0, 0],
|
||||
cursor: 'pointer',
|
||||
})
|
||||
nameContainer.add(taskRecordSymbol)
|
||||
}
|
||||
|
||||
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],
|
||||
})
|
||||
nameContainer.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,
|
||||
},
|
||||
}
|
||||
console.log(taskBar, '0000000');
|
||||
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',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'nowrap',
|
||||
})
|
||||
|
||||
const day = new Text({
|
||||
text: startDate.toLocaleDateString(),
|
||||
// scale === 'day'
|
||||
// ? startDate.toLocaleDateString()
|
||||
// : startDate.toLocaleTimeString(),
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
fontFamily: 'sans-serif',
|
||||
fill: textColor,
|
||||
textAlign: 'right',
|
||||
maxLineWidth: width,
|
||||
})
|
||||
container.add(day)
|
||||
return {
|
||||
rootContainer: container,
|
||||
}
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
return { renderMainTask, changeTimeScales, currentImage }
|
||||
}
|
||||
|
||||
export default useGantt
|
66
src/views/Gantt/components/Gantt2/index.jsx
Executable file
66
src/views/Gantt/components/Gantt2/index.jsx
Executable file
@ -0,0 +1,66 @@
|
||||
import { NImage } from 'naive-ui'
|
||||
import useGantt from './hooks/gantt'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
scale: {
|
||||
type: String,
|
||||
default: 'day',
|
||||
},
|
||||
dateRange: {
|
||||
type: Array,
|
||||
require: true,
|
||||
},
|
||||
types: {
|
||||
type: Array,
|
||||
require: true,
|
||||
}
|
||||
},
|
||||
setup(props, { expose }) {
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
const { renderMainTask, changeTimeScales, currentImage } = useGantt({
|
||||
route,
|
||||
router,
|
||||
})
|
||||
|
||||
expose({ renderMainTask })
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
// console.log(props);
|
||||
renderMainTask(document.querySelector('#tableContainer'), {
|
||||
ids: props.types,
|
||||
startTime: props.dateRange ? new Date(props.dateRange[0]).toISOString() : null,
|
||||
endTime: props.dateRange ? new Date(props.dateRange[1]).toISOString() : null
|
||||
})
|
||||
})
|
||||
})
|
||||
watch(
|
||||
() => props.scale,
|
||||
val => {
|
||||
changeTimeScales(val)
|
||||
}
|
||||
)
|
||||
|
||||
const imgRef = ref(null)
|
||||
watch(currentImage, imgUrl => {
|
||||
nextTick(() => {
|
||||
if (imgUrl) {
|
||||
imgRef.value.click()
|
||||
}
|
||||
})
|
||||
})
|
||||
return () => (
|
||||
<>
|
||||
<div id="tableContainer" class="bg-[#1c202c] w-h-full"></div>
|
||||
<NImage
|
||||
class="absolute h-0"
|
||||
ref={imgRef}
|
||||
src={currentImage.value?.[0]}
|
||||
></NImage>
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
0
src/views/Gantt/components/GanttEdit/hooks/ganttEdit.ts
Normal file → Executable file
0
src/views/Gantt/components/GanttEdit/hooks/ganttEdit.ts
Normal file → Executable file
0
src/views/Gantt/components/GanttEdit/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/GanttEdit/index.jsx
Normal file → Executable file
57
src/views/Gantt/components/MainGantt/index.jsx
Normal file → Executable file
57
src/views/Gantt/components/MainGantt/index.jsx
Normal file → Executable file
@ -7,41 +7,68 @@ import {
|
||||
NSelect,
|
||||
} from 'naive-ui'
|
||||
import GanttCom from '../Gantt'
|
||||
import { getDDList } from '@/api/Gantt/gantt'
|
||||
import { onBeforeMount } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const range = ref()
|
||||
const value = ref('day')
|
||||
const type = ref()
|
||||
const range = ref([new Date('2000-01-01').getTime(), Date.now()])
|
||||
const value = ref('year')
|
||||
const types = ref([])
|
||||
|
||||
const router = useRouter()
|
||||
const editEvent = () => {
|
||||
console.log(router)
|
||||
router.push('/gantt/mainEdit')
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await getDDOptions()
|
||||
})
|
||||
|
||||
const ddOptions = ref([])
|
||||
async function getDDOptions() {
|
||||
const { code, data } = await getDDList()
|
||||
if (code === 200) {
|
||||
ddOptions.value = data.list
|
||||
// types.value = ddOptions.value.map(item => item.id)
|
||||
}
|
||||
}
|
||||
|
||||
const ganttRef = ref(null)
|
||||
function searchGanttData() {
|
||||
ganttRef.value.refresh = true
|
||||
}
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<div class="flex gap-2">
|
||||
<NDatePicker
|
||||
v-model:value={range.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
disabled
|
||||
/>
|
||||
<NRadioGroup v-model:value={value.value} name="radiobuttongroup">
|
||||
<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>
|
||||
</NRadioGroup> */}
|
||||
<NSelect
|
||||
v-model:value={type.value}
|
||||
mode="multiple"
|
||||
style="width: 200px"
|
||||
v-model:value={types.value}
|
||||
multiple
|
||||
options={ddOptions.value}
|
||||
label-field="name"
|
||||
clearable
|
||||
value-field="id"
|
||||
></NSelect>
|
||||
{/* <NButton class="ml-auto" type="primary" onClick={editEvent}>
|
||||
编辑事件
|
||||
</NButton> */}
|
||||
<NButton class="ml-auto" type="primary" onClick={searchGanttData}>
|
||||
搜索
|
||||
</NButton>
|
||||
</div>
|
||||
<GanttCom scale={value.value} />
|
||||
<GanttCom
|
||||
ref={ganttRef}
|
||||
scale={value.value}
|
||||
dateRange={range.value}
|
||||
types={types.value}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
},
|
||||
|
48
src/views/Gantt/components/MainGantt1/index.jsx
Executable file
48
src/views/Gantt/components/MainGantt1/index.jsx
Executable file
@ -0,0 +1,48 @@
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
NDatePicker,
|
||||
NRadioButton,
|
||||
NRadioGroup,
|
||||
NButton,
|
||||
NSelect,
|
||||
} from 'naive-ui'
|
||||
import GanttCom from '../Gantt'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const range = ref()
|
||||
const value = ref('day')
|
||||
const type = ref()
|
||||
|
||||
const router = useRouter()
|
||||
const editEvent = () => {
|
||||
console.log(router)
|
||||
router.push('/gantt/mainEdit')
|
||||
}
|
||||
return () => (
|
||||
<>
|
||||
<div class="flex gap-2">
|
||||
<NDatePicker
|
||||
v-model:value={range.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
disabled
|
||||
/>
|
||||
<NRadioGroup v-model:value={value.value} name="radiobuttongroup">
|
||||
<NRadioButton value="hour" label="日" />
|
||||
<NRadioButton value="day" label="月" />
|
||||
</NRadioGroup>
|
||||
<NSelect
|
||||
v-model:value={type.value}
|
||||
mode="multiple"
|
||||
style="width: 200px"
|
||||
></NSelect>
|
||||
{/* <NButton class="ml-auto" type="primary" onClick={editEvent}>
|
||||
编辑事件
|
||||
</NButton> */}
|
||||
</div>
|
||||
<GanttCom scale={value.value} />
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
83
src/views/Gantt/components/MainGantt2/index.jsx
Executable file
83
src/views/Gantt/components/MainGantt2/index.jsx
Executable file
@ -0,0 +1,83 @@
|
||||
import { useRouter } from 'vue-router'
|
||||
import {
|
||||
NDatePicker,
|
||||
NRadioButton,
|
||||
NRadioGroup,
|
||||
NButton,
|
||||
NSelect,
|
||||
} from 'naive-ui'
|
||||
import GanttCom from '../Gantt'
|
||||
import {getDDList}from '@/api/Gantt/gantt'
|
||||
import { onBeforeMount } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const range = ref([new Date('2000-01-01').getTime(), Date.now()])
|
||||
const value = ref('year')
|
||||
const types = ref([])
|
||||
|
||||
const router = useRouter()
|
||||
const editEvent = () => {
|
||||
console.log(router)
|
||||
router.push('/gantt/mainEdit')
|
||||
}
|
||||
|
||||
onBeforeMount(async ()=>{
|
||||
await getDDOptions()
|
||||
})
|
||||
|
||||
const ddOptions = ref([])
|
||||
async function getDDOptions (){
|
||||
const {code,data} = await getDDList()
|
||||
if(code === 200) {
|
||||
ddOptions.value = data.list
|
||||
types.value = ddOptions.value.map(item=>item.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const ganttRef = ref(null)
|
||||
function searchGanttData(){
|
||||
// console.log(ganttRef);
|
||||
renderMainTask(document.querySelector('#tableContainer'),{
|
||||
ids: types.value,
|
||||
startTime: new Date(range.value[0]).toISOString(),
|
||||
endTime: new Date(range.value[1]).toISOString()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
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> */}
|
||||
<NSelect
|
||||
v-model:value={types.value}
|
||||
multiple
|
||||
options={ddOptions.value}
|
||||
label-field='name'
|
||||
clearable
|
||||
value-field='id'
|
||||
></NSelect>
|
||||
{/* <NButton class="ml-auto" type="primary" onClick={editEvent}>
|
||||
编辑事件
|
||||
</NButton> */}
|
||||
<NButton class="ml-auto" type="primary" onClick={searchGanttData}>
|
||||
搜索
|
||||
</NButton>
|
||||
</div>
|
||||
<GanttCom ref={ganttRef} scale={value.value} dateRange={range.value} types={types.value}/>
|
||||
</>
|
||||
)
|
||||
},
|
||||
})
|
0
src/views/Gantt/components/MainGanttEdit/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/MainGanttEdit/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/SubGantt/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/SubGantt/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/SubGanttEdit/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/SubGanttEdit/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/TaskList/components/NewTask/hooks.ts
Normal file → Executable file
0
src/views/Gantt/components/TaskList/components/NewTask/hooks.ts
Normal file → Executable file
0
src/views/Gantt/components/TaskList/components/NewTask/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/TaskList/components/NewTask/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/TaskList/index.jsx
Normal file → Executable file
0
src/views/Gantt/components/TaskList/index.jsx
Normal file → Executable file
0
src/views/Gantt/index copy.vue
Normal file → Executable file
0
src/views/Gantt/index copy.vue
Normal file → Executable file
95
src/views/Gantt/index.jsx
Normal file → Executable file
95
src/views/Gantt/index.jsx
Normal file → Executable file
@ -18,32 +18,52 @@ import NewTask from './components/TaskList/components/NewTask'
|
||||
|
||||
import useTask from './components/TaskList/components/NewTask/hooks'
|
||||
import { useEvent } from './components/EventList/hooks'
|
||||
import { getSimpList, getSimpTreeList } from '@/api/Gantt'
|
||||
import { onBeforeMount, nextTick } from 'vue'
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const show = ref(false)
|
||||
const range = ref()
|
||||
|
||||
const { showNewTask } = useTask()
|
||||
|
||||
const addNewTask = () => {
|
||||
showNewTask.value = true
|
||||
}
|
||||
async function getSimpListData() {
|
||||
const res = await getSimpList()
|
||||
ddList.value = res.data.list
|
||||
targetId.value = res.data.list[0].id
|
||||
}
|
||||
|
||||
const ddList = Array.from({ length: 8 }, (_, i) => ({
|
||||
label: `DD-${i + 1}`,
|
||||
value: `DD-${i + 1}`,
|
||||
}))
|
||||
|
||||
const dd = ref(`DD-1`)
|
||||
// const ddList = Array.from({ length: 8 }, (_, i) => ({
|
||||
// label: `DD-${i + 1}`,
|
||||
// value: `DD-${i + 1}`,
|
||||
// }))
|
||||
const ddList = ref([])
|
||||
|
||||
const paneClass = `border-1 h-full border-l-0 border-[var(--n-tab-border-color)] !p-2`
|
||||
|
||||
const { showMainEvent, mainEventData } = useEvent()
|
||||
const addNewMainEvent = () => {
|
||||
const {
|
||||
showMainEvent,
|
||||
mainEventData,
|
||||
targetId,
|
||||
range,
|
||||
searchTreeList,
|
||||
tableData,
|
||||
} = useEvent()
|
||||
const addNewMainEvent = async () => {
|
||||
showMainEvent.value = true
|
||||
// const res = await addNewMainEvent({ })
|
||||
mainEventData.value = {}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
nextTick(async () => {
|
||||
await getSimpListData()
|
||||
await searchTreeList()
|
||||
})
|
||||
})
|
||||
|
||||
return () => (
|
||||
<div class="flex flex-col bg-[#1c202c] w-h-full">
|
||||
<div class="relative h-[60px]">
|
||||
@ -74,7 +94,7 @@ export default defineComponent({
|
||||
>
|
||||
<NDrawerContent title="事件管理" closable>
|
||||
<div class="flex h-full flex-col gap-2">
|
||||
<NTabs
|
||||
{/* <NTabs
|
||||
class="h-full"
|
||||
pane-wrapper-class="h-full"
|
||||
type="card"
|
||||
@ -82,7 +102,7 @@ export default defineComponent({
|
||||
placement="left"
|
||||
defaultValue={'事件列表'}
|
||||
>
|
||||
{/* <NTabPane
|
||||
<NTabPane
|
||||
class={paneClass}
|
||||
name="任务列表"
|
||||
tab="任务列表"
|
||||
@ -103,35 +123,40 @@ export default defineComponent({
|
||||
<TaskList />
|
||||
</div>
|
||||
</div>
|
||||
</NTabPane> */}
|
||||
</NTabPane>
|
||||
<NTabPane
|
||||
class={paneClass}
|
||||
name="事件列表"
|
||||
tab="事件列表"
|
||||
display-directive={'show'}
|
||||
>
|
||||
<div class="flex h-full flex-col gap-2">
|
||||
<div class="flex justify-end gap-2 ">
|
||||
<NSelect
|
||||
class="w-[200px]"
|
||||
v-model:value={dd.value}
|
||||
options={ddList}
|
||||
></NSelect>
|
||||
<NDatePicker
|
||||
v-model:value={range.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
/>
|
||||
<NButton type="primary" onClick={addNewMainEvent}>
|
||||
添加事件
|
||||
</NButton>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<EventList dd={dd.value} />
|
||||
</div>
|
||||
</div>
|
||||
</NTabPane>
|
||||
</NTabs>
|
||||
> */}
|
||||
<div class="flex h-full flex-col gap-2">
|
||||
<div class="flex justify-end gap-2 ">
|
||||
<NSelect
|
||||
class="w-[200px]"
|
||||
v-model:value={targetId.value}
|
||||
options={ddList.value}
|
||||
label-field="name"
|
||||
value-field="id"
|
||||
></NSelect>
|
||||
<NDatePicker
|
||||
v-model:value={range.value}
|
||||
type="daterange"
|
||||
clearable
|
||||
/>
|
||||
<NButton type="primary" onClick={searchTreeList}>
|
||||
搜索
|
||||
</NButton>
|
||||
<NButton type="primary" onClick={addNewMainEvent}>
|
||||
添加事件
|
||||
</NButton>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<EventList dd={targetId.value} tableData={tableData.value} />
|
||||
</div>
|
||||
</div>
|
||||
{/* </NTabPane>
|
||||
</NTabs> */}
|
||||
{/* <div class="flex justify-end gap-2 ">
|
||||
<NDatePicker
|
||||
v-model:value={range.value}
|
||||
|
0
src/views/Gantt/index.vue
Normal file → Executable file
0
src/views/Gantt/index.vue
Normal file → Executable file
@ -39,28 +39,19 @@ const { mubiaoMap } = useEntity()
|
||||
|
||||
// const { showOrHideDdConfig } = useDaodan()
|
||||
const { flyTo } = useEarth()
|
||||
const latValue = {}
|
||||
const nodeProps = ({ option }: { option: TreeOption }) => {
|
||||
return {
|
||||
onclick: () => {
|
||||
if (option.children) {
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (mubiaoMap.size > 0) {
|
||||
mubiaoMap.forEach((entity, key) => {
|
||||
const positions = entity.position._value
|
||||
const [lon, lat, height] = cartesian32LonLat(positions)
|
||||
const {
|
||||
dataId,
|
||||
// data: { geom },
|
||||
} = option
|
||||
if (checkedKeys.value.includes(dataId as string)) {
|
||||
flyTo({ lon, lat })
|
||||
}
|
||||
})
|
||||
}
|
||||
}, 500)
|
||||
const { dataId } = option
|
||||
if (mubiaoMap.has(dataId)) {
|
||||
const [lon, lat, height] = cartesian32LonLat(
|
||||
mubiaoMap.get(dataId).position._value
|
||||
)
|
||||
flyTo({ lon, lat })
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,6 @@ interface ISatellite {
|
||||
tle: string
|
||||
}
|
||||
|
||||
interface IBaseFilterParam {
|
||||
treeData: Array<any>
|
||||
params: Array<string | number>
|
||||
paramName: string
|
||||
}
|
||||
const { filterTreeNodeByField } = useTree()
|
||||
const satelliteList = ref<ISatellite[]>([])
|
||||
const checkedKeys = ref<Array<string | number>>([])
|
||||
@ -121,6 +116,7 @@ export function useSatellite() {
|
||||
addSatellites,
|
||||
showPoint,
|
||||
showPointUnderSat,
|
||||
flyToSatellite,
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,8 +143,6 @@ function createSatelliteCommunicationPayload(satId: string) {
|
||||
|
||||
beam.create()
|
||||
|
||||
console.log(beam)
|
||||
|
||||
if (!satelliteBeamMap.has(satId)) {
|
||||
satelliteBeamMap.set(satId, new Map())
|
||||
}
|
||||
@ -198,6 +192,16 @@ async function getSatelliteList() {
|
||||
const checked = JSON.parse(JSON.stringify(checkedKeys.value))
|
||||
|
||||
const sateRes = await getSatellite()
|
||||
// const sateRes = {
|
||||
// code: '200',
|
||||
// data: [
|
||||
// {
|
||||
// id: '1',
|
||||
// name: 'CALSPHERE 1',
|
||||
// tle: 'CALSPHERE 1\n 1 00900U 64063C 25062.49198022 .00001185 00000+0 12127-2 0 9997\n2 00900 90.2081 61.0113 0023240 278.3857 208.6718 13.75857600 6688',
|
||||
// },
|
||||
// ],
|
||||
// }
|
||||
const { data, code } = sateRes
|
||||
if (code === '200') {
|
||||
checkedKeys.value = []
|
||||
@ -235,3 +239,17 @@ function getAllNodesToPayload() {
|
||||
})
|
||||
console.log('satellitePayloadShowMap', satellitePayloadShowMap)
|
||||
}
|
||||
|
||||
function flyToSatellite(satId: string) {
|
||||
const sat = satelliteMap.get(satId)?.entity
|
||||
if (sat) {
|
||||
viewer.flyTo(sat, {
|
||||
duration: 2,
|
||||
// offset: {
|
||||
// heading: Cesium.Math.toRadians(option.heading),
|
||||
// pitch: Cesium.Math.toRadians(option.pitch),
|
||||
// range: option.range,
|
||||
// },
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,14 +4,13 @@ import { NButton } from 'naive-ui'
|
||||
import Tree from '@/components/Tree/index.vue'
|
||||
import { useSatellite } from './hooks/satellite'
|
||||
import { showDetailsSatellite } from './components/SatDetail'
|
||||
import { useEarth } from '../Earth/hooks/earth'
|
||||
import { useEntity } from '@/hooks/entity'
|
||||
|
||||
const {
|
||||
satelliteList,
|
||||
checkedKeys,
|
||||
getSatelliteList,
|
||||
addSatellites,
|
||||
flyToSatellite,
|
||||
} = useSatellite()
|
||||
|
||||
onMounted(async () => {
|
||||
@ -21,32 +20,13 @@ onMounted(async () => {
|
||||
watch(checkedKeys, val => {
|
||||
addSatellites(val)
|
||||
})
|
||||
const { flyTo } = useEarth()
|
||||
const { satelliteMap } = useEntity()
|
||||
const nodeProps = ({ option }: { option: TreeOption }) => {
|
||||
// console.log(option, '卫星option')
|
||||
|
||||
return {
|
||||
onclick: () => {
|
||||
// console.log(satelliteMap, 'satelliteMap')
|
||||
const { id } = option
|
||||
id && flyToSatellite(id as string)
|
||||
},
|
||||
}
|
||||
// return {
|
||||
// onclick: () => {
|
||||
// if (option.children) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// const {
|
||||
// dataId,
|
||||
// data: { geom },
|
||||
// } = option
|
||||
// const [lon, lat] = parseWKT(geom).coordinates
|
||||
// if (checkedKeys.value.includes(dataId as string)) {
|
||||
// flyTo({ lon, lat })
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
}
|
||||
const renderSuffix = ({ option }: { option: TreeOption }) => {
|
||||
// console.log(option)
|
||||
|
Loading…
Reference in New Issue
Block a user