1. 优化IM用户列表搜索逻辑,支持长数字用户ID精确匹配 2. 修复前端雪花ID精度丢失问题,改用字符串传输用户ID 3. 新增邀请码批量绑定用户功能,支持搜索绑定指定用户 4. 新增字典配置接口,新增联系我们字典SQL脚本 5. 完善字典数据变更事件推送,优化弹窗关闭与页面刷新逻辑
178 lines
6.6 KiB
Go
178 lines
6.6 KiB
Go
package sysin
|
|
|
|
import (
|
|
"context"
|
|
"hotgo/internal/model/input/form"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
)
|
|
|
|
type ImInviteListInp struct {
|
|
form.PageReq
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
InviteCode string `json:"inviteCode" dc:"完整邀请码"`
|
|
Status string `json:"status" dc:"状态"`
|
|
BatchId string `json:"batchId" dc:"批次ID"`
|
|
CreatedBy string `json:"createdBy" dc:"创建人"`
|
|
CreatedAtStart *gtime.Time `json:"createdAtStart" dc:"创建开始时间"`
|
|
CreatedAtEnd *gtime.Time `json:"createdAtEnd" dc:"创建结束时间"`
|
|
ExpiresAtStart *gtime.Time `json:"expiresAtStart" dc:"过期开始时间"`
|
|
ExpiresAtEnd *gtime.Time `json:"expiresAtEnd" dc:"过期结束时间"`
|
|
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
|
|
ExpiresAt []*gtime.Time `json:"expiresAt" dc:"到期时间"`
|
|
}
|
|
|
|
func (in *ImInviteListInp) Filter(ctx context.Context) (err error) {
|
|
if in.Page <= 0 {
|
|
in.Page = 1
|
|
}
|
|
if in.PerPage <= 0 {
|
|
in.PerPage = 20
|
|
}
|
|
if in.PerPage > 100 {
|
|
return gerror.New("每页数量最大值不能大于100")
|
|
}
|
|
if in.InviteCode != "" && len(in.InviteCode) != 5 {
|
|
return gerror.New("邀请码必须为完整5位")
|
|
}
|
|
if len(in.CreatedAt) == 2 {
|
|
in.CreatedAtStart = in.CreatedAt[0]
|
|
in.CreatedAtEnd = in.CreatedAt[1]
|
|
}
|
|
if len(in.ExpiresAt) == 2 {
|
|
in.ExpiresAtStart = in.ExpiresAt[0]
|
|
in.ExpiresAtEnd = in.ExpiresAt[1]
|
|
}
|
|
return
|
|
}
|
|
|
|
type ImInviteCreateInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
ExpiresAt *gtime.Time `json:"expiresAt" v:"required#到期时间不能为空" dc:"到期时间"`
|
|
Remark string `json:"remark" dc:"备注"`
|
|
IdempotencyKey string `json:"idempotencyKey" dc:"幂等键"`
|
|
}
|
|
|
|
func (in *ImInviteCreateInp) Filter(ctx context.Context) (err error) {
|
|
in.IdempotencyKey = strings.TrimSpace(in.IdempotencyKey)
|
|
if in.ExpiresAt == nil || in.ExpiresAt.Before(gtime.Now()) {
|
|
return gerror.New("到期时间必须晚于当前时间")
|
|
}
|
|
if len(in.Remark) > 255 {
|
|
return gerror.New("备注不能超过255个字符")
|
|
}
|
|
if len(in.IdempotencyKey) > 128 {
|
|
return gerror.New("幂等键不能超过128个字符")
|
|
}
|
|
return
|
|
}
|
|
|
|
type ImInviteBatchCreateInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
Quantity int `json:"quantity" dc:"数量"`
|
|
ExpiresAt *gtime.Time `json:"expiresAt" v:"required#到期时间不能为空" dc:"到期时间"`
|
|
Remark string `json:"remark" dc:"备注"`
|
|
IdempotencyKey string `json:"idempotencyKey" dc:"幂等键"`
|
|
UserId int64 `json:"userId" dc:"绑定C端用户ID,非必填,>0时为批次内所有邀请码绑定该用户"`
|
|
}
|
|
|
|
func (in *ImInviteBatchCreateInp) Filter(ctx context.Context) (err error) {
|
|
in.IdempotencyKey = strings.TrimSpace(in.IdempotencyKey)
|
|
if in.Quantity < 1 || in.Quantity > 1000 {
|
|
return gerror.New("批量生成数量必须在1到1000之间")
|
|
}
|
|
if in.ExpiresAt == nil || in.ExpiresAt.Before(gtime.Now()) {
|
|
return gerror.New("到期时间必须晚于当前时间")
|
|
}
|
|
if len(in.Remark) > 255 {
|
|
return gerror.New("备注不能超过255个字符")
|
|
}
|
|
if len(in.IdempotencyKey) == 0 || len(in.IdempotencyKey) > 128 {
|
|
return gerror.New("批量生成必须提供不超过128个字符的幂等键")
|
|
}
|
|
if in.UserId < 0 {
|
|
return gerror.New("绑定用户ID不合法")
|
|
}
|
|
return
|
|
}
|
|
|
|
type ImInviteBatchViewInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
BatchId string `json:"batchId" v:"required#批次ID不能为空" dc:"批次ID"`
|
|
}
|
|
|
|
type ImInviteRevokeInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
Id string `json:"id" v:"required#邀请码ID不能为空" dc:"邀请码ID"`
|
|
}
|
|
|
|
type ImInviteBindUserInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
Id string `json:"id" v:"required#邀请码ID不能为空" dc:"邀请码ID"`
|
|
UserId int64 `json:"userId" v:"required|min:1#绑定用户不能为空|绑定用户不合法" dc:"绑定C端用户ID"`
|
|
}
|
|
|
|
func (in *ImInviteBindUserInp) Filter(ctx context.Context) (err error) {
|
|
if _, err = ParseOptionalInt64(in.Id); err != nil {
|
|
return gerror.New("邀请码ID不能为空")
|
|
}
|
|
if in.UserId <= 0 {
|
|
return gerror.New("绑定用户不能为空")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type ImInviteBatchRevokeInp struct {
|
|
TenantId int64 `json:"tenantId" dc:"IM租户ID"`
|
|
BatchId string `json:"batchId" v:"required#批次ID不能为空" dc:"批次ID"`
|
|
}
|
|
|
|
type ImInviteCodeModel struct {
|
|
Id string `json:"id" dc:"ID"`
|
|
TenantId string `json:"tenantId" dc:"IM租户ID"`
|
|
TenantName string `json:"tenantName" dc:"IM租户名称"`
|
|
BatchId string `json:"batchId" dc:"批次ID"`
|
|
Code string `json:"code" dc:"邀请码"`
|
|
Status string `json:"status" dc:"状态"`
|
|
ExpiresAt *gtime.Time `json:"expiresAt" dc:"到期时间"`
|
|
MaxUses int `json:"maxUses" dc:"最大可用次数,0表示不限制"`
|
|
UsageCount int `json:"usageCount" dc:"累计使用次数"`
|
|
BoundUserId string `json:"boundUserId" dc:"绑定用户ID"`
|
|
BoundUserLabel string `json:"boundUserLabel" dc:"绑定用户展示名"`
|
|
LastUsedAt *gtime.Time `json:"lastUsedAt" dc:"最后使用时间"`
|
|
CreatedBy string `json:"createdBy" dc:"创建人"`
|
|
Remark string `json:"remark" dc:"备注"`
|
|
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
|
}
|
|
|
|
type ImInviteBatchModel struct {
|
|
BatchId string `json:"batchId" dc:"批次ID"`
|
|
TenantId string `json:"tenantId" dc:"IM租户ID"`
|
|
Quantity int `json:"quantity" dc:"数量"`
|
|
ActiveCount int `json:"activeCount" dc:"有效数量"`
|
|
UsageCount int `json:"usageCount" dc:"累计使用次数"`
|
|
RevokedCount int `json:"revokedCount" dc:"已撤销数量"`
|
|
ExpiredCount int `json:"expiredCount" dc:"已过期数量"`
|
|
ExpiresAt *gtime.Time `json:"expiresAt" dc:"到期时间"`
|
|
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
|
|
}
|
|
|
|
type ImInviteBatchDetailModel struct {
|
|
ImInviteBatchModel
|
|
List []*ImInviteCodeModel `json:"list" dc:"批次邀请码"`
|
|
}
|
|
|
|
func ParseOptionalInt64(value string) (int64, error) {
|
|
if value == "" {
|
|
return 0, nil
|
|
}
|
|
parsed, err := strconv.ParseInt(value, 10, 64)
|
|
if err != nil || parsed <= 0 {
|
|
return 0, gerror.New("ID格式不正确")
|
|
}
|
|
return parsed, nil
|
|
}
|