Skip to content

Commit

Permalink
feat: ✨添加连线功能(基础)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyjone committed May 11, 2023
1 parent 9238946 commit faebcc7
Show file tree
Hide file tree
Showing 18 changed files with 289 additions and 45 deletions.
31 changes: 21 additions & 10 deletions demo/demo.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<template>
<div style="top: 20vh; width: 100%; height: 500px">
<x-gantt
:data="ganttData"
style="padding-left: 20vh"
@click-row="onClickRow"
>
<x-gantt :data="ganttData" :links="ganttLinks" @row-click="onClickRow">
<x-gantt-column label="group1">
<x-gantt-column prop="id" width="150px"></x-gantt-column>
<x-gantt-column label="group2">
<!-- <x-gantt-column label="group2">
<x-gantt-column
prop="name"
:merge="(scope: any) => scope.$index % 3 === 0"
Expand All @@ -17,7 +13,7 @@
:merge="(scope: any) => scope.$index % 2 === 0"
>n1</x-gantt-column
>
</x-gantt-column>
</x-gantt-column> -->
</x-gantt-column>

<div>div</div>
Expand All @@ -31,12 +27,14 @@
}}
</x-gantt-column>

<x-gantt-column v-slot="scope" label="结束日期">
<!-- <x-gantt-column v-slot="scope" label="结束日期">
{{ scope.row.endDate.getMonth() + 1 }}-{{
scope.row.endDate.getDate()
}}
{{ scope.row.endDate.getHours() }}:{{ scope.row.endDate.getMinutes() }}
</x-gantt-column>
</x-gantt-column> -->

<x-gantt-column label="结束日期" format="MM-dd HH:mm:ss" />

<x-gantt-slider prop="name"></x-gantt-slider>
</x-gantt>
Expand All @@ -56,7 +54,7 @@ let id = 0;
const ganttData = reactive<any>([]);
for (let i = 0; i < 100; i++) {
for (let i = 0; i < 50; i++) {
onAdd();
}
Expand All @@ -83,6 +81,19 @@ ganttData[0].children = [
}
];
const ganttLinks = [
{
id: 1,
from: 1,
to: 2
},
{
id: 2,
from: 2,
to: 3
}
];
function onAdd() {
ganttData.push({
id: ++id,
Expand Down
5 changes: 3 additions & 2 deletions src/components/column/selection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@click="
() => {
data?.setExpand(!data.isExpand);
$data.updateFlatData();
flattenData();
}
"
>
Expand Down Expand Up @@ -54,7 +54,8 @@ defineProps({
default: false
}
});
const { $data } = useData();
const { flattenData } = useData();
</script>

<style lang="scss" scoped>
Expand Down
18 changes: 15 additions & 3 deletions src/components/common/GanttBody.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
class="xg-gantt-body"
:style="{ height: bodyHeight, width: `${ganttWidth}px` }"
>
<!-- 滑动条 -->
<template v-for="d in inView" :key="d.uuid">
<RowVue :data="d" class="xg-gantt-row">
<component :is="$slotsBox.slider" :data="d" />
</RowVue>
</template>

<!-- 连线 -->
<svg class="xg-gantt-body-line-wrap" :style="{ width: `${ganttWidth}px` }">
<!-- <path stroke="red" fill="transparent" d="M 200 2 H 400 V 102"></path> -->
<LinkPath v-for="link in $links.links" :key="link.uuid" :link="link" />
</svg>

<!-- 周末 -->
<template v-for="(date, i) in ganttHeader.dates">
<div
v-if="date.isWeekend()"
Expand All @@ -22,6 +30,7 @@
></div>
</template>

<!-- 今天 -->
<div
v-if="showToday"
class="xg-gantt-body-date-line today"
Expand All @@ -31,8 +40,6 @@
backgroundColor: '#87CEFA'
}"
></div>

<div class="xg-gantt-body-line-wrap"></div>
</div>
</template>

Expand All @@ -44,13 +51,16 @@ import useSlotsBox from '@/composables/useSlotsBox';
import useStyle from '@/composables/useStyle';
import useToday from '@/composables/useToday';
import RowVue from './Row.vue';
import LinkPath from './LinkPath.vue';
import useLinks from '@/composables/useLinks';
const { $slotsBox } = useSlotsBox();
const { bodyHeight } = useStyle();
const { ganttWidth, ganttColumnWidth } = useGanttWidth();
const { inView } = useInView();
const { todayLeft, showToday } = useToday();
const { ganttHeader } = useGanttHeader();
const { $links } = useLinks();
</script>

<style lang="scss" scoped>
Expand All @@ -69,7 +79,7 @@ const { ganttHeader } = useGanttHeader();
}
.xg-gantt-body-date-line {
z-index: 9;
z-index: 2;
height: 100%;
position: absolute;
top: 0;
Expand All @@ -79,6 +89,8 @@ const { ganttHeader } = useGanttHeader();
.xg-gantt-body-line-wrap {
width: 100%;
height: 100%;
position: absolute;
z-index: 5;
}
}
</style>
53 changes: 53 additions & 0 deletions src/components/common/LinkPath.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<template>
<path stroke="red" fill="transparent" :d="path"></path>
</template>

<script lang="ts" setup>
import useData from '@/composables/useData';
import useGanttWidth from '@/composables/useGanttWidth';
import useStyle from '@/composables/useStyle';
import { LinkItem } from '@/models/data/links';
import { computed, PropType } from 'vue';
const props = defineProps({
link: {
type: Object as PropType<LinkItem>,
default: () => ({})
}
});
const { $data } = useData();
const { ganttColumnWidth, currentMillisecond } = useGanttWidth();
const { rowHeight } = useStyle();
const x = computed(
() =>
(props.link.fromRow.end.intervalTo($data.start) /
currentMillisecond.value) *
ganttColumnWidth.value
);
const y = computed(
() => props.link.fromRow.flatIndex * rowHeight.value + rowHeight.value / 2
);
const x2 = computed(
() =>
(props.link.toRow.start.intervalTo($data.start) /
currentMillisecond.value) *
ganttColumnWidth.value
);
const y2 = computed(
() => props.link.toRow.flatIndex * rowHeight.value + rowHeight.value / 2
);
const path = computed(
() =>
`M ${x.value + 10} ${y.value} H ${x.value + 50} V ${
y.value + rowHeight.value / 2
} H ${x2.value - 10} V ${y2.value}`
);
</script>

<style scoped lang="scss"></style>
4 changes: 2 additions & 2 deletions src/components/common/TableHeaderTh.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import useDrag from '@/composables/useDrag';
import useSlotsBox from '@/composables/useSlotsBox';
import useStyle from '@/composables/useStyle';
import { ref } from 'vue';
import { Ref, ref } from 'vue';
const props = defineProps({
column: {
Expand All @@ -41,7 +41,7 @@ while (column.value.children?.length > 0) {
const index = column.value.node.props.__index;
const headerRef = ref<HTMLElement | null>(null);
const headerRef = ref(null) as Ref<HTMLElement | null>;
onResizeTableColumn(headerRef, {
onEnd: x => {
$slotsBox.tableHeaders.leafs[index].width = Math.max(
Expand Down
12 changes: 9 additions & 3 deletions src/components/root/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
getCurrentInstance,
onMounted,
onUpdated,
Ref,
ref,
toRefs
} from 'vue';
Expand All @@ -73,6 +74,7 @@ import useParam from '@/composables/useParam';
import useGanttHeader from '@/composables/useGanttHeader';
import useDrag from '@/composables/useDrag';
import useElement from '@/composables/useElement';
import useLinks from '@/composables/useLinks';
const containerId = uuid(10);
const props = defineProps(rootProps);
Expand Down Expand Up @@ -125,11 +127,14 @@ setSlots(props.slots);
const { tableWidth } = useTableWidth();
// #endregion
// #region 处理数据
const { data } = toRefs(props);
// #region 初始化各种数据
const { data, links } = toRefs(props);
const { initData } = useData();
initData(data);
const { initLinks } = useLinks();
initLinks(links);
// #endregion
// #region 监听 gantt 尺寸变化,表头和宽度需要重新渲染
Expand All @@ -140,7 +145,7 @@ onMounted(() => useResizeObserver(ganttRef.value?.$el, setGanttHeaders));
// #region 加载示意线
const { showLine, lineLeft, onResizeTableColumn, mousedown } = useDrag();
const midLineRef = ref<HTMLElement | null>(null);
const midLineRef = ref(null) as Ref<HTMLElement | null>;
onResizeTableColumn(midLineRef, {
onEnd: x => {
$slotsBox.tableHeaders.leafs[
Expand Down Expand Up @@ -175,6 +180,7 @@ onResizeTableColumn(midLineRef, {
return true;
}
});
// #endregion
console.log('.....root', getCurrentInstance());
</script>
Expand Down
12 changes: 9 additions & 3 deletions src/components/root/rootProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ export default {
default: () => []
},

links: {
type: Array as PropType<any[]>,
default: () => []
},

/**
* 数据索引的label,默认 index。应当确保它是唯一的,如果不是,则会引起渲染错误。
* 数据索引的label,默认 id。应当确保它是唯一的,如果不是,则会引起渲染错误。
*/
dataIndex: {
type: String
dataId: {
type: String,
default: Variables.default.idKey
},

/**
Expand Down
Loading

0 comments on commit faebcc7

Please sign in to comment.