mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-12 08:58:11 +00:00
perf: 优化搜索加载提示
This commit is contained in:
parent
c5a0e04242
commit
0911bc2dc9
@ -3,15 +3,21 @@
|
||||
<PageTitle :title="$L('项目')"/>
|
||||
<div class="list-search">
|
||||
<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">
|
||||
<Loading v-if="loadProjects || projectKeyLoading"/>
|
||||
<Loading v-if="loadProjects"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
</Input>
|
||||
</div>
|
||||
</div>
|
||||
<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
|
||||
v-for="(item, key) in projectLists"
|
||||
:key="key"
|
||||
@ -49,7 +55,6 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
projectKeyValue: '',
|
||||
projectKeyAlready: {},
|
||||
projectKeyLoading: 0,
|
||||
}
|
||||
},
|
||||
@ -89,31 +94,25 @@ export default {
|
||||
if (val == '') {
|
||||
return;
|
||||
}
|
||||
this.projectKeyLoading++;
|
||||
setTimeout(() => {
|
||||
if (this.projectKeyValue == val) {
|
||||
this.searchProject();
|
||||
}
|
||||
this.projectKeyLoading--;
|
||||
}, 600);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
searchProject() {
|
||||
if (this.projectKeyAlready[this.projectKeyValue] === true) {
|
||||
return;
|
||||
}
|
||||
this.projectKeyAlready[this.projectKeyValue] = true;
|
||||
//
|
||||
setTimeout(() => {
|
||||
this.projectKeyLoading++;
|
||||
}, 1000)
|
||||
this.projectKeyLoading++;
|
||||
this.$store.dispatch("getProjects", {
|
||||
keys: {
|
||||
name: this.projectKeyValue
|
||||
}
|
||||
}).then(() => {
|
||||
this.projectKeyLoading--;
|
||||
}).catch(() => {
|
||||
},
|
||||
hideLoad: true,
|
||||
}).finally(_ => {
|
||||
this.projectKeyLoading--;
|
||||
});
|
||||
},
|
||||
|
||||
@ -5,7 +5,9 @@
|
||||
<div class="dashboard-hello">{{$L('欢迎您,' + userInfo.nickname)}}</div>
|
||||
<div class="dashboard-desc">
|
||||
{{$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>
|
||||
<ul class="dashboard-block">
|
||||
<li @click="scrollTo('today')">
|
||||
|
||||
@ -5,16 +5,16 @@
|
||||
<div class="messenger-select">
|
||||
<div class="messenger-search">
|
||||
<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">
|
||||
<Loading v-if="loadDialogs"/>
|
||||
<Icon v-else type="ios-search" />
|
||||
</div>
|
||||
</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 v-if="tabActive==='dialog'" class="messenger-nav">
|
||||
<div v-if="tabActive==='dialog' && !dialogKey" class="messenger-nav">
|
||||
<p
|
||||
v-for="(item, key) in dialogType"
|
||||
:key="key"
|
||||
@ -34,7 +34,11 @@
|
||||
v-if="tabActive==='dialog'"
|
||||
ref="dialogWrapper"
|
||||
class="dialog" >
|
||||
<li v-if="dialogList.length === 0" class="nothing">
|
||||
{{$L(dialogKey ? `没有任何与"${dialogKey}"相关的对话` : `没有任何对话`)}}
|
||||
</li>
|
||||
<li
|
||||
v-else
|
||||
v-for="(dialog, key) in dialogList"
|
||||
:ref="`dialog_${dialog.id}`"
|
||||
:key="key"
|
||||
@ -76,17 +80,24 @@
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-else class="contacts">
|
||||
<li v-for="(users, label) in contactsData">
|
||||
<div class="label">{{label}}</div>
|
||||
<ul>
|
||||
<li v-for="(user, index) in users" :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 v-if="contactsLoad > 0" class="loading"><Loading/></li>
|
||||
<li v-else-if="!contactsHasMorePages" class="loaded">{{$L('共' + contactsList.length + '位联系人')}}</li>
|
||||
<template v-if="contactsFilter.length === 0">
|
||||
<li v-if="contactsLoad > 0" class="loading"><Loading/></li>
|
||||
<li v-else class="nothing">
|
||||
{{$L(contactsKey ? `没有任何与"${contactsKey}"相关的联系人` : `没有任何联系人`)}}
|
||||
</li>
|
||||
</template>
|
||||
<template v-else>
|
||||
<li v-for="items in contactsList">
|
||||
<div class="label">{{items.az}}</div>
|
||||
<ul>
|
||||
<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>
|
||||
<div class="top-operate" :style="topOperateStyles">
|
||||
<Dropdown
|
||||
@ -156,7 +167,6 @@ export default {
|
||||
|
||||
contactsKey: '',
|
||||
contactsLoad: 0,
|
||||
contactsList: [],
|
||||
contactsData: null,
|
||||
contactsCurrentPage: 1,
|
||||
contactsHasMorePages: false,
|
||||
@ -200,7 +210,13 @@ export default {
|
||||
if (!this.filterDialog(dialog)) {
|
||||
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) {
|
||||
case 'project':
|
||||
case 'task':
|
||||
@ -217,13 +233,6 @@ export default {
|
||||
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;
|
||||
}).sort((a, b) => {
|
||||
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() {
|
||||
return function (type) {
|
||||
let num = 0;
|
||||
@ -285,11 +324,15 @@ export default {
|
||||
}
|
||||
},
|
||||
contactsKey(val) {
|
||||
if (val == '') {
|
||||
return;
|
||||
}
|
||||
this.contactsLoad++;
|
||||
setTimeout(() => {
|
||||
if (this.contactsKey == val) {
|
||||
this.contactsData = null;
|
||||
this.getContactsList(1);
|
||||
}
|
||||
this.contactsLoad--;
|
||||
}, 600);
|
||||
},
|
||||
tabActive: {
|
||||
@ -399,9 +442,6 @@ export default {
|
||||
},
|
||||
|
||||
getContactsList(page) {
|
||||
if (this.contactsData === null) {
|
||||
this.contactsData = {};
|
||||
}
|
||||
this.contactsLoad++;
|
||||
this.$store.dispatch("call", {
|
||||
url: 'users/search',
|
||||
@ -416,19 +456,15 @@ export default {
|
||||
pagesize: 50
|
||||
},
|
||||
}).then(({data}) => {
|
||||
if (this.contactsData === null) {
|
||||
this.contactsData = [];
|
||||
}
|
||||
data.data.some((user) => {
|
||||
if (user.userid === this.userId) {
|
||||
return false;
|
||||
}
|
||||
let az = user.az ? user.az.toUpperCase() : "#";
|
||||
if (typeof this.contactsData[az] === "undefined") this.contactsData[az] = [];
|
||||
//
|
||||
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);
|
||||
if (this.contactsData.findIndex(item => item.userid = user.userid) === -1) {
|
||||
this.contactsData.push(user)
|
||||
}
|
||||
});
|
||||
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'});
|
||||
return;
|
||||
}
|
||||
state.loadProjects++;
|
||||
let showLoad = true;
|
||||
if (data.hideLoad !== undefined) {
|
||||
showLoad = !data.hideLoad;
|
||||
delete data.hideLoad;
|
||||
}
|
||||
showLoad && state.loadProjects++;
|
||||
dispatch("call", {
|
||||
url: 'project/lists',
|
||||
data: data || {}
|
||||
@ -723,7 +728,7 @@ export default {
|
||||
console.warn(e);
|
||||
reject(e)
|
||||
}).finally(_ => {
|
||||
state.loadProjects--;
|
||||
showLoad && state.loadProjects--;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
@ -24,14 +24,14 @@
|
||||
overflow: hidden;
|
||||
|
||||
.search-pre {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.common-loading {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
@ -60,6 +60,25 @@
|
||||
border-radius: 12px;
|
||||
background-color: #ffffff;
|
||||
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 {
|
||||
font-size: 16px;
|
||||
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) {
|
||||
.page-dashboard {
|
||||
.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;
|
||||
overflow: hidden;
|
||||
.search-pre {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.common-loading {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
@ -262,6 +262,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.nothing {
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.contacts {
|
||||
@ -277,18 +284,31 @@
|
||||
line-height: 34px;
|
||||
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 {
|
||||
margin: 0;
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.common-loading {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
> ul {
|
||||
> li {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user