538 lines
9.4 KiB
Vue
538 lines
9.4 KiB
Vue
<script setup>
|
||
/**
|
||
* 通讯录
|
||
*/
|
||
import {
|
||
useStore,
|
||
} from 'vuex'
|
||
import {
|
||
ref,
|
||
computed,
|
||
reactive,
|
||
onMounted,
|
||
onUnmounted,
|
||
inject,
|
||
getCurrentInstance,
|
||
} from 'vue'
|
||
// 工具库
|
||
import util from '@/common/js/util.js'
|
||
// 腾讯云聊天
|
||
import TencentCloudChat from '@tencentcloud/chat';
|
||
// api
|
||
import api from '@/api/index.js'
|
||
import pinyin from 'js-pinyin'
|
||
import {
|
||
forEach
|
||
} from 'lodash';
|
||
const {
|
||
proxy
|
||
} = getCurrentInstance();
|
||
const store = useStore()
|
||
const userinfo = computed(() => {
|
||
let result = store.state.userinfo
|
||
return result
|
||
})
|
||
const msgType = {}
|
||
// 用户列表
|
||
const userList = reactive({
|
||
data: [],
|
||
pageNum: 1,
|
||
pageSize: 10,
|
||
total: 0,
|
||
})
|
||
// 当前操作的用户
|
||
let user = reactive({})
|
||
// 列表下标
|
||
const listKey = ref('')
|
||
// 字母列表
|
||
const letterList = [{
|
||
key: 'other',
|
||
name: '#',
|
||
},
|
||
{
|
||
key: 'a',
|
||
name: 'A',
|
||
},
|
||
{
|
||
key: 'b',
|
||
name: 'B',
|
||
},
|
||
{
|
||
key: 'c',
|
||
name: 'C',
|
||
},
|
||
{
|
||
key: 'd',
|
||
name: 'D',
|
||
},
|
||
{
|
||
key: 'e',
|
||
name: 'E',
|
||
},
|
||
{
|
||
key: 'f',
|
||
name: 'F',
|
||
},
|
||
{
|
||
key: 'g',
|
||
name: 'G',
|
||
},
|
||
{
|
||
key: 'h',
|
||
name: 'H',
|
||
},
|
||
{
|
||
key: 'i',
|
||
name: 'I',
|
||
},
|
||
{
|
||
key: 'j',
|
||
name: 'J',
|
||
},
|
||
{
|
||
key: 'k',
|
||
name: 'K',
|
||
},
|
||
{
|
||
key: 'l',
|
||
name: 'L',
|
||
},
|
||
{
|
||
key: 'm',
|
||
name: 'M',
|
||
},
|
||
{
|
||
key: 'n',
|
||
name: 'N',
|
||
},
|
||
{
|
||
key: 'o',
|
||
name: 'O',
|
||
},
|
||
{
|
||
key: 'p',
|
||
name: 'P',
|
||
},
|
||
{
|
||
key: 'q',
|
||
name: 'Q',
|
||
},
|
||
{
|
||
key: 'r',
|
||
name: 'R',
|
||
},
|
||
{
|
||
key: 's',
|
||
name: 'S',
|
||
},
|
||
{
|
||
key: 't',
|
||
name: 'T',
|
||
},
|
||
{
|
||
key: 'u',
|
||
name: 'U',
|
||
},
|
||
{
|
||
key: 'v',
|
||
name: 'V',
|
||
},
|
||
{
|
||
key: 'w',
|
||
name: 'W',
|
||
},
|
||
{
|
||
key: 'x',
|
||
name: 'X',
|
||
},
|
||
{
|
||
key: 'y',
|
||
name: 'Y',
|
||
},
|
||
{
|
||
key: 'z',
|
||
name: 'Z',
|
||
},
|
||
]
|
||
// 是否移动
|
||
const touchmove = ref(false)
|
||
// 字母列表dom属性
|
||
const letterDom = reactive({
|
||
itemHeight: 0,
|
||
minHeight: 0,
|
||
maxHeight: 0,
|
||
height: 0,
|
||
})
|
||
// 右滑菜单
|
||
const rightOption = [{
|
||
text: '删除',
|
||
style: {
|
||
backgroundColor: '#F85050'
|
||
},
|
||
fn: (user) => delFriend(user),
|
||
},
|
||
// {
|
||
// text: '修改备注',
|
||
// style: {
|
||
// backgroundColor: '#10C100'
|
||
// },
|
||
// fn: (user) => setFriendNote(user),
|
||
// },
|
||
]
|
||
|
||
onMounted(() => {
|
||
// 获取朋友列表
|
||
getFriendList()
|
||
// 获取字母属性
|
||
getLetterProperty()
|
||
// 添加监听
|
||
addlistener()
|
||
|
||
// proxy.$refs.note.open()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
removelistener()
|
||
})
|
||
|
||
const viewData = ref([])
|
||
|
||
// 添加加好友监听
|
||
function addlistener() {
|
||
let onFriendListUpdated = (event) => {
|
||
console.log('onFriendListUpdated', event.data);
|
||
getFriendList()
|
||
}
|
||
|
||
// #ifdef APP
|
||
uni.$chat.on(TencentCloudChat.EVENT.FRIEND_LIST_UPDATED, onFriendListUpdated);
|
||
// #endif
|
||
}
|
||
|
||
// 移除加好友监听
|
||
function removelistener() {
|
||
// #ifdef APP
|
||
uni.$chat.off(TencentCloudChat.EVENT.FRIEND_LIST_UPDATED, () => { });
|
||
// #endif
|
||
}
|
||
|
||
// 获取朋友列表
|
||
function getFriendList() {
|
||
// 验证sdk是否准备完毕
|
||
let isReady = uni.$chat.isReady();
|
||
console.log('getFriendList', isReady)
|
||
|
||
if (!isReady) {
|
||
setTimeout(function () {
|
||
getFriendList()
|
||
}, 500);
|
||
return
|
||
}
|
||
|
||
//
|
||
api.news.getFriendList().then(rs => {
|
||
if (rs.code == 200) {
|
||
const result = rs.data
|
||
userList.data.length = 0
|
||
userList.data = handleUserList(result)
|
||
return
|
||
}
|
||
util.alert({
|
||
content: rs.msg,
|
||
showCancel: false,
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 用户列表排序
|
||
* @param {Object} userList
|
||
*/
|
||
function handleUserList(userList) {
|
||
// 筛选后的用户列表
|
||
const userArr = []
|
||
// 遍历用户列表
|
||
for (let i = 0; i < userList.length; i++) {
|
||
const user = userList[i]
|
||
// 取拼音
|
||
let char = pinyin.getCamelChars(user.remark || user.userNickname);
|
||
// 假设姓名的第一个字符为姓氏
|
||
const letter = char.charAt(0)
|
||
// 下标
|
||
let find_index = userArr.findIndex(item => {
|
||
return item.key === letter
|
||
})
|
||
|
||
// 未找到追加整过数组 找到追加到子数组
|
||
if (find_index == -1) {
|
||
userArr.push({
|
||
letter: letter,
|
||
key: letter,
|
||
child: [user]
|
||
})
|
||
} else {
|
||
userArr[find_index].child.push(user)
|
||
}
|
||
}
|
||
|
||
// 按照姓氏的字典序对二维数组进行排序
|
||
// userArr.sort((a, b) => {
|
||
// const surnameA = a.key;
|
||
// const surnameB = b.key;
|
||
// return surnameA.localeCompare(surnameB);
|
||
// });
|
||
return userArr;
|
||
}
|
||
|
||
|
||
// 获取
|
||
function getLetterProperty() {
|
||
const query = uni.createSelectorQuery().in(proxy);
|
||
|
||
query.select(".letterBox").boundingClientRect((data) => {
|
||
letterDom.minHeight = data.top
|
||
letterDom.height = data.height
|
||
letterDom.maxHeight = data.bottom
|
||
letterDom.itemHeight = data.height / letterList.length
|
||
}).exec();
|
||
}
|
||
|
||
// 手指触摸开始
|
||
function handleTouchStart(ev) {
|
||
touchmove.value = true
|
||
}
|
||
|
||
// 手指触摸移动
|
||
function handleTouchMove(ev) {
|
||
if (!touchmove.value) return
|
||
// 判断临界值
|
||
let result = ev.touches[0].pageY
|
||
result = Math.max(result, letterDom.minHeight)
|
||
result = Math.min(result, letterDom.maxHeight)
|
||
|
||
// 计算当前在那个下标
|
||
let index = Math.floor(result - letterDom.minHeight) / letterDom.itemHeight
|
||
index = parseInt(index)
|
||
|
||
// 修改下标
|
||
listKey.value = letterList[index].key
|
||
}
|
||
|
||
// 手指触摸结束
|
||
function handleTouchEnd(ev) {
|
||
touchmove.value = false
|
||
}
|
||
|
||
/**
|
||
* 点击字母
|
||
* @param {Object} item 点击的当前项
|
||
*/
|
||
function handleLetter(item) {
|
||
listKey.value = item.key
|
||
}
|
||
|
||
/**
|
||
* 右滑菜单
|
||
* @param {Object} ev 默认事件
|
||
* @param {Object} user 用户信息
|
||
*/
|
||
function handleSwipeAction(ev, user) {
|
||
ev.content.fn(user)
|
||
proxy.$refs.swipeAction.closeAll()
|
||
}
|
||
|
||
/**
|
||
* 删除好友
|
||
* @param {Object} user 需要删除的好友信息
|
||
*/
|
||
function delFriend(user) {
|
||
new Promise((resolve, reject) => {
|
||
util.alert({
|
||
content: `确认删除好友${user.remark || user.userNickname}?`
|
||
}).then(res => {
|
||
if (!res.confirm) return
|
||
return resolve()
|
||
})
|
||
}).then(rs => {
|
||
api.news.deleteFriend({
|
||
query: {
|
||
toUserIds: user.userId,
|
||
},
|
||
}).then(rs => {
|
||
if (rs.code === 200) {
|
||
// 获取朋友列表
|
||
getFriendList()
|
||
return
|
||
}
|
||
util.alert({
|
||
content: rs.msg,
|
||
showCancel: false,
|
||
})
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 设置好友备注
|
||
* @param {Object} ev 需要操作的好友信息
|
||
*/
|
||
function setFriendNote(ev) {
|
||
// 合并用户信息
|
||
Object.assign(user, ev)
|
||
// 打开设置用户备注弹窗
|
||
setTimeout(() => {
|
||
proxy.$refs.note.open()
|
||
}, 50)
|
||
}
|
||
|
||
// 设置好友备注
|
||
function handleSaveNote() {
|
||
api.news.setNotes({
|
||
query: {
|
||
name: user.note || '',
|
||
friendId: user.userId,
|
||
}
|
||
}).then(rs => {
|
||
if (rs.code === 200) {
|
||
proxy.$refs.note.close()
|
||
//
|
||
refreshFriendList()
|
||
return
|
||
}
|
||
|
||
util.alert({
|
||
content: rs.msg,
|
||
showCancel: false,
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 点击用户
|
||
* @param {Object} user 当前用户信息
|
||
*/
|
||
function handleUser(user) {
|
||
util.toChat({
|
||
name: user.remark || user.userNickname,
|
||
msgId: user.userId,
|
||
type: 'C2C',
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 跳转
|
||
* @param {Object} url
|
||
*/
|
||
function link(url) {
|
||
uni.navigateTo({
|
||
url,
|
||
})
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<view class="firendBox pr">
|
||
<scroll-view scroll-y="true" class="scroll" :scroll-into-view="listKey">
|
||
<!-- 菜单 -->
|
||
<view class="menu oh c333 f34">
|
||
<view class="rows ptb20 plr30 bfff" @click="link('/pages/news/newFriend')">
|
||
<view class="">新朋友</view>
|
||
<uni-icons type="right" color="#999" size="30rpx" />
|
||
</view>
|
||
|
||
<view class="rows ptb20 plr30 bfff" @click="link('/pages/news/chatGroup')">
|
||
<view class="">群聊列表</view>
|
||
<uni-icons type="right" color="#999" size="30rpx" />
|
||
</view>
|
||
</view>
|
||
|
||
<uni-swipe-action ref="swipeAction">
|
||
<view class="list pb30">
|
||
<view class="li" v-for="(item, index) in userList.data" :key="item.key" :id="item.key">
|
||
<view class="letter ptb10 plr30 c666 f20">{{ item.letter }}</view>
|
||
<view class="child pl30 pr50">
|
||
<uni-swipe-action-item :right-options="rightOption" v-for="(user, secIndex) in item.child"
|
||
:key="secIndex" @click="handleSwipeAction($event, user)">
|
||
<view class="item rows ptb20" @click="handleUser(user)">
|
||
<image class="wh80 avatar cir" :src="user.avatar" mode="aspectFill" />
|
||
<view class="name thd f1 ml20 c333 f32">{{ user.remark || user.userNickname }}</view>
|
||
</view>
|
||
</uni-swipe-action-item>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="mtb20 nomore">到底啦~</view>
|
||
</view>
|
||
</uni-swipe-action>
|
||
</scroll-view>
|
||
|
||
<!-- 字母列表 -->
|
||
<view class="letterBox c666 f22" @touchstart="handleTouchStart" @touchmove.stop.prevent="handleTouchMove"
|
||
@touchend="handleTouchEnd">
|
||
<view class="item fmid ptb5 plr20" v-for="(item, index) in letterList" :key="item"
|
||
@click="handleLetter(item)">{{ item.name }}</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 好友备注 -->
|
||
<uni-popup ref="note" type="bottom" mask-background-color="rgba(0,0,0,0)">
|
||
<view class="noteAlt popBot plr25 bfff">
|
||
<view class="header rows ptb20">
|
||
<view class="title c333 f34">设置好友({{ user.remark }})备注</view>
|
||
<uni-icons type="closeempty" size="40rpx" @click="$refs.note.close()" />
|
||
</view>
|
||
|
||
<view class="content mt30 plr30">
|
||
<input class="input" v-model="user.note" placeholder="请输入好友备注" />
|
||
</view>
|
||
|
||
<view class="btn lg black mtb30" @click="handleSaveNote">保存</view>
|
||
</view>
|
||
</uni-popup>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
// 朋友列表
|
||
.firendBox {
|
||
height: 100%;
|
||
|
||
.scroll {
|
||
height: 100%;
|
||
}
|
||
|
||
// 列表项
|
||
.li {
|
||
.letter {
|
||
background-color: #eee;
|
||
}
|
||
}
|
||
|
||
// 子集
|
||
.child {
|
||
.item+.item {
|
||
border-top: 2rpx solid #eee;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 字母列表
|
||
.letterBox {
|
||
position: absolute;
|
||
top: 50%;
|
||
right: 0;
|
||
transform: translateY(-50%);
|
||
}
|
||
|
||
// 设置好友备注
|
||
.noteAlt {
|
||
box-shadow: 0 0 20rpx #0003;
|
||
|
||
.content {
|
||
.input {
|
||
padding: 20rpx 20rpx;
|
||
background-color: #eaeaea;
|
||
border-radius: 20rpx;
|
||
}
|
||
}
|
||
}
|
||
</style> |