【uniapp】仿微信通讯录列表实现

news/2024/7/5 2:14:51

效果图

在这里插入图片描述

代码实现

<view class="main-container">
    <!-- 成员列表 -->
    <scroll-view
        class="member-list"
        :style="computedHeight"
        :scroll-y="true"
        :enable-back-to-top="true"
        :scroll-with-animation="true"
        :scroll-into-view="toView"
        :scroll-top="scrollTop"
        @scroll="onScroll"
    >
        <view class="list-wrap">
            <view class="category">发起人</view>
            <view class="list-item">
                <image class="list-item-img" :src="initiatorInfo.headUrl" />
                <view class="list-item-name">{{ initiatorInfo.nickName }}</view>
            </view>
        </view>
        <view class="list-wrap last-wrap" v-for="(v, i) in memberList" :key="i" :id="v.sign == '#' ? 'intoView_' : 'intoView' + v.sign">
            <view class="category">{{ v.sign }} ({{ v.list.length }}人)</view>
            <view class="list-item" v-for="item in v.list" :key="item.numberId">
                <image class="list-item-img" :src="item.headUrl" />
                <view class="list-item-name">{{ item.nickName }}</view>
                <view class="list-item-btn" @click="handleRemove(item)" v-if="item.userType != 'System'">将TA移出</view>
            </view>
        </view>
    </scroll-view>
    <!-- 右侧字母栏 -->
    <scroll-view class="letter-list">
        <view :class="['letter-item', activeLetter == '↑' ? 'active' : '']" @click.stop="toTop" @touchend.stop="handleTouchEnd"></view>
        <!-- <view :class="['letter-item', activeLetter == '☆' ? 'active-item' : '']" @click="toStar">☆</view> -->
        <view :class="['letter-item', activeLetter == item ? 'active' : '']" v-for="(item, index) in allLetterList" :key="index" @click.stop="toLetter(item)" @touchend.stop="handleTouchEnd">
            {{ item }}
        </view>
    </scroll-view>
</view>

需要下载js-pinyin包

npm install js-pinyin --save

引入js-pinyin包

import pinyin from 'js-pinyin'
data() {
    return {
        statusBarHeight: 0,
        initiatorInfo: {}, // 发起人
        groupNo: '',
        allLetterList: ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '#'],
        memberList: [],
        scrollTop: 0,
        toView: '',
        activeLetter: ''
    }
},
computed: {
    computedHeight() {
        return { height: `calc(100vh - ${this.statusBarHeight}px - 54px )` }
    }
},
methods: {
    // 获取群组成员
    getList() {
        getGroupUserList({
            groupNo: this.groupNo
        }).then(res => {
            if (res.code == 'SUCCESS') {
                let userList = res.data.userList || []
                this.initiatorInfo = res.data.userList[0] || {}
                let arr = []
                this.allLetterList.forEach((item, index) => {
                    arr.push({
                        sign: item,
                        list: []
                    })
                })
                this.allLetterList.forEach((item, index) => {
                    userList.forEach(item2 => {
                        let firstLetter = pinyin.getCamelChars(item2.nickName)?.slice(0, 1)
                        if (firstLetter == item) {
                            arr[index].list.push(item2)
                        }
                        if (this.allLetterList.indexOf(firstLetter) == -1 && item == '#') {
                            arr[arr.length - 1].list.push(item2)
                        }
                    })
                })
                this.memberList = arr && arr.length ? arr.filter(item => item.list.length > 0) : []
            } else {
                // 弹出报错提示......
            }
        })
    },
    // 滚动
    onScroll(e) {
        this.scrollTop = e.detail.scrollTop
    },
    // 滚动到顶部
    toTop() {
        this.activeLetter = '↑'
        this.scrollTop = 0
    },
    // 滚动到星标好友
    toStar() {},
    // 滚动到某个字母位置
    toLetter(e) {
        this.activeLetter = e
        if (e == '#') {
            this.toView = 'intoView_'
        } else {
            this.toView = 'intoView' + e
        }
    },
    handleTouchEnd() {
        setTimeout(() => {
            this.activeLetter = ''
        }, 600)
    }
}
.main-container {
    width: 100%;
    height: 100%;
    padding: 20rpx 40rpx 0 24rpx;
    box-sizing: border-box;
    overflow-y: auto;
    position: relative;

    .member-list {
        box-sizing: border-box;

        .list-wrap {
            margin-top: 30rpx;
            .category {
                font-size: 24rpx;
                font-weight: 500;
                color: #adb3ba;
                line-height: 32rpx;
                margin-bottom: 20rpx;
            }
            .list-item {
                display: flex;
                align-items: center;
                margin-bottom: 40rpx;

                &-img {
                    width: 70rpx;
                    height: 70rpx;
                    background: #d8d8d8;
                    flex-shrink: 0;
                    border-radius: 50%;
                }
                &-name {
                    flex: 1;
                    font-size: 28rpx;
                    font-weight: 500;
                    color: #2d3f49;
                    line-height: 36rpx;
                    padding: 20rpx 16rpx 14rpx;
                }
                &-btn {
                    font-size: 24rpx;
                    font-weight: 500;
                    color: #ff466d;
                    line-height: 32rpx;
                    padding: 14rpx 21rpx;
                    flex-shrink: 0;
                    background: #ffedf1;
                    border-radius: 36rpx;
                }
            }
            .list-item:last-child {
                margin-bottom: 0;
            }
        }
        .last-wrap:last-of-type {
            padding-bottom: 30rpx;
        }
    }

    .letter-list {
        width: 32rpx;
        text-align: center;
        position: absolute;
        top: 50%;
        right: 6rpx;
        transform: translateY(-50%);

        .letter-item {
            width: 32rpx;
            height: 32rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 22rpx;
            font-weight: 500;
            color: #999999;
            line-height: 32rpx;
        }
        .active {
            width: 32rpx;
            height: 32rpx;
            background: #fb5c4e;
            color: #fff;
            border-radius: 50%;
        }
    }
}

http://lihuaxi.xjx100.cn/news/1776694.html

相关文章

c语言:用指针解决有关字符串等问题

题目1&#xff1a;将一个字符串str的内容颠倒过来&#xff0c;并输出。 数据范围&#xff1a;1≤len(str)≤10000 代码和思路&#xff1a; #include <stdio.h> #include<string.h> int main() {char str1[10000];gets(str1);//读取字符串内容char* p&str1[…

有符号数是如何判断正负符号位的?

文章目录 有符号数是如何判断正负符号位的&#xff1f; 运行结果&#xff1a; 有符号数是如何判断正负符号位的&#xff1f; #include<stdio.h> int main() {int input_data 0;printf("Please input the data ! \n");scanf("%d",&input_data);…

设计模式-解释器模式(Interpreter)

设计模式-解释器模式&#xff08;Interpreter&#xff09; 一、解释器模式概述1.1 什么是解释器模式1.2 简单实现解释器模式1.3 使用解释器模式的注意事项 二、解释器模式的用途三、解释器模式实现方式3.1 基于递归下降实现解释器模式3.2 基于LL(1)文法实现解释器模式3.3 基于A…

【广州华锐互动】太空探索VR模拟仿真教学系统

随着科技的不断发展&#xff0c;人类对宇宙的探索欲望愈发强烈。火星作为距离地球最近的行星之一&#xff0c;自然成为了人类关注的焦点。近年来&#xff0c;火星探测取得了一系列重要成果&#xff0c;为人类了解火星提供了宝贵的信息。然而&#xff0c;实地考察火星仍然面临着…

list部分接口模拟实现(c++)

List list简介list基本框架list构造函数list_node结构体的默认构造list类的默认构造 push_back()iteartor迭代器迭代器里面的其他接口const迭代器通过模板参数实现复用operator->() insert()erase()clear()析构函数迭代器区间构造拷贝构造operator() list简介 - list可以在…

设计模式-迭代器模式(Iterator)

设计模式-迭代器模式&#xff08;Iterator&#xff09; 一、迭代器模式概述1.1 什么是迭代器模式1.2 简单实现迭代器模式1.3 使用迭代器模式的注意事项 二、迭代器模式的用途三、迭代器模式实现方式3.1 使用Iterator接口实现迭代器模式3.2 使用Iterable接口和Iterator接口实现迭…

2022美亚杯团队赛

2022美亚杯团体赛 - XDforensics-Wiki 2022 美亚杯 团体赛AGC部分资格赛服务器部分 所有服务器部分解题思路_2022美亚杯团体赛复盘-CSDN博客 目录 AGC 1 2 Media Sever挂载 3 ssh登入的看法 PTS 4 5 ssh日志 6 7 查看docker列表 8 查看docker运行 9 建立网站…

【计算机网络笔记】Internet网络的网络层——IP协议之IP数据报的结构

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…