6
0

Compare commits

...

5 Commits

Author SHA1 Message Date
huangqz
039e707c4e Merge branch 'master' of https://golib.gaore.com/GaoreGo/gaore-common-sdk-go 2026-07-17 15:22:55 +08:00
huangqz
a376e0168e feat(chat): 新增 chat 服务聊天记录查询接口 QueryChatRecords 2026-07-17 15:22:01 +08:00
陈华健
ef8d969bdd feat(big-data): 新增 get_user_device 用户设备号查询接口
此前“查询设备号”功能的 SDK(GetUserDeviceParam / Request / Response +
client.GetUserDevice 方法)仅手工存在于 center-api 的 vendor 中,未合入 golib,
导致每次 go mod vendor 都会被冲掉。此处正式补入 golib,与 vendor 内容保持一致。
2026-07-03 16:08:34 +08:00
陈华健
3fb4728865 feat(big-data): get_user_profile 支持 ip / device_id 筛选透传
前端可按 IP / 设备号查账号,但 SDK 的 GetUserProfileParam / Request / body
结构体缺少 ip、device_id 字段,导致这两个筛选条件被静默丢弃、发不到大数据。
补齐三处结构体字段及 GetBodyReader、CreateGetUserProfileRequest 的透传。
2026-07-03 16:08:34 +08:00
huangqz
d3eef1328e 封装stat addWeworkCustomer接口 2026-07-03 14:44:22 +08:00
9 changed files with 339 additions and 2 deletions

View File

@ -51,6 +51,13 @@ func (c *Client) GetRoleCreateLog(req *GetRoleCreateLogRequest) (response *GetRo
return return
} }
// GetUserDevice 用户设备号查询
func (c *Client) GetUserDevice(req *GetUserDeviceRequest) (response *GetUserDeviceResponse, err error) {
response = CreateGetUserDeviceResponse()
err = c.DoAction(req, response)
return
}
// GetUserLoginLogOsOptions 登录日志 OS 选项查询 // GetUserLoginLogOsOptions 登录日志 OS 选项查询
func (c *Client) GetUserLoginLogOsOptions(req *GetUserLoginLogOsOptionsRequest) (response *GetUserLoginLogOsOptionsResponse, err error) { func (c *Client) GetUserLoginLogOsOptions(req *GetUserLoginLogOsOptionsRequest) (response *GetUserLoginLogOsOptionsResponse, err error) {
response = CreateGetUserLoginLogOsOptionsResponse() response = CreateGetUserLoginLogOsOptionsResponse()

View File

@ -0,0 +1,96 @@
package big_data
import (
"bytes"
"encoding/json"
"io"
"strings"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
)
// GetUserDeviceParam 用户设备号查询参数(全部为数组,空数组表示不限定该条件)
type GetUserDeviceParam struct {
Uid []string `json:"uid"`
DeviceId []string `json:"device_id"`
Ip []string `json:"ip"`
LoginDate []string `json:"login_date"` // 登录日期区间 [开始, 结束]
Page int `json:"page"`
PageSize int `json:"page_size"`
XDebug string `json:"x_debug"` // 测试环境调试头,正式调用可留空
}
// GetUserDeviceRequest 用户设备号查询请求
type GetUserDeviceRequest struct {
*requests.JsonRequest
Uid []string `position:"Json" field:"uid"`
DeviceId []string `position:"Json" field:"device_id"`
Ip []string `position:"Json" field:"ip"`
LoginDate []string `position:"Json" field:"login_date"`
Page int `position:"Json" field:"page"`
PageSize int `position:"Json" field:"page_size"`
Authorization string `position:"Header" field:"Authorization"`
XDebug string `position:"Header" field:"x-debug"`
}
// getUserDeviceBody 自定义请求体序列化:切片统一为非 nil 空数组 [],避免 nil→null 触发 DMS 类型校验失败
type getUserDeviceBody struct {
Uid []string `json:"uid"`
DeviceId []string `json:"device_id"`
Ip []string `json:"ip"`
LoginDate []string `json:"login_date"`
Page int `json:"page"`
PageSize int `json:"page_size"`
}
// GetBodyReader 覆盖 JsonRequest 默认实现,使用自定义结构序列化 body
func (request *GetUserDeviceRequest) GetBodyReader() io.Reader {
body := getUserDeviceBody{
Uid: emptyStrSlice(request.Uid),
DeviceId: emptyStrSlice(request.DeviceId),
Ip: emptyStrSlice(request.Ip),
LoginDate: emptyStrSlice(request.LoginDate),
Page: request.Page,
PageSize: request.PageSize,
}
b, err := json.Marshal(body)
if err != nil {
return strings.NewReader("")
}
return bytes.NewReader(b)
}
// GetUserDeviceResponse 用户设备号查询响应data 原样透出)
type GetUserDeviceResponse struct {
*responses.BaseResponse
Code int `json:"code"`
Message string `json:"message"`
Data json.RawMessage `json:"data"`
}
// CreateGetUserDeviceRequest 创建用户设备号查询请求
func CreateGetUserDeviceRequest(token string, param GetUserDeviceParam) *GetUserDeviceRequest {
req := &GetUserDeviceRequest{
JsonRequest: &requests.JsonRequest{},
Uid: param.Uid,
DeviceId: param.DeviceId,
Ip: param.Ip,
LoginDate: param.LoginDate,
Page: param.Page,
PageSize: param.PageSize,
Authorization: token,
XDebug: param.XDebug,
}
req.InitWithApiInfo(HOST, VERSION, "/api/internal/v1/get_user_device")
req.Method = requests.POST
req.Scheme = requests.HTTPS
return req
}
// CreateGetUserDeviceResponse 创建用户设备号查询响应
func CreateGetUserDeviceResponse() *GetUserDeviceResponse {
return &GetUserDeviceResponse{
BaseResponse: &responses.BaseResponse{},
}
}

View File

@ -25,6 +25,8 @@ type GetUserProfileParam struct {
TradeOrderId []string `json:"trade_order_id"` TradeOrderId []string `json:"trade_order_id"`
GameSign []string `json:"game_sign"` GameSign []string `json:"game_sign"`
GameId []string `json:"game_id"` GameId []string `json:"game_id"`
DeviceId []string `json:"device_id"` // 设备号集合,空表示不限定
IP []string `json:"ip"` // IP 集合,空表示不限定
RegisterDate []string `json:"register_date"` // 区间 [开始, 结束] RegisterDate []string `json:"register_date"` // 区间 [开始, 结束]
LastLoginDate []string `json:"last_login_date"` // 区间 [开始, 结束] LastLoginDate []string `json:"last_login_date"` // 区间 [开始, 结束]
LastPayDate []string `json:"last_pay_date"` // 区间 [开始, 结束] LastPayDate []string `json:"last_pay_date"` // 区间 [开始, 结束]
@ -52,6 +54,8 @@ type GetUserProfileRequest struct {
TradeOrderId []string `position:"Json" field:"trade_order_id"` TradeOrderId []string `position:"Json" field:"trade_order_id"`
GameSign []string `position:"Json" field:"game_sign"` GameSign []string `position:"Json" field:"game_sign"`
GameId []string `position:"Json" field:"game_id"` GameId []string `position:"Json" field:"game_id"`
DeviceId []string `position:"Json" field:"device_id"`
IP []string `position:"Json" field:"ip"`
RegisterDate []string `position:"Json" field:"register_date"` RegisterDate []string `position:"Json" field:"register_date"`
LastLoginDate []string `position:"Json" field:"last_login_date"` LastLoginDate []string `position:"Json" field:"last_login_date"`
LastPayDate []string `position:"Json" field:"last_pay_date"` LastPayDate []string `position:"Json" field:"last_pay_date"`
@ -81,6 +85,8 @@ type getUserProfileBody struct {
TradeOrderId []string `json:"trade_order_id"` TradeOrderId []string `json:"trade_order_id"`
GameSign []string `json:"game_sign"` GameSign []string `json:"game_sign"`
GameId []string `json:"game_id"` GameId []string `json:"game_id"`
DeviceId []string `json:"device_id"`
IP []string `json:"ip"`
RegisterDate []string `json:"register_date"` RegisterDate []string `json:"register_date"`
LastLoginDate []string `json:"last_login_date"` LastLoginDate []string `json:"last_login_date"`
LastPayDate []string `json:"last_pay_date"` LastPayDate []string `json:"last_pay_date"`
@ -108,6 +114,8 @@ func (request *GetUserProfileRequest) GetBodyReader() io.Reader {
TradeOrderId: emptyStrSlice(request.TradeOrderId), TradeOrderId: emptyStrSlice(request.TradeOrderId),
GameSign: emptyStrSlice(request.GameSign), GameSign: emptyStrSlice(request.GameSign),
GameId: emptyStrSlice(request.GameId), GameId: emptyStrSlice(request.GameId),
DeviceId: emptyStrSlice(request.DeviceId),
IP: emptyStrSlice(request.IP),
RegisterDate: emptyStrSlice(request.RegisterDate), RegisterDate: emptyStrSlice(request.RegisterDate),
LastLoginDate: emptyStrSlice(request.LastLoginDate), LastLoginDate: emptyStrSlice(request.LastLoginDate),
LastPayDate: emptyStrSlice(request.LastPayDate), LastPayDate: emptyStrSlice(request.LastPayDate),
@ -166,6 +174,8 @@ func CreateGetUserProfileRequest(token string, param GetUserProfileParam) *GetUs
TradeOrderId: param.TradeOrderId, TradeOrderId: param.TradeOrderId,
GameSign: param.GameSign, GameSign: param.GameSign,
GameId: param.GameId, GameId: param.GameId,
DeviceId: param.DeviceId,
IP: param.IP,
RegisterDate: param.RegisterDate, RegisterDate: param.RegisterDate,
LastLoginDate: param.LastLoginDate, LastLoginDate: param.LastLoginDate,
LastPayDate: param.LastPayDate, LastPayDate: param.LastPayDate,

View File

@ -0,0 +1,83 @@
package chat
import (
"strconv"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
)
// QueryChatRecordsParams 查询聊天记录入参。均为可选,建议至少给一个身份或时间范围,避免全量扫描。
type QueryChatRecordsParams struct {
GrUid string // 高热 uid精确匹配多个用英文逗号分隔
Uid string // CP uid精确匹配多个用英文逗号分隔
Gkey string // 游戏 key
Type string // 频道类型 1私聊 2喇叭 3邮件 4世界 5国家 6工会 7队伍 8附近 9其他
Sid string // 区服 ID多个用英文逗号分隔
Keyword string // 内容关键词(分词匹配)
DateStart string // 起始时间 Y-m-d H:i:s按 ctime 过滤)
DateEnd string // 截止时间 Y-m-d H:i:s
Page int // 页码,默认 1
PageSize int // 每页条数,默认 100上限 500
}
type QueryChatRecordsRequest struct {
*requests.RpcRequest
}
// QueryChatRecordsResponse 聊天记录查询响应。
// Items 为 ES child 文档原样字段map字段随 ES mapping 变化,调用方按需取用。
type QueryChatRecordsResponse struct {
*responses.BaseResponse
Code int `json:"code"`
Msg string `json:"msg"`
Data QueryChatRecordsData `json:"data"`
}
type QueryChatRecordsData struct {
Total int `json:"total"`
Page int `json:"page"`
PageSize int `json:"page_size"`
Items []map[string]interface{} `json:"items"`
}
// CreateQueryChatRecordsRequest 组装请求:仅写入非空参数为 FormParams。
func CreateQueryChatRecordsRequest(params QueryChatRecordsParams) (req *QueryChatRecordsRequest) {
req = &QueryChatRecordsRequest{
RpcRequest: &requests.RpcRequest{},
}
req.InitWithApiInfo(HOST, VERSION, "/api/internal/chatRecords")
form := map[string]string{}
putNonEmpty(form, "gr_uid", params.GrUid)
putNonEmpty(form, "uid", params.Uid)
putNonEmpty(form, "gkey", params.Gkey)
putNonEmpty(form, "type", params.Type)
putNonEmpty(form, "sid", params.Sid)
putNonEmpty(form, "keyword", params.Keyword)
putNonEmpty(form, "date_start", params.DateStart)
putNonEmpty(form, "date_end", params.DateEnd)
if params.Page > 0 {
form["page"] = strconv.Itoa(params.Page)
}
if params.PageSize > 0 {
form["page_size"] = strconv.Itoa(params.PageSize)
}
req.FormParams = form
req.Method = requests.POST
return
}
func CreateQueryChatRecordsResponse() (resp *QueryChatRecordsResponse) {
resp = &QueryChatRecordsResponse{
BaseResponse: &responses.BaseResponse{},
}
return
}
func putNonEmpty(m map[string]string, key, val string) {
if val != "" {
m[key] = val
}
}

33
services/chat/client.go Normal file
View File

@ -0,0 +1,33 @@
package chat
import (
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
)
const (
VERSION = "2026-07-17"
)
// HOST chat 服务主机键,解析为 chat.gaore.comsdk 自动补 .gaore.com 后缀)。
var HOST = requests.Host{
Default: "chat",
}
type Client struct {
sdk.Client
}
func NewClient() (client *Client, err error) {
client = new(Client)
err = client.Init()
return
}
// QueryChatRecords 查询聊天记录ES 原样返回,不做二次装配)。
// 对应 chat 服务 POST /api/internal/chatRecords。
func (c *Client) QueryChatRecords(req *QueryChatRecordsRequest) (resp *QueryChatRecordsResponse, err error) {
resp = CreateQueryChatRecordsResponse()
err = c.DoAction(req, resp)
return
}

View File

@ -0,0 +1,43 @@
package chat
import (
"fmt"
"testing"
)
// TestQueryChatRecords 集成测试:真实调用 chat.gaore.com 的 /api/internal/chatRecords。
//
// 运行前请确认:
// - chat 服务已部署本接口InternalController::chatRecords且网络可达
// - 按需替换下面的 gr_uid / 时间范围为有数据的样本。
//
// 运行go test ./services/chat/ -run TestQueryChatRecords -v
func TestQueryChatRecords(t *testing.T) {
client, err := NewClient()
if err != nil {
t.Fatalf("NewClient: %v", err)
}
req := CreateQueryChatRecordsRequest(QueryChatRecordsParams{
GrUid: "188549603", // TODO: 换成有聊天记录的高热 uid
DateStart: "2026-07-01 00:00:00", // TODO: 换成实际时间范围
DateEnd: "2026-07-17 23:59:59",
Page: 1,
PageSize: 5,
})
resp, err := client.QueryChatRecords(req)
if err != nil {
t.Fatalf("QueryChatRecords: %v", err)
}
fmt.Printf("code=%d msg=%s total=%d 返回条数=%d\n",
resp.Code, resp.Msg, resp.Data.Total, len(resp.Data.Items))
for i, item := range resp.Data.Items {
fmt.Printf(" [%d] %+v\n", i, item)
}
if resp.Code != 1 {
t.Errorf("接口返回非成功code=%d msg=%s", resp.Code, resp.Msg)
}
}

View File

@ -2,10 +2,11 @@ package stat
import ( import (
"fmt" "fmt"
"time"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
"time"
) )
const ( const (
@ -171,3 +172,11 @@ func (c *Client) KafkaEvent(req *KafkaEventReq) (resp *KafkaEventResp, err error
err = c.DoAction(req, resp) err = c.DoAction(req, resp)
return return
} }
func (c *Client) AddWeworkCustomer(req *AddWeworkCustomerRequest) (resp *AddWeworkCustomerResponse, err error) {
resp = &AddWeworkCustomerResponse{
BaseResponse: &responses.BaseResponse{},
}
err = c.DoAction(req, resp)
return
}

View File

@ -402,3 +402,29 @@ func TestKafkaEvent(t *testing.T) {
t.Errorf("TestKafkaEvent failed: code=%d msg=%s", resp.Code, resp.Msg) t.Errorf("TestKafkaEvent failed: code=%d msg=%s", resp.Code, resp.Msg)
} }
} }
// 测试添加客服方法
func TestAddWeworkCustomer(t *testing.T) {
client, err := NewClient()
if err != nil {
t.Fatal(err)
}
request := CreateAddWeworkCustomerRequest(&AddWeworkCustomerParam{
CustomerUseId: 3,
UserName: "1231",
})
resp, err := client.AddWeworkCustomer(request)
if err != nil {
t.Fatal(err)
}
fmt.Println(resp.Code, resp.Msg)
// 成功码为 1
if resp.Code != 0 {
t.Errorf("TestKafkaEvent failed: code=%d msg=%s", resp.Code, resp.Msg)
}
}

View File

@ -5,9 +5,10 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"time"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses" "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
"time"
) )
type SetUserNewGameAuthReq struct { type SetUserNewGameAuthReq struct {
@ -272,3 +273,32 @@ func CreateUserLoginRequest(param *UserLoginParam) *UserLoginRequest {
req.Method = requests.POST req.Method = requests.POST
return req return req
} }
// 玩家添加客服事件
type AddWeworkCustomerParam struct {
CustomerUseId int64 `position:"Body" field:"customer_id" default:"0" json:"customer_id"`
UserName string `position:"Body" field:"user_name" default:"" json:"user_name"`
}
type AddWeworkCustomerRequest struct {
*requests.JsonRequest
}
type AddWeworkCustomerResponse struct {
*responses.BaseResponse
Code int64 `json:"code"`
Msg string `json:"msg"`
}
func CreateAddWeworkCustomerRequest(param *AddWeworkCustomerParam) *AddWeworkCustomerRequest {
req := &AddWeworkCustomerRequest{
JsonRequest: &requests.JsonRequest{},
}
req.InitWithApiInfo(HOST, VERSION, "/user/addWeworkCustomer")
req.Method = requests.POST
req.JsonParams["customer_use_id"] = param.CustomerUseId
req.JsonParams["user_name"] = param.UserName
return req
}