mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-16 05:52:49 +00:00
perf: 添加全局搜索功能
This commit is contained in:
parent
5e46b2cd1a
commit
1c4c4fe3fb
@ -36,11 +36,12 @@
|
|||||||
<li class="item-label">{{typeLabel(type)}}</li>
|
<li class="item-label">{{typeLabel(type)}}</li>
|
||||||
<li v-for="item in items" :key="item.id" @click="onClick(item)">
|
<li v-for="item in items" :key="item.id" @click="onClick(item)">
|
||||||
<div class="item-icon">
|
<div class="item-icon">
|
||||||
<EAvatar v-if="item.icons[0]==='avatar'" class="img-avatar" :src="item.icons[1]" :size="38"/>
|
<div v-if="item.icons[0]==='file'" :class="`no-dark-content file-icon ${item.icons[1]}`"></div>
|
||||||
<i v-else-if="item.icons[0]==='department'" class="taskfont icon-avatar department"></i>
|
<i v-else-if="item.icons[0]==='department'" class="taskfont icon-avatar department"></i>
|
||||||
<i v-else-if="item.icons[0]==='project'" class="taskfont icon-avatar project"></i>
|
<i v-else-if="item.icons[0]==='project'" class="taskfont icon-avatar project"></i>
|
||||||
<i v-else-if="item.icons[0]==='task'" class="taskfont icon-avatar task"></i>
|
<i v-else-if="item.icons[0]==='task'" class="taskfont icon-avatar task"></i>
|
||||||
<UserAvatar v-else-if="item.icons[0]==='user'" class="user-avatar" :userid="item.icons[1]" :size="38"/>
|
<UserAvatar v-else-if="item.icons[0]==='user'" class="user-avatar" :userid="item.icons[1]" :size="38"/>
|
||||||
|
<EAvatar v-else-if="item.icons[0]==='avatar'" class="img-avatar" :src="item.icons[1]" :size="38"/>
|
||||||
<Icon v-else-if="item.icons[0]==='people'" class="icon-avatar" type="ios-people" />
|
<Icon v-else-if="item.icons[0]==='people'" class="icon-avatar" type="ios-people" />
|
||||||
<Icon v-else class="icon-avatar" type="md-person" />
|
<Icon v-else class="icon-avatar" type="md-person" />
|
||||||
</div>
|
</div>
|
||||||
@ -54,7 +55,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="item-desc">
|
<div class="item-desc">
|
||||||
<span
|
<span
|
||||||
class="desc-tag no-dark-content"
|
class="desc-tag"
|
||||||
v-if="item.tags"
|
v-if="item.tags"
|
||||||
v-for="tag in item.tags"
|
v-for="tag in item.tags"
|
||||||
:style="tag.style">{{tag.name}}</span>
|
:style="tag.style">{{tag.name}}</span>
|
||||||
@ -84,6 +85,7 @@ export default {
|
|||||||
loadIng: 0,
|
loadIng: 0,
|
||||||
searchKey: '',
|
searchKey: '',
|
||||||
searchResults: [],
|
searchResults: [],
|
||||||
|
searchTimer: null,
|
||||||
|
|
||||||
showModal: false,
|
showModal: false,
|
||||||
}
|
}
|
||||||
@ -129,14 +131,13 @@ export default {
|
|||||||
list({searchKey, searchResults}) {
|
list({searchKey, searchResults}) {
|
||||||
const items = searchResults.filter(item => item.key === searchKey)
|
const items = searchResults.filter(item => item.key === searchKey)
|
||||||
const groups = {}
|
const groups = {}
|
||||||
items.some(item => {
|
items.forEach(item => {
|
||||||
if (!groups[item.type]) {
|
if (!groups[item.type]) {
|
||||||
groups[item.type] = []
|
groups[item.type] = []
|
||||||
}
|
}
|
||||||
if (groups[item.type].length > 10) {
|
if (groups[item.type].length < 10) {
|
||||||
return true
|
groups[item.type].push(item)
|
||||||
}
|
}
|
||||||
groups[item.type].push(item)
|
|
||||||
})
|
})
|
||||||
return groups
|
return groups
|
||||||
},
|
},
|
||||||
@ -197,9 +198,21 @@ export default {
|
|||||||
|
|
||||||
onSearch() {
|
onSearch() {
|
||||||
this.searchTask(this.searchKey)
|
this.searchTask(this.searchKey)
|
||||||
|
this.searchProject(this.searchKey)
|
||||||
this.searchMessage(this.searchKey)
|
this.searchMessage(this.searchKey)
|
||||||
this.searchContact(this.searchKey)
|
this.searchContact(this.searchKey)
|
||||||
// todo searchFile、searchProject
|
this.searchFile(this.searchKey)
|
||||||
|
},
|
||||||
|
|
||||||
|
pushResults(items) {
|
||||||
|
items.forEach(item => {
|
||||||
|
const index = this.searchResults.findIndex(({id, type}) => id === item.id && type === item.type)
|
||||||
|
if (index > -1) {
|
||||||
|
this.searchResults.splice(index, 1, item)
|
||||||
|
} else {
|
||||||
|
this.searchResults.push(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
searchTask(key) {
|
searchTask(key) {
|
||||||
@ -218,17 +231,17 @@ export default {
|
|||||||
if (item.complete_at) {
|
if (item.complete_at) {
|
||||||
tags.push({
|
tags.push({
|
||||||
name: this.$L('已完成'),
|
name: this.$L('已完成'),
|
||||||
style: 'background-color:#666;color:#ddd',
|
style: 'background-color:#ccc',
|
||||||
})
|
})
|
||||||
} else if (item.overdue) {
|
} else if (item.overdue) {
|
||||||
tags.push({
|
tags.push({
|
||||||
name: this.$L('超期'),
|
name: this.$L('超期'),
|
||||||
style: 'background-color:#f00;color:#ddd',
|
style: 'background-color:#f00',
|
||||||
})
|
})
|
||||||
} else if ($A.dayjs(item.end_at).unix() - nowTime < 86400) {
|
} else if ($A.dayjs(item.end_at).unix() - nowTime < 86400) {
|
||||||
tags.push({
|
tags.push({
|
||||||
name: this.$L('即将到期'),
|
name: this.$L('即将到期'),
|
||||||
style: 'background-color:#f80;color:#ddd',
|
style: 'background-color:#f80',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -245,14 +258,53 @@ export default {
|
|||||||
rawData: item,
|
rawData: item,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
items.forEach(item => {
|
this.pushResults(items)
|
||||||
const index = this.searchResults.findIndex(it => it.id === item.id && it.type === 'task')
|
}).finally(_ => {
|
||||||
if (index > -1) {
|
this.loadIng--;
|
||||||
this.searchResults.splice(index, 1, item)
|
})
|
||||||
} else {
|
},
|
||||||
this.searchResults.push(item)
|
|
||||||
|
searchProject(key) {
|
||||||
|
this.loadIng++;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'project/lists',
|
||||||
|
data: {
|
||||||
|
keys: {
|
||||||
|
name: key
|
||||||
|
},
|
||||||
|
archived: 'all',
|
||||||
|
pagesize: 10,
|
||||||
|
},
|
||||||
|
}).then(({data}) => {
|
||||||
|
const items = data.data.map(item => {
|
||||||
|
const tags = [];
|
||||||
|
if (item.owner) {
|
||||||
|
tags.push({
|
||||||
|
name: this.$L('负责人'),
|
||||||
|
style: 'background-color:#0bc037',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
if (item.archived_at) {
|
||||||
|
tags.push({
|
||||||
|
name: this.$L('已归档'),
|
||||||
|
style: 'background-color:#ccc',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
type: 'project',
|
||||||
|
icons: ['project', null],
|
||||||
|
tags,
|
||||||
|
|
||||||
|
id: item.id,
|
||||||
|
title: item.name,
|
||||||
|
desc: item.desc || '',
|
||||||
|
activity: item.updated_at,
|
||||||
|
|
||||||
|
rawData: item,
|
||||||
|
};
|
||||||
})
|
})
|
||||||
|
this.pushResults(items)
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
})
|
})
|
||||||
@ -301,14 +353,7 @@ export default {
|
|||||||
rawData: item,
|
rawData: item,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
items.forEach(item => {
|
this.pushResults(items)
|
||||||
const index = this.searchResults.findIndex(it => it.id === item.id && it.type === 'task')
|
|
||||||
if (index > -1) {
|
|
||||||
this.searchResults.splice(index, 1, item)
|
|
||||||
} else {
|
|
||||||
this.searchResults.push(item)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
})
|
})
|
||||||
@ -332,24 +377,51 @@ export default {
|
|||||||
|
|
||||||
id: item.userid,
|
id: item.userid,
|
||||||
title: item.nickname,
|
title: item.nickname,
|
||||||
desc: item?.profession || '',
|
desc: item.profession || '',
|
||||||
activity: item.line_at,
|
activity: item.line_at,
|
||||||
|
|
||||||
rawData: item,
|
rawData: item,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
items.forEach(item => {
|
this.pushResults(items)
|
||||||
const index = this.searchResults.findIndex(it => it.id === item.id && it.type === 'contact')
|
|
||||||
if (index > -1) {
|
|
||||||
this.searchResults.splice(index, 1, item)
|
|
||||||
} else {
|
|
||||||
this.searchResults.push(item)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}).finally(_ => {
|
}).finally(_ => {
|
||||||
this.loadIng--;
|
this.loadIng--;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
searchFile(key) {
|
||||||
|
this.loadIng++;
|
||||||
|
this.$store.dispatch("call", {
|
||||||
|
url: 'file/search',
|
||||||
|
data: {key},
|
||||||
|
}).then(({data}) => {
|
||||||
|
const items = data.map(item => {
|
||||||
|
const tags = [];
|
||||||
|
if (item.share) {
|
||||||
|
tags.push({
|
||||||
|
name: this.$L(item.userid == this.userId ? '已共享' : '共享'),
|
||||||
|
style: 'background-color:#0bc037',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
type: 'file',
|
||||||
|
icons: ['file', item.type],
|
||||||
|
tags,
|
||||||
|
|
||||||
|
id: item.id,
|
||||||
|
title: item.name,
|
||||||
|
desc: item.type === 'folder' ? '' : $A.bytesToSize(item.size),
|
||||||
|
activity: item.updated_at,
|
||||||
|
|
||||||
|
rawData: item,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
this.pushResults(items)
|
||||||
|
}).finally(_ => {
|
||||||
|
this.loadIng--;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -976,6 +976,11 @@ export default {
|
|||||||
this.onAddShow()
|
this.onAddShow()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 70: // F - 搜索
|
||||||
|
e.preventDefault();
|
||||||
|
this.$refs.searchBox.onShow();
|
||||||
|
break;
|
||||||
|
|
||||||
case 75:
|
case 75:
|
||||||
case 78: // K/N - 新建任务
|
case 78: // K/N - 新建任务
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@ -7,8 +7,9 @@
|
|||||||
<div class="dashboard-wrapper" :style="wrapperStyle">
|
<div class="dashboard-wrapper" :style="wrapperStyle">
|
||||||
<div class="dashboard-hello">
|
<div class="dashboard-hello">
|
||||||
<h2>{{dashboardHello}}</h2>
|
<h2>{{dashboardHello}}</h2>
|
||||||
<div class="dashboard-search" @click="openSearch">
|
<div class="dashboard-search" :class="{'min-search': windowPortrait}" @click="openSearch">
|
||||||
<i class="taskfont"></i>
|
<Icon type="ios-search"/>
|
||||||
|
<span>{{$L('搜索')}} ({{mateName}}+F)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="systemConfig.timezoneDifference" class="dashboard-time">
|
<div v-if="systemConfig.timezoneDifference" class="dashboard-time">
|
||||||
@ -121,6 +122,8 @@ export default {
|
|||||||
loadIng: 0,
|
loadIng: 0,
|
||||||
dashboard: 'today',
|
dashboard: 'today',
|
||||||
|
|
||||||
|
mateName: /macintosh|mac os x/i.test(navigator.userAgent) ? '⌘' : 'Ctrl',
|
||||||
|
|
||||||
warningMsg: '',
|
warningMsg: '',
|
||||||
|
|
||||||
hiddenColumns: hiddenCaches,
|
hiddenColumns: hiddenCaches,
|
||||||
|
|||||||
13
resources/assets/sass/components/search-box.scss
vendored
13
resources/assets/sass/components/search-box.scss
vendored
@ -159,6 +159,7 @@
|
|||||||
background-color: #ffffff !important;
|
background-color: #ffffff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-icon,
|
||||||
.img-avatar,
|
.img-avatar,
|
||||||
.user-avatar,
|
.user-avatar,
|
||||||
.icon-avatar {
|
.icon-avatar {
|
||||||
@ -169,6 +170,14 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file-icon {
|
||||||
|
display: flex;
|
||||||
|
&:before {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.img-avatar {
|
.img-avatar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -243,8 +252,8 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
background-color: #f0f0f0;
|
background-color: #cccccc;
|
||||||
color: #303133;
|
color: #ffffff;
|
||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
7
resources/assets/sass/dark.scss
vendored
7
resources/assets/sass/dark.scss
vendored
@ -641,6 +641,13 @@ body.dark-mode-reverse {
|
|||||||
.icon-avatar {
|
.icon-avatar {
|
||||||
color: #1c1917;
|
color: #1c1917;
|
||||||
}
|
}
|
||||||
|
.item-content {
|
||||||
|
.item-desc {
|
||||||
|
.desc-tag {
|
||||||
|
color: #1c1917;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
resources/assets/sass/pages/page-dashboard.scss
vendored
32
resources/assets/sass/pages/page-dashboard.scss
vendored
@ -44,7 +44,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
> h2 {
|
> h2 {
|
||||||
flex: 3;
|
flex: 1;
|
||||||
color: $primary-title-color;
|
color: $primary-title-color;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -54,28 +54,44 @@
|
|||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
.dashboard-search {
|
.dashboard-search {
|
||||||
flex: 1;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
max-width: 180px;
|
min-width: 120px;
|
||||||
|
max-width: 220px;
|
||||||
|
margin-left: 24px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
padding: 0 2px 0 24px;
|
padding: 0 12px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
color: #515a6e;
|
color: #515a6e;
|
||||||
background-color: #fff;
|
background-color: #F4F5F7;
|
||||||
background-image: none;
|
background-image: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
transition: opacity 0.3s;
|
transition: opacity 0.3s;
|
||||||
flex: none;
|
|
||||||
> i {
|
> i {
|
||||||
font-size: 20px;
|
font-size: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
padding: 0 4px 0 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
&.min-search {
|
||||||
|
min-width: auto;
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 1;
|
||||||
|
> i {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
> span {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.dashboard-time,
|
.dashboard-time,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user