19、显示好友列表和群

一、如何添加/显示好友 添加/显示群

可以具体成如下的几个接口

/contact/addfriend 自动添加好友,参数userid,dstid
//
用户10000添加好友10086,往contact表中添加俩条记录
//一条ownerid =10000,dstobj=10086 
//一条ownerid =10086,dstobj=10000
/contact/loadfriend 显示全部好友,参数userid
/contact/createcommunity 建群,头像pic,名称name,备注memo,创建者userid
/contact/loadcommunity 显示全部群 参数userid
//加群逻辑特殊一点
/contact/joincommunity 加群,参数userid,dstid

二、创建模型(实体)

model/contact.go

package model
import "time"
// 好友和群都存在这个表里
// 可根据具体业务做拆分
type Contact struct {
    Id int64 `xorm:"pk autoincr bigint(20)" form:"id" json:"id"`
    // 谁的10000 添加的人
    Ownerid int64 `xorm:"bigint(20)" form:"ownerid" json:"ownerid"`
    // 对端10001 被添加的人
    Dstobj int64 `xorm:"bigint(20)" form:"dstobj" json:"dstobj"`
    // 是下面定义的常量 用户加用户是0x01  用户加群0x02
    Cate     int       `xorm:"int(11)" form:"cate" json:"cate"`
    Memo     string    `xorm:"varchar(120)" form:"memo" json:"memo"`     // 什么角色
    Createat time.Time `xorm:"datetime" form:"createat" json:"createat"` // 什么角色
}
const (
    CONCAT_CATE_USER     = 0x01 //用户
    CONCAT_CATE_COMUNITY = 0x02 //群组
)

model/community.go 群聊模型

package model
import "time"
type Community struct {
    Id         int64     `xorm:"pk autoincr bigint(20)" form:"id" json:"id"`
    //名称
    Name   string         `xorm:"varchar(30)" form:"name" json:"name"`
    //群主ID
    Ownerid       int64    `xorm:"bigint(20)" form:"ownerid" json:"ownerid"`   // 什么角色
    //群logo
    Icon       string         `xorm:"varchar(250)" form:"icon" json:"icon"`
    //como
    Cate      int    `xorm:"int(11)" form:"cate" json:"cate"`   // 什么角色
    //描述
    Memo    string    `xorm:"varchar(120)" form:"memo" json:"memo"`   // 什么角色
    //
    Createat   time.Time    `xorm:"datetime" form:"createat" json:"createat"`   // 什么角色
}
const (
        COMMUNITY_CATE_COM = 0x01
    )
在service/init.go中自动同步模型的结构体和数居库的表结构生成映射的关系

19、显示好友列表和群 - 图1

三、创建控制器controller

 
func Addfriend(w http.ResponseWriter, req *http.Request) {
    //request.ParseForm()
    //mobile := request.PostForm.Get("mobile")
    //passwd := request.PostForm.Get("passwd")
    //str->int
    //
    var arg args.ContactArg
    //对象绑定
    util.Bind(req,&arg)
    //
    err := contactService.AddFriend(arg.Userid,arg.Dstid)
    if err!=nil{
        util.RespFail(w,err.Error())
    }else{
        util.RespOk(w,msgs)
    }
}

 封装第9行代码的util.Bind方法

19、显示好友列表和群 - 图2

package util
import (
    "net/http"
    "encoding/json"
    "errors"
    "fmt"
    "io/ioutil"
    "reflect"
    "strconv"
    "strings"
    "time"
)
func Bind(req *http.Request, obj interface{}) error {
    contentType := req.Header.Get("Content-Type")
    //如果是简单的json
    if strings.Contains(strings.ToLower(contentType), "application/json") {
        return BindJson(req, obj)
    }
    if strings.Contains(strings.ToLower(contentType), "application/x-www-form-urlencoded") {
        return BindForm(req, obj)
    }
    return errors.New("当前方法暂不支持")
}
func BindJson(req *http.Request, obj interface{}) error {
    s, err := ioutil.ReadAll(req.Body) //把  body 内容读入字符串
    if err != nil {
        return err
    }
    err = json.Unmarshal(s, obj)
    return err
}
func BindForm(req *http.Request, ptr interface{}) error {
    req.ParseForm()
    fmt.Println(req.Form.Encode())
    err := mapForm(ptr, req.Form)
    return err
}
// 自动绑定方法
// 借鉴了gin
// 改良了时间绑定,
func mapForm(ptr interface{}, form map[string][]string) error {
    typ := reflect.TypeOf(ptr).Elem()
    val := reflect.ValueOf(ptr).Elem()
    for i := 0; i < typ.NumField(); i++ {
        typeField := typ.Field(i)
        structField := val.Field(i)
        if !structField.CanSet() {
            continue
        }
        structFieldKind := structField.Kind()
        inputFieldName := typeField.Tag.Get("form")
        if inputFieldName == "" {
            inputFieldName = typeField.Name
            // if "form" tag is nil, we inspect if the field is a struct.
            // this would not make sense for JSON parsing but it does for a form
            // since data is flatten
            if structFieldKind == reflect.Struct {
                err := mapForm(structField.Addr().Interface(), form)
                if err != nil {
                    return err
                }
                continue
            }
        }
        inputValue, exists := form[inputFieldName]
        if !exists {
            continue
        }
        numElems := len(inputValue)
        if structFieldKind == reflect.Slice && numElems > 0 {
            sliceOf := structField.Type().Elem().Kind()
            slice := reflect.MakeSlice(structField.Type(), numElems, numElems)
            for i := 0; i < numElems; i++ {
                if err := setWithProperType(sliceOf, inputValue[i], slice.Index(i)); err != nil {
                    return err
                }
            }
            val.Field(i).Set(slice)
        } else {
            if _, isTime := structField.Interface().(time.Time); isTime {
                if err := setTimeField(inputValue[0], typeField, structField); err != nil {
                    return err
                }
                continue
            }
            if err := setWithProperType(typeField.Type.Kind(), inputValue[0], structField); err != nil {
                return err
            }
        }
    }
    return nil
}
func setWithProperType(valueKind reflect.Kind, val string, structField reflect.Value) error {
    switch valueKind {
    case reflect.Int:
        return setIntField(val, 0, structField)
    case reflect.Int8:
        return setIntField(val, 8, structField)
    case reflect.Int16:
        return setIntField(val, 16, structField)
    case reflect.Int32:
        return setIntField(val, 32, structField)
    case reflect.Int64:
        return setIntField(val, 64, structField)
    case reflect.Uint:
        return setUintField(val, 0, structField)
    case reflect.Uint8:
        return setUintField(val, 8, structField)
    case reflect.Uint16:
        return setUintField(val, 16, structField)
    case reflect.Uint32:
        return setUintField(val, 32, structField)
    case reflect.Uint64:
        return setUintField(val, 64, structField)
    case reflect.Bool:
        return setBoolField(val, structField)
    case reflect.Float32:
        return setFloatField(val, 32, structField)
    case reflect.Float64:
        return setFloatField(val, 64, structField)
    case reflect.String:
        structField.SetString(val)
    default:
        return errors.New("Unknown type")
    }
    return nil
}
func setIntField(val string, bitSize int, field reflect.Value) error {
    if val == "" {
        val = "0"
    }
    intVal, err := strconv.ParseInt(val, 10, bitSize)
    if err == nil {
        field.SetInt(intVal)
    }
    return err
}
func setUintField(val string, bitSize int, field reflect.Value) error {
    if val == "" {
        val = "0"
    }
    uintVal, err := strconv.ParseUint(val, 10, bitSize)
    if err == nil {
        field.SetUint(uintVal)
    }
    return err
}
func setBoolField(val string, field reflect.Value) error {
    if val == "" {
        val = "false"
    }
    boolVal, err := strconv.ParseBool(val)
    if err == nil {
        field.SetBool(boolVal)
    }
    return nil
}
func setFloatField(val string, bitSize int, field reflect.Value) error {
    if val == "" {
        val = "0.0"
    }
    floatVal, err := strconv.ParseFloat(val, bitSize)
    if err == nil {
        field.SetFloat(floatVal)
    }
    return err
}
func setTimeField(val string, structField reflect.StructField, value reflect.Value) error {
    timeFormat := structField.Tag.Get("time_format")
    //2018-01-02 01:02:03
    if timeFormat == "" {
        timeFormat = "2006-01-02 15:04:05"
        val = strings.Replace(val, "/", "-", 0)
        num := len(strings.Split(val, " "))
        if num == 1 {
            val = val + " 00:00:00"
        } else {
            //2018-01-02 00
            num = len(strings.Split(val, ":"))
            if num == 1 {
                val = val + ":00:00"
            } else if num == 2 {
                val = val + ":00"
            }
        }
    }
    if val == "" {
        value.Set(reflect.ValueOf(time.Time{}))
        return nil
    }
    l := time.Local
    if isUTC, _ := strconv.ParseBool(structField.Tag.Get("time_utc")); isUTC {
        l = time.UTC
    }
    if locTag := structField.Tag.Get("time_location"); locTag != "" {
        loc, err := time.LoadLocation(locTag)
        if err != nil {
            return err
        }
        l = loc
    }
    t, err := time.ParseInLocation(timeFormat, val, l)
    if err != nil {
        return err
    }
    value.Set(reflect.ValueOf(t))
    return nil
}
// Don't pass in pointers to bind to. Can lead to bugs. See:
// https://github.com/codegangsta/martini-contrib/issues/40
// https://github.com/codegangsta/martini-contrib/pull/34#issuecomment-29683659
func ensureNotPointer(obj interface{}) {
    if reflect.TypeOf(obj).Kind() == reflect.Ptr {
        panic("Pointers are not accepted as binding models")
    }
}

 

四、配置路由

http.HandleFunc(“/contact/addfriend”, controller.Addfriend)

19、显示好友列表和群 - 图3

五、配置service

service下contact.go自动添加好友业务逻辑

19、显示好友列表和群 - 图4

 

package service
import (
    "errors"
    "hello/model"
    "time"
)
type ContactService struct {
}
//自动添加好友
func (service *ContactService) AddFriend(
    userid, //用户id 10086,
    dstid int64) error {
    //如果加自己
    if userid == dstid {
        return errors.New("不能添加自己为好友啊")
    }
    //判断是否已经加了好友
    tmp := model.Contact{}
    //查询是否已经是好友
    // 条件的链式操作
    DbEngin.Where("ownerid = ?", userid).
        And("dstid = ?", dstid).
        And("cate = ?", model.CONCAT_CATE_USER).
        Get(&tmp)
    //获得1条记录
    //count()
    //如果存在记录说明已经是好友了不加
    if tmp.Id > 0 {
        return errors.New("该用户已经被添加过啦")
    }
    //事务,
    session := DbEngin.NewSession()
    session.Begin()
    //插自己的
    _, e2 := session.InsertOne(model.Contact{
        Ownerid:  userid,
        Dstobj:   dstid,
        Cate:     model.CONCAT_CATE_USER,
        Createat: time.Now(),
    })
    //插对方的
    _, e3 := session.InsertOne(model.Contact{
        Ownerid:  dstid,
        Dstobj:   userid,
        Cate:     model.CONCAT_CATE_USER,
        Createat: time.Now(),
    })
    //没有错误
    if e2 == nil && e3 == nil {
        //提交
        session.Commit()
        return nil
    } else {
        //回滚
        session.Rollback()
        if e2 != nil {
            return e2
        } else {
            return e3
        }
    }
}

 

实现controller层下contact.go的Addfriend方法

package controller
import (
    "hello/args"
    "hello/service"
    "hello/util"
    "net/http"
)
var contactService service.ContactService
func Addfriend(w http.ResponseWriter, req *http.Request) {
    //定义一个参数结构体
    /*request.ParseForm()
    mobile := request.PostForm.Get("mobile")
    passwd := request.PostForm.Get("passwd")
    */
    var arg args.ContactArg
    util.Bind(req, &arg)
    //调用service
    err := contactService.AddFriend(arg.Userid, arg.Dstid)
    //
    if err != nil {
        util.RespFail(w, err.Error())
    } else {
        util.RespOk(w, nil, "好友添加成功")
    }
}

 会发现调用的一些包没有,则进行扩展

19、显示好友列表和群 - 图5

 args目录下的contact.go

19、显示好友列表和群 - 图6

 

package args
type ContactArg struct {
    PageArg
    Userid int64     `json:"userid" form:"userid"`
    Dstid int64     `json:"dstid" form:"dstid"`
}

args目录下的pagearg.go

package args
import (
    "fmt"
    "time"
)
type PageArg struct {
    //从哪页开始
    Pagefrom int  `json:"pagefrom" form:"pagefrom"`
    //每页大小
    Pagesize int  `json:"pagesize" form:"pagesize"`
    //关键词
    Kword string  `json:"kword" form:"kword"`
    //asc:“id”  id asc
    Asc string     `json:"asc" form:"asc"`
    Desc string     `json:"desc" form:"desc"`
    //
    Name string     `json:"name" form:"name"`
    //
    Userid int64     `json:"userid" form:"userid"`
    //dstid
    Dstid int64     `json:"dstid" form:"dstid"`
    //时间点1
    Datefrom time.Time     `json:"datafrom" form:"datafrom"`
    //时间点2
    Dateto time.Time     `json:"dateto" form:"dateto"`
    //
    Total  int64          `json:"total" form:"total"`
}
func (p*PageArg) GetPageSize() int{
    if p.Pagesize==0{
        return 100
    }else{
        return p.Pagesize
    }
}
func (p*PageArg) GetPageFrom() int{
    if p.Pagefrom<0{
        return 0
    }else{
        return p.Pagefrom
    }
}
func (p*PageArg) GetOrderBy() string{
    if len(p.Asc)>0{
        return fmt.Sprintf(" %s asc",p.Asc)
    } else if len(p.Desc)>0{
        return fmt.Sprintf(" %s desc",p.Desc)
    }else{
        return ""
    }
}

 六、前端js

addfriend:function(){
    //弹窗提示用户输入
    // mui.prompt()
}
_addfriend:function(){
   //网络请求
}

19、显示好友列表和群 - 图7

七、测试

一定要进行更换view/chat的代码及完善controller下/contact.go代码完善了好友列表等方法,main.go也完善了路由

自己添加自己不成功

19、显示好友列表和群 - 图8

19、显示好友列表和群 - 图9

 

 

  1. /contact/loadfriend 显示全部好友,参数userid
  2. /contact/createcommunity 建群,头像pic,名称name,备注memo,创建者userid
  3. /contact/loadcommunity 显示全部群 参数userid
  4. //加群逻辑特殊一点
  5. /contact/joincommunity 加群,参数userid,dstid

这5个接口自行编写,或者参下面的git仓库地址v1.2标签

封装了分页返回数据util/resp.go

19、显示好友列表和群 - 图10

后续的接口代码放到了gitee仓库中:显示好友列表和群 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值