193 lines
4.2 KiB
Go
193 lines
4.2 KiB
Go
package response
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"strings"
|
|
"time"
|
|
|
|
"affiliate_dash/internal/pkg/timeutil"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
var (
|
|
timeType = reflect.TypeOf(time.Time{})
|
|
rawMessageType = reflect.TypeOf(json.RawMessage{})
|
|
)
|
|
|
|
type Body struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"message"`
|
|
Data interface{} `json:"data,omitempty"`
|
|
}
|
|
|
|
func OK(c *gin.Context, data interface{}) {
|
|
WithStatus(c, http.StatusOK, data)
|
|
}
|
|
|
|
func WithStatus(c *gin.Context, httpStatus int, data interface{}) {
|
|
c.JSON(httpStatus, Body{Code: 0, Message: "ok", Data: NormalizeTime(data)})
|
|
}
|
|
|
|
func Fail(c *gin.Context, httpStatus int, code int, message string) {
|
|
c.JSON(httpStatus, Body{Code: code, Message: message})
|
|
}
|
|
|
|
func BadRequest(c *gin.Context, message string) {
|
|
Fail(c, http.StatusBadRequest, 400, message)
|
|
}
|
|
|
|
func Unauthorized(c *gin.Context, message string) {
|
|
Fail(c, http.StatusUnauthorized, 401, message)
|
|
}
|
|
|
|
func Forbidden(c *gin.Context, message string) {
|
|
Fail(c, http.StatusForbidden, 403, message)
|
|
}
|
|
|
|
func NotFound(c *gin.Context, message string) {
|
|
Fail(c, http.StatusNotFound, 404, message)
|
|
}
|
|
|
|
func ServerError(c *gin.Context, message string) {
|
|
Fail(c, http.StatusInternalServerError, 500, message)
|
|
}
|
|
|
|
type PageData struct {
|
|
List interface{} `json:"list"`
|
|
Total int64 `json:"total"`
|
|
Page int `json:"page"`
|
|
Size int `json:"size"`
|
|
}
|
|
|
|
func Page(c *gin.Context, list interface{}, total int64, page, size int) {
|
|
OK(c, PageData{List: list, Total: total, Page: page, Size: size})
|
|
}
|
|
|
|
func FormatTime(value time.Time) string {
|
|
return timeutil.FormatAPITime(value)
|
|
}
|
|
|
|
func NormalizeTime(value interface{}) interface{} {
|
|
return normalizeTimeValue(reflect.ValueOf(value))
|
|
}
|
|
|
|
func normalizeTimeValue(value reflect.Value) interface{} {
|
|
if !value.IsValid() {
|
|
return nil
|
|
}
|
|
if value.Kind() == reflect.Interface {
|
|
if value.IsNil() {
|
|
return nil
|
|
}
|
|
return normalizeTimeValue(value.Elem())
|
|
}
|
|
if value.Type() == rawMessageType {
|
|
return value.Interface()
|
|
}
|
|
if value.Type() == timeType {
|
|
if !value.CanInterface() {
|
|
return nil
|
|
}
|
|
return FormatTime(value.Interface().(time.Time))
|
|
}
|
|
switch value.Kind() {
|
|
case reflect.Pointer:
|
|
if value.IsNil() {
|
|
return nil
|
|
}
|
|
if value.Type().Elem() == timeType {
|
|
return FormatTime(value.Elem().Interface().(time.Time))
|
|
}
|
|
return normalizeTimeValue(value.Elem())
|
|
case reflect.Slice, reflect.Array:
|
|
if value.Kind() == reflect.Slice && value.IsNil() {
|
|
return nil
|
|
}
|
|
if value.Type().Elem().Kind() == reflect.Uint8 {
|
|
return value.Interface()
|
|
}
|
|
out := make([]interface{}, 0, value.Len())
|
|
for i := 0; i < value.Len(); i++ {
|
|
out = append(out, normalizeTimeValue(value.Index(i)))
|
|
}
|
|
return out
|
|
case reflect.Map:
|
|
if value.IsNil() {
|
|
return nil
|
|
}
|
|
out := make(map[string]interface{}, value.Len())
|
|
iter := value.MapRange()
|
|
for iter.Next() {
|
|
out[mapKeyString(iter.Key())] = normalizeTimeValue(iter.Value())
|
|
}
|
|
return out
|
|
case reflect.Struct:
|
|
return normalizeTimeStruct(value)
|
|
default:
|
|
if value.CanInterface() {
|
|
return value.Interface()
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func normalizeTimeStruct(value reflect.Value) map[string]interface{} {
|
|
out := make(map[string]interface{}, value.NumField())
|
|
valueType := value.Type()
|
|
for i := 0; i < value.NumField(); i++ {
|
|
field := valueType.Field(i)
|
|
if field.PkgPath != "" {
|
|
continue
|
|
}
|
|
name, skip, omitEmpty := jsonFieldName(field)
|
|
if skip {
|
|
continue
|
|
}
|
|
fieldValue := value.Field(i)
|
|
if omitEmpty && fieldValue.IsZero() {
|
|
continue
|
|
}
|
|
out[name] = normalizeTimeValue(fieldValue)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func jsonFieldName(field reflect.StructField) (string, bool, bool) {
|
|
tag := field.Tag.Get("json")
|
|
if tag == "-" {
|
|
return "", true, false
|
|
}
|
|
if tag == "" {
|
|
return field.Name, false, false
|
|
}
|
|
parts := strings.Split(tag, ",")
|
|
name := parts[0]
|
|
if name == "" {
|
|
name = field.Name
|
|
}
|
|
return name, false, hasTagOption(parts[1:], "omitempty")
|
|
}
|
|
|
|
func hasTagOption(options []string, target string) bool {
|
|
for _, option := range options {
|
|
if option == target {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func mapKeyString(value reflect.Value) string {
|
|
if value.Kind() == reflect.String {
|
|
return value.String()
|
|
}
|
|
if value.CanInterface() {
|
|
return fmt.Sprint(value.Interface())
|
|
}
|
|
return ""
|
|
}
|