package service import ( "bytes" "city_chips/internal/model" "city_chips/internal/repository" "context" "encoding/json" "errors" "fmt" "github.com/spf13/viper" "io" "net/http" "net/url" "reflect" ) type IlluminatingService interface { GetIlluminating(ctx context.Context, id int64) (*model.Illuminating, error) Illuminating(method, url string, body any) ([]byte, error) GetStatistics() ([]byte, error) GetBaseecic(currentPage, device_type_id, devices_enabled, pageSize int, query string) (model.IlluminatingBaseecic, error) } func NewIlluminatingService( service *Service, illuminatingRepository repository.IlluminatingRepository, viperViper *viper.Viper, client *http.Client, ) IlluminatingService { if client == nil { client = http.DefaultClient } return &illuminatingService{ Service: service, illuminatingRepository: illuminatingRepository, conf: viperViper, client: client, } } type illuminatingService struct { *Service illuminatingRepository repository.IlluminatingRepository conf *viper.Viper client *http.Client } func (s *illuminatingService) GetIlluminating(ctx context.Context, id int64) (*model.Illuminating, error) { return s.illuminatingRepository.GetIlluminating(ctx, id) } // func (s *illuminatingService) Illuminating(methond, url string, body any) ([]byte, error) { // urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.login") // authorization := s.conf.GetString("illuminating.authorization") // clientId := s.conf.GetInt("illuminating.clientId") // mobile := s.conf.GetString("illuminating.mobile") // password := s.conf.GetString("illuminating.password") // requst := model.LoginRequst{ // Authorization: authorization, // ClientId: clientId, // Mobile: mobile, // Password: password, // } // var login model.Login // var reqBody io.Reader // bodyBytes, err := json.Marshal(requst) // if err != nil { // return nil, err // } // reqBody = bytes.NewBuffer(bodyBytes) // request, err := http.NewRequest("POST", urls, reqBody) // if err != nil { // return nil, err // } // client := &http.Client{} // response, err := client.Do(request) // defer response.Body.Close() // if err != nil { // return nil, err // } // responseBody, err := io.ReadAll(response.Body) // if err != nil { // return nil, err // } // err = json.Unmarshal(responseBody, &login) // if err != nil { // return nil, err // } // if body != nil { // bodyBytes, err := json.Marshal(requst) // if err != nil { // return nil, err // } // reqBody = bytes.NewBuffer(bodyBytes) // } // var Bodys io.Reader // if body != nil { // Bytes, err := json.Marshal(body) // if err != nil { // return nil, err // } // Bodys = bytes.NewBuffer(Bytes) // } // newRequest, err := http.NewRequest(methond, url, Bodys) // if err != nil { // return nil, err // } // newRequest.Header.Set("Authorization", login.AccessToken) // newResponse, err := client.Do(newRequest) // defer newResponse.Body.Close() // if err != nil { // return nil, err // } // respBody, err := io.ReadAll(newResponse.Body) // if err != nil { // return nil, err // } // return respBody, nil // } func (s *illuminatingService) Illuminating(method, url string, body any) ([]byte, error) { login, err := s.login() if err != nil { return nil, err } var reqBody io.Reader var finalURL = url // 如果是 GET 请求,把 body 当作 query 参数处理 if method == http.MethodGet || method == "" { vals, err := buildQueryParams(body) if err != nil { return nil, err } finalURL = addQueryParams(url, vals) } else { // 非 GET 请求才构造 body reqBody, err = buildRequestBody(body) if err != nil { return nil, err } } request, err := http.NewRequest(method, finalURL, reqBody) if err != nil { return nil, err } request.Header.Set("Authorization", login.AccessToken) response, err := s.client.Do(request) if err != nil { return nil, err } defer response.Body.Close() respBody, err := io.ReadAll(response.Body) if err != nil { return nil, err } return respBody, nil } // login 封装登录逻辑 func (s *illuminatingService) login() (*model.Login, error) { auth := s.conf.GetString("illuminating.authorization") clientId := s.conf.GetInt("illuminating.clientId") mobile := s.conf.GetString("illuminating.mobile") password := s.conf.GetString("illuminating.password") loginReq := model.LoginRequst{ Authorization: auth, ClientId: clientId, Mobile: mobile, Password: password, } bodyBytes, err := json.Marshal(loginReq) if err != nil { return nil, err } url := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.login") request, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) if err != nil { return nil, err } response, err := s.client.Do(request) if err != nil { return nil, err } defer response.Body.Close() respBody, err := io.ReadAll(response.Body) if err != nil { return nil, err } var login model.Login if err := json.Unmarshal(respBody, &login); err != nil { return nil, err } return &login, nil } // 构建请求体工具函数 func buildRequestBody(body any) (io.Reader, error) { if body == nil { return nil, nil } bodyBytes, err := json.Marshal(body) if err != nil { return nil, err } return bytes.NewBuffer(bodyBytes), nil } func buildQueryParams(params any) (url.Values, error) { vals := make(url.Values) switch p := params.(type) { case nil: return vals, nil case url.Values: return p, nil case map[string]string: for k, v := range p { vals.Add(k, v) } case map[string][]string: for k, v := range p { for _, vv := range v { vals.Add(k, vv) } } default: // 使用反射解析结构体字段 t := reflect.TypeOf(p) v := reflect.ValueOf(p) for i := 0; i < t.NumField(); i++ { field := t.Field(i) value := v.Field(i).Interface() tag := field.Tag.Get("json") if tag == "" { tag = field.Name } vals.Add(tag, fmt.Sprintf("%v", value)) } } return vals, nil } func addQueryParams(baseURL string, values url.Values) string { if len(values) == 0 { return baseURL } u, err := url.Parse(baseURL) if err != nil { return baseURL // 忽略错误直接返回原值 } q := u.Query() for k, vs := range values { for _, v := range vs { q.Add(k, v) } } u.RawQuery = q.Encode() return u.String() } // GetStatistics 获取统计信息 func (s *illuminatingService) GetStatistics() ([]byte, error) { urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.statistics") illuminating, err := s.Illuminating("GET", urls, nil) if err != nil { return nil, errors.New("获取统计信息失败") } return illuminating, nil } // GetBaseecic 获取照明监控列表 func (s *illuminatingService) GetBaseecic(currentPage, device_type_id, devices_enabled, pageSize int, query string) (model.IlluminatingBaseecic, error) { var baseecic model.IlluminatingBaseecic urls := s.conf.GetString("illuminating.baseUrl") + s.conf.GetString("illuminating.api.baseecic") m := make(map[string]any) m["currentPage"] = currentPage m["device_type_id"] = device_type_id m["devices_enabled"] = devices_enabled m["pageSize"] = pageSize m["query"] = query illuminating, err := s.Illuminating("POST", urls, m) if err != nil { return model.IlluminatingBaseecic{}, errors.New("获取统计信息失败") } err = json.Unmarshal(illuminating, &baseecic) if err != nil { return model.IlluminatingBaseecic{}, errors.New("json反序列化失败") } return baseecic, nil }