react+egg+mysql 写一个评论组件(一)

前言

最近想用react 写一款自己的博客 此篇文章主要为设计一个评论框组件~

最终的功能实现效果图

留言本.gif

需求

1、用户对某一文章评论 系统可以获取用户的信息 并展示出来
2、其余用户可以评论别人的回复信息
3、输入QQ 可以后台查询对应的用户头像保存下来

数据库设计

用户表

id用户名联系方式头像地址

评论表

评论id文章id评论内容用户id状态点赞数回复信息

状态分为 是否审核通过 防止恶意评论
回复表

评论id文章id回复的内容用户id被回复人id状态点赞数回复信息

前端评论框组件设计

前端主要使用antd 里面的form 表单 以及留言板 模块

主要的逻辑

  • 用户在输入qq号那一栏 会利用正则判断是否为qq号 如果为qq号 则动态设置用户联系方式那一栏为qq邮箱地址,并且保存用户的qq号 利用后端去查询用户的头像。
  • 首次进入 会判断 localstorage里面有没有用户信息 如果没有则让用户填写用户信息
  • 前端利用nanoid生成随机数 确保用户id的唯一性
  • 当用户在输入留言以后 会将用户的信息 用localstorage 保存到本地 这样 用户下次登录 或者再次评论别人的信息 就不用再次填写信息,(打算以后改为用户利用qq登录功能)
  • 若为文章评论 还要隐去评论表的取消按钮 若为评论他人信息 要保留评论的取消按钮
  • 还要判断出该条回复信息 是否为评论他人的信息
import React,{useState,useEffect} from 'react'
import { Form, Input, Button,message} from 'antd';
import moment from 'moment';
import {nanoid} from 'nanoid'; //生成随机数 用确保用户的id唯一
import axios from 'axios'
import  servicePath  from '../config/apiUrl'
const { TextArea } = Input;
    
function MessageModal(props){
    const [form] = Form.useForm();
    const [flag,setFlag] = useState(false)
    const [cancelFlag,setCancelFlag] = useState(false)
    const [replyId,setReplyId] = useState(props.replyId)
    const [loadings,setLoadings] = useState(false)
    const [imgUrl,setImgUrl] =useState("")
    useEffect(()=>{
        // 如果有用户id 就设置用户名跟联系方式 且 不能修改
        if(localStorage.getItem("user_id")){
            setFlag(true)
            form.setFieldsValue({
                name:localStorage.getItem("userName")?localStorage.getItem("userName"):"",
                contact:localStorage.getItem("contact")?localStorage.getItem("contact"):""
            })
            if(localStorage.getItem("img_url")){
                setImgUrl(localStorage.getItem("img_url"))
            }
        }
        if(!props.closeComment){
            // 如果不是点击回复进来的 是没有 closeComment函数 即 点击取消的 事件
            setCancelFlag(true)
        } 
    },[])
      const onFinish = (values: any) => {
        setLoadings(true)
        // 用户提交评论信息以后把用户名 用户联系方式 用户的id 保存到本地上
        let commentData={
            user_id:localStorage.getItem("user_id") ? localStorage.getItem("user_id") : nanoid(),
            createtime:moment().format('X'),
            state:0,
            likes:0,
            replys:null,
            article_id:props.id,
            content:values.content,
            contact:values.contact,
            name:values.name,
            img_url:imgUrl,
            // 以下为回复评论的数据
            comment_id:replyId && replyId.comment_id,
            reply_id:replyId && replyId.user_id,
        }
        axios({
            method:'post',
            url:servicePath.addComment,
            data:commentData,
            withCredentials: true
        }).then(
            res=>{
                setLoadings(false)
                if(res.data.isScuccess){
                    form.setFieldsValue({
                        content:""
                    })
                    localStorage.setItem("userName",commentData.name)
                    localStorage.setItem("contact",commentData.contact)
                    localStorage.setItem("user_id",commentData.user_id)
                    localStorage.setItem("img_url",imgUrl)
                    setFlag(true)
                    message.success('评论成功,请等待审核~')
                    !cancelFlag && props.closeComment()
                }else{
                    message.error('评论失败,请刷新重试~');
                }
            }
        )
    };
    const onFinishFailed = (errorInfo: any) => {
        console.log('Failed:', errorInfo);
    };
     // 根据输入的qq号或昵称设置 邮箱 12位邮箱
    const changeContact =()=>{
        let reg = /^[1-9][0-9]{4,9}$/gim
        if(reg.test(form.getFieldValue("name"))){
            form.setFieldsValue({
                contact:form.getFieldValue("name")+'@qq.com'
            })
            //获取QQ头像 没有找到合适的接口获取QQ昵称
            setImgUrl('https://q2.qlogo.cn/headimg_dl?dst_uin='+form.getFieldValue("name")+'&spec=100')
        }else{
   setImgUrl("https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png")
            form.setFieldsValue({
                contact:""
            })
        }	
    }            
     return(   
           <Form
            name="basic"
            labelCol={{ span: 0 }}
            wrapperCol={{ span: 24 }}
            initialValues={{ remember: true }}
            onFinish={onFinish}
            onFinishFailed={onFinishFailed}
            className = "message-modal"
            form={form}
            >
            <Form.Item
                label=""
                name="name"
                rules={[{ required: true, message: '请确认昵称/QQ号' }]}
                className ={flag ? "display-none" : "">
                <Input  placeholder="昵称/QQ号" onChange={changeContact}/>
            </Form.Item>
            <Form.Item
                label=""
                name="contact"
                rules={[
                    { required: true, message: '请确认您的邮箱' },
                    {
                        pattern: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
                        message: '邮箱格式不正确',
                        },
                ]}
                className ={flag ? "display-none" : ""}
            >
                <Input placeholder="请输入邮箱"  />
            </Form.Item>
            <Form.Item
                label=""
                name="content"
                rules={[{ required: true, message: '输入您的留言 ' }]}
            >
                <TextArea showCount maxLength={100}  placeholder="1.输入您的留言        2.在昵称框输入QQ号可自动识别头像哦" />
            </Form.Item>
            <Form.Item wrapperCol={{ offset: 0, span: 24 }}>
                <Button  htmlType="button" className ={cancelFlag ? "display-none" : "margin-r10"} onClick={props.closeComment}>
                    取消
                </Button>
                <Button type="primary" htmlType="submit" loading={loadings}>
                提交评论 ✪ω✪
                </Button>
            </Form.Item>
            </Form>)
  }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gis_KG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值