@lee576/vue3-gantt 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en-US.md +147 -138
- package/README.md +145 -141
- package/dist/vue3-gantt.css +1 -1
- package/dist/vue3-gantt.es.js +4769 -4242
- package/dist/vue3-gantt.es.js.map +1 -1
- package/dist/vue3-gantt.umd.js +84 -84
- package/dist/vue3-gantt.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,37 +21,78 @@
|
|
|
21
21
|
|
|
22
22
|
## 界面预览
|
|
23
23
|
|
|
24
|
-
<
|
|
25
|
-
<img
|
|
24
|
+
<div align="center">
|
|
25
|
+
<img src="https://github.com/user-attachments/assets/34562bf8-0709-44aa-a05d-6e970ea8b57f" alt="Vue3 Gantt Chart - Light Theme" />
|
|
26
|
+
<p><em>浅色主题 - 完整的任务管理界面</em></p>
|
|
27
|
+
|
|
28
|
+
<img src="https://github.com/user-attachments/assets/d6a60ba1-9f5b-479a-b402-68014ec7c935" alt="Vue3 Gantt Chart - Dark Theme" />
|
|
29
|
+
<p><em>深色主题 - 护眼模式</em></p>
|
|
30
|
+
</div>
|
|
26
31
|
|
|
27
32
|
```
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
- 🎯 左侧任务列表 +
|
|
31
|
-
- 📊
|
|
32
|
-
- 🔗
|
|
33
|
-
- 🎨
|
|
34
|
-
- 🖱️
|
|
35
|
-
- 🌍
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
**核心亮点:**
|
|
35
|
+
- 🎯 **双栏布局** - 左侧任务列表 + 右侧甘特图时间轴,信息一目了然
|
|
36
|
+
- 📊 **可视化进度** - 实时进度条显示,支持拖拽调整完成度
|
|
37
|
+
- 🔗 **智能依赖** - 四种依赖类型(FS/SS/FF/SF),自动绘制连线
|
|
38
|
+
- 🎨 **多主题切换** - 5种内置主题,支持深色模式和自定义主题
|
|
39
|
+
- 🖱️ **交互丰富** - 拖拽移动、调整大小、父子任务联动
|
|
40
|
+
- 🌍 **国际化** - 内置8种语言,轻松扩展更多语言
|
|
41
|
+
- ⚡ **高性能** - 虚拟滚动优化,轻松处理大量任务数据
|
|
42
|
+
- 💎 **里程碑** - 菱形标记关键节点,支持依赖关系
|
|
43
|
+
|
|
44
|
+
## ✨ 核心特性
|
|
45
|
+
|
|
46
|
+
### 📅 多视图模式
|
|
47
|
+
支持四种时间粒度,满足不同场景需求:
|
|
48
|
+
- **月视图** - 长期项目规划,按天显示
|
|
49
|
+
- **周视图** - 中期项目跟踪,按周显示
|
|
50
|
+
- **日视图** - 短期任务管理,精确到天
|
|
51
|
+
- **时视图** - 精细任务调度,按小时显示
|
|
52
|
+
|
|
53
|
+
### 🔗 任务依赖管理
|
|
54
|
+
- **完成-开始 (FS)** - 前置任务完成后,后续任务才能开始
|
|
55
|
+
- **开始-开始 (SS)** - 两个任务同时开始
|
|
56
|
+
- **完成-完成 (FF)** - 两个任务同时完成
|
|
57
|
+
- **开始-完成 (SF)** - 后续任务开始后,前置任务才能完成
|
|
58
|
+
|
|
59
|
+
### 💎 里程碑功能
|
|
60
|
+
- 菱形图标标记项目关键节点
|
|
61
|
+
- 支持作为依赖关系的源和目标
|
|
62
|
+
- 自动识别(开始时间=结束时间)或手动标记
|
|
63
|
+
|
|
64
|
+
### 🎨 主题系统
|
|
65
|
+
- 内置 5 种精美主题(Metro/Dark/Modern/Classic/Colorful)
|
|
66
|
+
- 支持深色模式,护眼舒适
|
|
67
|
+
- 完整的 CSS 变量支持,轻松自定义主题
|
|
68
|
+
- 主题设置自动保存到浏览器
|
|
69
|
+
|
|
70
|
+
### 🌍 国际化支持
|
|
71
|
+
- 内置 8 种语言(中/英/日/韩/法/德/西/俄)
|
|
72
|
+
- 即时切换,无需刷新页面
|
|
73
|
+
- 所有界面元素完整翻译
|
|
74
|
+
- 时间轴表头自动本地化
|
|
75
|
+
- 易于扩展新语言
|
|
76
|
+
|
|
77
|
+
### 🖱️ 交互操作
|
|
78
|
+
- **拖拽移动** - 修改任务开始和结束日期
|
|
79
|
+
- **调整大小** - 拖拽边缘调整任务时长
|
|
80
|
+
- **进度调整** - 拖拽三角滑块调整完成度
|
|
81
|
+
- **父子联动** - 父任务移动时子任务自动跟随
|
|
82
|
+
- **分割面板** - 可调整左右区域比例
|
|
83
|
+
|
|
84
|
+
### ⚡ 性能优化
|
|
85
|
+
- 虚拟滚动渲染,支持海量任务数据
|
|
86
|
+
- 节流更新机制,避免频繁重绘
|
|
87
|
+
- 计算结果缓存,提升响应速度
|
|
88
|
+
- 按需渲染连线,优化绘制性能
|
|
89
|
+
|
|
90
|
+
## 🚀 安装使用
|
|
50
91
|
|
|
51
92
|
### 方式一:通过 npm 安装(推荐)
|
|
52
93
|
|
|
53
94
|
```bash
|
|
54
|
-
# 使用 npm
|
|
95
|
+
# 使用 npm
|
|
55
96
|
npm install @lee576/vue3-gantt
|
|
56
97
|
|
|
57
98
|
# 或使用 yarn
|
|
@@ -64,8 +105,9 @@ pnpm add @lee576/vue3-gantt
|
|
|
64
105
|
### 方式二:从源码构建
|
|
65
106
|
|
|
66
107
|
```bash
|
|
67
|
-
#
|
|
108
|
+
# 克隆仓库
|
|
68
109
|
git clone https://github.com/lee576/vue3-gantt.git
|
|
110
|
+
cd vue3-gantt
|
|
69
111
|
|
|
70
112
|
# 安装依赖
|
|
71
113
|
npm install
|
|
@@ -74,151 +116,118 @@ npm install
|
|
|
74
116
|
npm run dev
|
|
75
117
|
```
|
|
76
118
|
|
|
77
|
-
##
|
|
119
|
+
## 📚 快速开始
|
|
120
|
+
|
|
121
|
+
### 1️⃣ 引入组件
|
|
78
122
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
-
|
|
83
|
-
- vue ^3.5.13
|
|
84
|
-
- zod ^3.24.2
|
|
123
|
+
```typescript
|
|
124
|
+
import { createApp } from 'vue';
|
|
125
|
+
import Gantt from '@lee576/vue3-gantt';
|
|
126
|
+
import '@lee576/vue3-gantt/style.css';
|
|
85
127
|
|
|
86
|
-
|
|
128
|
+
const app = createApp(App);
|
|
129
|
+
app.use(Gantt); // 全局注册
|
|
130
|
+
```
|
|
87
131
|
|
|
88
|
-
|
|
132
|
+
或在组件中单独引入:
|
|
89
133
|
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
import
|
|
93
|
-
// 引入甘特图组件和类型
|
|
134
|
+
```vue
|
|
135
|
+
<script setup lang="ts">
|
|
136
|
+
import { ref } from 'vue';
|
|
94
137
|
import Gantt, {
|
|
95
138
|
type DataConfig,
|
|
96
139
|
type StyleConfig,
|
|
97
|
-
type EventConfig
|
|
140
|
+
type EventConfig,
|
|
141
|
+
LinkType
|
|
98
142
|
} from '@lee576/vue3-gantt';
|
|
99
|
-
// 引入样式文件
|
|
100
143
|
import '@lee576/vue3-gantt/style.css';
|
|
101
|
-
|
|
144
|
+
</script>
|
|
102
145
|
```
|
|
103
146
|
|
|
104
|
-
### 2
|
|
147
|
+
### 2️⃣ 配置容器高度(重要!)
|
|
105
148
|
|
|
106
|
-
|
|
149
|
+
> ⚠️ **注意**:组件**必须有明确的容器高度**才能正常显示。
|
|
107
150
|
|
|
108
|
-
|
|
151
|
+
**推荐方法(任选其一):**
|
|
109
152
|
|
|
110
153
|
```vue
|
|
154
|
+
<!-- 方法1:使用视口高度(最简单) -->
|
|
111
155
|
<template>
|
|
112
|
-
<div
|
|
113
|
-
<gantt
|
|
114
|
-
:styleConfig="styleConfig"
|
|
115
|
-
:dataConfig="dataConfig"
|
|
116
|
-
:eventConfig="eventConfig"
|
|
117
|
-
/>
|
|
156
|
+
<div style="height: 100vh;">
|
|
157
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
118
158
|
</div>
|
|
119
159
|
</template>
|
|
120
160
|
|
|
121
|
-
|
|
122
|
-
.gantt-container {
|
|
123
|
-
height: 100vh; /* 直接使用视口高度 */
|
|
124
|
-
}
|
|
125
|
-
</style>
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
#### 方式 2:使用百分比高度(需要配置 html/body)
|
|
129
|
-
|
|
130
|
-
```vue
|
|
161
|
+
<!-- 方法2:使用固定高度 -->
|
|
131
162
|
<template>
|
|
132
|
-
<div
|
|
133
|
-
<gantt
|
|
134
|
-
:styleConfig="styleConfig"
|
|
135
|
-
:dataConfig="dataConfig"
|
|
136
|
-
:eventConfig="eventConfig"
|
|
137
|
-
/>
|
|
163
|
+
<div style="height: 800px;">
|
|
164
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
138
165
|
</div>
|
|
139
166
|
</template>
|
|
140
167
|
|
|
141
|
-
|
|
142
|
-
/* 全局样式:确保 html 和 body 有高度 */
|
|
143
|
-
html, body {
|
|
144
|
-
height: 100%;
|
|
145
|
-
margin: 0;
|
|
146
|
-
padding: 0;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
#app {
|
|
150
|
-
height: 100%; /* 现在 100% 就能正常工作了 */
|
|
151
|
-
}
|
|
152
|
-
</style>
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
#### 方式 3:使用固定像素值
|
|
156
|
-
|
|
157
|
-
```vue
|
|
158
|
-
<style scoped>
|
|
159
|
-
.gantt-container {
|
|
160
|
-
height: 800px; /* 固定高度 */
|
|
161
|
-
}
|
|
162
|
-
</style>
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
#### 方式 4:使用 Flex 布局
|
|
166
|
-
|
|
167
|
-
```vue
|
|
168
|
+
<!-- 方法3:Flex 布局 -->
|
|
168
169
|
<template>
|
|
169
|
-
<div
|
|
170
|
-
<div
|
|
171
|
-
<div
|
|
172
|
-
<gantt
|
|
170
|
+
<div style="display: flex; flex-direction: column; height: 100vh;">
|
|
171
|
+
<div>Header</div>
|
|
172
|
+
<div style="flex: 1;"> <!-- 自动填充剩余空间 -->
|
|
173
|
+
<gantt :dataConfig="dataConfig" :styleConfig="styleConfig" />
|
|
173
174
|
</div>
|
|
174
175
|
</div>
|
|
175
176
|
</template>
|
|
177
|
+
```
|
|
176
178
|
|
|
177
|
-
<
|
|
178
|
-
|
|
179
|
-
display: flex;
|
|
180
|
-
flex-direction: column;
|
|
181
|
-
height: 100vh;
|
|
182
|
-
}
|
|
179
|
+
<details>
|
|
180
|
+
<summary>💡 为什么需要设置高度?</summary>
|
|
183
181
|
|
|
184
|
-
|
|
185
|
-
flex: 1; /* 自动填充剩余空间 */
|
|
186
|
-
}
|
|
187
|
-
</style>
|
|
188
|
-
```
|
|
182
|
+
组件内部使用了 `height: 100%`,根据 CSS 规范,百分比高度需要父元素有明确的高度才能计算。如果父容器没有设置高度,组件会高度坑塌。
|
|
189
183
|
|
|
190
|
-
|
|
184
|
+
**解决方案**:
|
|
185
|
+
- 使用 `100vh`(视口高度)
|
|
186
|
+
- 使用固定像素值(如 `800px`)
|
|
187
|
+
- 使用 Flex 布局的 `flex: 1`
|
|
188
|
+
- 配置 `html, body { height: 100%; }` 后使用 `100%`
|
|
189
|
+
|
|
190
|
+
</details>
|
|
191
|
+
|
|
192
|
+
### 3️⃣ 基本配置
|
|
191
193
|
|
|
192
194
|
```vue
|
|
193
195
|
<template>
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
<div style="height: 100vh;">
|
|
197
|
+
<gantt
|
|
198
|
+
:dataConfig="dataConfig"
|
|
199
|
+
:styleConfig="styleConfig"
|
|
200
|
+
:eventConfig="eventConfig"
|
|
201
|
+
/>
|
|
202
|
+
</div>
|
|
199
203
|
</template>
|
|
200
|
-
```
|
|
201
204
|
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
<script setup lang="ts">
|
|
206
|
+
import { ref, onMounted } from 'vue';
|
|
207
|
+
import dayjs from 'dayjs';
|
|
208
|
+
import Gantt, {
|
|
209
|
+
type DataConfig,
|
|
210
|
+
type StyleConfig,
|
|
211
|
+
type EventConfig,
|
|
212
|
+
LinkType
|
|
213
|
+
} from '@lee576/vue3-gantt';
|
|
214
|
+
import '@lee576/vue3-gantt/style.css';
|
|
215
|
+
|
|
216
|
+
// 🎨 样式配置
|
|
204
217
|
const styleConfig = ref<StyleConfig>({
|
|
205
218
|
headersHeight: 100, // 表头高度
|
|
206
219
|
rowHeight: 60, // 行高
|
|
207
220
|
setBarColor: (row) => {
|
|
208
221
|
// 自定义任务条颜色
|
|
209
|
-
const colorMap = {
|
|
210
|
-
|
|
211
|
-
'重要': 'blue',
|
|
212
|
-
'一般': 'gray'
|
|
213
|
-
};
|
|
214
|
-
return colorMap[row.level] ?? 'black';
|
|
222
|
+
const colorMap = { '紧急': '#ef4444', '重要': '#3b82f6', '一般': '#6b7280' };
|
|
223
|
+
return colorMap[row.level] ?? '#000';
|
|
215
224
|
}
|
|
216
225
|
});
|
|
217
226
|
|
|
218
|
-
// 数据配置
|
|
227
|
+
// 📊 数据配置
|
|
219
228
|
const dataConfig = ref<DataConfig>({
|
|
220
|
-
queryStartDate: '',
|
|
221
|
-
queryEndDate: '',
|
|
229
|
+
queryStartDate: dayjs().startOf('month').format('YYYY-MM-DD'),
|
|
230
|
+
queryEndDate: dayjs().endOf('month').format('YYYY-MM-DD'),
|
|
222
231
|
dataSource: [],
|
|
223
232
|
dependencies: [],
|
|
224
233
|
mapFields: {
|
|
@@ -233,40 +242,35 @@ const dataConfig = ref<DataConfig>({
|
|
|
233
242
|
},
|
|
234
243
|
taskHeaders: [
|
|
235
244
|
{ title: '序号', width: 80, property: 'no', show: true },
|
|
236
|
-
{ title: '任务名称', width:
|
|
245
|
+
{ title: '任务名称', width: 200, property: 'task', show: true },
|
|
237
246
|
{ title: '优先级', width: 90, property: 'priority', show: true },
|
|
238
247
|
{ title: '开始时间', width: 150, property: 'startdate', show: true },
|
|
239
248
|
{ title: '结束时间', width: 150, property: 'enddate', show: true },
|
|
240
|
-
{ title: '耗时', width: 90, property: 'takestime', show: true }
|
|
241
249
|
]
|
|
242
250
|
});
|
|
243
251
|
|
|
244
|
-
// 事件配置
|
|
252
|
+
// ⚡ 事件配置
|
|
245
253
|
const eventConfig = ref<EventConfig>({
|
|
246
|
-
addRootTask: (row) => console.log('添加根任务', row),
|
|
247
|
-
addSubTask: (task) => console.log('添加子任务', task),
|
|
248
|
-
removeTask: (task) => console.log('删除任务', task),
|
|
249
|
-
editTask: (task) => console.log('编辑任务', task),
|
|
250
254
|
queryTask: async (startDate, endDate, mode) => {
|
|
251
255
|
// 查询任务数据
|
|
252
|
-
|
|
256
|
+
const tasks = await fetchTasks(startDate, endDate);
|
|
257
|
+
dataConfig.value.dataSource = tasks;
|
|
253
258
|
},
|
|
254
259
|
barDate: (id, startDate, endDate) => {
|
|
255
|
-
console.log('任务日期变更', id, startDate, endDate);
|
|
256
|
-
},
|
|
257
|
-
allowChangeTaskDate: (allow) => {
|
|
258
|
-
console.log('允许修改日期', allow);
|
|
260
|
+
console.log('任务日期变更', { id, startDate, endDate });
|
|
259
261
|
},
|
|
260
262
|
updateProgress: (detail) => {
|
|
261
263
|
console.log('进度更新', detail);
|
|
262
264
|
}
|
|
263
265
|
});
|
|
264
266
|
|
|
267
|
+
// 初始化加载数据
|
|
265
268
|
onMounted(() => {
|
|
266
|
-
const
|
|
267
|
-
const
|
|
268
|
-
eventConfig.value.queryTask(
|
|
269
|
+
const start = dayjs().startOf('month').format('YYYY-MM-DD');
|
|
270
|
+
const end = dayjs().endOf('month').format('YYYY-MM-DD');
|
|
271
|
+
eventConfig.value.queryTask?.(start, end, '月');
|
|
269
272
|
});
|
|
273
|
+
</script>
|
|
270
274
|
```
|
|
271
275
|
|
|
272
276
|
## 配置详解
|