Commit b893c104 by licheng

feat: 新增甘特图组件

parent 40d2fbc7
......@@ -44,6 +44,7 @@
"cropperjs": "^1.6.1",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.10",
"dhtmlx-gantt": "^9.0.14",
"diagram-js": "^12.8.0",
"driver.js": "^1.3.1",
"echarts": "^6.0.0",
......
......@@ -65,6 +65,9 @@ importers:
dayjs:
specifier: ^1.11.10
version: 1.11.13
dhtmlx-gantt:
specifier: ^9.0.14
version: 9.0.14
diagram-js:
specifier: ^12.8.0
version: 12.8.1
......@@ -3028,6 +3031,9 @@ packages:
engines: {node: '>=0.10'}
hasBin: true
dhtmlx-gantt@9.0.14:
resolution: {integrity: sha512-1dy27u2oqw3regBKm6Ww7FkexOtUmg+IhHtH6BG6crpBr8dLltjJKwdSj9tcs2YVY+Ocsa3ANVS14rrViEwKoQ==}
diagram-js-direct-editing@3.2.0:
resolution: {integrity: sha512-+pyxeQGBSdLiZX0/tmmsm2qZSvm9YtVzod5W3RMHSTR7VrkUMD6E7EX/W9JQv3ebxO7oIdqFmytmNDDpSHnYEw==}
peerDependencies:
......@@ -8531,6 +8537,8 @@ snapshots:
detect-libc@1.0.3:
optional: true
dhtmlx-gantt@9.0.14: {}
diagram-js-direct-editing@3.2.0(diagram-js@14.11.3):
dependencies:
diagram-js: 14.11.3
......
import Gantt from './src/Gantt.vue'
export { Gantt }
\ No newline at end of file
<template>
<div id="gantt" ref="ganttRef"></div>
</template>
<script setup lang="ts">
import { gantt } from 'dhtmlx-gantt'
import 'dhtmlx-gantt/codebase/dhtmlxgantt.css'
export interface GanttTask {
id: number | string
taskname: string
parent?: number | string
start_date: string
end_date: string
progress: number
types: number
text?: string
color?: string
[key: string]: any
}
const props = defineProps<{
tasks: GanttTask[]
}>()
const ganttRef = ref<HTMLElement | null>(null)
// 初始化甘特图配置
const initGantt = () => {
gantt.config.readonly = true // 只读
gantt.config.date_format = '%Y-%m-%d %H:%i:%s' // 日期格式
gantt.config.use_end_date = true // 使用结束时间
gantt.config.grid_width = 350 // 左侧列表宽度
gantt.config.add_column = false // 添加符号
gantt.config.autosize = true // 自适应尺寸
gantt.config.autofit = true // 表格列宽自适应
gantt.config.autoscroll = false // 把任务或者连线拖拽到浏览器屏幕外时,自动触发滚动效果
gantt.config.drag_progress = false // 任务进度条进度拖动
gantt.config.scale_height = 60 // 时间栏高度
gantt.config.row_height = 60 // 行高
gantt.config.bar_height = 34 // 任务条高度
gantt.config.fit_tasks = true // 自动延长时间刻度,以适应所有显示的任务
gantt.config.auto_types = true // 将包含子任务的任务转换为项目,将没有子任务的项目转换回任务
gantt.i18n.setLocale('cn') // 设置语言
// 时间栏配置
gantt.config.scales = [
// { unit: 'month', step: 1, format: '%Y年%m月' },
{ unit: 'day', step: 1, format: '%m/%d' }
// { unit: 'hour', step: 1, format: '%H:%i' },
// { unit: 'minute', step: 30, format: '%H:%i' },
]
// 左侧列表配置
gantt.config.columns = [
{ name: 'taskname', label: '任务名称', align: 'left', tree: true, width: 140 },
{
name: 'type',
label: '任务类别',
align: 'center',
width: 100,
template: (task) => {
let obj = {
color: task.types === 1 ? '#f29d38' : task.types === 2 ? '#65c16f' : '#1890ff',
icon:
task.types === 1
? 'icon-gongji'
: task.types === 2
? 'icon-kaiqifangyu'
: 'icon-icon--mubiaoku',
text: task.types === 1 ? '紧急' : task.types === 2 ? '普通' : '一般'
}
return `<div class="tasktype" style="color:${obj.color};font-size:14px;">
<i class="iconfont ${obj.icon}"></i>
<span style="margin-left:3px;"> ${obj.text}</span>
</div>`
}
},
{
name: 'progress',
label: '任务进度',
align: 'center',
width: 80,
template: function (task: any) {
return `<div class="jindu" style="width:100%;height:30px;padding-left:10px;font-size:13px;color:black;"><span>${(task.progress * 100).toFixed(0) + '%'}</span></div>`
}
}
]
gantt.plugins({
tooltip: true, // 启用工具提示插件
marker: true // 启用时间标记插件
})
// 鼠标移入弹框
const dateFormatter = gantt.date.date_to_str('%Y-%m-%d %H:%i:%s') // 设置弹窗中的时间格式
gantt.config.tooltip_timeout = 0 // 鼠标悬停后提示框的延迟时间(ms)
gantt.templates.tooltip_text = function (start, end, task) {
return `
卫星名称: ${task.text}<br/>
开始时间: ${dateFormatter(start)}<br/>
结束时间: ${dateFormatter(end)}<br/>
`
}
// 添加当前时间标记
const today = new Date()
gantt.addMarker({
start_date: today,
css: 'today',
text: '今天',
title: '今天: ' + dateFormatter(today)
})
//更改父项图标
gantt.templates.grid_folder = (item) => {
return ''
}
//更改子项图标
gantt.templates.grid_file = (item) => {
return ''
}
//任务条内显示内容
gantt.templates.task_text = function (_start, _end, task) {
return `
<div style="color:#454545;font-size:14px;font-weight:700;">执行:${task.text}</div>
`
}
//任务条左侧显示内容
// gantt.templates.leftside_text = function (_start, _end, task) {
// return `<div class="jindu" style="width:100%;height:30px;background-color:#e6f4ff;padding-left:10px;font-size:13px;color:#629eff;"><span>当前进度${(task.progress * 100).toFixed(0) + '%'}</span></div>`
// }
//展开树图标
// gantt.templates.grid_open = function (item) {
// return `<i style="font-size:14px;background:none; color:#1890ff; padding-left:10px;" class="gantt_tree_icon gantt_${item.$open ? "close" : "open"} iconfont ${item.$open ? 'icon-zhankaishousuo' : 'icon-zhankaishousuo1'}"></i>`
// };
gantt.init('gantt') // 初始化
}
// 更新甘特图数据
const updateGanttData = () => {
if (ganttRef.value && props.tasks && props.tasks.length > 0) {
gantt.clearAll()
gantt.parse({ data: props.tasks })
}
}
watch(
() => props.tasks,
() => {
updateGanttData()
},
{ deep: true }
)
onMounted(() => {
initGantt()
updateGanttData()
})
</script>
<!-- 甘特图使用示例 -->
<template>
<div>
<Gantt :tasks="tasks" />
</div>
</template>
<script setup lang="ts">
import { type GanttTask } from '@/components/A_NewComponents/Gantt/src/Gantt.vue'
const tasks: GanttTask[] = [
{
id: 1,
taskname: 'satellite1过境',
parent: 0,
start_date: '2025-08-29 13:00:00',
end_date: '2025-08-30 18:00:00',
progress: 0.3,
types: 1,
text: 'satellite1',
color: '#f2e6c2'
},
{
id: 2,
taskname: 'satellite2过境',
parent: 0,
start_date: '2025-08-29 15:00:00',
end_date: '2025-08-30 18:00:00',
progress: 0.42,
types: 2,
text: 'satellite2',
color: '#b5e09b'
},
{
id: 3,
taskname: 'satellite3过境',
parent: 0,
start_date: '2025-08-29 13:00:00',
end_date: '2025-08-31 18:00:00',
progress: 0.65,
types: 3,
text: 'satellite3',
color: '#baefe2'
}
]
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment