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
e9f103ea
Commit
e9f103ea
authored
Nov 16, 2020
by
周远喜
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ok
parent
d7038a49
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
571 additions
and
17 deletions
+571
-17
userGroup.vue
components/page/userGroup.vue
+3
-0
gantt-header.vue
pages/project/plan/components/gantt-header.vue
+325
-0
gant.vue
pages/project/plan/gant.vue
+215
-0
detail.vue
pages/project/project/detail.vue
+19
-11
add.vue
pages/project/task/add.vue
+4
-3
index.vue
pages/project/task/index.vue
+5
-3
No files found.
components/page/userGroup.vue
View file @
e9f103ea
...
...
@@ -96,6 +96,9 @@ export default {
this
.
load
();
}
},
value
(
v
){
this
.
name
=
v
;
}
},
};
</
script
>
...
...
pages/project/plan/components/gantt-header.vue
0 → 100644
View file @
e9f103ea
<!--
/**
* @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/project/plan/gant.vue
0 → 100644
View file @
e9f103ea
<
template
>
<div
class=
"q-pa-sm"
>
<div
class=
"pr mt50"
v-if=
"tasks.length == 0"
>
<Spin
size=
"large"
fix
></Spin>
</div>
<gantt-elastic
v-else
: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"
/>
</div>
</
template
>
<
style
>
</
style
>
<
script
>
import
GanttElastic
from
"gantt-elastic"
;
import
GanttHeader
from
"./components/gantt-header"
;
import
dayjs
from
"dayjs"
;
import
Api
from
"./api"
;
function
GetTimeByTimeStr
(
dateString
)
{
if
(
dateString
){
var
timeArr
=
dateString
.
split
(
" "
);
var
d
=
timeArr
[
0
].
split
(
"-"
);
var
t
=
timeArr
[
1
].
split
(
":"
);
return
new
Date
(
d
[
0
],
d
[
1
]
-
1
,
d
[
2
],
t
[
0
],
t
[
1
],
t
[
2
]).
getTime
();
}
else
{
return
0
;
}
}
let
that
;
export
default
{
name
:
"Gantt"
,
components
:
{
GanttElastic
,
GanttHeader
,
},
props
:
{
eid
:
String
,
},
data
()
{
return
{
tasks
:
[],
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
:
true
,
},
},
chart
:
{
progress
:
{
bar
:
false
,
},
expander
:
{
display
:
true
,
},
},
taskList
:
{
expander
:
{
straight
:
false
,
},
columns
:
[
// {
// id: 1,
// label: "ID",
// value: "id",
// width: 40,
// },
{
id
:
2
,
label
:
"名称"
,
value
:
v
=>
{
return
`<a>
${
v
.
name
}
</a>`
},
width
:
200
,
expander
:
true
,
html
:
true
,
events
:
{
click
({
data
,
column
})
{
alert
(
data
.
name
);
console
.
log
(
this
)
that
.
$Message
.
info
(
data
.
name
)
},
},
},
{
id
:
3
,
label
:
"状态"
,
value
:
"status"
,
width
:
100
,
html
:
true
,
events
:
{
click
(
e
)
{
console
.
log
(
e
)
that
.
$Message
.
info
(
e
.
data
.
name
)
},
},
},
{
id
:
4
,
label
:
"计划开始时间"
,
// value: 'startDate',
value
:
(
task
)
=>
dayjs
(
task
.
startDate
).
format
(
"YYYY-MM-DD"
),
width
:
160
,
},
{
id
:
5
,
label
:
"计划结束时间"
,
// value:'endDate',
value
:
(
task
)
=>
dayjs
(
task
.
endDate
).
format
(
"YYYY-MM-DD"
),
width
:
180
,
},
{
id
:
6
,
label
:
"计划类型"
,
value
:
"type"
,
width
:
80
,
}
],
},
locale
:
{
weekdays
:
[
"周日"
,
"周一"
,
"周二"
,
"周三"
,
"周四"
,
"周五"
,
"周六"
],
months
:
[
"一月"
,
"二月"
,
"三月"
,
"四月"
,
"五月"
,
"六月"
,
"七月"
,
"八月"
,
"九月"
,
"十月"
,
"十一月"
,
"十二月"
,
],
},
},
dynamicStyle
:
{},
lastId
:
16
,
};
},
created
()
{
that
=
this
;
this
.
gantData
();
},
methods
:
{
gantData
()
{
var
params
=
{
conditions
:
[
{
fieldName
:
"projectId"
,
conditionalType
:
"Equal"
,
fieldValue
:
this
.
eid
,
},
],
};
Api
.
list
(
params
).
then
((
r
)
=>
{
let
tasks
=
r
.
result
;
var
types
=
[
"project"
,
"milestone"
,
"task"
]
tasks
=
tasks
.
map
(
u
=>
{
var
obj
=
{
id
:
u
.
id
,
parentId
:
u
.
upId
,
name
:
u
.
title
,
startDate
:
u
.
startDate
,
endDate
:
u
.
endDate
,
start
:
GetTimeByTimeStr
(
u
.
startDate
),
duration
:
GetTimeByTimeStr
(
u
.
endDate
)
-
GetTimeByTimeStr
(
u
.
startDate
)
,
percent
:
85
,
status
:
u
.
status
,
type
:
types
[
u
.
type
],
};
return
obj
;
})
this
.
tasks
=
tasks
;
});
},
tasksUpdate
(
tasks
)
{
this
.
tasks
=
tasks
;
},
optionsUpdate
(
options
)
{
this
.
options
=
options
;
},
styleUpdate
(
style
)
{
this
.
dynamicStyle
=
style
;
},
},
};
</
script
>
pages/project/project/detail.vue
View file @
e9f103ea
...
...
@@ -12,8 +12,14 @@
<DateRange
v-model=
"entity"
/>
</Filed>
<Filed
:span=
"24"
:name=
"l('users') + ':'"
>
<User
v-for=
"(u,i) in users"
:value=
"u.userId"
:key=
"u.userId"
mode=
"text"
class=
"mr10"
/>
<a
@
click=
"group"
><Avatar
icon=
"md-add"
/></a>
<User
v-for=
"(u, i) in users"
:value=
"u.userId"
:key=
"u.userId"
mode=
"text"
class=
"mr10"
/>
<a
@
click=
"group"
><Avatar
icon=
"md-add"
/></a>
</Filed>
</Row>
</div>
...
...
@@ -35,10 +41,15 @@
<span>
|
</span>
</li>
<li>
<a
@
click=
"
task
"
>
<Icon
type=
"ios-list-box"
size=
"18"
/>
任务监控
</a>
<a
@
click=
"
gant
"
>
<Icon
type=
"ios-list-box"
size=
"18"
/>
任务监控
</a>
<span>
|
</span>
</li>
<!--
<li>
<a
@
click=
"task"
>
<Icon
type=
"ios-list-box"
size=
"18"
/>
任务监控
</a>
<span>
|
</span>
</li>
-->
<li>
<a
@
click=
"group"
>
<Icon
type=
"ios-people"
size=
"18"
/>
成员
</a>
...
...
@@ -75,7 +86,7 @@ export default {
curId
:
this
.
eid
,
avatorPath
:
""
,
entity
:
{},
users
:[],
users
:
[],
rules
:
{
name
:
[
{
...
...
@@ -129,15 +140,12 @@ export default {
this
.
detail
=
()
=>
import
(
"../plan"
);
},
task
()
{
//this.curId = this.eid;
this
.
title
=
"任务"
;
this
.
detail
=
()
=>
import
(
"../task/index"
);
// this.$router.push({
// name: "project-task",
// params: {
// id: this.curId
// }
// });
},
gant
()
{
this
.
title
=
"任务监控"
;
this
.
detail
=
()
=>
import
(
"../plan/gant"
);
},
group
()
{
this
.
title
=
"项目成员"
;
...
...
pages/project/task/add.vue
View file @
e9f103ea
...
...
@@ -12,7 +12,7 @@
</Col>
<Col
:span=
"12"
>
<FormItem
:label=
"l('userId')"
prop=
"userId"
>
<UserGroup
v-model=
"entity.userId"
:projectId=
"
ei
d"
/>
<UserGroup
v-model=
"entity.userId"
:projectId=
"
projectI
d"
/>
</FormItem>
</Col>
<Col
:span=
"12"
>
...
...
@@ -75,8 +75,9 @@ export default {
},
props
:
{
v
:
Object
,
eid
:
String
,
pid
:
String
,
eid
:
String
,
//当前id
pid
:
String
,
//计划id
projectId
:
String
,
//项目id
},
mounted
()
{
// if (this.eid != '' && this.eid != null) {
...
...
pages/project/task/index.vue
View file @
e9f103ea
...
...
@@ -61,7 +61,7 @@
</
template
>
</DataGrid>
<Modal
v-model=
"modal"
:title=
"title"
width=
"1200"
:fullscreen=
"fullScreen"
footer-hide
>
<component
:is=
"detail"
:eid=
"curId"
:pid=
"planId"
:row=
"rowObj"
@
on-close=
"cancel"
@
on-ok=
"ok"
/>
<component
:is=
"detail"
:eid=
"curId"
:pid=
"planId"
:
projectId=
"projectId"
:
row=
"rowObj"
@
on-close=
"cancel"
@
on-ok=
"ok"
/>
</Modal>
</Content>
</Layout>
...
...
@@ -109,7 +109,7 @@ export default {
rowObj
:
null
,
curId
:
''
,
fullScreen
:
false
,
projectId
:
''
,
projectId
:
this
.
eid
,
columns
:
[
// {
// key: "selection",
...
...
@@ -407,6 +407,7 @@ export default {
},
productSearch
(
id
,
item
,
planIds
)
{
this
.
planId
=
item
.
selected
?
id
:
''
;
this
.
projectId
=
item
.
projectId
;
this
.
planIdsCur
=
item
.
selected
?
planIds
:
[]
let
where
=
{
planId
:
{
...
...
@@ -415,9 +416,10 @@ export default {
},
projectId
:
{
op
:
"Equal"
,
value
:
this
.
ei
d
value
:
item
.
projectI
d
},
};
this
.
curId
=
this
.
$refs
.
grid
.
reload
(
where
);
},
updatepart
(
valId
,
valStatus
)
{
...
...
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