Skip to content

Commit

Permalink
feat: ✨add reactive gantt header by unit and width
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyjone committed Apr 17, 2023
1 parent c926e9d commit e315b06
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 38 deletions.
2 changes: 1 addition & 1 deletion demo/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ganttData[0].children = [
id: ++id,
name: 'sub-t' + id,
startDate: new Date(2020, 0, 1),
endDate: new Date(2020, 5, 5),
endDate: new Date(2020, 0, 5),
children: [
{
id: ++id,
Expand Down
5 changes: 2 additions & 3 deletions src/components/common/GanttHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ import useStyle from '@/composables/useStyle';
const { $styleBox } = useStyle();
const { getDateList } = useData();
const dateList = getDateList();
console.log('getDateList', dateList);
const { dateList } = useData();
console.log('getDateList', dateList.value);
</script>

<style lang="scss" scoped>
Expand Down
27 changes: 24 additions & 3 deletions src/components/root/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ import GanttBody from '@/components/common/GanttBody.vue';
import useSlotsBox from '@/composables/useSlotsBox';
import useTableWidth from '@/composables/useTableWidth';
import { uuid } from '@/utils/common';
import { getCurrentInstance, onMounted, onUpdated, ref, toRefs } from 'vue';
import {
getCurrentInstance,
onMounted,
onUnmounted,
onUpdated,
ref,
toRefs
} from 'vue';
import rootProps from './rootProps';
import useData from '@/composables/useData';
import useStyle from '@/composables/useStyle';
Expand Down Expand Up @@ -93,15 +100,29 @@ const { setSlots } = useSlotsBox();
setSlots(props.slots);
// #endregion
// #region 获取表格宽度
const { tableWidth } = useTableWidth();
// #endregion
// #region 处理数据
const { data } = toRefs(props);
const { initData } = useData();
initData(data);
// #endregion
// #region 获取表格宽度
const { tableWidth } = useTableWidth();
// #region 监听 gantt 尺寸变化,表头和宽度需要重新渲染
const ganttResizeObserver = ref<ResizeObserver>();
const { setGanttHeaders } = useData();
onMounted(() => {
ganttResizeObserver.value = new ResizeObserver(setGanttHeaders);
ganttRef?.value && ganttResizeObserver.value?.observe(ganttRef.value.$el);
});
onUnmounted(() => {
ganttResizeObserver.value = undefined;
});
// #endregion
console.log('.....root', getCurrentInstance());
Expand Down
17 changes: 10 additions & 7 deletions src/components/root/rootProps.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { type PropType, type Slots } from 'vue';
import { Errors } from '@/constants/errors';
import { Variables } from '@/constants/vars';
import {
type GanttColumnSize,
type ParamBodyOptions,
type ParamHeaderOptions
} from '@/typings/ParamOptions';
import { parseNumber } from '@/utils/common';

export default {
Expand Down Expand Up @@ -185,7 +180,7 @@ export default {
* 头部样式,一个对象
*/
headerStyle: {
type: Object as PropType<ParamHeaderOptions>,
type: Object as PropType<HeaderOptions>,
default: () => {
return {};
}
Expand All @@ -195,7 +190,7 @@ export default {
* 内容样式,一个对象
*/
bodyStyle: {
type: Object as PropType<ParamBodyOptions>,
type: Object as PropType<BodyOptions>,
default: () => {
return {};
}
Expand Down Expand Up @@ -223,5 +218,13 @@ export default {
showSettingBtn: {
type: Boolean,
default: true
},

/**
* 日期单位
*/
unit: {
type: String as PropType<HeaderDateUnit>,
default: 'day'
}
};
25 changes: 18 additions & 7 deletions src/composables/useData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import { useStore } from '@/store';
import { watch, type Ref } from 'vue';
import { computed, watch, type Ref } from 'vue';
import useGanttWidth from './useGanttWidth';
import useTableWidth from './useTableWidth';

export default () => {
const store = useStore();
const { ganttColumnWidth } = useGanttWidth();
const { tableWidth } = useTableWidth();

// 设置甘特日期头
function setGanttHeaders() {
store.ganttHeader.setDate(store.$data.start, store.$data.end);
store.ganttHeader.setDate(
// 使用 window 的宽度减去 table 的宽度,就是最小需要的列数,再加一个阈值即可
(window.innerWidth - tableWidth.value) / ganttColumnWidth.value + 5,
store.$data.start,
store.$data.end,
store.$styleBox.unit
);
}

function initData(data: Ref<any[]>) {
Expand All @@ -26,9 +36,10 @@ export default () => {
);
}

function getDateList() {
return store.ganttHeader.headers;
}

return { $data: store.$data, initData, getDateList };
return {
$data: store.$data,
initData,
dateList: computed(() => store.ganttHeader.headers),
setGanttHeaders
};
};
21 changes: 19 additions & 2 deletions src/composables/useGanttWidth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,26 @@ import { computed } from 'vue';
export default () => {
const store = useStore();

const ganttColumnWidth = computed(() => {
// const size = store.$styleBox.ganttColumnSize;
// switch (size) {
// case 'small':
// if (store.$styleBox.unit === 'week') return 7;
// return 15;
// case 'large':
// if (store.$styleBox.unit === 'week') return 30;
// return 60;
// case 'normal':
// default:
// if (store.$styleBox.unit === 'week') return 15;
// return 30;
// }
return 30;
});

const ganttWidth = computed(() => {
return store.ganttHeader.headers[1].length * 30;
return store.ganttHeader.headers[1].length * ganttColumnWidth.value;
});

return { ganttWidth };
return { ganttWidth, ganttColumnWidth };
};
3 changes: 3 additions & 0 deletions src/composables/useStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ export default () => {
const setStyles = (props: ExtractPropTypes<typeof rootProps>) => {
store.$styleBox.setBorder(props.border);
store.$styleBox.setBorderColor(props.borderColor);

store.$styleBox.ganttColumnSize = props.ganttColumnSize;
store.$styleBox.unit = props.unit;
};

return { bodyHeight, setStyles, $styleBox: store.$styleBox };
Expand Down
40 changes: 32 additions & 8 deletions src/models/param/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,18 @@ class GanttColumn extends Column {
super();

this.date = date;
this.label = this.date.getBy(unit).toString();

// this.label = this.date.getBy(unit).toString();
switch (unit) {
case 'month':
this.label = this.date.toMonth();
break;
case 'week':
this.label = this.date.toWeek();
break;
default:
this.label = this.date.getBy(unit).toString();
}
}
}

Expand Down Expand Up @@ -179,32 +190,45 @@ class GanttHeader extends Header {
start?: XDate;
end?: XDate;
unit: HeaderDateUnit = 'day';
minLength: number = 0;

/**
* 设置日期
*/
setDate(start?: XDate, end?: XDate, unit: HeaderDateUnit = 'day') {
setDate(
minLen: number,
start?: XDate,
end?: XDate,
unit: HeaderDateUnit = 'day'
) {
this.start = start;
this.end = end;
this.unit = unit;
this.minLength = minLen;

this.generate();
}

generate() {
this.dates = [];

// 通过 start 和 end 以及 unit 来生成 columns
const columns: GanttColumn[] = [];

const start = this.start!.date.getTime();
const end = this.end!.date.getTime();

// TODO 这里可以优化一下,直接一次循环就可以组成 headers。因为是固定格式
for (
let i = start;
i <= end;
i += Variables.time.millisecondOf[this.unit]
) {
this.dates.push(new XDate(i));
let s: number;
const step = Variables.time.millisecondOf[this.unit];
for (s = start; s <= end; s += step) {
this.dates.push(new XDate(s));
}

// 保证要占满所有宽度
while (this.dates.length < this.minLength) {
this.dates.push(new XDate(s));
s += step;
}

let last: number;
Expand Down
31 changes: 24 additions & 7 deletions src/models/param/styles.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
type Style = Record<string, string>;

export default class StyleBox {
private border: number = 1;
private borderColor: string = '#e5e5e5';

private __border: number = 1;
setBorder(b: number) {
this.border = b;
this.__border = b;
}

getBorder(): Style {
return { border: `${this.border}px solid` };
return { border: `${this.__border}px solid` };
}

private __borderColor: string = '#e5e5e5';
setBorderColor(bc: string) {
this.borderColor = bc;
this.__borderColor = bc;
}

getBorderColor(): Style {
return { 'border-color': this.borderColor };
return { 'border-color': this.__borderColor };
}

private __ganttColumnSize: GanttColumnSize = 'normal';
public set ganttColumnSize(gs: GanttColumnSize) {
this.__ganttColumnSize = gs;
}

public get ganttColumnSize(): GanttColumnSize {
return this.__ganttColumnSize;
}

private __unit: HeaderDateUnit = 'day';
public get unit(): HeaderDateUnit {
return this.__unit;
}

public set unit(v: HeaderDateUnit) {
this.__unit = v;
}
}
15 changes: 15 additions & 0 deletions src/typings/size.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare type GanttColumnSize = 'small' | 'normal' | 'large';

declare interface HeaderOptions {
bgColor?: string;
textColor?: string;
}

declare interface BodyOptions {
todayColor?: string;
weekendColor?: string;
bgColor?: string;
textColor?: string;
hoverColor?: string;
selectColor?: string;
}

0 comments on commit e315b06

Please sign in to comment.