diff --git a/packages/vtable-gantt/examples/gantt/gantt-theme-adaptation.ts b/packages/vtable-gantt/examples/gantt/gantt-theme-adaptation.ts new file mode 100644 index 0000000000..a241ab8165 --- /dev/null +++ b/packages/vtable-gantt/examples/gantt/gantt-theme-adaptation.ts @@ -0,0 +1,397 @@ +import type { ColumnsDefine } from '@visactor/vtable'; +import * as VTable from '@visactor/vtable'; +import type { GanttConstructorOptions, TYPES } from '../../src/index'; +import * as VTableGantt from '../../src/index'; +import { Gantt } from '../../src/index'; +import { bindDebugTool } from '../../../vtable/src/scenegraph/debug-tool'; +const CONTAINER_ID = 'vTable'; + +export function createTable() { + const records = [ + { + id: 1, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-04', + end: '2024-07-14', + progress: 31, + priority: 'P0' + }, + { + id: 2, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-05', + progress: 60, + priority: 'P0', + type: 'milestone' + }, + { + id: 3, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024/07/08', + end: '2024/07/14', + progress: 100, + priority: 'P1' + }, + { + id: 4, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-09', + end: '2024-07-14', + progress: 90, + priority: 'P0' + }, + { + id: 5, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '07/14/2024', + end: '07/24/2024', + progress: 60, + priority: 'P0' + }, + { + id: 6, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-10', + end: '2024-07-14', + progress: 100, + priority: 'P1' + }, + { + id: 7, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-24', + end: '2024-08-04', + progress: 31, + priority: 'P0' + }, + { + id: 8, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024.07.06', + end: '2024.07.08', + progress: 60, + priority: 'P0' + }, + { + id: 9, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024/07/09', + end: '2024/07/11', + progress: 100, + priority: 'P1' + }, + { + id: 10, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '07.24.2024', + end: '08.04.2024', + progress: 31, + priority: 'P0' + }, + { + id: 11, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-06', + end: '2024-07-08', + progress: 60, + priority: 'P0' + }, + { + id: 12, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-08-09', + end: '2024-09-11', + progress: 100, + priority: 'P1' + }, + { + id: 13, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-24', + end: '2024-08-04', + progress: 31, + priority: 'P0' + }, + { + id: 14, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-06', + end: '2024-07-08', + progress: 60, + priority: 'P0' + }, + { + id: 15, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-09', + end: '2024-07-11', + progress: 100, + priority: 'P1' + }, + { + id: 16, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-24', + end: '2024-08-04', + progress: 31, + priority: 'P0' + }, + { + id: 17, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-06', + end: '2024-07-08', + progress: 60, + priority: 'P0' + }, + { + id: 18, + title: 'Determine project scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-09', + end: '2024-07-11', + progress: 100, + priority: 'P1' + }, + { + id: 19, + title: 'Software Development', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-24', + end: '2024-08-04', + progress: 31, + priority: 'P0' + }, + { + id: 20, + title: 'Scope', + developer: 'liufangfang.jane@bytedance.com', + start: '2024-07-06', + end: '2024-07-08', + progress: 60, + priority: 'P0' + } + ]; + + const columns = [ + // { + // field: 'id', + // title: 'ID', + // width: 80, + // sort: true + // }, + { + field: 'title', + title: 'title', + width: 200, + sort: true + }, + { + field: 'start', + title: 'start', + width: 150, + sort: true + }, + { + field: 'end', + title: 'end', + width: 150, + sort: true + }, + { + field: 'priority', + title: 'priority', + width: 100, + sort: true + }, + + { + field: 'progress', + title: 'progress', + width: 200, + sort: true + } + ]; + const option: GanttConstructorOptions = { + records: [], + theme: VTableGantt.themes.SIMPLIFY, + taskListTable: { + columns: columns, + tableWidth: 400, + minTableWidth: 100, + maxTableWidth: 600, + theme: VTable.themes.SIMPLIFY, + }, + dependency: { + links: [ + { + type: VTableGantt.TYPES.DependencyType.FinishToStart, + linkedFromTaskKey: 1, + linkedToTaskKey: 2 + }, + { + type: VTableGantt.TYPES.DependencyType.StartToFinish, + linkedFromTaskKey: 2, + linkedToTaskKey: 3 + }, + { + type: VTableGantt.TYPES.DependencyType.StartToStart, + linkedFromTaskKey: 3, + linkedToTaskKey: 4 + }, + { + type: VTableGantt.TYPES.DependencyType.FinishToFinish, + linkedFromTaskKey: 4, + linkedToTaskKey: 5 + }, + { + type: VTableGantt.TYPES.DependencyType.StartToFinish, + linkedFromTaskKey: 5, + linkedToTaskKey: 2 + }, + { + type: VTableGantt.TYPES.DependencyType.StartToStart, + linkedFromTaskKey: 52, + linkedToTaskKey: 1 + }, + { + type: VTableGantt.TYPES.DependencyType.StartToStart, + linkedFromTaskKey: 53, + linkedToTaskKey: 3 + }, + { + type: VTableGantt.TYPES.DependencyType.FinishToFinish, + linkedFromTaskKey: 4, + linkedToTaskKey: 54 + }, + { + type: VTableGantt.TYPES.DependencyType.FinishToStart, + linkedFromTaskKey: 1, + linkedToTaskKey: 5 + } + ], + // linkLineSelectable: false, + linkSelectedLineStyle: { + shadowBlur: 5, //阴影宽度 + shadowColor: 'red', + lineColor: 'red', + lineWidth: 1 + }, + linkCreatable: true + }, + frame: { + verticalSplitLineMoveable: true, + outerFrameStyle: { + borderLineWidth: 2, + borderColor: 'red', + cornerRadius: 8 + }, + verticalSplitLine: { + lineWidth: 3, + lineColor: '#e1e4e8' + }, + verticalSplitLineHighlight: { + lineColor: 'green', + lineWidth: 3 + } + }, + headerRowHeight: 60, + rowHeight: 40, + timelineHeader: { + scales: [ + { + unit: 'week', + step: 1, + startOfWeek: 'sunday', + format(date) { + return `Week ${date.dateIndex}`; + }, + style: { + fontSize: 20, + fontWeight: 'bold', + color: 'red' + } + }, + { + unit: 'day', + step: 1, + format(date) { + return date.dateIndex.toString(); + }, + style: { + fontSize: 20, + fontWeight: 'bold', + color: 'red' + } + } + ] + }, + scrollStyle: { + visible: 'scrolling' + }, + overscrollBehavior: 'none' + }; + // columns:[ + // { + // title:'2024-07', + // columns:[ + // { + // title:'01' + // }, + // { + // title:'02' + // }, + // ... + // ] + // }, + // ... + // ] + const ganttInstance = new Gantt(document.getElementById(CONTAINER_ID)!, option); + window.ganttInstance = ganttInstance; + ganttInstance.setRecords(records); + + ganttInstance.on('scroll', e => { + console.log('scroll', e); + }); + ganttInstance.on('change_date_range', e => { + console.log('change_date_range', e); + }); + ganttInstance.on('mouseenter_task_bar', e => { + console.log('mouseenter_taskbar', e); + }); + ganttInstance.on('mouseleave_task_bar', e => { + console.log('mouseleave_taskbar', e); + }); + ganttInstance.on('click_task_bar', e => { + console.log('click_task_bar', e); + }); + ganttInstance.taskListTableInstance?.on('scroll', e => { + console.log('listTable scroll', e); + }); + ganttInstance.taskListTableInstance?.on('change_header_position_start', e => { + console.log('change_header_position_start ', e); + }); + ganttInstance.taskListTableInstance?.on('changing_header_position', e => { + console.log('changing_header_position ', e); + }); + bindDebugTool(ganttInstance.scenegraph.stage as any, { + customGrapicKeys: ['role', '_updateTag'] + }); +} diff --git a/packages/vtable-gantt/examples/menu.ts b/packages/vtable-gantt/examples/menu.ts index e9868ff81a..4e89527ffb 100644 --- a/packages/vtable-gantt/examples/menu.ts +++ b/packages/vtable-gantt/examples/menu.ts @@ -10,6 +10,10 @@ export const menus = [ path: 'gantt', name: 'gantt-milestone' }, + { + path: 'gantt', + name: 'gantt-theme-adaptation' + }, { path: 'gantt', name: 'gantt-hour' diff --git a/packages/vtable-gantt/src/gantt-helper.ts b/packages/vtable-gantt/src/gantt-helper.ts index e0aafff355..dc7a58c322 100644 --- a/packages/vtable-gantt/src/gantt-helper.ts +++ b/packages/vtable-gantt/src/gantt-helper.ts @@ -120,6 +120,22 @@ export { isNode }; export function initOptions(gantt: Gantt) { const options = gantt.options; + + const theme = options.theme; + if (theme) { + const themeTimelineHeader = theme.timelineHeader || {}; + options.timelineHeader = Object.assign({}, themeTimelineHeader, options.timelineHeader); + + const themeTaskBar = theme.taskBar || {}; + options.taskBar = Object.assign({}, themeTaskBar, options.taskBar); + + const themeGridStyle = theme.grid || {}; + options.grid = Object.assign({}, themeGridStyle, options.grid); + + const themeRowSeriesNumber = theme.rowSeriesNumber || {}; + options.rowSeriesNumber = Object.assign({},themeRowSeriesNumber,options.rowSeriesNumber); + } + gantt.parsedOptions.tasksShowMode = options?.tasksShowMode ?? TasksShowMode.Tasks_Separate; gantt.parsedOptions.pixelRatio = options?.pixelRatio ?? 1; gantt.parsedOptions.rowHeight = options?.rowHeight ?? 40; diff --git a/packages/vtable-gantt/src/index.ts b/packages/vtable-gantt/src/index.ts index d3fd7b445c..0d738701a0 100644 --- a/packages/vtable-gantt/src/index.ts +++ b/packages/vtable-gantt/src/index.ts @@ -42,3 +42,4 @@ export { VTable, plugins }; +export * as themes from './themes'; diff --git a/packages/vtable-gantt/src/themes.ts b/packages/vtable-gantt/src/themes.ts index 7df66cec2b..d3d8b8abba 100644 --- a/packages/vtable-gantt/src/themes.ts +++ b/packages/vtable-gantt/src/themes.ts @@ -1,59 +1,54 @@ -// /* eslint-disable sort-imports */ -// import { extend, getIgnoreCase } from './tools/helper'; -// import darkTheme from './themes/DARK'; -// import brightTheme from './themes/BRIGHT'; -// import arcoTheme from './themes/ARCO'; -// import defaultTheme from './themes/DEFAULT'; -// import materialDesignTheme from './themes/SIMPLIFY'; -// import { themes as plugins } from './plugins/themes'; -// import { TableTheme } from './themes/theme'; -// import type { ITableThemeDefine } from './ts-types'; -// export const DARK = new TableTheme(darkTheme, darkTheme); -// export const BRIGHT = new TableTheme(brightTheme, brightTheme); -// export const ARCO = new TableTheme(arcoTheme, arcoTheme); -// export const DEFAULT = new TableTheme(defaultTheme, defaultTheme); -// export const SIMPLIFY = new TableTheme(materialDesignTheme, materialDesignTheme); +import { extend, getIgnoreCase } from './tools/helper'; +import { TableTheme } from './themes/theme-define'; +import ganttSimplifyTheme from './themes/SIMPLIFY'; +import arcoTheme from './themes/ARCO'; +import darkTheme from './themes/DARK'; +import defaultTheme from './themes/DEFAULT'; +import brightTheme from './themes/BRIGHT'; -// const builtin: { [key: string]: TableTheme } = { -// DEFAULT, -// SIMPLIFY, -// ARCO, -// DARK, -// BRIGHT -// }; -// // let defTheme = DEFAULT; -// export const theme = { TableTheme }; -// export function of(value: ITableThemeDefine | string | undefined | null): TableTheme | null { -// if (!value) { -// return null; -// } -// if (typeof value === 'string') { -// const t = getIgnoreCase(get(), value); -// if (t) { -// if (t instanceof TableTheme) { -// return t; -// } -// return new TableTheme(t, t); -// } -// return null; -// } -// if (value instanceof TableTheme) { -// return value; -// } -// return new TableTheme(value, value); -// } +export const SIMPLIFY = new TableTheme(ganttSimplifyTheme, ganttSimplifyTheme); +export const ARCO = new TableTheme(arcoTheme, arcoTheme); +export const DARK = new TableTheme(darkTheme, darkTheme); +export const DEFAULT = new TableTheme(defaultTheme, defaultTheme); +export const BRIGHT = new TableTheme(brightTheme, brightTheme); -// export function get(): { [key: string]: TableTheme } { -// return extend(builtin, plugins); -// } -// export { ITableThemeDefine }; -// export default { -// DARK, -// BRIGHT, -// ARCO, -// DEFAULT, -// SIMPLIFY, -// theme, -// of, -// get -// }; +const builtin: { [key: string]: TableTheme } = { + SIMPLIFY, + ARCO, + DARK, + DEFAULT, + BRIGHT +}; + +export const theme = { TableTheme }; + +export function of(value: any | string | undefined | null): TableTheme | null { + if (!value) { + return null; + } + if (typeof value === 'string') { + const t = getIgnoreCase(get(), value); + if (t) { + if (t instanceof TableTheme) { + return t; + } + return new TableTheme(t, t); + } + return null; + } + if (value instanceof TableTheme) { + return value; + } + return new TableTheme(value, value); +} + +export function get(): { [key: string]: TableTheme } { + // 这里可以扩展插件主题 + return extend(builtin, {}); +} + +export default { + theme, + of, + get +}; diff --git a/packages/vtable-gantt/src/themes/ARCO.ts b/packages/vtable-gantt/src/themes/ARCO.ts new file mode 100644 index 0000000000..da4070994c --- /dev/null +++ b/packages/vtable-gantt/src/themes/ARCO.ts @@ -0,0 +1,69 @@ +const ARCO = { + name: 'ARCO', + rowSeriesNumber: { + title: '行号', + dragOrder: true, + headerStyle: { + bgColor: '#EEF1F5', + borderColor: '#e1e4e8', + color: '#1B1F23' + }, + style: { + bgColor: '#FFF', + color: '#1B1F23', + fontSize: 14 + } + }, + grid: { + verticalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + backgroundColor: '#FFF' + }, + taskBar: { + startDateField: 'start', + endDateField: 'end', + progressField: 'progress', + labelText: '{title} {progress}%', + barStyle: { + barColor: '#ee8800', + completedBarColor: '#91e8e0', + width: 20, + cornerRadius: 8, + borderColor: 'black', + borderWidth: 1 + }, + milestoneStyle: { + borderColor: '#3073f2', + borderLineWidth: 1, + fillColor: '#c8daf6', + width: 15, + cornerRadius: 0 + }, + labelTextStyle: { + fontFamily: 'Arial', + fontSize: 14, + color: '#1B1F23', + textAlign: 'left' + } + }, + timelineHeader: { + backgroundColor: '#EEF1F5', + colWidth: 60, + verticalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + } + } +}; + +export default ARCO; diff --git a/packages/vtable-gantt/src/themes/BRIGHT.ts b/packages/vtable-gantt/src/themes/BRIGHT.ts new file mode 100644 index 0000000000..8a1d749c54 --- /dev/null +++ b/packages/vtable-gantt/src/themes/BRIGHT.ts @@ -0,0 +1,69 @@ +const BRIGHT = { + name: 'BRIGHT', + rowSeriesNumber: { + title: '行号', + dragOrder: true, + headerStyle: { + bgColor: '#5389FF', + borderColor: '#A1C1FF', + color: '#FFF' + }, + style: { + bgColor: '#F4F8FF', + color: '#000', + fontSize: 14 + } + }, + grid: { + verticalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + backgroundColor: '#FFF' + }, + taskBar: { + startDateField: 'start', + endDateField: 'end', + progressField: 'progress', + labelText: '{title} {progress}%', + barStyle: { + barColor: '#5389FF', + completedBarColor: '#E0EAFE', + width: 20, + cornerRadius: 8, + borderColor: '#5286FA', + borderWidth: 1 + }, + milestoneStyle: { + borderColor: '#A1C1FF', + borderLineWidth: 1, + fillColor: '#5389FF', + width: 15, + cornerRadius: 0 + }, + labelTextStyle: { + fontFamily: 'Arial', + fontSize: 14, + color: '#000', + textAlign: 'left' + } + }, + timelineHeader: { + backgroundColor: '#5389FF', + colWidth: 60, + verticalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#e1e4e8' + } + } +}; + +export default BRIGHT; diff --git a/packages/vtable-gantt/src/themes/DARK.ts b/packages/vtable-gantt/src/themes/DARK.ts new file mode 100644 index 0000000000..b6ffc800d2 --- /dev/null +++ b/packages/vtable-gantt/src/themes/DARK.ts @@ -0,0 +1,69 @@ +const DARK = { + name: 'DARK', + rowSeriesNumber: { + title: '行号', + dragOrder: true, + headerStyle: { + bgColor: '#373b45', + borderColor: '#444A54', + color: '#D3D5DA' + }, + style: { + bgColor: '#2d3137', + color: '#D3D5DA', + fontSize: 12 + } + }, + grid: { + verticalLine: { + lineWidth: 1, + lineColor: '#444A54' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#444A54' + }, + backgroundColor: '#282a2e' + }, + taskBar: { + startDateField: 'start', + endDateField: 'end', + progressField: 'progress', + labelText: '{title} {progress}%', + barStyle: { + barColor: '#4284FF', + completedBarColor: '#2F4774', + width: 20, + cornerRadius: 8, + borderColor: '#4284FF', + borderWidth: 1 + }, + milestoneStyle: { + borderColor: '#4284FF', + borderLineWidth: 1, + fillColor: '#2F4774', + width: 15, + cornerRadius: 0 + }, + labelTextStyle: { + fontFamily: 'PingFang SC', + fontSize: 12, + color: '#D3D5DA', + textAlign: 'left' + } + }, + timelineHeader: { + backgroundColor: '#373b45', + colWidth: 60, + verticalLine: { + lineWidth: 1, + lineColor: '#444A54' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#444A54' + } + } +}; + +export default DARK; diff --git a/packages/vtable-gantt/src/themes/DEFAULT.ts b/packages/vtable-gantt/src/themes/DEFAULT.ts new file mode 100644 index 0000000000..e442c054fe --- /dev/null +++ b/packages/vtable-gantt/src/themes/DEFAULT.ts @@ -0,0 +1,70 @@ +const DEFAULT = { + name: 'DEFAULT', + rowSeriesNumber: { + title: '行号', + dragOrder: true, + headerStyle: { + bgColor: '#ECF1F5', + color: '#000', + fontWeight: 'bold', + fontSize: 16 + }, + style: { + bgColor: '#FAF9FB', + color: '#000', + fontSize: 14 + } + }, + grid: { + verticalLine: { + lineWidth: 1, + lineColor: '#E1E4E8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#E1E4E8' + }, + backgroundColor: '#FDFDFD' + }, + taskBar: { + startDateField: 'start', + endDateField: 'end', + progressField: 'progress', + labelText: '{title} {progress}%', + barStyle: { + barColor: '#82b2f5', + completedBarColor: '#CCE0FF', + width: 20, + cornerRadius: 8, + borderColor: '#0000ff', + borderWidth: 1 + }, + milestoneStyle: { + borderColor: '#0000ff', + borderLineWidth: 1, + fillColor: '#CCE0FF', + width: 15, + cornerRadius: 0 + }, + labelTextStyle: { + fontFamily: 'Arial', + fontSize: 14, + color: '#000', + textAlign: 'left' + } + }, + timelineHeader: { + backgroundColor: '#ECF1F5', + colWidth: 60, + verticalLine: { + lineWidth: 1, + lineColor: '#E1E4E8' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#E1E4E8' + } + } +}; + +export default DEFAULT; diff --git a/packages/vtable-gantt/src/themes/SIMPLIFY.ts b/packages/vtable-gantt/src/themes/SIMPLIFY.ts new file mode 100644 index 0000000000..769a8066c9 --- /dev/null +++ b/packages/vtable-gantt/src/themes/SIMPLIFY.ts @@ -0,0 +1,73 @@ +const SIMPLIFY = { + name: 'SIMPLIFY', + underlayBackgroundColor: '#FFF', + defaultStyle: { + bgColor: '#FFF' + }, + rowSeriesNumber: { + title: '行号', + dragOrder: true, + headerStyle: { + bgColor: '#FFF', + borderColor: '#f2f2f2', + color: 'rgba(0, 0, 0, 0.87)' + }, + style: { + bgColor: '#FFF', + color: 'rgba(0, 0, 0, 0.87)', + fontSize: 14 + } + }, + grid: { + verticalLine: { + lineWidth: 1, + lineColor: '#ccc7c7' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#ccc7c7' + }, + backgroundColor: '#FFF' + }, + taskBar: { + startDateField: 'start', + endDateField: 'end', + progressField: 'progress', + labelText: '{title} {progress}%', + barStyle: { + barColor: '#6FA8DC', + completedBarColor: '#D0E0E3', + width: 20, + cornerRadius: 8, + borderColor: '#6FA8DC', + borderWidth: 1 + }, + milestoneStyle: { + borderColor: '#6FA8DC', + borderLineWidth: 1, + fillColor: '#D0E0E3', + width: 15, + cornerRadius: 0 + }, + labelTextStyle: { + fontFamily: 'Arial', + fontSize: 14, + color: 'rgba(0, 0, 0, 0.87)', + textAlign: 'left' + } + }, + timelineHeader: { + backgroundColor: '#FFF', + colWidth: 60, + verticalLine: { + lineWidth: 1, + lineColor: '#f2f2f2' + }, + horizontalLine: { + lineWidth: 1, + lineColor: '#ccc7c7' + } + } +}; + +export default SIMPLIFY; diff --git a/packages/vtable-gantt/src/themes/theme-define.ts b/packages/vtable-gantt/src/themes/theme-define.ts new file mode 100644 index 0000000000..2b14b5100a --- /dev/null +++ b/packages/vtable-gantt/src/themes/theme-define.ts @@ -0,0 +1,42 @@ +// 主题 TableTheme 实现,兼容 vtable 主题合并机制 +import { ingoreNoneValueMerge } from '../tools/helper'; + +// 主题类型定义(可根据实际需要扩展) +export type RequiredTableThemeDefine = { + grid: any; + rowSeriesNumber: any; + taskBar: any; + timelineHeader: any; + // ...可继续扩展其他主题字段 +}; + +export class TableTheme { + internalTheme: { obj: any; superTheme: any }; + name: string = ''; + constructor(obj: any, superTheme: any) { + this.internalTheme = { obj: obj || {}, superTheme: superTheme || {} }; + this.name = obj?.name || superTheme?.name || ''; + } + + get grid(): RequiredTableThemeDefine['grid'] { + const { obj, superTheme } = this.internalTheme; + return ingoreNoneValueMerge({}, superTheme.grid, obj.grid); + } + + get rowSeriesNumber(): RequiredTableThemeDefine['rowSeriesNumber'] { + const { obj, superTheme } = this.internalTheme; + return ingoreNoneValueMerge({}, superTheme.rowSeriesNumber, obj.rowSeriesNumber); + } + + get taskBar(): RequiredTableThemeDefine['taskBar'] { + const { obj, superTheme } = this.internalTheme; + return ingoreNoneValueMerge({}, superTheme.taskBar, obj.taskBar); + } + + get timelineHeader(): RequiredTableThemeDefine['timelineHeader'] { + const { obj, superTheme } = this.internalTheme; + return ingoreNoneValueMerge({}, superTheme.timelineHeader, obj.timelineHeader); + } +} + +export default TableTheme; diff --git a/packages/vtable-gantt/src/tools/helper.ts b/packages/vtable-gantt/src/tools/helper.ts new file mode 100644 index 0000000000..6de7a111ec --- /dev/null +++ b/packages/vtable-gantt/src/tools/helper.ts @@ -0,0 +1,43 @@ +export function extend(target: any, ...sources: any[]): any { + for (const source of sources) { + if (source) { + for (const key of Object.keys(source)) { + target[key] = source[key]; + } + } + } + return target; +} + +export function getIgnoreCase(obj: any, key: string) { + if (!obj) return undefined; + const lowerKey = key.toLowerCase(); + for (const k of Object.keys(obj)) { + if (k.toLowerCase() === lowerKey) { + return obj[k]; + } + } + return undefined; +} + +// 合并多个对象,遇到 undefined/null 跳过,遇到对象递归合并,遇到基本类型后者覆盖前者 +export function ingoreNoneValueMerge(target: any, ...sources: any[]): any { + for (const source of sources) { + if (!source) continue; + for (const key of Object.keys(source)) { + const value = source[key]; + if (value === undefined || value === null) continue; + if ( + typeof value === 'object' && + !Array.isArray(value) && + typeof target[key] === 'object' && + target[key] !== null + ) { + target[key] = ingoreNoneValueMerge({}, target[key], value); + } else { + target[key] = value; + } + } + } + return target; +} diff --git a/packages/vtable-gantt/src/ts-types/gantt-engine.ts b/packages/vtable-gantt/src/ts-types/gantt-engine.ts index 5292b3da03..647f83edb9 100644 --- a/packages/vtable-gantt/src/ts-types/gantt-engine.ts +++ b/packages/vtable-gantt/src/ts-types/gantt-engine.ts @@ -42,6 +42,7 @@ export interface IGrid { } //#region gantt export interface GanttConstructorOptions { + theme?: any; /** * 数据集合 */ diff --git a/packages/vtable-gantt/src/ts-types/gantt-theme-define.ts b/packages/vtable-gantt/src/ts-types/gantt-theme-define.ts new file mode 100644 index 0000000000..b655d11de6 --- /dev/null +++ b/packages/vtable-gantt/src/ts-types/gantt-theme-define.ts @@ -0,0 +1,8 @@ +// vtable-gantt/src/ts-types/gantt-theme-define.ts + +export interface IGanttTableThemeDefine { + grid?: Record; + rowSeriesNumber?: Record; + timelineHeader?: Record; + taskBar?: Record; +}