Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mes-ui
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
周远喜
mes-ui
Commits
a6337052
Commit
a6337052
authored
May 09, 2020
by
仇晓婷
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
甘特图
parent
a5f4d12f
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
714 additions
and
0 deletions
+714
-0
gantt-header.vue
pages/order/components/gantt-header.vue
+325
-0
gantt.vue
pages/order/gantt.vue
+389
-0
No files found.
pages/order/components/gantt-header.vue
0 → 100644
View file @
a6337052
<!--
/**
* @fileoverview Header component
* @license MIT
* @author Rafal Pospiech <neuronet.io@gmail.com>
* @package GanttElasticHeader
*/
-->
<
template
>
<div
class=
"gantt-elastic__header"
:style=
"
{ ...style['header'] }">
<div
class=
"gantt-elastic__header-title"
:style=
"
{ ...style['header-title'] }">
<div
class=
"gantt-elastic__header-title--text"
:style=
"
{ ...style['header-title--text'] }"
v-if="!opts.title.html"
>
{{
opts
.
title
.
label
}}
</div>
<div
class=
"gantt-elastic__header-title--html"
:style=
"
{ ...style['header-title--html'] }"
v-if="opts.title.html"
v-html="opts.title.label"
>
</div>
</div>
<div
class=
"gantt-elastic__header-options"
:style=
"
{ ...style['header-options'] }">
<!--
<button
class=
"gantt-elastic__header-btn-recenter"
:style=
"
{ ...style['header-btn-recenter'] }"
@click.prevent="recenterPosition"
>
{{
opts
.
locale
.
Now
}}
</button>
-->
<label
class=
"gantt-elastic__header-label"
:style=
"
{ ...style['header-label'] }">
{{
opts
.
locale
[
"X-Scale"
]
}}
<div
class=
"gantt-elastic__header-slider-wrapper"
:style=
"
{ ...style['header-slider-wrapper'] }"
>
<vue-slider
class=
"gantt-elastic__header-slider"
tooltip=
"none"
:style=
"
{ ...style['header-slider'] }"
:process-style="{ ...style['header-slider--process'] }"
:slider-style="{ ...style['header-slider--slider'] }"
v-model="scale"
:max="24"
:min="2"
width="100px"
>
</vue-slider>
</div>
</label>
<label
class=
"gantt-elastic__header-label"
:style=
"
{ ...style['header-label'] }">
{{
opts
.
locale
[
"Y-Scale"
]
}}
<div
class=
"gantt-elastic__header-slider-wrapper"
:style=
"
{ ...style['header-slider-wrapper'] }"
>
<vue-slider
class=
"gantt-elastic__header-slider"
tooltip=
"none"
:style=
"
{ ...style['header-slider'] }"
:process-style="{ ...style['header-slider--process'] }"
:slider-style="{ ...style['header-slider--slider'] }"
v-model="height"
:max="100"
:min="7"
width="100px"
>
</vue-slider>
</div>
</label>
<label
class=
"gantt-elastic__header-label"
:style=
"
{ ...style['header-label'] }">
{{
opts
.
locale
[
"Before/After"
]
}}
<div
class=
"gantt-elastic__header-slider-wrapper"
:style=
"
{ ...style['header-slider-wrapper'] }"
>
<vue-slider
class=
"gantt-elastic__header-slider"
tooltip=
"none"
:style=
"
{ ...style['header-slider'] }"
:process-style="{ ...style['header-slider--process'] }"
:slider-style="{ ...style['header-slider--slider'] }"
v-model="scope"
:max="31"
:min="0"
width="100px"
>
</vue-slider>
</div>
</label>
<label
class=
"gantt-elastic__header-label"
:style=
"
{ ...style['header-label'] }">
{{
opts
.
locale
[
"Task list width"
]
}}
<div
class=
"gantt-elastic__header-slider-wrapper"
:style=
"
{ ...style['header-slider-wrapper'] }"
>
<vue-slider
class=
"gantt-elastic__header-slider"
tooltip=
"none"
:style=
"
{ ...style['header-slider'] }"
:process-style="{ ...style['header-slider--process'] }"
:slider-style="{ ...style['header-slider--slider'] }"
v-model="divider"
:max="100"
:min="0"
width="100px"
>
</vue-slider>
</div>
</label>
<label
class=
"gantt-elastic__header-task-list-switch--wrapper"
:style=
"
{ ...style['header-task-list-switch--label'] }"
>
<switches
class=
"gantt-elastic__header-task-list-switch"
:style=
"
{ ...style['header-task-list-switch'] }"
v-model="root.state.options.taskList.display"
>
</switches>
{{
opts
.
locale
[
"Display task list"
]
}}
</label>
</div>
</div>
</
template
>
<
script
>
import
vueSlider
from
"vue-slider-component"
;
import
"vue-slider-component/theme/default.css"
;
import
Switches
from
"vue-switches"
;
const
defaultStyle
=
{
header
:
{
margin
:
"0px auto"
,
background
:
"#f3f5f747"
,
padding
:
"10px"
,
overflow
:
"hidden"
,
clear
:
"both"
,
display
:
"flex"
,
"justify-content"
:
"space-between"
},
"header-title"
:
{
float
:
"left"
},
"header-options"
:
{
float
:
"right"
},
"header-title--text"
:
{
"font-size"
:
"20px"
,
"vertical-align"
:
"middle"
,
"font-weight"
:
"400"
,
"line-height"
:
"35px"
,
"padding-left"
:
"22px"
,
"letter-spacing"
:
"1px"
},
"header-title--html"
:
{
"font-size"
:
"20px"
,
"vertical-align"
:
"middle"
,
"font-weight"
:
"400"
,
"line-height"
:
"35px"
,
"padding-left"
:
"22px"
,
"letter-spacing"
:
"1px"
},
"header-btn-recenter"
:
{
background
:
"#95A5A6"
,
border
:
"none"
,
outline
:
"none"
,
cursor
:
"pointer"
,
color
:
"white"
,
"border-radius"
:
"3px"
,
"margin-right"
:
"27px"
,
"font-size"
:
"16px"
,
padding
:
"8px 12px"
},
"header-slider"
:
{
"box-sizing"
:
"content-box"
},
"header-slider-wrapper"
:
{
display
:
"inline-block"
,
"vertical-align"
:
"middle"
},
"header-slider--slider"
:
{
"box-sizing"
:
"content-box"
},
"header-slider--process"
:
{
"box-sizing"
:
"content-box"
},
"header-task-list-switch--label"
:
{
"box-sizing"
:
"content-box"
},
"header-task-list-switch"
:
{
margin
:
"0px 15px"
,
"vertical-align"
:
"middle"
},
"header-label"
:
{}
};
const
defaultOptions
=
{
title
:
{
label
:
"任务甘特图"
,
html
:
false
},
locale
:
{
Now
:
"Now"
,
"X-Scale"
:
"缩放-X"
,
"Y-Scale"
:
"缩放-Y"
,
"Task list width"
:
"任务列表"
,
"Before/After"
:
"展开日期"
,
"Display task list"
:
"是否展开任务列表"
}
};
export
default
{
name
:
"GanttHeader"
,
components
:
{
vueSlider
,
Switches
},
props
:
[
"options"
,
"dynamicStyle"
],
inject
:
[
"root"
],
data
()
{
return
{
scaleTimeoutId
:
null
,
firstScale
:
false
,
localScale
:
0
,
localHeight
:
0
,
localBefore
:
0
,
localPercent
:
0
,
sliderOptions
:
{
xScale
:
{
value
:
0
}
},
style
:
{},
opts
:
{}
};
},
created
()
{
this
.
localScale
=
this
.
root
.
state
.
options
.
times
.
timeZoom
;
this
.
localHeight
=
this
.
root
.
state
.
options
.
row
.
height
;
this
.
localBefore
=
this
.
root
.
state
.
options
.
scope
.
before
;
this
.
localPercent
=
this
.
root
.
state
.
options
.
taskList
.
percent
;
this
.
sliderOptions
.
xScale
.
value
=
this
.
root
.
state
.
options
.
times
.
timeZoom
;
this
.
style
=
this
.
root
.
mergeDeep
({},
defaultStyle
,
this
.
dynamicStyle
);
this
.
opts
=
this
.
root
.
mergeDeep
({},
defaultOptions
,
this
.
options
);
},
methods
:
{
getImage
()
{
this
.
root
.
getImage
(
"image/png"
).
then
(
imgB64
=>
{
const
link
=
document
.
createElement
(
"a"
);
link
.
href
=
imgB64
;
link
.
download
=
"gantt-elastic.png"
;
document
.
body
.
appendChild
(
link
);
link
.
click
();
document
.
body
.
removeChild
(
link
);
});
},
recenterPosition
()
{
this
.
root
.
$emit
(
"recenterPosition"
);
},
setScale
(
value
)
{
if
(
this
.
scaleTimeoutId
!==
null
)
{
clearTimeout
(
this
.
scaleTimeoutId
);
this
.
scaleTimeoutId
=
null
;
}
// debouncing
if
(
this
.
firstScale
)
{
this
.
scaleTimeoutId
=
setTimeout
(()
=>
{
this
.
root
.
$emit
(
"times-timeZoom-change"
,
value
);
this
.
scaleTimeoutId
=
null
;
},
50
);
}
else
{
this
.
root
.
$emit
(
"times-timeZoom-change"
,
value
);
this
.
firstScale
=
true
;
}
}
},
computed
:
{
/**
* If there is a component slot specified for header
* @returns {bool}
*/
beforeOptionsIsComponent
()
{
const
headerSlot
=
this
.
options
.
slots
.
header
;
if
(
typeof
headerSlot
.
beforeOptions
===
"object"
&&
!
Array
.
isArray
(
headerSlot
.
beforeOptions
)
)
{
return
true
;
}
return
false
;
},
/**
* If there is a slot with beforeOptions html content
* @returns {bool}
*/
beforeOptionsIsHtml
()
{
if
(
typeof
this
.
options
.
slots
.
header
.
beforeOptions
===
"string"
)
{
return
true
;
}
return
false
;
},
scale
:
{
get
()
{
return
this
.
localScale
;
},
set
(
value
)
{
this
.
localScale
=
Number
(
value
);
this
.
setScale
(
this
.
localScale
);
}
},
height
:
{
get
()
{
return
this
.
localHeight
;
},
set
(
value
)
{
this
.
localHeight
=
Number
(
value
);
this
.
root
.
$emit
(
"row-height-change"
,
Number
(
value
));
}
},
scope
:
{
get
()
{
return
this
.
localBefore
;
},
set
(
value
)
{
this
.
localBefore
=
Number
(
value
);
this
.
root
.
$emit
(
"scope-change"
,
Number
(
value
));
}
},
divider
:
{
get
()
{
return
this
.
localPercent
;
},
set
(
value
)
{
this
.
localPercent
=
Number
(
value
);
this
.
root
.
$emit
(
"taskList-width-change"
,
Number
(
value
));
}
}
}
};
</
script
>
pages/order/gantt.vue
0 → 100644
View file @
a6337052
<
template
>
<div
class=
"q-pa-sm"
>
<gantt-elastic
:options=
"options"
:tasks=
"tasks"
@
tasks-changed=
"tasksUpdate"
@
options-changed=
"optionsUpdate"
@
dynamic-style-changed=
"styleUpdate"
>
<gantt-header
slot=
"header"
></gantt-header>
</gantt-elastic>
<div
class=
"q-mt-md"
/>
<!--
<q-btn
@
click=
"addTask"
icon=
"mdi-plus"
label=
"Add task"
/>
-->
</div>
</
template
>
<
style
>
</
style
>
<
script
>
import
GanttElastic
from
"gantt-elastic"
;
import
GanttHeader
from
"./components/gantt-header"
;
import
dayjs
from
"dayjs"
;
// just helper to get current dates
function
getDate
(
hours
)
{
const
currentDate
=
new
Date
();
const
currentYear
=
currentDate
.
getFullYear
();
const
currentMonth
=
currentDate
.
getMonth
();
const
currentDay
=
currentDate
.
getDate
();
const
timeStamp
=
new
Date
(
currentYear
,
currentMonth
,
currentDay
,
0
,
0
,
0
).
getTime
();
return
new
Date
(
timeStamp
+
hours
*
60
*
60
*
1000
).
getTime
();
}
let
tasks
=
[
{
id
:
1
,
label
:
"任务1"
,
user
:
'<a href="https://www.google.com/search?q=John+Doe" target="_blank" style="color:#0077c0;">John Doe</a>'
,
start
:
getDate
(
-
24
*
5
),
duration
:
15
*
24
*
60
*
60
*
1000
,
percent
:
85
,
type
:
"project"
//collapsed: true,
},
{
id
:
2
,
label
:
"任务2"
,
user
:
'<a href="https://www.google.com/search?q=Peter+Parker" target="_blank" style="color:#0077c0;">Peter Parker</a>'
,
parentId
:
1
,
start
:
getDate
(
-
24
*
4
),
duration
:
4
*
24
*
60
*
60
*
1000
,
percent
:
50
,
type
:
"milestone"
,
collapsed
:
true
,
style
:
{
base
:
{
fill
:
"#1EBC61"
,
stroke
:
"#0EAC51"
}
}
},
{
id
:
3
,
label
:
"任务3"
,
user
:
'<a href="https://www.google.com/search?q=John+Wayne" target="_blank" style="color:#0077c0;">John Wayne</a>'
,
parentId
:
2
,
start
:
getDate
(
-
24
*
3
),
duration
:
2
*
24
*
60
*
60
*
1000
,
percent
:
100
,
type
:
"task"
},
{
id
:
4
,
label
:
"任务4"
,
user
:
'<a href="https://www.google.com/search?q=Clark+Kent" target="_blank" style="color:#0077c0;">Clark Kent</a>'
,
start
:
getDate
(
-
24
*
2
),
duration
:
2
*
24
*
60
*
60
*
1000
,
percent
:
50
,
type
:
"task"
,
dependentOn
:
[
3
]
},
{
id
:
5
,
label
:
"任务5"
,
user
:
'<a href="https://www.google.com/search?q=Austin+Powers" target="_blank" style="color:#0077c0;">Austin Powers</a>'
,
parentId
:
4
,
start
:
getDate
(
0
),
duration
:
2
*
24
*
60
*
60
*
1000
,
percent
:
10
,
type
:
"milestone"
,
style
:
{
base
:
{
fill
:
"#0287D0"
,
stroke
:
"#0077C0"
}
}
},
{
id
:
6
,
label
:
"任务6"
,
user
:
'<a href="https://www.google.com/search?q=Mario+Bros" target="_blank" style="color:#0077c0;">Mario Bros</a>'
,
parentId
:
5
,
start
:
getDate
(
24
),
duration
:
1
*
24
*
60
*
60
*
1000
,
percent
:
50
,
type
:
"task"
,
collapsed
:
true
,
style
:
{
base
:
{
fill
:
"#8E44AD"
,
stroke
:
"#7E349D"
}
}
},
{
id
:
7
,
label
:
"任务7"
,
user
:
'<a href="https://www.google.com/search?q=Knight+Rider" target="_blank" style="color:#0077c0;">Knight Rider</a>'
,
parentId
:
2
,
dependentOn
:
[
6
],
start
:
getDate
(
24
*
2
),
duration
:
4
*
60
*
60
*
1000
,
percent
:
20
,
type
:
"task"
,
collapsed
:
true
},
{
id
:
8
,
label
:
"任务8"
,
user
:
'<a href="https://www.google.com/search?q=Johhny+Bravo" target="_blank" style="color:#0077c0;">Johhny Bravo</a>'
,
parentId
:
7
,
dependentOn
:
[
7
],
start
:
getDate
(
24
*
3
),
duration
:
1
*
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
},
{
id
:
9
,
label
:
"任务9"
,
user
:
'<a href="https://www.google.com/search?q=Dexter
\'
s+Laboratory" target="_blank" style="color:#0077c0;">Dexter
\'
s Laboratory</a>'
,
parentId
:
8
,
dependentOn
:
[
8
,
7
],
start
:
getDate
(
24
*
4
),
duration
:
4
*
60
*
60
*
1000
,
percent
:
20
,
type
:
"task"
,
style
:
{
base
:
{
fill
:
"#8E44AD"
,
stroke
:
"#7E349D"
}
}
},
{
id
:
10
,
label
:
"任务10"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
5
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
},
{
id
:
11
,
label
:
"任务11"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
6
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
},
{
id
:
12
,
label
:
"任务12"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
7
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
,
parentId
:
11
},
{
id
:
13
,
label
:
"任务13"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
8
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
},
{
id
:
14
,
label
:
"任务14"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
9
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
},
{
id
:
15
,
label
:
"任务15"
,
user
:
'<a href="https://www.google.com/search?q=Johnattan+Owens" target="_blank" style="color:#0077c0;">Johnattan Owens</a>'
,
start
:
getDate
(
24
*
16
),
duration
:
24
*
60
*
60
*
1000
,
percent
:
0
,
type
:
"task"
}
];
let
options
=
{
taskMapping
:
{
progress
:
"percent"
},
maxRows
:
100
,
maxHeight
:
500
,
title
:
{
label
:
"Your project title as html (link or whatever...)"
,
html
:
false
},
row
:
{
height
:
24
},
calendar
:
{
hour
:
{
display
:
false
}
},
chart
:
{
progress
:
{
bar
:
false
},
expander
:
{
display
:
true
}
},
taskList
:
{
expander
:
{
straight
:
false
},
columns
:
[
{
id
:
1
,
label
:
"ID"
,
value
:
"id"
,
width
:
40
},
{
id
:
2
,
label
:
"任务"
,
value
:
"label"
,
width
:
200
,
expander
:
true
,
html
:
true
,
events
:
{
click
({
data
,
column
})
{
alert
(
"description clicked!
\n
"
+
data
.
label
);
}
}
},
{
id
:
3
,
label
:
"责任人"
,
value
:
"user"
,
width
:
130
,
html
:
true
},
{
id
:
3
,
label
:
"开始时间"
,
value
:
task
=>
dayjs
(
task
.
start
).
format
(
"YYYY-MM-DD"
),
width
:
78
},
{
id
:
4
,
label
:
"类型"
,
value
:
"type"
,
width
:
68
},
{
id
:
5
,
label
:
"%"
,
value
:
"progress"
,
width
:
35
,
style
:
{
"task-list-header-label"
:
{
"text-align"
:
"center"
,
width
:
"100%"
},
"task-list-item-value-container"
:
{
"text-align"
:
"center"
,
width
:
"100%"
}
}
}
]
},
locale
:
{
weekdays
:
[
"周日"
,
"周一"
,
"周二"
,
"周三"
,
"周四"
,
"周五"
,
"周六"
],
months
:
[
"一月"
,
"二月"
,
"三月"
,
"四月"
,
"五月"
,
"六月"
,
"七月"
,
"八月"
,
"九月"
,
"十月"
,
"十一月"
,
"十二月"
],
// name: "en",
// Now: "Now",
// "X-Scale": "Zoom-X",
// "Y-Scale": "Zoom-Y",
// "Task list width": "Task list",
// "Before/After": "Expand",
// "Display task list": "Task list"
}
};
export
default
{
name
:
"Gantt"
,
components
:
{
GanttElastic
,
GanttHeader
},
data
()
{
return
{
tasks
,
options
,
dynamicStyle
:
{},
lastId
:
16
};
},
methods
:
{
addTask
()
{
this
.
tasks
.
push
({
id
:
this
.
lastId
++
,
label
:
'<a href="https://images.pexels.com/photos/423364/pexels-photo-423364.jpeg?auto=compress&cs=tinysrgb&h=650&w=940" target="_blank" style="color:#0077c0;">Yeaahh! you have added a task bro!</a>'
,
user
:
'<a href="https://images.pexels.com/photos/423364/pexels-photo-423364.jpeg?auto=compress&cs=tinysrgb&h=650&w=940" target="_blank" style="color:#0077c0;">Awesome!</a>'
,
start
:
getDate
(
24
*
3
),
duration
:
1
*
24
*
60
*
60
*
1000
,
percent
:
50
,
type
:
"project"
});
},
tasksUpdate
(
tasks
)
{
this
.
tasks
=
tasks
;
},
optionsUpdate
(
options
)
{
this
.
options
=
options
;
},
styleUpdate
(
style
)
{
this
.
dynamicStyle
=
style
;
}
}
};
</
script
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment