更新记录

2.0(2024-08-23)

2.0 优化组件显示样式,摒弃多级评论、支持扁平化层级评论,点赞点踩、展开回复、展开更多、收起、IP归属地显示等。


平台兼容性

HbuilderX/cli最低兼容版本
4.0

uni-app

Vue2 Vue3
?
app-vue app-nvue app-android app-ios app-harmony
? ? ? ? ?
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
? ? ? ? ? ? ? ? ?
微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序 钉钉小程序 快手小程序 飞书小程序 京东小程序
? ? ? ? ? ? ? ? ?
快应用-华为 快应用-联盟
? ?

uni-app x

app-android app-ios
? ?
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
? ? ? ? ? ? ? ? ?

使用示例

引入组件

import weiyichenComment from '@/uni_modules/weiyichen-comment/components/weiyichen-comment/weiyichen-comment.vue';

使用模板

<template>
    <view class="container">
        <weiyichen-comment v-for="(comment, index) in commentList" :key="index" :commentList="commentList" :comment="comment"
            :index="index" @submitReply="submitReply" @hideChildren="hideChildren" @submitLike="submitLike"
            @submitUnlike="submitUnlike" />
    </view>
</template>

数据加载及其函数调用

<script setup lang="ts">
    import { ref } from 'vue';
    import weiyichenComment from '@/uni_modules/weiyichen-comment/components/weiyichen-comment/weiyichen-comment.vue';
    import { onLoad } from '@dcloudio/uni-app';
    import { getTreeCommentList, replyComment, like, getStatusBatch, unlike } from '@/apis/appComment';

    const commentList = ref([]);

    // 发送点赞请求
    const submitLike = async (_likeObject : any) => {
        const res : any = await like(_likeObject.commentId, _likeObject.status);
        if (res && res.code === 10000) {
            console.error(`点赞成功,评论ID为${_likeObject.commentId},点赞状态为${_likeObject.status}`);
        }
    }

    // 发送点踩请求
    const submitUnlike = async (_unlikeObject : any) => {
        const res : any = await unlike(_unlikeObject.commentId, _unlikeObject.status);
        if (res && res.code === 10000) {
            console.error(`点踩成功,评论ID为${_unlikeObject.commentId},点踩状态为${_unlikeObject.status}`);
        }
    }

    // 收起子级评论
    const hideChildren = (_comment : any) => {
        console.error(_comment.parentId);
        console.log(typeof _comment.parentId);
        // 当前为顶级评论(当前是收起顶级评论时,其他子级评论也全部收起,若要收起一个有子级的评论也想收起对应其他子级时,把if条件去掉即可)
        if (BigInt(_comment.parentId) === 0n) {
            hideReplies(_comment); // 从传入的 _comment 开始递归
            // 使用 Vue 的响应式方式更新 `expanded` 属性
            _comment.replies = [..._comment.replies]; // 强制触发 Vue 的响应式系统更新
        }
        console.error(`评论ID为${_comment.commentId}的子级评论列表`, _comment.replies);
    }

    // 递归设置 expanded 属性为false
    const hideReplies = (comment : any) => {
        comment.expanded = false; // 设置当前评论的 expanded 为 false
        if (comment.replies && comment.replies.length > 0) {
            comment.replies.forEach((reply : any) => {
                hideReplies(reply); // 递归调用对子评论进行处理
            });
        }
    };

    // 处理子组件的评论事件
    const submitReply = (_newReply : any) => {
        // 创建新对象,而非引用
        const _reply = { ..._newReply };
        // 截取用户名
        _reply.username = _reply.username.split('>>>')[0].trim();
        sendNewComment(_reply);
    };

    // 发送评论请求
    const sendNewComment = async (_reply : any) => {
        const res : any = await replyComment(_reply);
        if (res && res.code === 10000) {
            console.error('新增评论', _reply);
        }
    }

    // 获取评论列表
    const getCommentList = async (videoId : bigint) => {
        const res : any = await getTreeCommentList(videoId);
        if (res && res.code === 10000 && res.data) {
            commentList.value = res.data;
            const commentIds : Array<bigint> = [];
            // 收集所有评论和回复的 commentId
            commentList.value.forEach((comment : any) => {
                commentIds.push(comment.commentId);
                if (comment.replies && comment.replies.length > 0) {
                    comment.replies.forEach((reply : any) => {
                        commentIds.push(reply.commentId);
                    });
                }
            });
            // 批量查询点赞状态
            const statusArray = await queryLikeStatusBatch(commentIds);
            // 根据查询结果更新评论和回复的点赞状态
            commentList.value.forEach((comment : any) => {
                comment.liked = statusArray[0][comment.commentId] || false;
                comment.unliked = statusArray[1][comment.commentId] || false;
                if (comment.replies && comment.replies.length > 0) {
                    comment.replies.forEach((reply : any) => {
                        reply.liked = statusArray[0][reply.commentId] || false;
                        reply.unliked = statusArray[1][reply.commentId] || false;
                    });
                }
            });
        }
        console.error('更新行为状态后的评论列表', commentList.value);
    };

    // 批量查询点赞状态的函数
    const queryLikeStatusBatch = async (commentIds : Array<bigint>) => {
        const response : any = await getStatusBatch(commentIds);
        const likedStatus : any = {};
        const unlikedStatus : any = {};
        if (response && response.code === 10000 && response.data) {
            response.data.forEach((status : any) => {
                likedStatus[status.commentId] = status.liked;
                unlikedStatus[status.commentId] = status.unliked;
            });
        }
        // 创建一个数组,包含点赞和点踩两个对象
        const statusArray = [likedStatus, unlikedStatus];
        return statusArray;
    };

    onLoad((options : any) => {
        console.error(options.videoId);
        getCommentList(2n);
    });
</script>

参数含义

:commentList ==> 评论数据列表 :comment ==> 遍历列表中的单个评论对象 :index ==> 当前评论索引 @submitReply ==> 处理回复提交事件函数,拿到组件传递的一个_newReply对象,此处写发送请求逻辑 @hideChildren ==> 树形结构时生效,调用此函数,可以在收起最外层评论时,内层评论也全部收起,逻辑可以自定义 @submitLike==> 处理点赞提交事件函数,此处写发送请求逻辑 @submitUnlike==> 处理点踩提交事件函数,此处写发送请求逻辑

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问