114 lines
4.7 KiB
Vue
114 lines
4.7 KiB
Vue
<template>
|
|
<view class="page">
|
|
<fy-header title="搜索" back />
|
|
<wd-search v-model="q" placeholder="搜索同事、会话或待办" hide-cancel focus placeholder-left />
|
|
<view v-if="!q.trim()">
|
|
<wd-status-tip image="search" tip="搜索同事、会话或待办" />
|
|
</view>
|
|
<view v-else>
|
|
<view v-if="people.length" class="sec">同事</view>
|
|
<view v-for="p in people" :key="'p' + p.id" class="item" @click="openPerson(p)">
|
|
<image v-if="p.avatar" class="av img" :src="p.avatar" mode="aspectFill" />
|
|
<view v-else class="av">{{ (p.name || '?').slice(0, 1) }}</view>
|
|
<view class="meta">
|
|
<text class="n">{{ p.name }}</text>
|
|
<text class="s">{{ p.department }} {{ p.title }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="convs.length" class="sec">会话</view>
|
|
<view v-for="c in convs" :key="'c' + c.id" class="item" @click="openConv(c)">
|
|
<view v-if="c.type === 'files'" class="av"><fy-file-mark /></view>
|
|
<view v-else class="av">{{ (c.name || '?').slice(0, 1) }}</view>
|
|
<view class="meta">
|
|
<text class="n">{{ c.name }}</text>
|
|
<text class="s">{{ c.lastMessage }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="hits.length" class="sec">聊天记录</view>
|
|
<view v-for="h in hits" :key="h.id" class="item" @click="openConv(h.conv)">
|
|
<view v-if="h.conv.type === 'files'" class="av"><fy-file-mark /></view>
|
|
<view v-else class="av">{{ (h.conv.name || '?').slice(0, 1) }}</view>
|
|
<view class="meta">
|
|
<text class="n">{{ h.conv.name }}</text>
|
|
<text class="s">{{ h.text }}</text>
|
|
</view>
|
|
</view>
|
|
<view v-if="todos.length" class="sec">待办</view>
|
|
<view v-for="t in todos" :key="t.no || t.id" class="item" @click="openTodo(t)">
|
|
<view class="av work">审</view>
|
|
<view class="meta">
|
|
<text class="n">{{ t.title || t.no }}</text>
|
|
</view>
|
|
</view>
|
|
<wd-status-tip v-if="!people.length && !convs.length && !hits.length && !todos.length" image="search" tip="没有找到相关内容" />
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import FyHeader from '../../components/fy-header.vue'
|
|
import FyFileMark from '../../components/fy-file-mark.vue'
|
|
import { store, previewOf } from '../../utils/store.js'
|
|
|
|
export default {
|
|
components: { FyHeader, FyFileMark },
|
|
data() { return { q: '' } },
|
|
computed: {
|
|
people() {
|
|
const q = this.q.trim()
|
|
if (!q) return []
|
|
return Object.values(store.people).filter((p) => (p.name + p.phone + p.department).includes(q)).slice(0, 8)
|
|
},
|
|
convs() {
|
|
const q = this.q.trim()
|
|
if (!q) return []
|
|
return store.conversations.filter((c) => (c.name + (c.lastMessage || '')).includes(q)).slice(0, 8)
|
|
},
|
|
hits() {
|
|
const q = this.q.trim()
|
|
if (!q) return []
|
|
const out = []
|
|
store.conversations.forEach((c) => {
|
|
(c.messages || []).forEach((m) => {
|
|
if (m.recalled) return
|
|
const text = previewOf(m)
|
|
if (text.indexOf(q) >= 0) out.push({ id: c.id + ':' + m.id, conv: c, text })
|
|
})
|
|
})
|
|
return out.slice(0, 12)
|
|
},
|
|
todos() {
|
|
const q = this.q.trim()
|
|
if (!q) return []
|
|
return (store.todos || []).filter((t) => String(t.title || t.no || '').includes(q)).slice(0, 8)
|
|
}
|
|
},
|
|
methods: {
|
|
openPerson(p) {
|
|
uni.navigateTo({ url: '/pages/contact/detail?id=' + encodeURIComponent(p.id) })
|
|
},
|
|
openConv(c) {
|
|
if (c.type === 'work') uni.navigateTo({ url: '/pages/chat/work?sid=' + encodeURIComponent(c.id) })
|
|
else uni.navigateTo({ url: '/pages/chat/chat?sid=' + encodeURIComponent(c.id) })
|
|
},
|
|
openTodo(t) {
|
|
uni.navigateTo({ url: '/pages/todo/detail?no=' + encodeURIComponent(t.no || t.id) })
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.search { padding: 12rpx 28rpx 16rpx; }
|
|
.search input { height: 80rpx; background: #fff; border-radius: 20rpx; padding: 0 28rpx; font-size: 28rpx; border: 1rpx solid rgba(17,24,39,0.06); }
|
|
.sec { padding: 24rpx 28rpx 8rpx; font-size: 24rpx; color: #6B7280; }
|
|
.item { display: flex; align-items: center; padding: 20rpx 24rpx; background: #fff; }
|
|
.av { width: 72rpx; height: 72rpx; border-radius: 10rpx; background: #E8F1FF; color: #1677FF; display: flex; align-items: center; justify-content: center; font-weight: 700; overflow: hidden; flex-shrink: 0; }
|
|
.av.img { width: 72rpx; height: 72rpx; }
|
|
.av.work { background: #1677FF; color: #fff; }
|
|
.meta { margin-left: 16rpx; min-width: 0; }
|
|
.n { display: block; font-size: 28rpx; }
|
|
.s { font-size: 22rpx; color: #888; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
.empty { text-align: center; color: #6B7280; padding: 120rpx 40rpx; font-size: 28rpx; }
|
|
</style>
|