467 lines
8.5 KiB
Vue
467 lines
8.5 KiB
Vue
<script setup>
|
||
/**
|
||
* 通讯录
|
||
*/
|
||
|
||
// 腾讯云聊天
|
||
import TencentCloudChat from '@tencentcloud/chat';
|
||
import {
|
||
useStore,
|
||
} from 'vuex'
|
||
import {
|
||
ref,
|
||
computed,
|
||
reactive,
|
||
onMounted,
|
||
onUnmounted,
|
||
inject,
|
||
getCurrentInstance,
|
||
} from 'vue'
|
||
// 工具库
|
||
import util from '@/common/js/util.js'
|
||
import api from '@/api/index.js'
|
||
import pinyin from 'js-pinyin'
|
||
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()
|
||
})
|
||
|
||
// 添加加好友监听
|
||
function addlistener() {
|
||
let onFriendListUpdated = (event) => {
|
||
getList(event.data)
|
||
}
|
||
|
||
uni.$chat.on(TencentCloudChat.EVENT.FRIEND_LIST_UPDATED, onFriendListUpdated);
|
||
}
|
||
|
||
// 移除加好友监听
|
||
function removelistener() {
|
||
uni.$chat.off(TencentCloudChat.EVENT.FRIEND_LIST_UPDATED, () => {});
|
||
}
|
||
|
||
// 获取朋友列表
|
||
function getFriendList() {
|
||
// 验证sdk是否准备完毕
|
||
let isReady = uni.$chat.isReady();
|
||
|
||
if (!isReady) {
|
||
setTimeout(function() {
|
||
getFriendList()
|
||
}, 200);
|
||
return
|
||
}
|
||
|
||
uni.$chat.getFriendList().then(rs => {
|
||
if (rs.code == 0) {
|
||
//
|
||
getList(rs.data)
|
||
}
|
||
})
|
||
}
|
||
|
||
// 获取列表
|
||
function getList(list) {
|
||
//
|
||
userList.data.length = 0
|
||
//
|
||
userList.data.push(...list.map(item => {
|
||
// 取拼音
|
||
let char = pinyin.getCamelChars(item.remark || item.profile.nick);
|
||
return {
|
||
key: char.charAt(0),
|
||
letter: char.charAt(0),
|
||
child: [item]
|
||
}
|
||
}))
|
||
}
|
||
|
||
// 获取
|
||
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.profile.nick}?`
|
||
}).then(res => {
|
||
if (!res.confirm) return
|
||
return resolve()
|
||
})
|
||
}).then(rs => {
|
||
uni.$chat.deleteFriend({
|
||
userIDList: [user.userID],
|
||
type: TencentCloudChat.TYPES.SNS_DELETE_TYPE_BOTH
|
||
}).then(rs => {
|
||
// 获取朋友列表
|
||
getFriendList()
|
||
})
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 设置好友备注
|
||
* @param {Object} ev 需要操作的好友信息
|
||
*/
|
||
function setFriendNote(ev) {
|
||
|
||
// 合并用户信息
|
||
Object.assign(user, ev)
|
||
// 打开设置用户备注弹窗
|
||
setTimeout(() => {
|
||
proxy.$refs.note.open()
|
||
}, 50)
|
||
}
|
||
|
||
// 设置好友备注
|
||
function handleSaveNote() {
|
||
uni.$chat.updateFriend({
|
||
userID: user.userID,
|
||
remark: user.remark || ''
|
||
}).then((rs) => {
|
||
proxy.$refs.note.close()
|
||
})
|
||
}
|
||
|
||
/**
|
||
* 点击用户
|
||
* @param {Object} user 当前用户信息
|
||
*/
|
||
function handleUser(user) {
|
||
util.toChat({
|
||
name: user.remark || user.profile.nick,
|
||
msgId: user.userID,
|
||
type: 'C2C',
|
||
})
|
||
}
|
||
|
||
// 跳转
|
||
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 ptb40 plr30 bw" @click="link('/pages/news/newFriend')">
|
||
<view class="">好友申请</view>
|
||
<uni-icons type="right" color="#999" size="40rpx" />
|
||
</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.profile.avatar" mode="aspectFill" />
|
||
<view class="name thd f1 ml20 c333 f32">{{user.remark || user.profile.nick}}</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,.1)">
|
||
<view class="noteAlt popBot plr25 bfff">
|
||
<view class="header rows ptb20">
|
||
<view class="title c333 f34">设置好友({{user.profile.nick}})备注</view>
|
||
<uni-icons type="closeempty" size="40rpx" @click="$refs.note.close()" />
|
||
</view>
|
||
|
||
<view class="content mt30 plr30">
|
||
<input class="input" v-model="user.remark" 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> |