240 lines
5.6 KiB
Go
240 lines
5.6 KiB
Go
package sys
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"hotgo/internal/dao"
|
|
"hotgo/internal/library/imadmin"
|
|
"hotgo/internal/library/imtenant"
|
|
"hotgo/internal/model/entity"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
)
|
|
|
|
type imAdminQueryPage struct {
|
|
Items []map[string]any `json:"items"`
|
|
Total int `json:"total"`
|
|
Page int `json:"page"`
|
|
PerPage int `json:"per_page"`
|
|
}
|
|
|
|
func resolveImAdminTenant(ctx context.Context, selectedTenantId int64) (tenant *entity.ImTenant, err error) {
|
|
scope, err := resolveImAdminScope(ctx, selectedTenantId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = imtenant.RegistryDB().Model(dao.ImTenant.Table()).Safe().Ctx(ctx).WherePri(scope.TenantId).Scan(&tenant); err != nil {
|
|
return nil, gerror.Wrap(err, "获取IM租户失败")
|
|
}
|
|
if tenant == nil || tenant.Id <= 0 || tenant.Code == "" {
|
|
return nil, gerror.New("IM租户不存在或编码为空")
|
|
}
|
|
return tenant, nil
|
|
}
|
|
|
|
func imAdminQueryList[T any](ctx context.Context, tenant *entity.ImTenant, path string, values url.Values, aliases map[string]string) (list []*T, totalCount int, err error) {
|
|
if values == nil {
|
|
values = url.Values{}
|
|
}
|
|
query := values.Encode()
|
|
if query != "" {
|
|
path += "?" + query
|
|
}
|
|
var page imAdminQueryPage
|
|
if err = imadmin.DefaultClient(ctx).InternalGet(ctx, path, &page); err != nil {
|
|
return nil, 0, err
|
|
}
|
|
normalizeImAdminRows(page.Items, aliases)
|
|
if len(page.Items) == 0 {
|
|
return []*T{}, page.Total, nil
|
|
}
|
|
raw, err := json.Marshal(page.Items)
|
|
if err != nil {
|
|
return nil, 0, gerror.Wrap(err, "转换IM内部查询列表失败")
|
|
}
|
|
if err = json.Unmarshal(raw, &list); err != nil {
|
|
return nil, 0, gerror.Wrap(err, "解析IM内部查询列表失败")
|
|
}
|
|
fillImTenantFields(tenant, &list)
|
|
return list, page.Total, nil
|
|
}
|
|
|
|
func imAdminQueryOne[T any](ctx context.Context, tenant *entity.ImTenant, path string, aliases map[string]string) (res *T, err error) {
|
|
row := map[string]any{}
|
|
if err = imadmin.DefaultClient(ctx).InternalGet(ctx, path, &row); err != nil {
|
|
return nil, err
|
|
}
|
|
normalizeImAdminRow(row, aliases)
|
|
raw, err := json.Marshal(row)
|
|
if err != nil {
|
|
return nil, gerror.Wrap(err, "转换IM内部查询详情失败")
|
|
}
|
|
if err = json.Unmarshal(raw, &res); err != nil {
|
|
return nil, gerror.Wrap(err, "解析IM内部查询详情失败")
|
|
}
|
|
fillImTenantFields(tenant, res)
|
|
return res, nil
|
|
}
|
|
|
|
func normalizeImAdminRows(rows []map[string]any, aliases map[string]string) {
|
|
for _, row := range rows {
|
|
normalizeImAdminRow(row, aliases)
|
|
}
|
|
}
|
|
|
|
func normalizeImAdminRow(row map[string]any, aliases map[string]string) {
|
|
for key, value := range row {
|
|
target := snakeToLowerCamel(key)
|
|
if aliases != nil {
|
|
if alias := aliases[key]; alias != "" {
|
|
target = alias
|
|
}
|
|
}
|
|
value = normalizeImAdminValue(target, value)
|
|
if target == key {
|
|
row[key] = value
|
|
continue
|
|
}
|
|
row[target] = value
|
|
delete(row, key)
|
|
}
|
|
if _, ok := row["authNames"]; !ok {
|
|
username, _ := row["username"].(string)
|
|
phone, _ := row["phone"].(string)
|
|
authNames := username
|
|
if phone != "" && phone != username {
|
|
if authNames != "" {
|
|
authNames += ", "
|
|
}
|
|
authNames += phone
|
|
}
|
|
if authNames != "" {
|
|
row["authNames"] = authNames
|
|
}
|
|
}
|
|
}
|
|
|
|
func normalizeImAdminValue(target string, value any) any {
|
|
if target != "credentials" {
|
|
return value
|
|
}
|
|
items, ok := value.([]any)
|
|
if !ok {
|
|
return value
|
|
}
|
|
parts := make([]string, 0, len(items))
|
|
for _, item := range items {
|
|
m, ok := item.(map[string]any)
|
|
if !ok {
|
|
continue
|
|
}
|
|
method, _ := m["method"].(string)
|
|
val, _ := m["value"].(string)
|
|
if method == "" && val == "" {
|
|
continue
|
|
}
|
|
text := method
|
|
if val != "" {
|
|
if text != "" {
|
|
text += ":"
|
|
}
|
|
text += val
|
|
}
|
|
if done, ok := m["done"].(bool); ok && !done {
|
|
text += "(未验证)"
|
|
}
|
|
parts = append(parts, text)
|
|
}
|
|
return strings.Join(parts, ", ")
|
|
}
|
|
|
|
func snakeToLowerCamel(s string) string {
|
|
if !strings.Contains(s, "_") {
|
|
return s
|
|
}
|
|
parts := strings.Split(s, "_")
|
|
var b strings.Builder
|
|
for i, part := range parts {
|
|
if part == "" {
|
|
continue
|
|
}
|
|
if i == 0 {
|
|
b.WriteString(part)
|
|
continue
|
|
}
|
|
b.WriteString(strings.ToUpper(part[:1]))
|
|
if len(part) > 1 {
|
|
b.WriteString(part[1:])
|
|
}
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
func fillImTenantFields(tenant *entity.ImTenant, target any) {
|
|
raw, err := json.Marshal(target)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var rows []map[string]any
|
|
if err = json.Unmarshal(raw, &rows); err == nil {
|
|
for _, row := range rows {
|
|
row["tenantId"] = tenant.Id
|
|
row["tenantName"] = tenant.Name
|
|
}
|
|
updated, _ := json.Marshal(rows)
|
|
_ = json.Unmarshal(updated, target)
|
|
return
|
|
}
|
|
var row map[string]any
|
|
if err = json.Unmarshal(raw, &row); err == nil {
|
|
row["tenantId"] = tenant.Id
|
|
row["tenantName"] = tenant.Name
|
|
updated, _ := json.Marshal(row)
|
|
_ = json.Unmarshal(updated, target)
|
|
}
|
|
}
|
|
|
|
func addPageQuery(values url.Values, page int, perPage int) url.Values {
|
|
if values == nil {
|
|
values = url.Values{}
|
|
}
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
if perPage <= 0 {
|
|
perPage = 20
|
|
}
|
|
values.Set("page", intToString(page))
|
|
values.Set("per_page", intToString(perPage))
|
|
return values
|
|
}
|
|
|
|
func addTimeRangeQuery(values url.Values, prefix string, times []*gtime.Time) {
|
|
if len(times) != 2 {
|
|
return
|
|
}
|
|
if times[0] != nil {
|
|
values.Set(prefix+"_start", times[0].Time.UTC().Format(time.RFC3339Nano))
|
|
}
|
|
if times[1] != nil {
|
|
values.Set(prefix+"_end", times[1].Time.UTC().Format(time.RFC3339Nano))
|
|
}
|
|
}
|
|
|
|
func intToString(v int) string {
|
|
return strconvFormatInt(int64(v))
|
|
}
|
|
|
|
func int64ToString(v int64) string {
|
|
return strconvFormatInt(v)
|
|
}
|
|
|
|
func strconvFormatInt(v int64) string {
|
|
return strconv.FormatInt(v, 10)
|
|
}
|