mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-13 03:52:50 +00:00
perf: 优化仪表盘使用sticky方式
This commit is contained in:
parent
8e0a684a9a
commit
e969b5b7e4
@ -5,72 +5,78 @@
|
||||
<div class="dashboard-hello">{{$L('欢迎您,' + userInfo.nickname)}}</div>
|
||||
<div class="dashboard-desc">{{$L('以下是你当前的任务统计数据')}}</div>
|
||||
<ul class="dashboard-block">
|
||||
<li @click="dashboard='today'">
|
||||
<div class="block-title">{{$L('今日待完成')}}</div>
|
||||
<li @click="scrollTo('today')">
|
||||
<div class="block-title">{{getTitle('today')}}</div>
|
||||
<div class="block-data">
|
||||
<div class="block-num">{{dashboardTask.today.length}}</div>
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li @click="dashboard='overdue'">
|
||||
<div class="block-title">{{$L('超期未完成')}}</div>
|
||||
<li @click="scrollTo('overdue')">
|
||||
<div class="block-title">{{getTitle('overdue')}}</div>
|
||||
<div class="block-data">
|
||||
<div class="block-num">{{dashboardTask.overdue.length}}</div>
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
</li>
|
||||
<li @click="dashboard='all'">
|
||||
<div class="block-title">{{$L('待完成任务')}}</div>
|
||||
<li @click="scrollTo('all')">
|
||||
<div class="block-title">{{getTitle('all')}}</div>
|
||||
<div class="block-data">
|
||||
<div class="block-num">{{dashboardTask.all.length}}</div>
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<template v-if="list.length > 0">
|
||||
<div class="dashboard-title">{{title}}</div>
|
||||
<ul class="dashboard-list overlay-y">
|
||||
<li
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:class="{complete: item.complete_at}"
|
||||
:style="item.color ? {backgroundColor: item.color} : {}"
|
||||
@click="openTask(item)">
|
||||
<em
|
||||
v-if="item.p_name"
|
||||
class="priority-color"
|
||||
:style="{backgroundColor:item.p_color}"></em>
|
||||
<TaskMenu :ref="`taskMenu_${item.id}`" :task="item">
|
||||
<div slot="icon" class="drop-icon" @click.stop="">
|
||||
<i class="taskfont" v-html="item.complete_at ? '' : ''"></i>
|
||||
<div class="dashboard-list overlay-y">
|
||||
<div
|
||||
:ref="`type_${column.type}`"
|
||||
v-for="(column, index) in columns"
|
||||
v-if="column.list.length > 0"
|
||||
:key="index">
|
||||
<div class="dashboard-title">{{column.title}}</div>
|
||||
<ul class="dashboard-li">
|
||||
<li
|
||||
v-for="(item, index) in column.list"
|
||||
:key="index"
|
||||
:class="{complete: item.complete_at}"
|
||||
:style="item.color ? {backgroundColor: item.color} : {}"
|
||||
@click="openTask(item)">
|
||||
<em
|
||||
v-if="item.p_name"
|
||||
class="priority-color"
|
||||
:style="{backgroundColor:item.p_color}"></em>
|
||||
<TaskMenu :ref="`taskMenu_${item.id}`" :task="item">
|
||||
<div slot="icon" class="drop-icon" @click.stop="">
|
||||
<i class="taskfont" v-html="item.complete_at ? '' : ''"></i>
|
||||
</div>
|
||||
</TaskMenu>
|
||||
<div class="item-title">
|
||||
<!--工作流状态-->
|
||||
<span v-if="item.flow_item_name" :class="item.flow_item_status" @click.stop="openMenu(item)">{{item.flow_item_name}}</span>
|
||||
<!--是否子任务-->
|
||||
<span v-if="item.sub_top === true">{{$L('子任务')}}</span>
|
||||
<!--有多少个子任务-->
|
||||
<span v-if="item.sub_my && item.sub_my.length > 0">+{{item.sub_my.length}}</span>
|
||||
<!--任务描述-->
|
||||
{{item.name}}
|
||||
</div>
|
||||
</TaskMenu>
|
||||
<div class="item-title">
|
||||
<!--工作流状态-->
|
||||
<span v-if="item.flow_item_name" :class="item.flow_item_status" @click.stop="openMenu(item)">{{item.flow_item_name}}</span>
|
||||
<!--是否子任务-->
|
||||
<span v-if="item.sub_top === true">{{$L('子任务')}}</span>
|
||||
<!--有多少个子任务-->
|
||||
<span v-if="item.sub_my && item.sub_my.length > 0">+{{item.sub_my.length}}</span>
|
||||
<!--任务描述-->
|
||||
{{item.name}}
|
||||
</div>
|
||||
<div v-if="item.desc" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
<div v-if="item.sub_num > 0" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{item.sub_complete}}/{{item.sub_num}}</em>
|
||||
</div>
|
||||
<ETooltip v-if="item.end_at" :content="item.end_at" placement="right">
|
||||
<div :class="['item-icon', item.today ? 'today' : '', item.overdue ? 'overdue' : '']">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{expiresFormat(item.end_at)}}</em>
|
||||
<div v-if="item.desc" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
</div>
|
||||
</ETooltip>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<div v-if="item.sub_num > 0" class="item-icon">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{item.sub_complete}}/{{item.sub_num}}</em>
|
||||
</div>
|
||||
<ETooltip v-if="item.end_at" :content="item.end_at" placement="right">
|
||||
<div :class="['item-icon', item.today ? 'today' : '', item.overdue ? 'overdue' : '']">
|
||||
<i class="taskfont"></i>
|
||||
<em>{{expiresFormat(item.end_at)}}</em>
|
||||
</div>
|
||||
</ETooltip>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -110,13 +116,34 @@ export default {
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState(['userInfo', 'cacheProjects', 'taskId']),
|
||||
...mapState(['userInfo']),
|
||||
|
||||
...mapGetters(['dashboardTask', 'transforTasks']),
|
||||
|
||||
title() {
|
||||
const {dashboard} = this;
|
||||
switch (dashboard) {
|
||||
columns() {
|
||||
let list = [];
|
||||
['today', 'overdue', 'all'].some(type => {
|
||||
let data = this.transforTasks(this.dashboardTask[type]);
|
||||
list.push({
|
||||
type,
|
||||
title: this.getTitle(type),
|
||||
list: data.sort((a, b) => {
|
||||
return $A.Date(a.end_at || "2099-12-31 23:59:59") - $A.Date(b.end_at || "2099-12-31 23:59:59");
|
||||
})
|
||||
})
|
||||
})
|
||||
return list;
|
||||
},
|
||||
|
||||
total() {
|
||||
const {dashboardTask} = this;
|
||||
return dashboardTask.today.length + dashboardTask.overdue.length + dashboardTask.all.length;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
getTitle(type) {
|
||||
switch (type) {
|
||||
case 'today':
|
||||
return this.$L('今日任务');
|
||||
case 'overdue':
|
||||
@ -128,27 +155,20 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
list() {
|
||||
const {dashboard} = this;
|
||||
let data = [];
|
||||
switch (dashboard) {
|
||||
case 'today':
|
||||
data = this.transforTasks(this.dashboardTask.today);
|
||||
break
|
||||
case 'overdue':
|
||||
data = this.transforTasks(this.dashboardTask.overdue);
|
||||
break
|
||||
case 'all':
|
||||
data = this.transforTasks(this.dashboardTask.all);
|
||||
break
|
||||
scrollTo(type) {
|
||||
try {
|
||||
this.$refs[`type_${type}`][0].scrollIntoView({
|
||||
behavior: 'instant',
|
||||
inline: 'end',
|
||||
});
|
||||
} catch (e) {
|
||||
scrollIntoView(this.$refs[`type_${type}`][0], {
|
||||
behavior: 'instant',
|
||||
inline: 'end',
|
||||
})
|
||||
}
|
||||
return data.sort((a, b) => {
|
||||
return $A.Date(a.end_at || "2099-12-31 23:59:59") - $A.Date(b.end_at || "2099-12-31 23:59:59");
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
openTask(task) {
|
||||
this.$store.dispatch("openTask", task)
|
||||
},
|
||||
|
||||
277
resources/assets/sass/pages/page-dashboard.scss
vendored
277
resources/assets/sass/pages/page-dashboard.scss
vendored
@ -5,13 +5,22 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #ffffff;
|
||||
.dashboard-wrapper {
|
||||
width: 664px;
|
||||
max-width: 80%;
|
||||
width: 100%;
|
||||
max-height: 80%;
|
||||
margin-bottom: 2%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.dashboard-hello,
|
||||
.dashboard-desc ,
|
||||
.dashboard-block ,
|
||||
.dashboard-list .dashboard-title,
|
||||
.dashboard-list .dashboard-li {
|
||||
width: 660px;
|
||||
max-width: 80%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.dashboard-hello {
|
||||
padding: 0 12px;
|
||||
color: #333333;
|
||||
@ -41,10 +50,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.3s;
|
||||
&:hover {
|
||||
box-shadow: 0 0 10px #cccccc;
|
||||
}
|
||||
transition: transform 0.5s ease-out 0s, box-shadow 0.3s ease-out 0s;
|
||||
&:first-child {
|
||||
background-color: #6f9ef6;
|
||||
}
|
||||
@ -52,6 +58,16 @@
|
||||
background-color: #98de6e;
|
||||
margin-right: 0;
|
||||
}
|
||||
&:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 2px 10px 0 #fa8e8c;
|
||||
&:first-child {
|
||||
box-shadow: 0 2px 10px 0 #6f9ef6;
|
||||
}
|
||||
&:last-child {
|
||||
box-shadow: 0 2px 10px 0 #98de6e;
|
||||
}
|
||||
}
|
||||
.block-title {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-size: 12px;
|
||||
@ -74,114 +90,130 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.dashboard-title {
|
||||
margin-top: 60px;
|
||||
padding: 0 12px;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
}
|
||||
.dashboard-list {
|
||||
margin-top: 4px;
|
||||
padding: 0 12px;
|
||||
width: 100%;
|
||||
margin-top: 48px;
|
||||
overflow: auto;
|
||||
> li {
|
||||
position: relative;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
background: #F9FAFB;
|
||||
margin-top: 12px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.3s;
|
||||
&:hover {
|
||||
box-shadow: 0 0 6px #dfdfdf;
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
&.complete {
|
||||
.dashboard-title {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
margin: 0 auto;
|
||||
padding: 0 12px;
|
||||
height: 46px;
|
||||
line-height: 46px;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
.dashboard-li {
|
||||
margin: 0 auto;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
> li {
|
||||
position: relative;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
background: #F9FAFB;
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.3s,transform 0.2s;
|
||||
border-bottom: 1px solid #f1f2f4;
|
||||
&:hover {
|
||||
transform: translateX(-2px);
|
||||
}
|
||||
&:first-child {
|
||||
border-top-right-radius: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
&:last-child {
|
||||
border-bottom-right-radius: 6px;
|
||||
border-bottom-left-radius: 6px;
|
||||
border-bottom: 0;
|
||||
}
|
||||
&.complete {
|
||||
.item-title {
|
||||
opacity: 0.5;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.item-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.priority-color {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 0;
|
||||
height: 12px;
|
||||
width: 2px;
|
||||
}
|
||||
.el-dropdown {
|
||||
flex-shrink: 0;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
.taskfont {
|
||||
color: #bbbbbb;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
.item-title {
|
||||
opacity: 0.5;
|
||||
text-decoration: line-through;
|
||||
flex: 1;
|
||||
padding-left: 6px;
|
||||
line-height: 22px;
|
||||
> span {
|
||||
font-size: 12px;
|
||||
height: 18px;
|
||||
min-width: 20px;
|
||||
line-height: 16px;
|
||||
padding: 0 2px;
|
||||
border-radius: 3px;
|
||||
color: #8bcf70;
|
||||
border: 1px solid #8bcf70;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 3px;
|
||||
margin-right: 3px;
|
||||
text-align: center;
|
||||
&.start {
|
||||
background-color: rgba(38, 38, 38, 0.05);
|
||||
border-color: rgba(38, 38, 38, 0.05);
|
||||
color: #595959;
|
||||
}
|
||||
&.progress {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
color: #038a24;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.priority-color {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 0;
|
||||
height: 12px;
|
||||
width: 2px;
|
||||
}
|
||||
.el-dropdown {
|
||||
flex-shrink: 0;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
.taskfont {
|
||||
color: #bbbbbb;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
.item-title {
|
||||
flex: 1;
|
||||
padding-left: 6px;
|
||||
line-height: 22px;
|
||||
> span {
|
||||
font-size: 12px;
|
||||
height: 18px;
|
||||
min-width: 20px;
|
||||
line-height: 16px;
|
||||
padding: 0 2px;
|
||||
border-radius: 3px;
|
||||
color: #8bcf70;
|
||||
border: 1px solid #8bcf70;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 3px;
|
||||
margin-right: 3px;
|
||||
text-align: center;
|
||||
&.start {
|
||||
background-color: rgba(38, 38, 38, 0.05);
|
||||
border-color: rgba(38, 38, 38, 0.05);
|
||||
color: #595959;
|
||||
}
|
||||
&.progress {
|
||||
background-color: rgba(27, 154, 238, 0.1);
|
||||
border-color: rgba(27, 154, 238, 0.1);
|
||||
color: #0171c2;
|
||||
}
|
||||
&.end {
|
||||
background-color: rgba(21, 173, 49, 0.1);
|
||||
border-color: rgba(21, 173, 49, 0.1);
|
||||
color: #038a24;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item-icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
margin-left: 16px;
|
||||
height: 22px;
|
||||
color: #aaaaaa;
|
||||
cursor: pointer;
|
||||
.taskfont {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 13px;
|
||||
}
|
||||
> em {
|
||||
font-style: normal;
|
||||
margin-left: 4px;
|
||||
}
|
||||
&.overdue {
|
||||
color: #ed4014;
|
||||
}
|
||||
&.today {
|
||||
color: #ff9900;
|
||||
margin-left: 16px;
|
||||
height: 22px;
|
||||
color: #aaaaaa;
|
||||
cursor: pointer;
|
||||
.taskfont {
|
||||
font-size: 13px;
|
||||
}
|
||||
> em {
|
||||
font-style: normal;
|
||||
margin-left: 4px;
|
||||
}
|
||||
&.overdue {
|
||||
color: #ed4014;
|
||||
}
|
||||
&.today {
|
||||
color: #ff9900;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,8 +249,14 @@
|
||||
.page-dashboard {
|
||||
.dashboard-wrapper {
|
||||
display: block;
|
||||
max-width: 86%;
|
||||
max-height: 86%;
|
||||
.dashboard-hello,
|
||||
.dashboard-desc ,
|
||||
.dashboard-block ,
|
||||
.dashboard-list .dashboard-title,
|
||||
.dashboard-list .dashboard-li {
|
||||
max-width: 86%;
|
||||
}
|
||||
.dashboard-block {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
@ -227,16 +265,17 @@
|
||||
padding: 8px 12px;
|
||||
}
|
||||
}
|
||||
.dashboard-title {
|
||||
margin-top: 36px;
|
||||
}
|
||||
.dashboard-list {
|
||||
padding-bottom: 22px;
|
||||
> li {
|
||||
.item-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap
|
||||
overflow: visible !important;
|
||||
padding-bottom: 2px;
|
||||
> ul {
|
||||
margin-bottom: 36px;
|
||||
> li {
|
||||
.item-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user