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/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 useGanttEdit = ({ router, route }: GanttParams) => {
const { subId } = route.params
const records = ref([])
const dialog = useDialog()
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,
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(),
timelineHeader: {
backgroundColor: headerBgColor,
colWidth: 150,
verticalLine: {
lineColor: textColorWithOp,
lineWidth: 1,
lineDash: [4, 2],
},
horizontalLine: {
lineColor: textColorWithOp,
lineWidth: 1,
lineDash: [4, 2],
},
scales: getTimeScales('day'),
},
minDate: '2024-11-14',
maxDate: '2024-12-30',
scrollStyle: {
scrollRailColor: 'RGBA(246,246,246,0)',
visible: 'focus',
width: 6,
scrollSliderCornerRadius: 2,
scrollSliderColor: 'rgba(255,255,255,0.25)',
},
underlayBackgroundColor: bgColor,
}
return option as TYPES.GanttConstructorOptions
}
function renderColumn() {
const columns = [
{
field: 'name',
title: subId ? '事件类型' : '事件主体',
width: '120',
mergeCell: true,
},
]
// 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',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
// alignItems: 'center',
cursor: 'pointer',
})
if (!subId) {
container.addEventListener('click', event => {
router.push({
path: `/gantt/subEdit/${taskRecord.id}`,
})
})
}
if (subId) {
const image = new Image({
image: taskRecord.avatar,
width: 100,
height: 100,
x: 10,
y: 10,
boundsPadding: [0, 0, 10, 0],
})
container.add(image)
}
const checkBoxGroup = new Group({
width,
//height,
fill: 'transparent',
display: 'flex',
})
container.add(checkBoxGroup)
// const checkbox = new CheckBox({
// id: taskRecord.id,
// text: '',
// checked: false,
// })
// checkBoxGroup.add(checkbox)
// checkbox.addEventListener('click', event => {
// event.stopPropagation()
// console.log(checkbox, 'checkbox')
// })
const name = new Text({
text: taskRecord.name,
fontSize: 16,
fontFamily: 'sans-serif',
fill: textColor,
fontWeight: 'bold',
maxLineWidth: width,
textAlign: 'center',
// boundsPadding: [0, 0, 0, 10],
})
checkBoxGroup.add(name)
const editSymbol = new Image({
width: 20,
height: 20,
fill: '#fff',
image:
'',
boundsPadding: [-2, 0, 0, 10],
cursor: 'pointer',
})
checkBoxGroup.add(editSymbol)
editSymbol.addEventListener('click', event => {
event.stopPropagation()
console.log(editSymbol, 'editSymbol')
})
const deleteSymbol = new Image({
width: 20,
height: 20,
fill: '#fff',
image:
'',
boundsPadding: [-2, 0, 0, 10],
cursor: 'pointer',
})
checkBoxGroup.add(deleteSymbol)
deleteSymbol.addEventListener('click', event => {
event.stopPropagation()
// console.log(dialog, '----')
dialog.warning({
title: '警告',
content: '确认删除当前事件?',
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {},
onNegativeClick: () => {},
})
console.log(deleteSymbol, 'deleteSymbol')
})
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:
scale === 'day'
? startDate.toLocaleDateString()
: startDate.toLocaleTimeString(),
fontSize: 14,
fontWeight: 'bold',
fontFamily: 'sans-serif',
fill: textColor,
textAlign: 'center',
maxLineWidth: width,
// boundsPadding: [25, 12, 10, 12],
})
container.add(day)
return {
rootContainer: container,
}
},
},
]
}
return { renderMainTask, changeTimeScales }
}
export default useGanttEdit