mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-16 05:52:49 +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-hello">{{$L('欢迎您,' + userInfo.nickname)}}</div>
|
||||||
<div class="dashboard-desc">{{$L('以下是你当前的任务统计数据')}}</div>
|
<div class="dashboard-desc">{{$L('以下是你当前的任务统计数据')}}</div>
|
||||||
<ul class="dashboard-block">
|
<ul class="dashboard-block">
|
||||||
<li @click="dashboard='today'">
|
<li @click="scrollTo('today')">
|
||||||
<div class="block-title">{{$L('今日待完成')}}</div>
|
<div class="block-title">{{getTitle('today')}}</div>
|
||||||
<div class="block-data">
|
<div class="block-data">
|
||||||
<div class="block-num">{{dashboardTask.today.length}}</div>
|
<div class="block-num">{{dashboardTask.today.length}}</div>
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li @click="dashboard='overdue'">
|
<li @click="scrollTo('overdue')">
|
||||||
<div class="block-title">{{$L('超期未完成')}}</div>
|
<div class="block-title">{{getTitle('overdue')}}</div>
|
||||||
<div class="block-data">
|
<div class="block-data">
|
||||||
<div class="block-num">{{dashboardTask.overdue.length}}</div>
|
<div class="block-num">{{dashboardTask.overdue.length}}</div>
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li @click="dashboard='all'">
|
<li @click="scrollTo('all')">
|
||||||
<div class="block-title">{{$L('待完成任务')}}</div>
|
<div class="block-title">{{getTitle('all')}}</div>
|
||||||
<div class="block-data">
|
<div class="block-data">
|
||||||
<div class="block-num">{{dashboardTask.all.length}}</div>
|
<div class="block-num">{{dashboardTask.all.length}}</div>
|
||||||
<i class="taskfont"></i>
|
<i class="taskfont"></i>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<template v-if="list.length > 0">
|
<div class="dashboard-list overlay-y">
|
||||||
<div class="dashboard-title">{{title}}</div>
|
<div
|
||||||
<ul class="dashboard-list overlay-y">
|
:ref="`type_${column.type}`"
|
||||||
<li
|
v-for="(column, index) in columns"
|
||||||
v-for="(item, index) in list"
|
v-if="column.list.length > 0"
|
||||||
:key="index"
|
:key="index">
|
||||||
:class="{complete: item.complete_at}"
|
<div class="dashboard-title">{{column.title}}</div>
|
||||||
:style="item.color ? {backgroundColor: item.color} : {}"
|
<ul class="dashboard-li">
|
||||||
@click="openTask(item)">
|
<li
|
||||||
<em
|
v-for="(item, index) in column.list"
|
||||||
v-if="item.p_name"
|
:key="index"
|
||||||
class="priority-color"
|
:class="{complete: item.complete_at}"
|
||||||
:style="{backgroundColor:item.p_color}"></em>
|
:style="item.color ? {backgroundColor: item.color} : {}"
|
||||||
<TaskMenu :ref="`taskMenu_${item.id}`" :task="item">
|
@click="openTask(item)">
|
||||||
<div slot="icon" class="drop-icon" @click.stop="">
|
<em
|
||||||
<i class="taskfont" v-html="item.complete_at ? '' : ''"></i>
|
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>
|
</div>
|
||||||
</TaskMenu>
|
<div v-if="item.desc" class="item-icon">
|
||||||
<div class="item-title">
|
<i class="taskfont"></i>
|
||||||
<!--工作流状态-->
|
|
||||||
<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>
|
</div>
|
||||||
</ETooltip>
|
<div v-if="item.sub_num > 0" class="item-icon">
|
||||||
</li>
|
<i class="taskfont"></i>
|
||||||
</ul>
|
<em>{{item.sub_complete}}/{{item.sub_num}}</em>
|
||||||
</template>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -110,13 +116,34 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['userInfo', 'cacheProjects', 'taskId']),
|
...mapState(['userInfo']),
|
||||||
|
|
||||||
...mapGetters(['dashboardTask', 'transforTasks']),
|
...mapGetters(['dashboardTask', 'transforTasks']),
|
||||||
|
|
||||||
title() {
|
columns() {
|
||||||
const {dashboard} = this;
|
let list = [];
|
||||||
switch (dashboard) {
|
['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':
|
case 'today':
|
||||||
return this.$L('今日任务');
|
return this.$L('今日任务');
|
||||||
case 'overdue':
|
case 'overdue':
|
||||||
@ -128,27 +155,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
list() {
|
scrollTo(type) {
|
||||||
const {dashboard} = this;
|
try {
|
||||||
let data = [];
|
this.$refs[`type_${type}`][0].scrollIntoView({
|
||||||
switch (dashboard) {
|
behavior: 'instant',
|
||||||
case 'today':
|
inline: 'end',
|
||||||
data = this.transforTasks(this.dashboardTask.today);
|
});
|
||||||
break
|
} catch (e) {
|
||||||
case 'overdue':
|
scrollIntoView(this.$refs[`type_${type}`][0], {
|
||||||
data = this.transforTasks(this.dashboardTask.overdue);
|
behavior: 'instant',
|
||||||
break
|
inline: 'end',
|
||||||
case 'all':
|
})
|
||||||
data = this.transforTasks(this.dashboardTask.all);
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
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) {
|
openTask(task) {
|
||||||
this.$store.dispatch("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;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
background-color: #ffffff;
|
||||||
.dashboard-wrapper {
|
.dashboard-wrapper {
|
||||||
width: 664px;
|
width: 100%;
|
||||||
max-width: 80%;
|
|
||||||
max-height: 80%;
|
max-height: 80%;
|
||||||
margin-bottom: 2%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
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 {
|
.dashboard-hello {
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
color: #333333;
|
color: #333333;
|
||||||
@ -41,10 +50,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: box-shadow 0.3s;
|
transition: transform 0.5s ease-out 0s, box-shadow 0.3s ease-out 0s;
|
||||||
&:hover {
|
|
||||||
box-shadow: 0 0 10px #cccccc;
|
|
||||||
}
|
|
||||||
&:first-child {
|
&:first-child {
|
||||||
background-color: #6f9ef6;
|
background-color: #6f9ef6;
|
||||||
}
|
}
|
||||||
@ -52,6 +58,16 @@
|
|||||||
background-color: #98de6e;
|
background-color: #98de6e;
|
||||||
margin-right: 0;
|
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 {
|
.block-title {
|
||||||
color: rgba(255, 255, 255, 0.6);
|
color: rgba(255, 255, 255, 0.6);
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@ -74,114 +90,130 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dashboard-title {
|
|
||||||
margin-top: 60px;
|
|
||||||
padding: 0 12px;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
.dashboard-list {
|
.dashboard-list {
|
||||||
margin-top: 4px;
|
width: 100%;
|
||||||
padding: 0 12px;
|
margin-top: 48px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
> li {
|
.dashboard-title {
|
||||||
position: relative;
|
position: sticky;
|
||||||
list-style: none;
|
top: 0;
|
||||||
display: flex;
|
z-index: 1;
|
||||||
background: #F9FAFB;
|
margin: 0 auto;
|
||||||
margin-top: 12px;
|
padding: 0 12px;
|
||||||
padding: 8px 12px;
|
height: 46px;
|
||||||
border-radius: 6px;
|
line-height: 46px;
|
||||||
cursor: pointer;
|
font-weight: 600;
|
||||||
transition: box-shadow 0.3s;
|
font-size: 15px;
|
||||||
&:hover {
|
background-color: #ffffff;
|
||||||
box-shadow: 0 0 6px #dfdfdf;
|
}
|
||||||
}
|
.dashboard-li {
|
||||||
&:last-child {
|
margin: 0 auto;
|
||||||
margin-bottom: 12px;
|
padding: 0 12px;
|
||||||
}
|
overflow: hidden;
|
||||||
&.complete {
|
> 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 {
|
.item-title {
|
||||||
opacity: 0.5;
|
flex: 1;
|
||||||
text-decoration: line-through;
|
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 {
|
.item-icon {
|
||||||
display: none;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
}
|
|
||||||
.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 {
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
margin-left: 16px;
|
||||||
> em {
|
height: 22px;
|
||||||
font-style: normal;
|
color: #aaaaaa;
|
||||||
margin-left: 4px;
|
cursor: pointer;
|
||||||
}
|
.taskfont {
|
||||||
&.overdue {
|
font-size: 13px;
|
||||||
color: #ed4014;
|
}
|
||||||
}
|
> em {
|
||||||
&.today {
|
font-style: normal;
|
||||||
color: #ff9900;
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
&.overdue {
|
||||||
|
color: #ed4014;
|
||||||
|
}
|
||||||
|
&.today {
|
||||||
|
color: #ff9900;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,8 +249,14 @@
|
|||||||
.page-dashboard {
|
.page-dashboard {
|
||||||
.dashboard-wrapper {
|
.dashboard-wrapper {
|
||||||
display: block;
|
display: block;
|
||||||
max-width: 86%;
|
|
||||||
max-height: 86%;
|
max-height: 86%;
|
||||||
|
.dashboard-hello,
|
||||||
|
.dashboard-desc ,
|
||||||
|
.dashboard-block ,
|
||||||
|
.dashboard-list .dashboard-title,
|
||||||
|
.dashboard-list .dashboard-li {
|
||||||
|
max-width: 86%;
|
||||||
|
}
|
||||||
.dashboard-block {
|
.dashboard-block {
|
||||||
display: block;
|
display: block;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@ -227,16 +265,17 @@
|
|||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dashboard-title {
|
|
||||||
margin-top: 36px;
|
|
||||||
}
|
|
||||||
.dashboard-list {
|
.dashboard-list {
|
||||||
padding-bottom: 22px;
|
overflow: visible !important;
|
||||||
> li {
|
padding-bottom: 2px;
|
||||||
.item-title {
|
> ul {
|
||||||
overflow: hidden;
|
margin-bottom: 36px;
|
||||||
text-overflow: ellipsis;
|
> li {
|
||||||
white-space: nowrap
|
.item-title {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user