mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-21 16:48:13 +00:00
perf: 优化搜索加载提示
This commit is contained in:
parent
c5a0e04242
commit
0911bc2dc9
@ -3,15 +3,21 @@
|
|||||||
<PageTitle :title="$L('项目')"/>
|
<PageTitle :title="$L('项目')"/>
|
||||||
<div class="list-search">
|
<div class="list-search">
|
||||||
<div class="search-wrapper">
|
<div class="search-wrapper">
|
||||||
<Input v-model="projectKeyValue" :placeholder="$L(loadProjects || projectKeyLoading ? '读取中...' : '搜索...')" clearable>
|
<Input v-model="projectKeyValue" :placeholder="$L(loadProjects ? '更新中...' : '搜索项目')" clearable>
|
||||||
<div class="search-pre" slot="prefix">
|
<div class="search-pre" slot="prefix">
|
||||||
<Loading v-if="loadProjects || projectKeyLoading"/>
|
<Loading v-if="loadProjects"/>
|
||||||
<Icon v-else type="ios-search" />
|
<Icon v-else type="ios-search" />
|
||||||
</div>
|
</div>
|
||||||
</Input>
|
</Input>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
|
<template v-if="projectLists.length === 0">
|
||||||
|
<li v-if="projectKeyLoading > 0" class="loading"><Loading/></li>
|
||||||
|
<li v-else class="nothing">
|
||||||
|
{{$L(projectLists ? `没有任何与"${projectKeyValue}"相关的项目` : `没有任何项目`)}}
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
<li
|
<li
|
||||||
v-for="(item, key) in projectLists"
|
v-for="(item, key) in projectLists"
|
||||||
:key="key"
|
:key="key"
|
||||||
@ -49,7 +55,6 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
projectKeyValue: '',
|
projectKeyValue: '',
|
||||||
projectKeyAlready: {},
|
|
||||||
projectKeyLoading: 0,
|
projectKeyLoading: 0,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -89,31 +94,25 @@ export default {
|
|||||||
if (val == '') {
|
if (val == '') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.projectKeyLoading++;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.projectKeyValue == val) {
|
if (this.projectKeyValue == val) {
|
||||||
this.searchProject();
|
this.searchProject();
|
||||||
}
|
}
|
||||||
|
this.projectKeyLoading--;
|
||||||
}, 600);
|
}, 600);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
searchProject() {
|
searchProject() {
|
||||||
if (this.projectKeyAlready[this.projectKeyValue] === true) {
|
this.projectKeyLoading++;
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.projectKeyAlready[this.projectKeyValue] = true;
|
|
||||||
//
|
|
||||||
setTimeout(() => {
|
|
||||||
this.projectKeyLoading++;
|
|
||||||
}, 1000)
|
|
||||||
this.$store.dispatch("getProjects", {
|
this.$store.dispatch("getProjects", {
|
||||||
keys: {
|
keys: {
|
||||||
name: this.projectKeyValue
|
name: this.projectKeyValue
|
||||||
}
|
},
|
||||||
}).then(() => {
|
hideLoad: true,
|
||||||
this.projectKeyLoading--;
|
}).finally(_ => {
|
||||||
}).catch(() => {
|
|
||||||
this.projectKeyLoading--;
|
this.projectKeyLoading--;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -5,7 +5,9 @@
|
|||||||
<div class="dashboard-hello">{{$L('欢迎您,' + userInfo.nickname)}}</div>
|
<div class="dashboard-hello">{{$L('欢迎您,' + userInfo.nickname)}}</div>
|
||||||
<div class="dashboard-desc">
|
<div class="dashboard-desc">
|
||||||
{{$L('以下是你当前的任务统计数据')}}
|
{{$L('以下是你当前的任务统计数据')}}
|
||||||
<div v-if="loadDashboardTasks" class="dashboard-load"><Loading/></div>
|
<transition name="dashboard-load">
|
||||||
|
<div v-if="loadDashboardTasks" class="dashboard-load"><Loading/></div>
|
||||||
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
<ul class="dashboard-block">
|
<ul class="dashboard-block">
|
||||||
<li @click="scrollTo('today')">
|
<li @click="scrollTo('today')">
|
||||||
|
|||||||
@ -5,16 +5,16 @@
|
|||||||
<div class="messenger-select">
|
<div class="messenger-select">
|
||||||
<div class="messenger-search">
|
<div class="messenger-search">
|
||||||
<div class="search-wrapper">
|
<div class="search-wrapper">
|
||||||
<Input v-if="tabActive==='dialog'" v-model="dialogKey" :placeholder="$L(loadDialogs ? '读取中...' : '搜索...')" clearable >
|
<Input v-if="tabActive==='dialog'" v-model="dialogKey" :placeholder="$L(loadDialogs ? '更新中...' : '搜索消息')" clearable >
|
||||||
<div class="search-pre" slot="prefix">
|
<div class="search-pre" slot="prefix">
|
||||||
<Loading v-if="loadDialogs"/>
|
<Loading v-if="loadDialogs"/>
|
||||||
<Icon v-else type="ios-search" />
|
<Icon v-else type="ios-search" />
|
||||||
</div>
|
</div>
|
||||||
</Input>
|
</Input>
|
||||||
<Input v-else prefix="ios-search" v-model="contactsKey" :placeholder="$L('搜索...')" clearable />
|
<Input v-else prefix="ios-search" v-model="contactsKey" :placeholder="$L('搜索联系人')" clearable />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="tabActive==='dialog'" class="messenger-nav">
|
<div v-if="tabActive==='dialog' && !dialogKey" class="messenger-nav">
|
||||||
<p
|
<p
|
||||||
v-for="(item, key) in dialogType"
|
v-for="(item, key) in dialogType"
|
||||||
:key="key"
|
:key="key"
|
||||||
@ -34,7 +34,11 @@
|
|||||||
v-if="tabActive==='dialog'"
|
v-if="tabActive==='dialog'"
|
||||||
ref="dialogWrapper"
|
ref="dialogWrapper"
|
||||||
class="dialog" >
|
class="dialog" >
|
||||||
|
<li v-if="dialogList.length === 0" class="nothing">
|
||||||
|
{{$L(dialogKey ? `没有任何与"${dialogKey}"相关的对话` : `没有任何对话`)}}
|
||||||
|
</li>
|
||||||
<li
|
<li
|
||||||
|
v-else
|
||||||
v-for="(dialog, key) in dialogList"
|
v-for="(dialog, key) in dialogList"
|
||||||
:ref="`dialog_${dialog.id}`"
|
:ref="`dialog_${dialog.id}`"
|
||||||
:key="key"
|
:key="key"
|
||||||
@ -76,17 +80,24 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul v-else class="contacts">
|
<ul v-else class="contacts">
|
||||||
<li v-for="(users, label) in contactsData">
|
<template v-if="contactsFilter.length === 0">
|
||||||
<div class="label">{{label}}</div>
|
<li v-if="contactsLoad > 0" class="loading"><Loading/></li>
|
||||||
<ul>
|
<li v-else class="nothing">
|
||||||
<li v-for="(user, index) in users" :key="index" @click="openContacts(user)">
|
{{$L(contactsKey ? `没有任何与"${contactsKey}"相关的联系人` : `没有任何联系人`)}}
|
||||||
<div class="avatar"><UserAvatar :userid="user.userid" :size="30"/></div>
|
</li>
|
||||||
<div class="nickname">{{user.nickname}}</div>
|
</template>
|
||||||
</li>
|
<template v-else>
|
||||||
</ul>
|
<li v-for="items in contactsList">
|
||||||
</li>
|
<div class="label">{{items.az}}</div>
|
||||||
<li v-if="contactsLoad > 0" class="loading"><Loading/></li>
|
<ul>
|
||||||
<li v-else-if="!contactsHasMorePages" class="loaded">{{$L('共' + contactsList.length + '位联系人')}}</li>
|
<li v-for="(user, index) in items.list" :key="index" @click="openContacts(user)">
|
||||||
|
<div class="avatar"><UserAvatar :userid="user.userid" :size="30"/></div>
|
||||||
|
<div class="nickname">{{user.nickname}}</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li class="loaded">{{$L('共' + contactsFilter.length + '位联系人')}}</li>
|
||||||
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="top-operate" :style="topOperateStyles">
|
<div class="top-operate" :style="topOperateStyles">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
@ -156,7 +167,6 @@ export default {
|
|||||||
|
|
||||||
contactsKey: '',
|
contactsKey: '',
|
||||||
contactsLoad: 0,
|
contactsLoad: 0,
|
||||||
contactsList: [],
|
|
||||||
contactsData: null,
|
contactsData: null,
|
||||||
contactsCurrentPage: 1,
|
contactsCurrentPage: 1,
|
||||||
contactsHasMorePages: false,
|
contactsHasMorePages: false,
|
||||||
@ -200,7 +210,13 @@ export default {
|
|||||||
if (!this.filterDialog(dialog)) {
|
if (!this.filterDialog(dialog)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (dialogActive) {
|
if (dialogKey) {
|
||||||
|
let existName = $A.strExists(dialog.name, dialogKey);
|
||||||
|
let existMsg = dialog.last_msg && dialog.last_msg.type === 'text' && $A.strExists(dialog.last_msg.msg.text, dialogKey);
|
||||||
|
if (!existName && !existMsg) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (dialogActive) {
|
||||||
switch (dialogActive) {
|
switch (dialogActive) {
|
||||||
case 'project':
|
case 'project':
|
||||||
case 'task':
|
case 'task':
|
||||||
@ -217,13 +233,6 @@ export default {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dialogKey) {
|
|
||||||
let existName = $A.strExists(dialog.name, dialogKey);
|
|
||||||
let existMsg = dialog.last_msg && dialog.last_msg.type === 'text' && $A.strExists(dialog.last_msg.msg.text, dialogKey);
|
|
||||||
if (!existName && !existMsg) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}).sort((a, b) => {
|
}).sort((a, b) => {
|
||||||
if (a.top_at || b.top_at) {
|
if (a.top_at || b.top_at) {
|
||||||
@ -233,6 +242,36 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
contactsFilter() {
|
||||||
|
const {contactsData, contactsKey} = this;
|
||||||
|
if (contactsData === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
if (contactsKey) {
|
||||||
|
return contactsData.filter(item => $A.strExists(item.email, contactsKey) || $A.strExists(item.nickname, contactsKey))
|
||||||
|
}
|
||||||
|
return contactsData;
|
||||||
|
},
|
||||||
|
|
||||||
|
contactsList() {
|
||||||
|
let list = [];
|
||||||
|
this.contactsFilter.some(user => {
|
||||||
|
let az = user.az ? user.az.toUpperCase() : "#";
|
||||||
|
let item = list.find(item => item.az = az);
|
||||||
|
if (item) {
|
||||||
|
if (item.list.findIndex(({userid}) => userid == user.userid) === -1) {
|
||||||
|
item.list.push(user)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
list.push({
|
||||||
|
az,
|
||||||
|
list: [user]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return list;
|
||||||
|
},
|
||||||
|
|
||||||
msgUnread() {
|
msgUnread() {
|
||||||
return function (type) {
|
return function (type) {
|
||||||
let num = 0;
|
let num = 0;
|
||||||
@ -285,11 +324,15 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
contactsKey(val) {
|
contactsKey(val) {
|
||||||
|
if (val == '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.contactsLoad++;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this.contactsKey == val) {
|
if (this.contactsKey == val) {
|
||||||
this.contactsData = null;
|
|
||||||
this.getContactsList(1);
|
this.getContactsList(1);
|
||||||
}
|
}
|
||||||
|
this.contactsLoad--;
|
||||||
}, 600);
|
}, 600);
|
||||||
},
|
},
|
||||||
tabActive: {
|
tabActive: {
|
||||||
@ -399,9 +442,6 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getContactsList(page) {
|
getContactsList(page) {
|
||||||
if (this.contactsData === null) {
|
|
||||||
this.contactsData = {};
|
|
||||||
}
|
|
||||||
this.contactsLoad++;
|
this.contactsLoad++;
|
||||||
this.$store.dispatch("call", {
|
this.$store.dispatch("call", {
|
||||||
url: 'users/search',
|
url: 'users/search',
|
||||||
@ -416,19 +456,15 @@ export default {
|
|||||||
pagesize: 50
|
pagesize: 50
|
||||||
},
|
},
|
||||||
}).then(({data}) => {
|
}).then(({data}) => {
|
||||||
|
if (this.contactsData === null) {
|
||||||
|
this.contactsData = [];
|
||||||
|
}
|
||||||
data.data.some((user) => {
|
data.data.some((user) => {
|
||||||
if (user.userid === this.userId) {
|
if (user.userid === this.userId) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let az = user.az ? user.az.toUpperCase() : "#";
|
if (this.contactsData.findIndex(item => item.userid = user.userid) === -1) {
|
||||||
if (typeof this.contactsData[az] === "undefined") this.contactsData[az] = [];
|
this.contactsData.push(user)
|
||||||
//
|
|
||||||
let index = this.contactsData[az].findIndex(({userid}) => userid === user.userid);
|
|
||||||
if (index > -1) {
|
|
||||||
this.contactsData[az].splice(index, 1, user);
|
|
||||||
} else {
|
|
||||||
this.contactsData[az].push(user);
|
|
||||||
this.contactsList.push(user);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.contactsCurrentPage = data.current_page;
|
this.contactsCurrentPage = data.current_page;
|
||||||
|
|||||||
9
resources/assets/js/store/actions.js
vendored
9
resources/assets/js/store/actions.js
vendored
@ -711,7 +711,12 @@ export default {
|
|||||||
reject({msg: 'Parameter error'});
|
reject({msg: 'Parameter error'});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
state.loadProjects++;
|
let showLoad = true;
|
||||||
|
if (data.hideLoad !== undefined) {
|
||||||
|
showLoad = !data.hideLoad;
|
||||||
|
delete data.hideLoad;
|
||||||
|
}
|
||||||
|
showLoad && state.loadProjects++;
|
||||||
dispatch("call", {
|
dispatch("call", {
|
||||||
url: 'project/lists',
|
url: 'project/lists',
|
||||||
data: data || {}
|
data: data || {}
|
||||||
@ -723,7 +728,7 @@ export default {
|
|||||||
console.warn(e);
|
console.warn(e);
|
||||||
reject(e)
|
reject(e)
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
state.loadProjects--;
|
showLoad && state.loadProjects--;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@ -24,14 +24,14 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
.search-pre {
|
.search-pre {
|
||||||
width: 32px;
|
width: 100%;
|
||||||
height: 32px;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.common-loading {
|
.common-loading {
|
||||||
width: 16px;
|
width: 14px;
|
||||||
height: 16px;
|
height: 14px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -60,6 +60,25 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
&.nothing,
|
||||||
|
&.loading {
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
&.loading {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
.common-loading {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.project-h1 {
|
.project-h1 {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
|
|||||||
16
resources/assets/sass/pages/page-dashboard.scss
vendored
16
resources/assets/sass/pages/page-dashboard.scss
vendored
@ -261,6 +261,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 加载状态(延时显示,立即隐藏)
|
||||||
|
.dashboard-load-enter-active {
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
transition-delay: 1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-load-leave-active {
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
transition-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-load-enter,
|
||||||
|
.dashboard-load-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.page-dashboard {
|
.page-dashboard {
|
||||||
.dashboard-wrapper {
|
.dashboard-wrapper {
|
||||||
|
|||||||
40
resources/assets/sass/pages/page-messenger.scss
vendored
40
resources/assets/sass/pages/page-messenger.scss
vendored
@ -37,14 +37,14 @@
|
|||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
.search-pre {
|
.search-pre {
|
||||||
width: 32px;
|
width: 100%;
|
||||||
height: 32px;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.common-loading {
|
.common-loading {
|
||||||
width: 16px;
|
width: 14px;
|
||||||
height: 16px;
|
height: 14px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,6 +262,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.nothing {
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24px;
|
||||||
|
margin: 0;
|
||||||
|
border: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.contacts {
|
&.contacts {
|
||||||
@ -277,18 +284,31 @@
|
|||||||
line-height: 34px;
|
line-height: 34px;
|
||||||
border-bottom: 1px solid #efefef;
|
border-bottom: 1px solid #efefef;
|
||||||
}
|
}
|
||||||
&.loading,
|
&.nothing,
|
||||||
|
&.loading {
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 24px;
|
||||||
|
border-radius: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
&.loading {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: center;
|
||||||
|
.common-loading {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
&.loaded {
|
&.loaded {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 52px;
|
height: 52px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.common-loading {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
> ul {
|
> ul {
|
||||||
> li {
|
> li {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user