Files
2026-09-24 14:19:36 +08:00

110 lines
4.0 KiB
Vue

<template>
<view class="page">
<fy-header title="选择聊天" back />
<view class="search">
<input v-model="q" placeholder="搜索" />
</view>
<view class="snip">
<text>{{ hint }}</text>
</view>
<view v-if="convs.length" class="sec">
<text>最近聊天</text>
</view>
<view class="list">
<view v-if="!convs.length && !people.length" class="empty">暂无可转发对象</view>
<view v-for="c in convs" :key="'c' + c.id" class="item" @click="pickConv(c)">
<image v-if="c.avatar" class="av img" :src="c.avatar" mode="aspectFill" />
<view v-else class="av">{{ (c.name || '?').slice(0, 1) }}</view>
<text class="n">{{ c.name }}</text>
</view>
</view>
<view v-if="people.length" class="sec">通讯录</view>
<view class="list">
<view v-for="p in people" :key="'p' + p.id" class="item" @click="pickPerson(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>
<text class="n">{{ p.name }}</text>
</view>
</view>
</view>
</template>
<script>
import FyHeader from '../../components/fy-header.vue'
import { store, previewOf } from '../../utils/store.js'
import { toast } from '../../utils/format.js'
export default {
components: { FyHeader },
data() {
return { fromSid: '', msgs: [], merge: false, q: '' }
},
computed: {
hint() {
if (!this.msgs.length) return '没有可转发的消息'
if (this.msgs.length === 1) return '将转发:' + previewOf(this.msgs[0])
return this.merge ? ('合并转发 ' + this.msgs.length + ' 条消息') : ('逐条转发 ' + this.msgs.length + ' 条消息')
},
convs() {
const q = this.q.trim()
return store.conversations.filter((c) => {
if (!c || c.id === this.fromSid) return false
if (c.type === 'work' || c.type === 'files') return false
if (q && String(c.name || '').indexOf(q) < 0) return false
return true
})
},
people() {
const seen = new Set(
this.convs.filter((c) => c.type === 'direct' && c.peerId).map((c) => String(c.peerId))
)
const me = store.me && store.me.id
const q = this.q.trim()
return Object.values(store.people).filter((p) => {
if (!p || !p.id || p.id === me || seen.has(String(p.id))) return false
if (q && (p.name + p.department + (p.phone || '')).indexOf(q) < 0) return false
return true
})
}
},
onLoad() {
const pack = store.pendingForward || {}
this.fromSid = pack.fromSid || ''
this.merge = !!pack.merge
this.msgs = pack.msgs || (pack.msg ? [pack.msg] : [])
if (!this.msgs.length) {
toast('没有可转发的消息')
setTimeout(() => uni.navigateBack(), 400)
}
},
onUnload() {
store.pendingForward = null
},
methods: {
done() {
toast('已转发')
store.pendingForward = null
uni.navigateBack()
},
sendTo(c) {
store.forwardMany(c, this.msgs, this.merge)
this.done()
},
pickConv(c) { this.sendTo(c) },
pickPerson(p) { this.sendTo(store.openDirect(p)) }
}
}
</script>
<style scoped>
.search { padding: 8rpx 24rpx 4rpx; }
.search input { height: 72rpx; background: #fff; border-radius: 12rpx; padding: 0 24rpx; font-size: 28rpx; color: #111827; border: 1rpx solid rgba(17, 24, 39, 0.06); }
.snip { padding: 12rpx 32rpx 8rpx; font-size: 22rpx; color: #6B7280; }
.sec { padding: 20rpx 32rpx 8rpx; font-size: 22rpx; color: #6B7280; }
.item { display: flex; align-items: center; margin: 0 24rpx; padding: 16rpx 0; border-bottom: 1rpx solid #F0F2F5; }
.av { width: 80rpx; height: 80rpx; border-radius: 18rpx; background: #E8F1FF; color: #1677FF; display: flex; align-items: center; justify-content: center; font-weight: 700; overflow: hidden; flex-shrink: 0; }
.av.img { width: 80rpx; height: 80rpx; }
.n { margin-left: 20rpx; font-size: 30rpx; color: #111827; }
.empty { padding: 120rpx 40rpx; text-align: center; color: #6B7280; font-size: 28rpx; }
</style>