question_uniapp/pages/im/member.vue
2025-06-15 22:12:30 +08:00

350 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<uni-nav-bar
:title="$t('im.my_team')"
left-icon="left"
@clickLeft="goto('/pages/im/index',2)"
:border="false"
:statusBar="true"
backgroundColor="F5f5f5">
</uni-nav-bar>
<view class="box-1">
<scroll-view
scroll-y
refresher-background="transparent"
style="height: 100%;"
@refresherrefresh="refresherrefresh"
:refresher-enabled="ajax.last_page > ajax.page"
:scroll-with-animation="false"
:refresher-triggered="scrollView.refresherTriggered"
>
<uni-list>
<template v-for="item in friend_list" >
<uni-list-chat
v-if="item.id"
:key="`${item.id}`"
:avatar-circle="true"
:title="item.display_name || item.name || item.nickname || item.email"
:avatar="getAvatarUrl(item)"
:note="item.last_msg ? (item.last_msg_type === 'image' ? '[图片]' : item.last_msg) : '暂无消息'"
:time="item.last_post_at ? date(item.last_post_at) : ''"
:badge-text="item.unread_count > 0 ? (item.unread_count > 99 ? '99+' : item.unread_count) : ''"
clickable
@click="handleContactClick(item)"
></uni-list-chat>
</template>
<!--这里显示最近联系人-->
</uni-list>
</scroll-view>
</view>
</view>
</template>
<script>
import {
mapState,
mapMutations
} from 'vuex';
import mattermost from '@/static/im/mattermost.js';
import base from '@/config/baseUrl'; // 导入base变量
export default {
data() {
return {
// 初始化数据
config: {
cdnurl: '',
// 其他初始化数据
},
friend_list: {},
// 聊天列表数据
ajax: {
limit: 20, // 每页数量
last_page: 1, // 总页数
page: 0, // 当前页码
flag: false, // 请求开关
loading: false // 加载状态
},
scrollView: {
refresherTriggered: false // 下拉刷新状态
},
}
},
computed: {
...mapState(['userInfo']),
// 添加计算属性来安全访问 ajax 数据
hasMoreData() {
return this.ajax && this.ajax.last_page > this.ajax.page;
}
},
onShow() {
this.init();
},
onLoad() {
this.init();
},
onUnload() {
// 移除消息事件监听
mattermost.off('posted', this.handleNewMessage);
},
onPullDownRefresh() {
this.loadContactList().finally(() => {
uni.stopPullDownRefresh();
});
},
methods: {
...mapMutations(['setUserInfo']),
async init(){
try {
if(!this.userInfo.token || !this.userInfo.im_token){
return ;
}
// 获取用户信息
//const userinfo = await this.$http.get('/api/user/profile');
//this.setUserInfo(userinfo.data);
//console.log('用户信息:', this.userInfo);
// 获取初始化数据
const initRes = await this.$http.get('/api/common/init?lang=' + this.$i18n.locale);
if (initRes.code === 0) {
this.config = initRes.data;
this.config.cdnurl = initRes.data.cdnurl || "https://www.dxmt.io";
}
// 检查 Mattermost 连接状态
await mattermost.init();
// 加载联系人列表
this.loadContactList();
// 注册消息事件监听
mattermost.on('posted', this.handleNewMessage);
} catch (error) {
console.error('页面加载失败:', error);
uni.showToast({
title: this.$t('im.loading_fail'),
icon: 'none'
});
}
},
// 加载联系人列表
async loadContactList() {
if (this.ajax.flag || this.ajax.loading) return;
this.ajax.flag = true;
this.ajax.loading = true;
try {
// 获取固定联系人列表
const fixedContactsRes = await this.$http.get('/api/chat/get_team_member_list');
let fixedContacts = [];
if (fixedContactsRes.code === 0 && Array.isArray(fixedContactsRes.data)) {
fixedContacts = fixedContactsRes.data;
}
// 获取私聊列表
const recent_contacts = await mattermost.getRecentContacts();
const sortedContacts = {};
for (const key in fixedContacts) {
if (Object.prototype.hasOwnProperty.call(fixedContacts, key)) {
sortedContacts[fixedContacts[key].id] = fixedContacts[key];
}
}
for (const key in sortedContacts) {
if (Object.prototype.hasOwnProperty.call(sortedContacts, key)) {
sortedContacts[key].unread_count = sortedContacts[key].unread_count || 0;
this.friend_list[key] = sortedContacts[key];
}
}
console.log('联系人列表:',this.friend_list);
// 更新列表
if (this.ajax.page === 0) {
//this.friend_list = sortedContacts;
} else {
//this.friend_list = [...this.friend_list, ...sortedContacts];
}
// 更新分页信息
this.ajax.page++;
this.ajax.last_page = Math.ceil(sortedContacts.length / this.ajax.limit);
} catch (error) {
console.error('加载联系人列表失败:', error);
uni.showToast({
title: this.$t('im.loading_fail'),
icon: 'none'
});
} finally {
this.ajax.flag = false;
this.ajax.loading = false;
this.scrollView.refresherTriggered = false;
}
},
// 处理联系人点击
async handleContactClick(item) {
try {
// 如果是私聊类型需要先查询直接消息频道ID
var url = await mattermost.talk_to_user(item); // 跳转到聊天页面
uni.navigateTo({
url: url
});
} catch (error) {
console.error('处理联系人点击失败:', error);
uni.showToast({
title: this.$t('im.loading_fail'),
icon: 'none'
});
}
},
// 处理新消息
async handleNewMessage(message) {
// 更新联系人列表中的消息
const updateContact = async(list) => {
let is_exist = false;
let post = JSON.parse(message.post);
for(var k in list){
const contact = list[k];
if(message.channel_type == 'D'){
//私聊消息
if(contact.id === post.user_id) {
is_exist = true;
list[k]= contact;
list[k]['last_msg']=post.message;
list[k]['last_msg_type']= post.type || 'text';
list[k]['last_msg_time']= post.create_at;
list[k]['unread_count']= contact.unread_count+=1;
}
}
if(message.channel_type == 'O'){
if(contact.id === post.channel_id) {
is_exist = true;
list[k]= contact;
list[k]['last_msg']=post.message;
list[k]['last_msg_type']= post.type || 'text';
list[k]['last_msg_time']= post.create_at;
list[k]['unread_count']= contact.unread_count+=1;
}
//群组消息
}
}
if(message.channel_type == 'D' && !is_exist){
console.log('新消息:', message,'不存在');
let send_user = await mattermost.getUserInfo(post.user_id);
//console.log('send_user',send_user);
let contact = send_user.data;
contact['last_msg']=post.message;
contact['last_msg_type']= post.type || 'text';
contact['last_msg_time']= post.create_at;
contact['unread_count']= 1;
list[k]= contact;
}
let _keys = Object.keys(list).sort((a, b) => {
const timeA = a.last_msg_time ? new Date(a.last_msg_time).getTime() : 0;
const timeB = b.last_msg_time ? new Date(b.last_msg_time).getTime() : 0;
return timeB - timeA;
});
let _list = {};
for (let index = 0; index < _keys.length; index++) {
_list[_keys[index]] = list[_keys[index]];
}
return _list;
};
this.friend_list = await updateContact(this.friend_list);
},
refresherrefresh() {
this.scrollView.refresherTriggered = true;
this.ajax.page = 0;
this.loadContactList();
},
goto(url,type){
if(type==2){
return uni.switchTab({url:url})
}
if(type==1){
return uni.navigateBack({delta:url});
}
uni.navigateTo({
url:url
})
},
/**
* JavaScript 仿 PHP date() 函数
* @param {string} format - 格式字符串
* @param {number|Date} [timestamp] - 可选的时间戳或Date对象默认为当前时间
* @return {string} 格式化后的日期时间字符串
*/
date(format, timestamp) {
// 处理时间参数
if(!timestamp){
return '';
}
let date = timestamp;
if(!(timestamp instanceof Date)){
date = Date(timestamp * 1000);
if(timestamp > 1749000000){
date = Date(timestamp);
}
}
// 定义替换规则
const replacements = {
// 日
'd': () => String(date.getDate()).padStart(2, '0'),
'j': () => date.getDate(),
// 月
'm': () => String(date.getMonth() + 1).padStart(2, '0'),
'n': () => date.getMonth() + 1,
// 年
'Y': () => date.getFullYear(),
'y': () => String(date.getFullYear()).slice(-2),
// 时间
'H': () => String(date.getHours()).padStart(2, '0'),
'i': () => String(date.getMinutes()).padStart(2, '0'),
's': () => String(date.getSeconds()).padStart(2, '0'),
// 其他
'w': () => date.getDay(), // 星期几 (0-6)
'A': () => date.getHours() >= 12 ? 'PM' : 'AM',
'a': () => date.getHours() >= 12 ? 'pm' : 'am',
};
// 执行替换
let result = '';
for (let i = 0; i < format.length; i++) {
const char = format[i];
if (char in replacements) {
result += replacements[char]();
} else {
result += char;
}
}
return result;
},
getAvatarUrl(item) {
if(!item.avatar){
return this.config.cdnurl+'/static/img/avatar.png';
}
return (item.avatar.startsWith('http') ? '' : this.config.cdnurl) + item.avatar;
}
}
}
</script>
<style lang="scss" scoped>
.container {
height: 100vh;
background-color: #F5F5F5;
font-family: "poppins";
.box-1 {
flex: 1;
height: calc(100vh - var(--window-top) - 44px);
}
}
</style>