oa_app仓库初始化
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<view class="page msg">
|
||||
<fy-header :title="unread ? ('消息(' + unread + ')') : '消息'">
|
||||
<template #right>
|
||||
<text class="ico sm" @click="goSearch">⌕</text>
|
||||
<text class="ico" @click="plus">+</text>
|
||||
</template>
|
||||
</fy-header>
|
||||
<scroll-view scroll-y class="list">
|
||||
<view v-if="!rows.length" class="empty">暂无会话</view>
|
||||
<view
|
||||
v-for="c in rows"
|
||||
:key="c.id"
|
||||
class="item"
|
||||
:class="{ pin: c.pinned }"
|
||||
@click="open(c)"
|
||||
@longpress="act(c)"
|
||||
>
|
||||
<view class="av-wrap">
|
||||
<image v-if="c.avatar" class="av" :src="c.avatar" mode="aspectFill" />
|
||||
<view v-else class="av txt" :class="avClass(c)">{{ avText(c) }}</view>
|
||||
<text v-if="c.unread && !c.muted" class="badge abs">{{ c.unread > 99 ? '99+' : c.unread }}</text>
|
||||
<text v-else-if="c.unread && c.muted" class="dotu" />
|
||||
</view>
|
||||
<view class="meta">
|
||||
<view class="top">
|
||||
<text class="name">{{ c.name }}</text>
|
||||
<text class="time">{{ c.lastTime }}</text>
|
||||
</view>
|
||||
<view class="bot">
|
||||
<text class="prev">{{ c.muted && c.unread ? '[' + c.unread + '条]' : '' }}{{ c.lastMessage || ' ' }}</text>
|
||||
<text v-if="c.muted" class="mute">🔕</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FyHeader from '../../components/fy-header.vue'
|
||||
import { store } from '../../utils/store.js'
|
||||
|
||||
export default {
|
||||
components: { FyHeader },
|
||||
data() {
|
||||
return { rows: [], unread: 0, off: null }
|
||||
},
|
||||
onShow() {
|
||||
if (this.off) this.off()
|
||||
this.guard()
|
||||
store.refreshPeoplePhotos()
|
||||
this.pull()
|
||||
this.off = store.on(() => this.pull())
|
||||
},
|
||||
onHide() {
|
||||
if (this.off) this.off()
|
||||
this.off = null
|
||||
},
|
||||
methods: {
|
||||
guard() {
|
||||
if (store.phase === 'login') uni.reLaunch({ url: '/pages/login/login' })
|
||||
if (store.phase === 'forcePassword') uni.redirectTo({ url: '/pages/password/password' })
|
||||
},
|
||||
pull() {
|
||||
this.rows = store.conversations.slice()
|
||||
this.unread = store.unreadTotal()
|
||||
},
|
||||
avText(c) {
|
||||
if (c.type === 'work') return '工'
|
||||
if (c.type === 'files') return '文'
|
||||
if (c.type === 'group') return '群'
|
||||
return (c.name || '?').slice(0, 1)
|
||||
},
|
||||
avClass(c) {
|
||||
if (c.type === 'work') return 'work'
|
||||
if (c.type === 'files') return 'file'
|
||||
return 'plain'
|
||||
},
|
||||
open(c) {
|
||||
if (c.type === 'work') {
|
||||
uni.navigateTo({ url: '/pages/chat/work?sid=' + encodeURIComponent(c.id) })
|
||||
return
|
||||
}
|
||||
uni.navigateTo({ url: '/pages/chat/chat?sid=' + encodeURIComponent(c.id) })
|
||||
},
|
||||
act(c) {
|
||||
const items = [
|
||||
c.pinned ? '取消置顶' : '置顶聊天',
|
||||
c.unread ? '标为已读' : '标为未读',
|
||||
c.muted ? '关闭免打扰' : '消息免打扰',
|
||||
'删除该聊天'
|
||||
]
|
||||
uni.showActionSheet({
|
||||
itemList: items,
|
||||
success: (res) => {
|
||||
if (res.tapIndex === 0) store.setSession(c, { pinned: !c.pinned })
|
||||
else if (res.tapIndex === 1) {
|
||||
if (c.unread) {
|
||||
c.unread = 0
|
||||
store.emit()
|
||||
} else store.markUnread(c)
|
||||
} else if (res.tapIndex === 2) store.setSession(c, { muted: !c.muted })
|
||||
else if (res.tapIndex === 3) {
|
||||
uni.showModal({
|
||||
title: '删除聊天',
|
||||
content: '仅从消息列表移除,聊天记录仍保留在服务器。',
|
||||
success: (r) => { if (r.confirm) store.hideConv(c) }
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
plus() {
|
||||
uni.showActionSheet({
|
||||
itemList: ['发起群聊', '添加同事'],
|
||||
success: (res) => {
|
||||
if (res.tapIndex === 0) uni.navigateTo({ url: '/pages/chat/create' })
|
||||
else uni.navigateTo({ url: '/pages/search/search' })
|
||||
}
|
||||
})
|
||||
},
|
||||
goSearch() { uni.navigateTo({ url: '/pages/search/search' }) }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.msg { display: flex; flex-direction: column; height: 100vh; background: #fff; }
|
||||
.list { flex: 1; height: 0; }
|
||||
.ico.sm { font-size: 36rpx; }
|
||||
.item { display: flex; align-items: center; padding: 20rpx 24rpx; background: #fff; }
|
||||
.item.pin { background: #f7f7f7; }
|
||||
.av-wrap { position: relative; width: 96rpx; height: 96rpx; flex-shrink: 0; }
|
||||
.av { width: 96rpx; height: 96rpx; border-radius: 12rpx; }
|
||||
.av.txt { display: flex; align-items: center; justify-content: center; font-size: 34rpx; font-weight: 600; }
|
||||
.av.work { background: #2563eb; color: #fff; }
|
||||
.av.file { background: #e2e7ff; color: #434655; }
|
||||
.av.plain { background: #e2e7ff; color: #004ac6; }
|
||||
.abs { position: absolute; top: -8rpx; right: -8rpx; }
|
||||
.dotu { position: absolute; top: -4rpx; right: -4rpx; width: 16rpx; height: 16rpx; border-radius: 50%; background: #fa5151; }
|
||||
.meta { flex: 1; margin-left: 20rpx; min-width: 0; padding: 4rpx 0; border-bottom: 1rpx solid #f0f0f0; }
|
||||
.top { display: flex; justify-content: space-between; align-items: center; }
|
||||
.name { font-size: 32rpx; font-weight: 500; max-width: 420rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.time { font-size: 22rpx; color: #b2b2b2; }
|
||||
.bot { display: flex; align-items: center; margin-top: 8rpx; }
|
||||
.prev { flex: 1; font-size: 24rpx; color: #888; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.mute { font-size: 22rpx; margin-left: 8rpx; }
|
||||
.empty { padding: 120rpx; text-align: center; color: #888; font-size: 26rpx; }
|
||||
.ico { font-size: 40rpx; color: #111; padding: 8rpx 16rpx; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user