yankun 6 meses atrás
pai
commit
56101734bf
100 arquivos alterados com 9172 adições e 1053 exclusões
  1. 57 30
      app/api/youngee_talent_api/talent_auth_get_api.go
  2. 10 1
      app/api/youngee_talent_api/talent_auth_post_api.go
  3. 11 0
      app/api/youngee_talent_api/talent_get_api.go
  4. 99 5
      app/model/youngee_talent_model/message.go
  5. 2 2
      app/model/youngee_talent_model/product_info.go
  6. 13 11
      app/model/youngee_talent_model/project_detail.go
  7. 39 37
      app/model/youngee_talent_model/selection.go
  8. 27 20
      app/model/youngee_talent_model/talent_bank.go
  9. 34 34
      app/model/youngee_talent_model/talent_income.go
  10. 1 1
      app/model/youngee_talent_model/talent_info.go
  11. 2 2
      app/model/youngee_talent_model/task_info.go
  12. 336 116
      app/service/youngee_sectask_service/seletion_square.go
  13. 138 88
      app/service/youngee_talent_service/log_message.go
  14. 183 79
      app/service/youngee_talent_service/talent_bank.go
  15. 254 254
      app/service/youngee_talent_service/talent_income.go
  16. 21 0
      app/service/youngee_talent_service/talent_info.go
  17. 100 6
      app/service/youngee_talent_service/talent_ks_auth.go
  18. 140 69
      app/service/youngee_task_service/project_info.go
  19. 202 87
      app/service/youngee_task_service/task_data.go
  20. 21 19
      app/service/youngee_task_service/task_info.go
  21. 141 82
      app/service/youngee_task_service/task_link.go
  22. 170 98
      app/service/youngee_task_service/task_sketch.go
  23. BIN
      bin/main
  24. BIN
      bin/v3.7.3/linux_amd64/.DS_Store
  25. BIN
      bin/v3.7.3/windows_amd64/youngmini_server.exe
  26. BIN
      bin/v3.7.4/linux_amd64/.DS_Store
  27. BIN
      bin/v3.7.4/windows_amd64/youngmini_server.exe
  28. 1 1
      config/config.toml
  29. 11 4
      go.mod
  30. 126 7
      go.sum
  31. 73 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/LICENSE
  32. 353 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic/basic_icredential.go
  33. 58 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/cache/auth_cache.go
  34. 45 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/derived_icredential.go
  35. 344 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global/global_icredential.go
  36. 30 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/icredential.go
  37. 325 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal/iam_service.go
  38. 73 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal/metadata.go
  39. 80 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/credential_provider.go
  40. 94 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/env_provider.go
  41. 73 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/metadata_provider.go
  42. 125 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/profile_provider.go
  43. 82 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/provider_chain.go
  44. 33 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm/signing_algorithm.go
  45. 121 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/derived_signer.go
  46. 89 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/hasher.go
  47. 45 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/iaksksigner.go
  48. 44 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/init.go
  49. 140 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/p256_sha256_signer.go
  50. 312 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/signer.go
  51. 110 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/signing_key.go
  52. 94 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/sm2_sm3_signer.go
  53. 75 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/sm3_signer.go
  54. 182 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config/http_config.go
  55. 96 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter/converters.go
  56. 183 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter/types.go
  57. 62 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/field.go
  58. 78 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/http_request_def.go
  59. 108 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/multipart.go
  60. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange/exchange.go
  61. 35 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange/reference.go
  62. 521 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/hc_http_client.go
  63. 155 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/hc_http_client_builder.go
  64. 64 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/httphandler/http_handler.go
  65. 251 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl/default_http_client.go
  66. 113 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/invoker.go
  67. 37 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/decorrelated_jitter.go
  68. 38 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/equal_jitter.go
  69. 42 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/exponential.go
  70. 28 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/none.go
  71. 38 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/random_jitter.go
  72. 52 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/strategy.go
  73. 45 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/event.go
  74. 24 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/listener.go
  75. 95 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/reader.go
  76. 27 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/request.go
  77. 73 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/env_region.go
  78. 136 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/profile_region.go
  79. 42 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region.go
  80. 39 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region_chain.go
  81. 24 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region_provider.go
  82. 423 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request/default_http_request.go
  83. 136 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request/http_request_builder.go
  84. 82 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response/default_http_response.go
  85. 39 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr/error_handler.go
  86. 175 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr/errors.go
  87. 40 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/json_utils.go
  88. 64 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/math_utils.go
  89. 28 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/string_utils.go
  90. 146 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_client.go
  91. 102 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_invoker.go
  92. 164 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_meta.go
  93. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_actions_list.go
  94. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_id_card_image_request.go
  95. 26 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_id_card_image_response.go
  96. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_name_and_id_request.go
  97. 26 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_name_and_id_response.go
  98. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_id_card_image_request.go
  99. 26 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_id_card_image_response.go
  100. 25 0
      vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_name_and_id_request.go

+ 57 - 30
app/api/youngee_talent_api/talent_auth_get_api.go

@@ -26,6 +26,17 @@ func (*talentAuthGetApi) GetProjectDetail(r *ghttp.Request) {
 	}
 }
 
+// todo: 获取本地生活详情页
+//func (*talentGetApi) GetLocalLifeDetail(r *ghttp.Request) {
+//	res := youngee_task_service.GetLocalLifeDetail(r)
+//	fmt.Println("我进入了talent_get_api中的GetProjectList(展示所有种草)")
+//
+//	err := r.Response.WriteJson(res)
+//	if err != nil {
+//		panic("write response error")
+//	}
+//}
+
 // GetTalentInfo 获取达人信息
 // youngee_talent_info
 func (*talentAuthGetApi) GetTalentInfo(r *ghttp.Request) {
@@ -221,15 +232,6 @@ func (*talentAuthGetApi) SignUpProjKuaishouList(r *ghttp.Request) {
 	}
 }
 
-// 带货加入橱窗---选中账号---点击提交(选品不存在/未开通)--需要提供productid和openid和粉丝数和销量(他们来自list中)
-func (*talentAuthGetApi) AddWindowWithKsAccount(r *ghttp.Request) {
-	res := youngee_talent_service.AddWindowWithKsAccount(r)
-	err := r.Response.WriteJson(res)
-	if err != nil {
-		panic("write response error")
-	}
-}
-
 func (*talentAuthGetApi) AddWindow(r *ghttp.Request) {
 	res := youngee_talent_service.AddWindow(r)
 	err := r.Response.WriteJson(res)
@@ -361,13 +363,13 @@ func (*talentAuthGetApi) GetTaskSketch(r *ghttp.Request) {
 
 // SubmitTaskSketch 提交任务初稿
 // younggee_sketch_info
-func (*talentAuthGetApi) SubmitTaskSketch(r *ghttp.Request) {
-	res := youngee_task_service.SubmitTaskSketch(r)
-	err := r.Response.WriteJson(res)
-	if err != nil {
-		panic("write response error")
-	}
-}
+//func (*talentAuthGetApi) SubmitTaskSketch(r *ghttp.Request) {
+//	res := youngee_task_service.SubmitTaskSketch(r)
+//	err := r.Response.WriteJson(res)
+//	if err != nil {
+//		panic("write response error")
+//	}
+//}
 
 // GetUnSubmitTaskSketch 获取未提交的任务初稿
 // younggee_sketch_info  //is_review = 0
@@ -391,13 +393,13 @@ func (*talentAuthGetApi) GetTaskData(r *ghttp.Request) {
 
 // SubmitTaskData 提交任务数据
 // younggee_data_info
-func (*talentAuthGetApi) SubmitTaskData(r *ghttp.Request) {
-	res := youngee_task_service.SubmitTaskData(r)
-	err := r.Response.WriteJson(res)
-	if err != nil {
-		panic("write response error")
-	}
-}
+//func (*talentAuthGetApi) SubmitTaskData(r *ghttp.Request) {
+//	res := youngee_task_service.SubmitTaskData(r)
+//	err := r.Response.WriteJson(res)
+//	if err != nil {
+//		panic("write response error")
+//	}
+//}
 
 // GetUnSubmitTaskData 获取未提交的任务数据
 // younggee_data_info
@@ -421,13 +423,13 @@ func (*talentAuthGetApi) GetTaskLink(r *ghttp.Request) {
 
 // SubmitTaskLink 提交任务链接
 // younggee_link_info
-func (*talentAuthGetApi) SubmitTaskLink(r *ghttp.Request) {
-	res := youngee_task_service.SubmitTaskLink(r)
-	err := r.Response.WriteJson(res)
-	if err != nil {
-		panic("write response error")
-	}
-}
+//func (*talentAuthGetApi) SubmitTaskLink(r *ghttp.Request) {
+//	res := youngee_task_service.SubmitTaskLink(r)
+//	err := r.Response.WriteJson(res)
+//	if err != nil {
+//		panic("write response error")
+//	}
+//}
 
 // GetUnSubmitTaskLink 获取未提交的任务链接
 // younggee_link_info
@@ -466,6 +468,7 @@ func (*talentAuthGetApi) GetTaskLog(r *ghttp.Request) {
 	}
 }
 
+// 弃用
 func (*talentAuthGetApi) GetMessage(r *ghttp.Request) {
 	res := youngee_talent_service.GetMessage(r)
 	err := r.Response.WriteJson(res)
@@ -474,6 +477,21 @@ func (*talentAuthGetApi) GetMessage(r *ghttp.Request) {
 	}
 }
 
+func (*talentAuthGetApi) GetMessageList(r *ghttp.Request) {
+	res := youngee_talent_service.GetMessageList(r)
+	err := r.Response.WriteJson(res)
+	if err != nil {
+		panic("write response error")
+	}
+}
+
+func (*talentAuthGetApi) GetMessageDetail(r *ghttp.Request) {
+	res := youngee_talent_service.GetMessageDetail(r)
+	err := r.Response.WriteJson(res)
+	if err != nil {
+		panic("write response error")
+	}
+}
 func (*talentAuthGetApi) HasUnReadMessage(r *ghttp.Request) {
 	res := youngee_talent_service.HasUnReadMessage(r)
 	err := r.Response.WriteJson(res)
@@ -618,6 +636,15 @@ func (*talentAuthGetApi) GetProjectCollectionList(r *ghttp.Request) {
 	}
 }
 
+// 达人是否已收藏商品
+func (*talentAuthGetApi) IsSecCollection(r *ghttp.Request) {
+	res := youngee_talent_service.IsSecCollection(r)
+	err := r.Response.WriteJson(res)
+	if err != nil {
+		panic("write response error")
+	}
+}
+
 // 收藏/取消收藏 收藏表中插入数据。带货项目 参数:selectionId,productId
 func (*talentAuthGetApi) SelectionCollection(r *ghttp.Request) {
 	res := youngee_task_service.SelectionCollection(r)

+ 10 - 1
app/api/youngee_talent_api/talent_auth_post_api.go

@@ -94,7 +94,7 @@ func (*talentAuthPostApi) UpdateTalentAccount(r *ghttp.Request) {
 // OnAddTalentBank 添加银行卡绑定信息
 // younggee_talent_bank
 func (*talentAuthPostApi) AddTalentBank(r *ghttp.Request) {
-	res := youngee_talent_service.OnAddTalentBank(r)
+	res := youngee_talent_service.AddTalentBank(r)
 	err := r.Response.WriteJson(res)
 	if err != nil {
 		panic("write response error")
@@ -210,6 +210,15 @@ func (*talentAuthPostApi) AddYoungTeam(r *ghttp.Request) {
 //	}
 //}
 
+// 带货加入橱窗---选中账号---点击提交(选品不存在/未开通)--需要提供productid和openid和粉丝数和销量(他们来自list中)
+func (*talentAuthGetApi) AddWindowWithKsAccount(r *ghttp.Request) {
+	res := youngee_talent_service.AddWindowWithKsAccount(r)
+	err := r.Response.WriteJson(res)
+	if err != nil {
+		panic("write response error")
+	}
+}
+
 // 带货---已选中账号--点击立即报名并加入橱窗
 func (*talentAuthPostApi) SignUpSecTaskWithKsAccount(r *ghttp.Request) {
 	res := youngee_sectask_service.SignUpSecTaskWithKsAccount(r)

+ 11 - 0
app/api/youngee_talent_api/talent_get_api.go

@@ -35,6 +35,17 @@ func (*talentGetApi) GetProjectList(r *ghttp.Request) {
 	}
 }
 
+// todo :获取种草列表
+//func (*talentGetApi) GetLocalLifeList(r *ghttp.Request) {
+//	res := youngee_task_service.GetLocalLifeList(r)
+//	fmt.Println("我进入了talent_get_api中的GetProjectList(展示所有种草)")
+//
+//	err := r.Response.WriteJson(res)
+//	if err != nil {
+//		panic("write response error")
+//	}
+//}
+
 // 获取选品任务广场展示列表
 // 前端可能传过来筛选和搜索的参数
 // 筛选参数参数形如&secform[]=2&secform[]=3&secform[]=9

+ 99 - 5
app/model/youngee_talent_model/message.go

@@ -1,5 +1,99 @@
-package youngee_talent_model
-
-type DeleteMessageReq struct {
-	MessageId int `orm:"message_id"           json:"message_id"`
-}
+package youngee_talent_model
+
+import (
+	"github.com/gogf/gf/os/gtime"
+	"github.com/gogf/gf/util/gmeta"
+)
+
+type DeleteMessageReq struct {
+	MessageId int `orm:"message_id"           json:"message_id"`
+}
+
+// 定义消息表的结构体
+// 分别表示--平台通知、执行进度通知、样品申请通知、悬赏领取通知、物流助手通知、提现进度
+type AllMessList struct {
+	SysMess      []YounggeeMessageSystem   `json:"sys_mess"`
+	ExeMess      []YounggeeMessageExe      `json:"exe_mess"`
+	SampleMess   []YounggeeMessageSample   `json:"sample_mess"`
+	RewardMess   []YounggeeMessageReward   `json:"reward_mess"`
+	DeliveryMess []YounggeeMessageDelivery `json:"delivery_mess"`
+	WithdrawMess []YounggeeMessageWithdraw `json:"withdraw_mess"`
+}
+
+// 执行进度消息
+type YounggeeMessageExe struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 样品申请通知
+type YounggeeMessageSample struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 悬赏领取通知
+type YounggeeMessageReward struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 物流助手通知
+type YounggeeMessageDelivery struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 提现进度通知
+type YounggeeMessageWithdraw struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 系统消息
+type YounggeeMessageSystem struct {
+	gmeta.Meta     `orm:"table:message_system"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}
+
+// 包含所有消息
+type YounggeeMutilMessInfo struct {
+	gmeta.Meta     `orm:"table:message_multi_info"`
+	Id             int         `orm:"id,primary"   json:"id"`                 // id,递增
+	MessageContent string      `orm:"message_content" json:"message_content"` //具体消息信息
+	MessType       int         `orm:"mess_type"     json:"mess_type"`         //消息类型
+	TalentId       string      `orm:"talent_id"     json:"talent_id"`
+	CreatedAt      *gtime.Time `orm:"created_at"   json:"created_at"` // 消息创建时间
+	IsReaded       int         `orm:"is_readed"    json:"is_readed"`  // 是否已读,1表示未读,2表示已读
+	IsDeleted      int         `orm:"is_deleted"   json:"is_deleted"` // 是否删除,1表示未删,2表示已删
+}

+ 2 - 2
app/model/youngee_talent_model/product_info.go

@@ -13,7 +13,7 @@ type YounggeeProduct struct {
 	ProductName         string      `json:"product_name"`         // 商品名称
 	ProductType         int         `json:"product_type"`         // 商品类型
 	ShopAddress         string      `json:"shop_address"`         // 店铺地址,商品类型为线下品牌时需填写
-	ProductPrice        int64       `json:"product_price"`        // 商品价值
+	ProductPrice        float64     `json:"product_price"`        // 商品价值
 	ProductDetail       string      `json:"product_detail"`       //
 	ProductUrl          string      `json:"product_url"`          // 商品链接,可为电商网址、公司官网、大众点评的店铺地址等可以说明商品信息或者品牌信息的线上地址;
 	EnterpriseId        int         `json:"enterprise_id"`        // 所属企业id
@@ -22,7 +22,7 @@ type YounggeeProduct struct {
 	BrandName           string      `json:"brand_name"`           //
 	CommissionPrice     string      `json:"commission_price"`     //api获取,佣金金额
 	PublicCommission    string      `json:"public_commission"`    //公开佣金%
-	ExclusiveCommission string      `json:"exclusive_commission"` //专属佣金%
+	ExclusiveCommission float64     `json:"exclusive_commission"` //专属佣金%
 	SalesCount          string      `json:"sales_count"`          //总销量
 }
 

+ 13 - 11
app/model/youngee_talent_model/project_detail.go

@@ -35,17 +35,17 @@ type ProductPhoto struct {
 
 type RecruitStrategy struct {
 	gmeta.Meta        `orm:"table:recruit_strategy"`
-	RecruitStrategyId int    `json:"recruit_strategy_id"` // 招募策略id
-	FeeForm           int    `json:"fee_form"`            // 稿费形式,1-3分别代表产品置换、固定稿费、自报价
-	StrategyId        int    `json:"strategy_id"`         // 策略id
-	FollowersLow      int    `json:"followers_low"`       // 达人粉丝数下限
-	FollowersUp       int    `json:"followers_up"`        // 达人粉丝数上限
-	RecruitNumber     int    `json:"recruit_number"`      // 招募数量
-	Offer             int    `json:"offer"`               // 报价
-	TOffer            int    `json:"t_offer"`             // 达人报价报价
-	ProjectId         string `json:"project_id"`          // 所属项目id
-	ServiceCharge     int    `json:"service_charge"`      // 平台服务费,稿费形式为产品置换时必填
-	IsFit             int    `json:"is_fit"`              //此策略是否匹配成功
+	RecruitStrategyId int     `json:"recruit_strategy_id"` // 招募策略id
+	FeeForm           int     `json:"fee_form"`            // 稿费形式,1-3分别代表产品置换、固定稿费、自报价
+	StrategyId        int     `json:"strategy_id"`         // 策略id
+	FollowersLow      int     `json:"followers_low"`       // 达人粉丝数下限
+	FollowersUp       int     `json:"followers_up"`        // 达人粉丝数上限
+	RecruitNumber     int     `json:"recruit_number"`      // 招募数量
+	Offer             int     `json:"offer"`               // 报价
+	TOffer            int     `json:"t_offer"`             // 达人报价报价
+	ProjectId         string  `json:"project_id"`          // 所属项目id
+	ServiceCharge     float64 `json:"service_charge"`      // 平台服务费,稿费形式为产品置换时必填
+	IsFit             int     `json:"is_fit"`              //此策略是否匹配成功
 }
 
 // 种草brief
@@ -151,4 +151,6 @@ type ProjectDetail struct {
 	PlatformInfo        *PlatformInfo        `orm:"with:platform_id=project_platform"`              //平台信息,目前为快手
 	ProductSnap         string               `orm:"product_snap"         json:"product_snap"`       // 商品信息快照
 	ProductPhotoSnap    string               `orm:"product_photo_snap"   json:"product_photo_snap"` // 商品图片快照
+	ServiceChargeRate   float64              `orm:"service_charge_rate" json:"service_charge_rate"` //服务费率
+	ViewNum             int                  `orm:"view_num" json:"view_num"`                       //浏览量
 }

+ 39 - 37
app/model/youngee_talent_model/selection.go

@@ -97,43 +97,45 @@ type SelectionExample struct {
 
 type SelectionDetail struct {
 	gmeta.Meta           `orm:"table:younggee_selection_info"`
-	SelectionName        string                  `json:"selection_name"`                // 选品项目名称
-	SelectionId          string                  `json:"selection_id"`                  // 选品项目id
-	EnterpriseId         string                  `json:"enterprise_id"`                 // 所属企业id
-	ProductId            int                     `json:"product_id"`                    // 商品id(主键)
-	ContentType          int                     `json:"content_type"`                  // 内容形式,1代表图文,2代表视频
-	SelectionStatus      int                     `json:"selection_status"`              // 选品项目状态,1-10分别代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
-	TaskMode             int                     `json:"task_mode"`                     // 任务形式,1、2分别表示悬赏任务、纯佣带货
-	Platform             int                     `json:"platform"`                      // 项目平台,1-7分别代表小红书、抖音、微博、快手、b站、大众点评、知乎
-	SampleMode           int                     `json:"sample_mode"`                   // 领样形式,1、2、3分别表示免费领样、垫付领样、不提供
-	ProductUrl           string                  `json:"product_url"`                   // 带货链接
-	SampleNum            int                     `json:"sample_num"`                    // 样品数量
-	RemainNum            int                     `json:"remain_num"`                    // 剩余数量
-	TaskDdl              *gtime.Time             `json:"task_ddl"`                      // 招募截止时间
-	Detail               string                  `json:"detail"`                        // 卖点总结
-	TaskReward           float64                 `json:"task_reward"`                   // 任务悬赏
-	CommissionRate       int                     `json:"commission_rate"`               // 佣金比例
-	EstimatedCost        float64                 `json:"estimated_cost"`                // 预估成本
-	SampleCondition      string                  `json:"sample_condition"`              // 领样条件
-	RewardCondition      string                  `json:"reward_condition"`              // 返现悬赏条件
-	CreatedAt            *gtime.Time             `json:"created_at"`                    // 创建时间
-	UpdatedAt            *gtime.Time             `json:"updated_at"`                    // 修改时间
-	FailReason           int                     `json:"fail_reason"`                   // 失效原因,1、2分别表示逾期未支付、项目存在风险
-	PassAt               *gtime.Time             `json:"pass_at"`                       // 审核通过时间
-	FinishAt             *gtime.Time             `json:"finish_at"`                     // 结案时间
-	IsRead               int                     `json:"is_read"`                       // 是否已读
-	SettlementAmount     float64                 `json:"settlement_amount"`             // 结算金额
-	ProductSnap          string                  `json:"product_snap"`                  // 商品信息快照
-	ProductPhotoSnap     string                  `json:"product_photo_snap"`            // 商品图片快照
-	SubmitAt             *gtime.Time             `json:"submit_at"`                     // 提交审核时间
-	SelectionBrief       []*SelectionBrief       `orm:"with:selection_id=selection_id"` // 项目brief 一个selection可能有多个brief,用列表
-	SelectionExample     []*SelectionExample     `orm:"with:selection_id=selection_id"` // 项目样例图
-	FreeStrategy         []*FreeStrategy         `orm:"with:selection_id=selection_id"` // 领样策略表
-	RewardStrategy       []*RewardStrategy       `orm:"with:selection_id=selection_id"` // 悬赏策略表
-	YounggeeProduct      []*YounggeeProduct      `orm:"with:product_id=product_id"`     // 商品基本表
-	YounggeeProductPhoto []*YounggeeProductPhoto `orm:"with:product_id=product_id"`     // 商品图片表
-	PlatformInfo         *PlatformInfo           `orm:"with:platform_id=platform"`      //一个selection只有一个平台,直接指针对象object
-	EnterpriseInfo       *Enterprise             `orm:"with:enterprise_id=enterprise_id"`
+	SelectionName        string                  `json:"selection_name"`                  // 选品项目名称
+	SelectionId          string                  `json:"selection_id"`                    // 选品项目id
+	EnterpriseId         string                  `json:"enterprise_id"`                   // 所属企业id
+	ProductId            int                     `json:"product_id"`                      // 商品id(主键)
+	ContentType          int                     `json:"content_type"`                    // 内容形式,1代表图文,2代表视频
+	SelectionStatus      int                     `json:"selection_status"`                // 选品项目状态,1-10分别代表创建中、待审核、审核通过、招募中、招募完毕、待支付、已支付、失效、执行中、已结案
+	TaskMode             int                     `json:"task_mode"`                       // 任务形式,1、2分别表示悬赏任务、纯佣带货
+	Platform             int                     `json:"platform"`                        // 项目平台,1-7分别代表小红书、抖音、微博、快手、b站、大众点评、知乎
+	SampleMode           int                     `json:"sample_mode"`                     // 领样形式,1、2、3分别表示免费领样、垫付领样、不提供
+	ProductUrl           string                  `json:"product_url"`                     // 带货链接
+	SampleNum            int                     `json:"sample_num"`                      // 样品数量
+	RemainNum            int                     `json:"remain_num"`                      // 剩余数量
+	TaskDdl              *gtime.Time             `json:"task_ddl"`                        // 招募截止时间
+	Detail               string                  `json:"detail"`                          // 卖点总结
+	TaskReward           float64                 `json:"task_reward"`                     // 任务悬赏
+	CommissionRate       int                     `json:"commission_rate"`                 // 佣金比例
+	EstimatedCost        float64                 `json:"estimated_cost"`                  // 预估成本
+	SampleCondition      string                  `json:"sample_condition"`                // 领样条件
+	RewardCondition      string                  `json:"reward_condition"`                // 返现悬赏条件
+	CreatedAt            *gtime.Time             `json:"created_at"`                      // 创建时间
+	UpdatedAt            *gtime.Time             `json:"updated_at"`                      // 修改时间
+	FailReason           int                     `json:"fail_reason"`                     // 失效原因,1、2分别表示逾期未支付、项目存在风险
+	PassAt               *gtime.Time             `json:"pass_at"`                         // 审核通过时间
+	FinishAt             *gtime.Time             `json:"finish_at"`                       // 结案时间
+	IsRead               int                     `json:"is_read"`                         // 是否已读
+	SettlementAmount     float64                 `json:"settlement_amount"`               // 结算金额
+	ProductSnap          string                  `json:"product_snap"`                    // 商品信息快照
+	ProductPhotoSnap     string                  `json:"product_photo_snap"`              // 商品图片快照
+	SubmitAt             *gtime.Time             `json:"submit_at"`                       // 提交审核时间
+	EnrollNum            int                     `json:"enroll_num"`                      //报名人数
+	SelectionBrief       []*SelectionBrief       `orm:"with:selection_id=selection_id"`   // 项目brief 一个selection可能有多个brief,用列表
+	SelectionExample     []*SelectionExample     `orm:"with:selection_id=selection_id"`   // 项目样例图
+	FreeStrategy         []*FreeStrategy         `orm:"with:selection_id=selection_id"`   // 领样策略表
+	RewardStrategy       *RewardStrategy         `orm:"with:selection_id=selection_id"`   // 悬赏策略表
+	YounggeeProduct      *YounggeeProduct        `orm:"with:product_id=product_id"`       // 商品基本表
+	YounggeeProductPhoto []*YounggeeProductPhoto `orm:"with:product_id=product_id"`       // 商品图片表
+	PlatformInfo         *PlatformInfo           `orm:"with:platform_id=platform"`        //一个selection只有一个平台,直接指针对象object
+	EnterpriseInfo       *Enterprise             `orm:"with:enterprise_id=enterprise_id"` //商家信息
+	IsCollected          int                     `json:"is_collected"`                    //此达人是否收藏 1表示已收藏,0表示没有收藏
 }
 
 // 种草收藏列表

+ 27 - 20
app/model/youngee_talent_model/talent_bank.go

@@ -1,20 +1,27 @@
-package youngee_talent_model
-
-import (
-	"github.com/gogf/gf/util/gmeta"
-)
-
-type TalentBankInfo struct {
-	gmeta.Meta      `orm:"table:younggee_talent_bank"`
-	TalentId        string `json:"talent_id"`         // 达人id(youngee_talent_info表中的id)
-	Name            string `json:"name"`              // 户主姓名
-	Phone           string `json:"phone"`             // 手机号
-	Bank            string `json:"bank"`              // 银行
-	BankCardNumber  string `json:"bank_card_number"`  // 银行卡号
-	BankOpenAddress int    `json:"bank_open_address"` // 开户地址区域码,取info_region表中的self_code字段值
-	AlipayNumber    string `json:"alipay_number"`     // 支付宝账号
-	AlipayRealName  string `json:"alipay_real_name"`  // 支付宝真实姓名
-	IsBindBank      int    `json:"is_bind_bank"`      //
-	AlipayCardId    string `json:"alipay_card_id"`    // 支付宝身份证号
-	BankCardId      string `json:"bank_card_id"`      // 银行卡身份证号
-}
+package youngee_talent_model
+
+import (
+	"github.com/gogf/gf/util/gmeta"
+)
+
+type TalentBankInfo struct {
+	gmeta.Meta      `orm:"table:younggee_talent_bank"`
+	TalentId        string `json:"talent_id"`         // 达人id(youngee_talent_info表中的id)
+	Name            string `json:"name"`              // 户主姓名
+	Phone           string `json:"phone"`             // 手机号
+	Bank            string `json:"bank"`              // 银行
+	BankCardNumber  string `json:"bank_card_number"`  // 银行卡号
+	BankOpenAddress int    `json:"bank_open_address"` // 开户地址区域码,取info_region表中的self_code字段值
+	AlipayNumber    string `json:"alipay_number"`     // 支付宝账号
+	AlipayRealName  string `json:"alipay_real_name"`  // 支付宝真实姓名
+	IsBindBank      int    `json:"is_bind_bank"`      //
+	AlipayCardId    string `json:"alipay_card_id"`    // 支付宝身份证号
+	BankCardId      string `json:"bank_card_id"`      // 银行卡身份证号
+}
+
+type AddBankReq struct {
+	Name           string `json:"name"`             // 户主姓名
+	Phone          string `json:"phone"`            // 手机号
+	BankCardNumber string `json:"bank_card_number"` // 银行卡号
+	BankCardId     string `json:"bank_card_id"`     // 银行卡身份证号
+}

+ 34 - 34
app/model/youngee_talent_model/talent_income.go

@@ -1,34 +1,34 @@
-package youngee_talent_model
-
-import (
-	"youngmini_server/app/model"
-
-	"github.com/gogf/gf/os/gtime"
-)
-
-type GetTalentIncomeReq struct {
-	Type        int    `json:"type"`         // 提现阶段,1-3分别表示可提现、已提现、提现中
-	SearchInput string `json:"search_input"` // 模糊搜索内容
-}
-
-type TalentIncomeInfo struct {
-	Id              int         `json:"id"`         // 收益记录id
-	ProjectId       string      `json:"project_id"` // 项目id
-	TaskId          string      `json:"task_id"`    // 任务id
-	BrandName       string      `json:"brand_name"` // 品牌名称
-	TaskName        string      `json:"task_name"`  // 任务名称
-	Type            int         `json:"type"`
-	PhotoUrl        string      `json:"photo_url"`
-	TeamId          string      `json:"team_id"`         // young之团id
-	Income          float64     `json:"income"`          // 收益金额
-	IncomeType      int         `json:"income_type"`     // 收益类型,1-4分别表示任务收益、开团收益、样品返现、悬赏收益
-	WithdrawStatus  int         `json:"withdraw_status"` // 提现状态,1-3分别表示可提现、提现中、已提现
-	IncomeAt        *gtime.Time `json:"income_at"`       // 收益产生时间
-	WithdrawAt      *gtime.Time `json:"withdraw_at"`     // 提现时间
-	PlatformIconUrl string      `json:"platform_icon_url"`
-}
-
-type TalentPointInfo struct {
-	Point             int                                `json:"point"`               // 现有积分
-	TalentPointRecord []*model.YounggeeTalentPointRecord `json:"talent_point_record"` // 达人积分收益记录
-}
+package youngee_talent_model
+
+import (
+	"youngmini_server/app/model"
+
+	"github.com/gogf/gf/os/gtime"
+)
+
+type GetTalentIncomeReq struct {
+	Type        int    `json:"type"`         // 提现阶段,1-3分别表示可提现、已提现、提现中
+	SearchInput string `json:"search_input"` // 模糊搜索内容
+}
+
+type TalentIncomeInfo struct {
+	Id              int         `json:"id"`              // 收益记录id
+	ProjectId       string      `json:"project_id"`      // 项目id
+	TaskId          string      `json:"task_id"`         // 任务id
+	BrandName       string      `json:"brand_name"`      // 品牌名称
+	TaskName        string      `json:"task_name"`       // 任务名称
+	Type            int         `json:"type"`            //种草、带货、本地生活
+	PhotoUrl        string      `json:"photo_url"`       //
+	TeamId          string      `json:"team_id"`         // young之团id
+	Income          float64     `json:"income"`          // 收益金额
+	IncomeType      int         `json:"income_type"`     // 收益类型,1-4分别表示任务收益、开团收益、样品返现、悬赏收益
+	WithdrawStatus  int         `json:"withdraw_status"` // 提现状态,1-3分别表示可提现、提现中、已提现
+	IncomeAt        *gtime.Time `json:"income_at"`       // 收益产生时间
+	WithdrawAt      *gtime.Time `json:"withdraw_at"`     // 提现时间
+	PlatformIconUrl string      `json:"platform_icon_url"`
+}
+
+type TalentPointInfo struct {
+	Point             int                                `json:"point"`               // 现有积分
+	TalentPointRecord []*model.YounggeeTalentPointRecord `json:"talent_point_record"` // 达人积分收益记录
+}

+ 1 - 1
app/model/youngee_talent_model/talent_info.go

@@ -20,7 +20,7 @@ type TalentInfo struct {
 	gmeta.Meta        `orm:"table:youngee_talent_info"`
 	Id                string      `json:"id"`                  // 达人id
 	TalentWxOpenid    string      `json:"talent_wx_openid"`    // 达人的微信openid
-	Avatar            string      `json:"avatar"`              //
+	Avatar            string      `json:"avatar"`              // 达人的头像
 	TalentWxNickname  string      `json:"talent_wx_nickname"`  // 达人的微信昵称
 	Income            float64     `json:"income"`              // 收益总数
 	Withdrawing       float64     `json:"withdrawing"`         // 提现中金额

+ 2 - 2
app/model/youngee_talent_model/task_info.go

@@ -47,7 +47,7 @@ type YoungeeTaskInfo struct {
 	SettleAmount           int            `json:"settle_amount"`             // 达人实际所得(扣除违约扣款)
 	AllPayment             float64        `json:"all_payment"`               // 企业支付总额
 	RealPayment            float64        `json:"real_payment"`              // 企业实际支付(扣除违约扣款)
-	ServiceRate            int            `json:"service_rate"`              // 服务费率(千分比)
+	ServiceRate            float64        `json:"service_rate"`              // 服务费率(千分比)
 	ServiceCharge          float64        `json:"service_charge"`            // 服务费
 	FeeForm                int            `json:"fee_form"`                  // 稿费形式 1: 产品置换 2: 固定稿费 3: 自报价
 	ErrBreakRate           int            `json:"err_break_rate"`            // 未上传类型违约扣款比例(百分比)
@@ -125,7 +125,7 @@ type TaskInfoBrief struct {
 
 type TaskInfoBriefList struct {
 	AllTaskInfoList       []*TaskInfoBrief `json:"all_Task_info_list"`
-	SignUpTaskInfoList    []*TaskInfoBrief `json:"sgin_up_Task_info_list"`
+	SignUpTaskInfoList    []*TaskInfoBrief `json:"sign_up_Task_info_list"`
 	GoingOnTaskInfoList   []*TaskInfoBrief `json:"going_on_Task_info_list"`
 	CompletedTaskInfoList []*TaskInfoBrief `json:"completed_Task_info_list"`
 }

+ 336 - 116
app/service/youngee_sectask_service/seletion_square.go

@@ -6,6 +6,8 @@ import (
 	"fmt"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/lin-jim-leon/kuaishou/open/merchant"
+	"reflect"
+	"sort"
 	"youngmini_server/app/dao"
 	"youngmini_server/app/model"
 	"youngmini_server/app/model/youngee_talent_model"
@@ -45,123 +47,123 @@ func GetSelectionList(r *ghttp.Request) *TalentHttpResult {
 
 	pageIndex := r.GetQueryInt("idx", -1)
 	cntPerPage := r.GetQueryInt("cnt", -1)
-	//platform := r.Get("platform")
-	//secForm := r.Get("secform")
-	//taskForm := r.Get("taskform")
-	//categoryForm := r.Get("categoryform")
-	//searchValue := r.Get("searchvalue")
-	//if pageIndex == -1 || cntPerPage == -1 || cntPerPage == 0 {
-	//	return &TalentHttpResult{Code: -1, Msg: "参数错误"}
-	//}
-	//
-	//// 如果有领样形式的过滤条件,则将过滤条件保存于secFormList
-	//var secFormList []interface{}
-	//if secForm != nil {
-	//	if reflect.TypeOf(secForm).Kind() != reflect.Slice {
-	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件领样形式错误"}
-	//	}
-	//
-	//	secFormList = make([]interface{}, 0)
-	//	secFormList = secForm.([]interface{})
-	//}
-	//
-	//// 如果有任务形式的过滤条件,则将过滤条件保存于taskFormList
-	//var taskFormList []interface{}
-	//if taskForm != nil {
-	//	if reflect.TypeOf(taskForm).Kind() != reflect.Slice {
-	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
-	//	}
-	//
-	//	taskFormList = make([]interface{}, 0)
-	//	taskFormList = taskForm.([]interface{})
-	//}
-	//
-	//// 如果有商品类目的过滤条件,则将过滤条件保存于categoryFormList
-	//var categoryFormList []interface{}
-	//if categoryForm != nil {
-	//	if reflect.TypeOf(categoryForm).Kind() != reflect.Slice {
-	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
-	//	}
-	//
-	//	categoryFormList = make([]interface{}, 0)
-	//	categoryFormList = categoryForm.([]interface{})
-	//}
-
-	// 如果有平台的过滤条件,则将平台列表保存于platformList  弃用
-	/*	var platformList []interface{}
-		if platform != nil {
-			if reflect.TypeOf(platform).Kind() != reflect.Slice {
-				return &TalentHttpResult{Code: -2, Msg: "搜索条件平台类型错误"}
-			}
+	//排序字段
+	sortField := r.GetString("sortField", "")  //根据哪个字段排序
+	orderTag := r.GetQueryInt("sortOrder", -1) //1降序,0升序
+	//领样和悬赏条件
+	secForm := r.Get("secform")
+	taskForm := r.Get("taskform")
+	//任务上线时间
+	createTime := r.Get("createTime")
+	//商品类目 智能家居、食品饮料等20种
+	categoryForm := r.Get("categoryform")
+	//搜索条件
+	searchValue := r.Get("searchvalue")
+
+	// 如果有领样形式的过滤条件,则将过滤条件保存于secFormList
+	var secFormList []interface{}
+	if secForm != nil {
+		if reflect.TypeOf(secForm).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件领样形式错误"}
+		}
+
+		secFormList = make([]interface{}, 0)
+		secFormList = secForm.([]interface{})
+	}
+
+	// 如果有任务形式的过滤条件,则将过滤条件保存于taskFormList
+	var taskFormList []interface{}
+	if taskForm != nil {
+		if reflect.TypeOf(taskForm).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+
+		taskFormList = make([]interface{}, 0)
+		taskFormList = taskForm.([]interface{})
+	}
+
+	// 上线时间
+	var createTimeList []interface{}
+	if createTime != nil {
+		if reflect.TypeOf(createTime).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+		createTimeList = make([]interface{}, 0)
+		createTimeList = createTime.([]interface{})
+	}
 
-			platformList = make([]interface{}, 0)
-			platformList = platform.([]interface{})
-		}*/
+	// 如果有商品类目的过滤条件,则将过滤条件保存于categoryFormList
+	var categoryFormList []interface{}
+	if categoryForm != nil {
+		if reflect.TypeOf(categoryForm).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+
+		categoryFormList = make([]interface{}, 0)
+		categoryFormList = categoryForm.([]interface{})
+	}
 
 	// 构造查询的条件
 	startId := pageIndex * cntPerPage
-	whereStr := fmt.Sprintf("(selection_status >= %d) AND (status = 0) ", selectionStatusInProgress)
-	/*	if platformList != nil {
-		whereStr = whereStr + " and platform in ("
-		for _, v := range platformList {
+	whereStr := fmt.Sprintf("(selection_status >= %d) AND (status = 0)", selectionStatusInProgress)
+	if taskFormList != nil {
+		whereStr += " and task_mode in ("
+		for _, v := range taskFormList {
+			whereStr += v.(string) + ", "
+		}
+
+		whereStr = whereStr[0 : len(whereStr)-2]
+		whereStr += ")"
+	}
+	if secFormList != nil {
+		whereStr += " and sample_mode in ("
+		for _, v := range secFormList {
+			whereStr += v.(string) + ", "
+		}
+
+		whereStr = whereStr[0 : len(whereStr)-2]
+		whereStr += ")"
+	}
+
+	// 处理 selectionFormList (创建时间的过滤条件)
+	if createTimeList != nil {
+		whereStr += " AND created_at >= (NOW() - INTERVAL "
+		for _, v := range createTimeList {
+			switch v.(string) {
+			case "1": // 近7天
+				whereStr += "7 DAY"
+			case "2": // 近30天
+				whereStr += "30 DAY"
+			case "3": // 近90天
+				whereStr += "90 DAY"
+			default:
+				continue // 无效的过滤条件,跳过
+			}
+		}
+		whereStr += ")"
+	}
+
+	//商品类目 来自product
+	if categoryFormList != nil {
+		whereStr += " and product_category in ("
+		for _, v := range categoryFormList {
 			whereStr += v.(string) + ", "
 		}
 
 		whereStr = whereStr[0 : len(whereStr)-2]
 		whereStr += ")"
-	}*/
-
-	//if taskFormList != nil {
-	//	whereStr += " and task_mode in ("
-	//	for _, v := range taskFormList {
-	//		whereStr += v.(string) + ", "
-	//	}
-	//
-	//	whereStr = whereStr[0 : len(whereStr)-2]
-	//	whereStr += ")"
-	//}
-	//if secFormList != nil {
-	//	whereStr += " and sample_mode in ("
-	//	for _, v := range secFormList {
-	//		whereStr += v.(string) + ", "
-	//	}
-	//
-	//	whereStr = whereStr[0 : len(whereStr)-2]
-	//	whereStr += ")"
-	//}
-	//
-	//if categoryFormList != nil {
-	//	whereStr += " and product_category in ("
-	//	for _, v := range categoryFormList {
-	//		whereStr += v.(string) + ", "
-	//	}
-	//
-	//	whereStr = whereStr[0 : len(whereStr)-2]
-	//	whereStr += ")"
-	//}
-
-	////搜索栏
-	//if searchValue != nil {
-	//	whereStr += " and selection_name like '%" + searchValue.(string) + "%'"
-	//}
-
-	// 查询所有selection
-	//YounggeeSelectionInfo含有表中的所有属性
-	var selectionList = []model.YounggeeSelectionInfo{}
-	//err := g.Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Scan(&selectionList)
-	//展示带货商品的排序规则  预估赚、ddl未处理
-	err := g.Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Order("commission_rate DESC , task_reward DESC ").Scan(&selectionList)
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: "查询数据库失败"}
-	}
-	//fmt.Println("****searchValue:", searchValue)
-	//fmt.Println("****secFormList:", secFormList)
-	//fmt.Println("****taskFormList:", taskFormList)
-
-	fmt.Println("****whereStr: ", whereStr)
+	}
+
+	//搜索栏
+	if searchValue != nil {
+		whereStr += " and selection_name like '%" + searchValue.(string) + "%'"
+	}
+
+	fmt.Println("whereStr----->:", whereStr)
 
 	// 判断请求页面是否超过最大页面
-	c, err := g.DB().Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Count()
+	c, err := g.DB().Model("younggee_selection_info").WithAll().Where(whereStr).Count()
+	fmt.Println("满足条件的selection数目--", c)
 	if err != nil {
 		return &TalentHttpResult{Code: -4, Msg: err.Error(), Data: nil}
 	}
@@ -174,22 +176,216 @@ func GetSelectionList(r *ghttp.Request) *TalentHttpResult {
 	if pageIndex+1 > maxPage {
 		return &TalentHttpResult{Code: -5, Msg: "over max page"}
 	}
+	fmt.Println("hereiiiii")
 
 	var selectionInfoList = youngee_talent_model.SelectionInfoList{
 		Count: c,
 	}
 
-	err = g.DB().Model(dao.YounggeeSelectionInfo.Table).WithAll().Where(whereStr).
-		Order("selection_status ASC , task_ddl DESC , commission_rate DESC , task_reward DESC, selection_id").Limit(startId, cntPerPage).Scan(&selectionInfoList.SelectionDetail)
+	err = g.DB().Model("younggee_selection_info").WithAll().
+		Where(whereStr).
+		Order("task_ddl DESC").Limit(startId, cntPerPage).Scan(&selectionInfoList.SelectionDetail)
 	if err != nil {
 		return &TalentHttpResult{Code: -6, Msg: "查询数据库失败"}
 	}
 
 	selectionInfoList.MaxPage = maxPage
 
+	//已经拿到了数据(where之后)。根据product中的字段排序
+	sort.Slice(selectionInfoList.SelectionDetail, func(i, j int) bool {
+		// 获取当前的产品信息
+		productI := selectionInfoList.SelectionDetail[i].YounggeeProduct
+		productJ := selectionInfoList.SelectionDetail[j].YounggeeProduct
+		// 计算 commission_price
+		commissionPriceI := productI.ExclusiveCommission * 0.01 * productI.ProductPrice
+		commissionPriceJ := productJ.ExclusiveCommission * 0.01 * productJ.ProductPrice
+
+		// 根据 sortField 选择排序的字段
+		switch sortField {
+		case "sales_count":
+			if orderTag == 1 {
+				return productI.SalesCount > productJ.SalesCount // 降序
+			}
+			return productI.SalesCount < productJ.SalesCount // 升序
+
+		case "exclusive_commission":
+			if orderTag == 1 {
+				return productI.ExclusiveCommission > productJ.ExclusiveCommission // 降序
+			}
+			return productI.ExclusiveCommission < productJ.ExclusiveCommission // 升序
+
+		case "commission_price":
+			if orderTag == 1 {
+				return commissionPriceI > commissionPriceJ // 降序
+			}
+			return commissionPriceI < commissionPriceJ // 升序
+
+		case "product_price":
+			if orderTag == 1 {
+				return productI.ProductPrice > productJ.ProductPrice // 降序
+			}
+			return productI.ProductPrice < productJ.ProductPrice // 升序
+
+		default:
+			// 如果没有匹配的字段,则不做排序,默认排序
+			return false
+		}
+	})
+
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: selectionInfoList}
 }
 
+// 获取项目信息列表service
+//func GetSelectionList(r *ghttp.Request) *TalentHttpResult {
+//
+//	pageIndex := r.GetQueryInt("idx", -1)
+//	cntPerPage := r.GetQueryInt("cnt", -1)
+//	//platform := r.Get("platform")
+//	//secForm := r.Get("secform")
+//	//taskForm := r.Get("taskform")
+//	//categoryForm := r.Get("categoryform")
+//	//searchValue := r.Get("searchvalue")
+//	//if pageIndex == -1 || cntPerPage == -1 || cntPerPage == 0 {
+//	//	return &TalentHttpResult{Code: -1, Msg: "参数错误"}
+//	//}
+//	//
+//	//// 如果有领样形式的过滤条件,则将过滤条件保存于secFormList
+//	//var secFormList []interface{}
+//	//if secForm != nil {
+//	//	if reflect.TypeOf(secForm).Kind() != reflect.Slice {
+//	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件领样形式错误"}
+//	//	}
+//	//
+//	//	secFormList = make([]interface{}, 0)
+//	//	secFormList = secForm.([]interface{})
+//	//}
+//	//
+//	//// 如果有任务形式的过滤条件,则将过滤条件保存于taskFormList
+//	//var taskFormList []interface{}
+//	//if taskForm != nil {
+//	//	if reflect.TypeOf(taskForm).Kind() != reflect.Slice {
+//	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+//	//	}
+//	//
+//	//	taskFormList = make([]interface{}, 0)
+//	//	taskFormList = taskForm.([]interface{})
+//	//}
+//	//
+//	//// 如果有商品类目的过滤条件,则将过滤条件保存于categoryFormList
+//	//var categoryFormList []interface{}
+//	//if categoryForm != nil {
+//	//	if reflect.TypeOf(categoryForm).Kind() != reflect.Slice {
+//	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+//	//	}
+//	//
+//	//	categoryFormList = make([]interface{}, 0)
+//	//	categoryFormList = categoryForm.([]interface{})
+//	//}
+//
+//	// 如果有平台的过滤条件,则将平台列表保存于platformList  弃用
+//	/*	var platformList []interface{}
+//		if platform != nil {
+//			if reflect.TypeOf(platform).Kind() != reflect.Slice {
+//				return &TalentHttpResult{Code: -2, Msg: "搜索条件平台类型错误"}
+//			}
+//
+//			platformList = make([]interface{}, 0)
+//			platformList = platform.([]interface{})
+//		}*/
+//
+//	// 构造查询的条件
+//	startId := pageIndex * cntPerPage
+//	whereStr := fmt.Sprintf("(selection_status >= %d) AND (status = 0) ", selectionStatusInProgress)
+//	/*	if platformList != nil {
+//		whereStr = whereStr + " and platform in ("
+//		for _, v := range platformList {
+//			whereStr += v.(string) + ", "
+//		}
+//
+//		whereStr = whereStr[0 : len(whereStr)-2]
+//		whereStr += ")"
+//	}*/
+//
+//	//if taskFormList != nil {
+//	//	whereStr += " and task_mode in ("
+//	//	for _, v := range taskFormList {
+//	//		whereStr += v.(string) + ", "
+//	//	}
+//	//
+//	//	whereStr = whereStr[0 : len(whereStr)-2]
+//	//	whereStr += ")"
+//	//}
+//	//if secFormList != nil {
+//	//	whereStr += " and sample_mode in ("
+//	//	for _, v := range secFormList {
+//	//		whereStr += v.(string) + ", "
+//	//	}
+//	//
+//	//	whereStr = whereStr[0 : len(whereStr)-2]
+//	//	whereStr += ")"
+//	//}
+//	//
+//	//if categoryFormList != nil {
+//	//	whereStr += " and product_category in ("
+//	//	for _, v := range categoryFormList {
+//	//		whereStr += v.(string) + ", "
+//	//	}
+//	//
+//	//	whereStr = whereStr[0 : len(whereStr)-2]
+//	//	whereStr += ")"
+//	//}
+//
+//	////搜索栏
+//	//if searchValue != nil {
+//	//	whereStr += " and selection_name like '%" + searchValue.(string) + "%'"
+//	//}
+//
+//	// 查询所有selection
+//	//YounggeeSelectionInfo含有表中的所有属性
+//	var selectionList = []model.YounggeeSelectionInfo{}
+//	//err := g.Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Scan(&selectionList)
+//	//展示带货商品的排序规则  预估赚、ddl未处理
+//	err := g.Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Order("commission_rate DESC , task_reward DESC ").Scan(&selectionList)
+//	if err != nil {
+//		return &TalentHttpResult{Code: -3, Msg: "查询数据库失败"}
+//	}
+//	//fmt.Println("****searchValue:", searchValue)
+//	//fmt.Println("****secFormList:", secFormList)
+//	//fmt.Println("****taskFormList:", taskFormList)
+//
+//	fmt.Println("****whereStr: ", whereStr)
+//
+//	// 判断请求页面是否超过最大页面
+//	c, err := g.DB().Model(dao.YounggeeSelectionInfo.Table).Where(whereStr).Count()
+//	if err != nil {
+//		return &TalentHttpResult{Code: -4, Msg: err.Error(), Data: nil}
+//	}
+//
+//	maxPage := c / cntPerPage
+//	if c%cntPerPage > 0 {
+//		maxPage += 1
+//	}
+//
+//	if pageIndex+1 > maxPage {
+//		return &TalentHttpResult{Code: -5, Msg: "over max page"}
+//	}
+//
+//	var selectionInfoList = youngee_talent_model.SelectionInfoList{
+//		Count: c,
+//	}
+//
+//	err = g.DB().Model(dao.YounggeeSelectionInfo.Table).WithAll().Where(whereStr).
+//		//Order("selection_status ASC , task_ddl DESC , commission_rate DESC , task_reward DESC, selection_id").Limit(startId, cntPerPage).Scan(&selectionInfoList.SelectionDetail)
+//		Order("commission_rate DESC").Limit(startId, cntPerPage).Scan(&selectionInfoList.SelectionDetail)
+//	if err != nil {
+//		return &TalentHttpResult{Code: -6, Msg: "查询数据库失败"}
+//	}
+//
+//	selectionInfoList.MaxPage = maxPage
+//
+//	return &TalentHttpResult{Code: 0, Msg: "success", Data: selectionInfoList}
+//}
+
 // 获取带货收藏列表
 func GetSelectionCollectionList(r *ghttp.Request) *TalentHttpResult {
 	// 从 session 中获取 talent_id
@@ -307,11 +503,24 @@ func GetSelectionDetail(r *ghttp.Request) *TalentHttpResult {
 
 	var selectionDetail *youngee_talent_model.SelectionDetail
 	err = g.DB().Model(youngee_talent_model.SelectionDetail{}).WithAll().Where("selection_id", sid).Scan(&selectionDetail)
+	//填充收藏信息
+	collectionInfo := []youngee_talent_model.SelectionCollection{}
+	err = g.DB().Model("younggee_selection_collect_info").Where("selection_id=? and talent_id = ?", sid, tid).Scan(&collectionInfo)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: err.Error()}
+	}
+	//已被收藏
+	if len(collectionInfo) != 0 && collectionInfo[0].Deleted == 0 { //有数据  且   没取消收藏
+		selectionDetail.IsCollected = 1
+	} else {
+		selectionDetail.IsCollected = 0 //没数据  或  有数据但取消了收藏
+	}
+	//返回的data作为收藏接口的is_collect字段传入
 	if err != nil {
 		return &TalentHttpResult{Code: -3, Msg: err.Error()}
 	}
 	// 查询younggee_product表数据
-	var younggeeProduct []*youngee_talent_model.YounggeeProduct
+	var younggeeProduct *youngee_talent_model.YounggeeProduct
 	err = g.DB().Model(youngee_talent_model.YounggeeProduct{}).WithAll().Where("product_id", pid).Scan(&younggeeProduct)
 	if err != nil {
 		return &TalentHttpResult{Code: -3, Msg: err.Error()}
@@ -545,17 +754,28 @@ func SignUpSecTaskWithKsAccount(r *ghttp.Request) *TalentHttpResult {
 		return &TalentHttpResult{Code: -17, Msg: "younggee_sec_task_info delete failed"}
 	}
 	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
-		// 减少选品库存
-		whereCondition1 := g.Map{
-			dao.YounggeeSelectionInfo.Columns.SelectionId: selectionDetail.SelectionId,
-		}
+		//// 减少选品库存
+		//whereCondition1 := g.Map{
+		//	dao.YounggeeSelectionInfo.Columns.SelectionId: selectionDetail.SelectionId,
+		//}
+		//updateData := g.Map{
+		//	dao.YounggeeSelectionInfo.Columns.RemainNum: gdb.Raw(fmt.Sprintf("%s - 1", dao.YounggeeSelectionInfo.Columns.RemainNum)),
+		//
+		//}
+		//_, err = tx.Ctx(ctx).Model(dao.YounggeeSelectionInfo.Table).Where(whereCondition1).Data(updateData).Update()
+		//if err != nil {
+		//	return err
+		//}
 		updateData := g.Map{
-			dao.YounggeeSelectionInfo.Columns.RemainNum: gdb.Raw(fmt.Sprintf("%s - 1", dao.YounggeeSelectionInfo.Columns.RemainNum)),
+			"remain_num": selectionDetail.RemainNum - 1,
+			"enroll_num": selectionDetail.EnrollNum + 1,
 		}
-		_, err = tx.Ctx(ctx).Model(dao.YounggeeSelectionInfo.Table).Where(whereCondition1).Data(updateData).Update()
+
+		_, err = tx.Ctx(ctx).Model("younggee_selection_info").Where("selection_id=?", selectionDetail.SelectionId).Data(updateData).Update()
 		if err != nil {
 			return err
 		}
+
 		// 新建任务,初始化状态为待发货
 		secTaskInfo.TaskStage = 6
 		_, err = tx.Ctx(ctx).Model(dao.YounggeeSecTaskInfo.Table).Data(&secTaskInfo).Insert()
@@ -674,7 +894,7 @@ func SignUpSecTaskFromWindow(r *ghttp.Request) *TalentHttpResult {
 		return &TalentHttpResult{Code: -16, Msg: err.Error(), Data: nil}
 	}
 	//2.如果task不为空。取出free_stage的值。插入的值含有删除数据的free_stage
-	//这种情况出现在报名只有又点击加入橱窗
+	//这种情况出现在报名之后又点击加入橱窗
 	if len(secTaskInfoList) != 0 {
 		free_stage := secTaskInfoList[0].FreeStage
 		//删除旧的,

+ 138 - 88
app/service/youngee_talent_service/log_message.go

@@ -1,88 +1,138 @@
-package youngee_talent_service
-
-import (
-	"log"
-	"youngmini_server/app/dao"
-	"youngmini_server/app/model"
-	"youngmini_server/app/model/youngee_talent_model"
-	"youngmini_server/app/utils"
-
-	"github.com/gogf/gf/frame/g"
-	"github.com/gogf/gf/net/ghttp"
-)
-
-// 获取任务日志
-func GetTaskLog(r *ghttp.Request) *TalentHttpResult {
-	taskId := r.GetQueryInt("task_id", -1)
-
-	var taskLog []*model.YounggeeTaskLog
-	err := g.Model(dao.YounggeeTaskLog.Table).Where("task_id = ?", taskId).Order("log_at").Scan(&taskLog)
-	if err != nil {
-		log.Println("GetTaskLog error:", err)
-		return &TalentHttpResult{Code: -1, Msg: "Get task log failed"}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: taskLog}
-}
-
-// 获取消息通知
-func GetMessage(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
-	}
-	var taskMessage []*model.YounggeeMessageInfo
-	err = g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ? and is_deleted = 0", tid).Order("created_at desc").Scan(&taskMessage)
-	if err != nil {
-		log.Println("GetMessage error:", err)
-		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: taskMessage}
-}
-
-// 设置消息已读
-func SetMessageRead(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
-	}
-	_, err = g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ?", tid).Update(g.Map{"is_readed": 1})
-	if err != nil {
-		log.Println("UpdateMessage error:", err)
-		return &TalentHttpResult{Code: -2, Msg: "Update task message failed"}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 删除消息
-func DeleteMessage(r *ghttp.Request) *TalentHttpResult {
-	var deleteMessageReq *youngee_talent_model.DeleteMessageReq
-	err := r.ParseForm(&deleteMessageReq)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "params error"}
-	}
-	_, err = g.Model(dao.YounggeeMessageInfo.Table).Where("id = ?", deleteMessageReq.MessageId).Update(g.Map{"is_deleted": 1})
-	if err != nil {
-		log.Println("UpdateMessage error:", err)
-		return &TalentHttpResult{Code: -2, Msg: "Update task message failed"}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 获取消息通知
-func HasUnReadMessage(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
-	}
-	UnReadMessageNum, err := g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ? and is_readed = 0", tid).Count()
-	if err != nil {
-		log.Println("GetMessage error:", err)
-		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: UnReadMessageNum}
-}
+package youngee_talent_service
+
+import (
+	"log"
+	"youngmini_server/app/dao"
+	"youngmini_server/app/model"
+	"youngmini_server/app/model/youngee_talent_model"
+	"youngmini_server/app/utils"
+
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/net/ghttp"
+)
+
+// 获取任务日志
+func GetTaskLog(r *ghttp.Request) *TalentHttpResult {
+	taskId := r.GetQueryInt("task_id", -1)
+
+	var taskLog []*model.YounggeeTaskLog
+	err := g.Model(dao.YounggeeTaskLog.Table).Where("task_id = ?", taskId).Order("log_at").Scan(&taskLog)
+	if err != nil {
+		log.Println("GetTaskLog error:", err)
+		return &TalentHttpResult{Code: -1, Msg: "Get task log failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: taskLog}
+}
+
+// 获取消息通知
+func GetMessage(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+	var taskMessage []*model.YounggeeMessageInfo
+	err = g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ? and is_deleted = 0", tid).Order("created_at desc").Scan(&taskMessage)
+	if err != nil {
+		log.Println("GetMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: taskMessage}
+}
+
+// 获取消息通知列表
+// GetMessageList 获取消息通知列表,按类型分类
+func GetMessageList(r *ghttp.Request) *TalentHttpResult {
+	// 获取 Talent ID
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+
+	// 定义不同类型的消息列表
+	var MessList []youngee_talent_model.YounggeeMutilMessInfo
+	err = g.Model("message_system").Where("talent_id = ? and is_deleted = 0", tid).Order("created_at desc").Scan(&MessList)
+
+	if err != nil {
+		log.Println("GetMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
+	}
+
+	// 使用 map 来按 mess_type 分类
+	messageMap := make(map[int][]youngee_talent_model.YounggeeMutilMessInfo)
+
+	// 遍历消息列表,将消息按类型添加到 map 中
+	for _, message := range MessList {
+		messageMap[message.MessType] = append(messageMap[message.MessType], message)
+	}
+
+	// 返回按类型分类的消息列表
+	return &TalentHttpResult{
+		Code: 0,
+		Msg:  "success",
+		Data: messageMap,
+	}
+}
+
+// 获取消息通知详情页
+func GetMessageDetail(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+	var taskMessage []*model.YounggeeMessageInfo
+	err = g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ? and is_deleted = 0", tid).Order("created_at desc").Scan(&taskMessage)
+	if err != nil {
+		log.Println("GetMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: taskMessage}
+}
+
+// 设置消息已读
+func SetMessageRead(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+	_, err = g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ?", tid).Update(g.Map{"is_readed": 1})
+	if err != nil {
+		log.Println("UpdateMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Update task message failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success"}
+}
+
+// 删除消息
+func DeleteMessage(r *ghttp.Request) *TalentHttpResult {
+	var deleteMessageReq *youngee_talent_model.DeleteMessageReq
+	err := r.ParseForm(&deleteMessageReq)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "params error"}
+	}
+	_, err = g.Model(dao.YounggeeMessageInfo.Table).Where("id = ?", deleteMessageReq.MessageId).Update(g.Map{"is_deleted": 1})
+	if err != nil {
+		log.Println("UpdateMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Update task message failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success"}
+}
+
+// 获取消息通知
+func HasUnReadMessage(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+	UnReadMessageNum, err := g.Model(dao.YounggeeMessageInfo.Table).Where("talent_id = ? and is_readed = 0", tid).Count()
+	if err != nil {
+		log.Println("GetMessage error:", err)
+		return &TalentHttpResult{Code: -2, Msg: "Get task message failed"}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: UnReadMessageNum}
+}

+ 183 - 79
app/service/youngee_talent_service/talent_bank.go

@@ -1,79 +1,183 @@
-package youngee_talent_service
-
-import (
-	"context"
-	"youngmini_server/app/dao"
-	"youngmini_server/app/model/youngee_talent_model"
-	"youngmini_server/app/utils"
-
-	"github.com/gogf/gf/database/gdb"
-	"github.com/gogf/gf/frame/g"
-	"github.com/gogf/gf/net/ghttp"
-)
-
-func GetTalentBankInfo(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
-	}
-
-	res, err := g.DB().Model(dao.YounggeeTalentBank.Table).Where("talent_id = ?", tid).One()
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: res}
-}
-
-func OnAddTalentBank(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Add talent address failed"}
-	}
-
-	tBank := youngee_talent_model.TalentBankInfo{}
-	err = r.ParseForm(&tBank)
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
-	}
-
-	// 更新
-	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
-		var tErr error
-		// 判断是否已经绑定
-		res, err := g.DB().Model(dao.YoungeeTalentInfo.Table).Fields("is_bind_bank").Where("id = ?", tid).Value()
-		if err != nil {
-			return err
-		}
-
-		if res.Int64() == 0 { // 新增
-			// 将达人id存入结构体
-			tBank.TalentId = tid
-			// 插入提现绑定信息
-			_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Insert(tBank)
-			if tErr != nil {
-				return tErr
-			}
-		} else { // 更新
-			// 将达人id存入结构体
-			tBank.TalentId = tid
-			// 更新提现绑定信息
-			_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Update(tBank, "talent_id", tid)
-			if tErr != nil {
-				return tErr
-			}
-		}
-
-		_, tErr = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Data("is_bind_bank", 1).Where("id", tid).Update()
-		if tErr != nil {
-			return tErr
-		}
-
-		return nil
-	})
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: err.Error()}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
+package youngee_talent_service
+
+import (
+	"context"
+	"fmt"
+	_ "io/ioutil"
+	_ "net/http"
+	_ "strings"
+	"youngmini_server/app/dao"
+	"youngmini_server/app/model/youngee_talent_model"
+	"youngmini_server/app/utils"
+
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/net/ghttp"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	ivs "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model"
+	region "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/region"
+)
+
+func GetTalentBankInfo(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+
+	res, err := g.DB().Model(dao.YounggeeTalentBank.Table).Where("talent_id = ?", tid).One()
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: res}
+}
+
+func AddTalentBank(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Add talent address failed"}
+	}
+	tBank := youngee_talent_model.TalentBankInfo{}
+	err = r.ParseForm(&tBank)
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+	// 从表单中提取自定义参数并赋值到 tBank 结构体中
+	tBank.Name = r.FormValue("name")
+	tBank.BankCardId = r.FormValue("bank_card_id")
+	// 生成唯一的UUID字符串
+	//randomString := utils.GetUuid.GetRandomString(6)
+
+	//ak := os.Getenv("YJRGTOWEITSYOXN3YPJY")
+	//sk := os.Getenv("Kd7WDeS2CxlLXjMhGpLW0AmdOZHafitQpBy13a0s")
+
+	auth := basic.NewCredentialsBuilder().
+		WithAk("YJRGTOWEITSYOXN3YPJY").
+		WithSk("Kd7WDeS2CxlLXjMhGpLW0AmdOZHafitQpBy13a0s").
+		Build()
+
+	client := ivs.NewIvsClient(
+		ivs.IvsClientBuilder().
+			WithRegion(region.ValueOf("cn-north-4")).
+			WithCredential(auth).
+			Build())
+
+	request := &model.DetectExtentionByNameAndIdRequest{}
+	var listReqDataData = []model.ExtentionReqDataByNameAndId{
+		{
+			VerificationName: tBank.Name,
+			VerificationId:   tBank.BankCardId,
+		},
+	}
+	databody := &model.IvsExtentionByNameAndIdRequestBodyData{
+		ReqData: &listReqDataData,
+	}
+	uuidMeta := "d41d8cd98f00b204e9800998ecf8427e"
+	metabody := &model.Meta{
+		Uuid: &uuidMeta,
+	}
+	request.Body = &model.IvsExtentionByNameAndIdRequestBody{
+		Data: databody,
+		Meta: metabody,
+	}
+	response, err := client.DetectExtentionByNameAndId(request)
+	if err == nil {
+		fmt.Printf("ya")
+		// 更新
+		err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+			var tErr error
+			// 判断是否已经绑定
+			res, err := g.DB().Model(dao.YoungeeTalentInfo.Table).Fields("is_bind_bank").Where("id = ?", tid).Value()
+			if err != nil {
+				return err
+			}
+
+			if res.Int64() == 0 { // 新增
+				// 将达人id存入结构体
+				tBank.TalentId = tid
+				// 插入提现绑定信息
+				_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Insert(tBank)
+				if tErr != nil {
+					return tErr
+				}
+			} else { // 更新
+				// 将达人id存入结构体
+				tBank.TalentId = tid
+				// 更新提现绑定信息
+				_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Update(tBank, "talent_id", tid)
+				if tErr != nil {
+					return tErr
+				}
+			}
+
+			_, tErr = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Data("is_bind_bank", 1).Where("id", tid).Update()
+			if tErr != nil {
+				return tErr
+			}
+
+			return nil
+		})
+		if err != nil {
+			return &TalentHttpResult{Code: -3, Msg: err.Error()}
+		}
+	} else {
+		return &TalentHttpResult{Code: -1, Msg: "人证验证失败", Data: response}
+	}
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: response}
+
+}
+
+func OnAddTalentBank(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Add talent address failed"}
+	}
+
+	tBank := youngee_talent_model.TalentBankInfo{}
+
+	err = r.ParseForm(&tBank)
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+
+	// 更新
+	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		var tErr error
+		// 判断是否已经绑定
+		res, err := g.DB().Model(dao.YoungeeTalentInfo.Table).Fields("is_bind_bank").Where("id = ?", tid).Value()
+		if err != nil {
+			return err
+		}
+
+		if res.Int64() == 0 { // 新增
+			// 将达人id存入结构体
+			tBank.TalentId = tid
+			// 插入提现绑定信息
+			_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Insert(tBank)
+			if tErr != nil {
+				return tErr
+			}
+		} else { // 更新
+			// 将达人id存入结构体
+			tBank.TalentId = tid
+			// 更新提现绑定信息
+			_, tErr = tx.Ctx(ctx).Model(dao.YounggeeTalentBank.Table).Update(tBank, "talent_id", tid)
+			if tErr != nil {
+				return tErr
+			}
+		}
+
+		_, tErr = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Data("is_bind_bank", 1).Where("id", tid).Update()
+		if tErr != nil {
+			return tErr
+		}
+
+		return nil
+	})
+	if err != nil {
+		return &TalentHttpResult{Code: -3, Msg: err.Error()}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success"}
+}

+ 254 - 254
app/service/youngee_talent_service/talent_income.go

@@ -1,254 +1,254 @@
-package youngee_talent_service
-
-import (
-	"context"
-	"encoding/json"
-	"fmt"
-	"math/rand"
-	"strconv"
-	"strings"
-	"time"
-	"youngmini_server/app/dao"
-	"youngmini_server/app/model"
-	"youngmini_server/app/model/youngee_talent_model"
-	"youngmini_server/app/utils"
-
-	"github.com/gogf/gf/database/gdb"
-	"github.com/gogf/gf/frame/g"
-	"github.com/gogf/gf/net/ghttp"
-	"github.com/gogf/gf/os/gtime"
-)
-
-func GetTalentIncomeInfo(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
-	}
-
-	var getTalentIncomeReq *youngee_talent_model.GetTalentIncomeReq
-	err = r.ParseForm(&getTalentIncomeReq)
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: "params error"}
-	}
-
-	var talentIncomerep []youngee_talent_model.TalentIncomeInfo
-	var talentIncomeList []*model.YounggeeTalentIncome
-	err = g.DB().Model(dao.YounggeeTalentIncome.Table).Where("talent_id = ? and withdraw_status = ?", tid, getTalentIncomeReq.Type).Scan(&talentIncomeList)
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: err.Error()}
-	}
-
-	platformMap := make(map[string]model.InfoThirdPlatform)
-	platformInfo := []*model.InfoThirdPlatform{}
-	if len(talentIncomeList) != 0 {
-		err := g.Model(dao.InfoThirdPlatform.Table).Scan(&platformInfo)
-		if err != nil {
-			return &TalentHttpResult{Code: -1, Msg: "Get platform failed"}
-		}
-
-		for i, _ := range platformInfo {
-			platformMap[strconv.Itoa(platformInfo[i].PlatformId)] = *platformInfo[i]
-		}
-	}
-
-	for _, v := range talentIncomeList {
-		var platform model.InfoThirdPlatform
-		switch v.Type {
-		case 1:
-			projectPlatform, err := g.Model(dao.ProjectInfo.Table).Fields("project_platform").Where("project_id = ?", v.ProjectId).Value()
-			if err != nil {
-				return &TalentHttpResult{Code: -1, Msg: "Get fullproject info failed"}
-			}
-			platform = platformMap[projectPlatform.String()]
-
-			talentIncomeInfo := youngee_talent_model.TalentIncomeInfo{
-				Id:              v.Id,
-				ProjectId:       v.ProjectId,
-				TaskId:          v.TaskId,
-				Type:            v.Type,
-				BrandName:       v.BrandName,
-				TaskName:        v.TaskName,
-				PhotoUrl:        v.PhotoUrl,
-				TeamId:          v.TeamId,
-				Income:          v.Income,
-				IncomeType:      v.IncomeType,
-				WithdrawStatus:  v.WithdrawStatus,
-				IncomeAt:        v.IncomeAt,
-				WithdrawAt:      v.WithdrawAt,
-				PlatformIconUrl: platform.PlatformIcon,
-			}
-
-			talentIncomerep = append(talentIncomerep, talentIncomeInfo)
-			break
-		case 2:
-			platformId, err := g.Model(dao.YounggeeSelectionInfo.Table).Fields("platform").Where("selection_id = ?", v.SelectionId).Value()
-			if err != nil {
-				return &TalentHttpResult{Code: -1, Msg: "Get fullproject info failed"}
-			}
-			platform = platformMap[platformId.String()]
-
-			talentIncomeInfo := youngee_talent_model.TalentIncomeInfo{
-				Id:              v.Id,
-				ProjectId:       v.SelectionId,
-				TaskId:          v.SectaskId,
-				Type:            v.Type,
-				BrandName:       v.BrandName,
-				TaskName:        v.TaskName,
-				PhotoUrl:        v.PhotoUrl,
-				TeamId:          v.TeamId,
-				Income:          v.Income,
-				IncomeType:      v.IncomeType,
-				WithdrawStatus:  v.WithdrawStatus,
-				IncomeAt:        v.IncomeAt,
-				WithdrawAt:      v.WithdrawAt,
-				PlatformIconUrl: platform.PlatformIcon,
-			}
-
-			talentIncomerep = append(talentIncomerep, talentIncomeInfo)
-			break
-		default:
-		}
-
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: talentIncomerep}
-}
-
-// 提现
-func Withdraw(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: err.Error()}
-	}
-
-	var DataInfoReq *youngee_talent_model.WithdrawInfo
-	err = r.ParseForm(&DataInfoReq)
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
-	}
-	incomeIdStrList := strings.Split(DataInfoReq.IncomeIdList, ",")
-	incomeIdList := utils.TypeTran.String2Int(incomeIdStrList)
-
-	// 检验是否均处于可提现状态,且达人id是否对应
-	var incomeList []model.YounggeeTalentIncome
-	err = g.Model(dao.YounggeeTalentIncome.Table).Where("talent_id = ? and withdraw_status = 1", tid).And("id IN (?)", incomeIdList).Scan(&incomeList)
-	if err != nil {
-		return &TalentHttpResult{Code: -4, Msg: err.Error()}
-	}
-	if len(incomeIdList) != len(incomeList) {
-		return &TalentHttpResult{Code: -3, Msg: "Req IncomeIdList Error"}
-	}
-
-	// 检查达人积分是否足够
-	totalPoint, err := g.Model(dao.YoungeeTalentInfo.Table).Fields("point").Where("id = ?", tid).Value()
-	if err != nil {
-		return &TalentHttpResult{Code: -5, Msg: err.Error()}
-	}
-	if totalPoint.Int() < DataInfoReq.Point {
-		return &TalentHttpResult{Code: -3, Msg: "Req Point Error"}
-	}
-
-	// 查询达人提现到账账户信息
-	var talentBank model.YounggeeTalentBank
-	err = g.Model(dao.YounggeeTalentBank.Table).Where("talent_id = ?", tid).Scan(&talentBank)
-	if err != nil {
-		return &TalentHttpResult{Code: -6, Msg: err.Error()}
-	}
-	bankJsons, errs := json.Marshal(talentBank) //转换成JSON返回的是byte[]
-	if errs != nil {
-		return &TalentHttpResult{Code: -7, Msg: err.Error()}
-	}
-
-	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
-		s1 := tid[7:]
-		s2 := fmt.Sprintf("%d", gtime.Now().YearDay())
-		s3 := fmt.Sprintf("%02v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(100))
-		s := "6" + s1 + s2 + s3
-		// 插入提现记录
-		_, err1 := tx.Ctx(ctx).Model(dao.YounggeeWithdrawRecord.Table).Data(model.YounggeeWithdrawRecord{
-			WithdrawId:     s,
-			TalentId:       tid,
-			WithdrawAmount: float64(DataInfoReq.TotalAmount),
-			AmountPayable:  float64(DataInfoReq.RealAmount),
-			IncomeIdList:   DataInfoReq.IncomeIdList,
-			PayPoint:       DataInfoReq.Point,
-			ReceiveInfo:    string(bankJsons),
-			BankType:       2,
-			Status:         1,
-			SubmitAt:       gtime.Now(),
-		}).InsertAndGetId()
-		if err1 != nil {
-			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
-			return err1
-		}
-
-		// 更新income表中提现状态
-		_, err1 = tx.Ctx(ctx).Model(dao.YounggeeTalentIncome.Table).Where("id IN (?)", incomeIdList).Update(g.Map{"withdraw_status": 2, "withdraw_at": gtime.Now()})
-		if err1 != nil {
-			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
-			return err1
-		}
-
-		// 更新talent表中提现金额
-		_, err1 = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Where("id = ?", tid).Increment("withdrawing", float64(DataInfoReq.TotalAmount))
-		if err1 != nil {
-			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
-			return err1
-		}
-		_, err1 = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Where("id = ?", tid).Decrement("canwithdraw", float64(DataInfoReq.TotalAmount))
-		if err1 != nil {
-			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
-			return err1
-		}
-
-		// 达人消息
-		for _, incomeInfo := range incomeList {
-			messageTypeId := [4]int{25, 26, 27, 28}
-			messageInfo := model.YounggeeMessageInfo{
-				MessageId:   messageTypeId[incomeInfo.IncomeType-1],
-				MessageType: 2,
-				CreatedAt:   gtime.Now(),
-				ProjectName: incomeInfo.TaskName,
-				IsReaded:    0,
-				IsDeleted:   0,
-			}
-			_, err = tx.Ctx(ctx).Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
-			if err != nil {
-				fmt.Printf("[Withdraw Transaction] Error:%+v\n", err)
-				return err
-			}
-		}
-		return nil
-	})
-	if err != nil {
-		return &TalentHttpResult{Code: -8, Msg: "Add Withdraw Record failed: " + err.Error()}
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 查询积分明细
-func GetTalentPointInfo(r *ghttp.Request) *TalentHttpResult {
-	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
-	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: err.Error()}
-	}
-
-	var talentPointList []*model.YounggeeTalentPointRecord
-	err = g.DB().Model(dao.YounggeeTalentPointRecord.Table).Where("talent_id = ?", tid).Order("income_at").Scan(talentPointList)
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
-	}
-
-	point, err := g.DB().Model(dao.YoungeeTalentInfo.Table).Fields("point").Where("talent_id = ?", tid).Value()
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
-	}
-
-	TalentPointInfo := youngee_talent_model.TalentPointInfo{
-		Point:             point.Int(),
-		TalentPointRecord: talentPointList,
-	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: TalentPointInfo}
-}
+package youngee_talent_service
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"math/rand"
+	"strconv"
+	"strings"
+	"time"
+	"youngmini_server/app/dao"
+	"youngmini_server/app/model"
+	"youngmini_server/app/model/youngee_talent_model"
+	"youngmini_server/app/utils"
+
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/net/ghttp"
+	"github.com/gogf/gf/os/gtime"
+)
+
+func GetTalentIncomeInfo(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+
+	var getTalentIncomeReq *youngee_talent_model.GetTalentIncomeReq
+	err = r.ParseForm(&getTalentIncomeReq)
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: "params error"}
+	}
+
+	var talentIncomerep []youngee_talent_model.TalentIncomeInfo
+	var talentIncomeList []*model.YounggeeTalentIncome
+	err = g.DB().Model(dao.YounggeeTalentIncome.Table).Where("talent_id = ? and withdraw_status = ?", tid, getTalentIncomeReq.Type).Scan(&talentIncomeList)
+	if err != nil {
+		return &TalentHttpResult{Code: -3, Msg: err.Error()}
+	}
+
+	platformMap := make(map[string]model.InfoThirdPlatform)
+	platformInfo := []*model.InfoThirdPlatform{}
+	if len(talentIncomeList) != 0 {
+		err := g.Model(dao.InfoThirdPlatform.Table).Scan(&platformInfo)
+		if err != nil {
+			return &TalentHttpResult{Code: -1, Msg: "Get platform failed"}
+		}
+
+		for i, _ := range platformInfo {
+			platformMap[strconv.Itoa(platformInfo[i].PlatformId)] = *platformInfo[i]
+		}
+	}
+
+	for _, v := range talentIncomeList { //遍历收入表中的所有信息
+		var platform model.InfoThirdPlatform
+		switch v.Type {
+		case 1: //种草收入
+			projectPlatform, err := g.Model(dao.ProjectInfo.Table).Fields("project_platform").Where("project_id = ?", v.ProjectId).Value()
+			if err != nil {
+				return &TalentHttpResult{Code: -1, Msg: "Get fullproject info failed"}
+			}
+			platform = platformMap[projectPlatform.String()]
+
+			talentIncomeInfo := youngee_talent_model.TalentIncomeInfo{
+				Id:              v.Id,
+				ProjectId:       v.ProjectId,
+				TaskId:          v.TaskId,
+				Type:            v.Type,
+				BrandName:       v.BrandName,
+				TaskName:        v.TaskName,
+				PhotoUrl:        v.PhotoUrl,
+				TeamId:          v.TeamId,
+				Income:          v.Income,
+				IncomeType:      v.IncomeType,
+				WithdrawStatus:  v.WithdrawStatus,
+				IncomeAt:        v.IncomeAt,
+				WithdrawAt:      v.WithdrawAt,
+				PlatformIconUrl: platform.PlatformIcon,
+			}
+
+			talentIncomerep = append(talentIncomerep, talentIncomeInfo)
+			break
+		case 2: //带货收入
+			platformId, err := g.Model(dao.YounggeeSelectionInfo.Table).Fields("platform").Where("selection_id = ?", v.SelectionId).Value()
+			if err != nil {
+				return &TalentHttpResult{Code: -1, Msg: "Get fullproject info failed"}
+			}
+			platform = platformMap[platformId.String()]
+
+			talentIncomeInfo := youngee_talent_model.TalentIncomeInfo{
+				Id:              v.Id,
+				ProjectId:       v.SelectionId,
+				TaskId:          v.SectaskId,
+				Type:            v.Type,
+				BrandName:       v.BrandName,
+				TaskName:        v.TaskName,
+				PhotoUrl:        v.PhotoUrl,
+				TeamId:          v.TeamId,
+				Income:          v.Income,
+				IncomeType:      v.IncomeType,
+				WithdrawStatus:  v.WithdrawStatus,
+				IncomeAt:        v.IncomeAt,
+				WithdrawAt:      v.WithdrawAt,
+				PlatformIconUrl: platform.PlatformIcon,
+			}
+
+			talentIncomerep = append(talentIncomerep, talentIncomeInfo)
+			break
+		default:
+		}
+
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: talentIncomerep}
+}
+
+// 提现
+func Withdraw(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: err.Error()}
+	}
+
+	var DataInfoReq *youngee_talent_model.WithdrawInfo
+	err = r.ParseForm(&DataInfoReq)
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+	incomeIdStrList := strings.Split(DataInfoReq.IncomeIdList, ",")
+	incomeIdList := utils.TypeTran.String2Int(incomeIdStrList)
+
+	// 检验是否均处于可提现状态,且达人id是否对应
+	var incomeList []model.YounggeeTalentIncome
+	err = g.Model(dao.YounggeeTalentIncome.Table).Where("talent_id = ? and withdraw_status = 1", tid).And("id IN (?)", incomeIdList).Scan(&incomeList)
+	if err != nil {
+		return &TalentHttpResult{Code: -4, Msg: err.Error()}
+	}
+	if len(incomeIdList) != len(incomeList) {
+		return &TalentHttpResult{Code: -3, Msg: "Req IncomeIdList Error"}
+	}
+
+	// 检查达人积分是否足够
+	totalPoint, err := g.Model(dao.YoungeeTalentInfo.Table).Fields("point").Where("id = ?", tid).Value()
+	if err != nil {
+		return &TalentHttpResult{Code: -5, Msg: err.Error()}
+	}
+	if totalPoint.Int() < DataInfoReq.Point {
+		return &TalentHttpResult{Code: -3, Msg: "Req Point Error"}
+	}
+
+	// 查询达人提现到账账户信息
+	var talentBank model.YounggeeTalentBank
+	err = g.Model(dao.YounggeeTalentBank.Table).Where("talent_id = ?", tid).Scan(&talentBank)
+	if err != nil {
+		return &TalentHttpResult{Code: -6, Msg: err.Error()}
+	}
+	bankJsons, errs := json.Marshal(talentBank) //转换成JSON返回的是byte[]
+	if errs != nil {
+		return &TalentHttpResult{Code: -7, Msg: err.Error()}
+	}
+
+	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		s1 := tid[7:]
+		s2 := fmt.Sprintf("%d", gtime.Now().YearDay())
+		s3 := fmt.Sprintf("%02v", rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(100))
+		s := "6" + s1 + s2 + s3
+		// 插入提现记录
+		_, err1 := tx.Ctx(ctx).Model(dao.YounggeeWithdrawRecord.Table).Data(model.YounggeeWithdrawRecord{
+			WithdrawId:     s,
+			TalentId:       tid,
+			WithdrawAmount: float64(DataInfoReq.TotalAmount),
+			AmountPayable:  float64(DataInfoReq.RealAmount),
+			IncomeIdList:   DataInfoReq.IncomeIdList,
+			PayPoint:       DataInfoReq.Point,
+			ReceiveInfo:    string(bankJsons),
+			BankType:       2,
+			Status:         1,
+			SubmitAt:       gtime.Now(),
+		}).InsertAndGetId()
+		if err1 != nil {
+			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
+			return err1
+		}
+
+		// 更新income表中提现状态
+		_, err1 = tx.Ctx(ctx).Model(dao.YounggeeTalentIncome.Table).Where("id IN (?)", incomeIdList).Update(g.Map{"withdraw_status": 2, "withdraw_at": gtime.Now()})
+		if err1 != nil {
+			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
+			return err1
+		}
+
+		// 更新talent表中提现金额
+		_, err1 = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Where("id = ?", tid).Increment("withdrawing", float64(DataInfoReq.TotalAmount))
+		if err1 != nil {
+			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
+			return err1
+		}
+		_, err1 = tx.Ctx(ctx).Model(dao.YoungeeTalentInfo.Table).Where("id = ?", tid).Decrement("canwithdraw", float64(DataInfoReq.TotalAmount))
+		if err1 != nil {
+			fmt.Printf("[Withdraw Transaction] Error:%+v\n", err1)
+			return err1
+		}
+
+		// 达人消息
+		for _, incomeInfo := range incomeList {
+			messageTypeId := [4]int{25, 26, 27, 28}
+			messageInfo := model.YounggeeMessageInfo{
+				MessageId:   messageTypeId[incomeInfo.IncomeType-1],
+				MessageType: 2,
+				CreatedAt:   gtime.Now(),
+				ProjectName: incomeInfo.TaskName,
+				IsReaded:    0,
+				IsDeleted:   0,
+			}
+			_, err = tx.Ctx(ctx).Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+			if err != nil {
+				fmt.Printf("[Withdraw Transaction] Error:%+v\n", err)
+				return err
+			}
+		}
+		return nil
+	})
+	if err != nil {
+		return &TalentHttpResult{Code: -8, Msg: "Add Withdraw Record failed: " + err.Error()}
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success"}
+}
+
+// 查询积分明细
+func GetTalentPointInfo(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: err.Error()}
+	}
+
+	var talentPointList []*model.YounggeeTalentPointRecord
+	err = g.DB().Model(dao.YounggeeTalentPointRecord.Table).Where("talent_id = ?", tid).Order("income_at").Scan(talentPointList)
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+
+	point, err := g.DB().Model(dao.YoungeeTalentInfo.Table).Fields("point").Where("talent_id = ?", tid).Value()
+	if err != nil {
+		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+	}
+
+	TalentPointInfo := youngee_talent_model.TalentPointInfo{
+		Point:             point.Int(),
+		TalentPointRecord: talentPointList,
+	}
+
+	return &TalentHttpResult{Code: 0, Msg: "success", Data: TalentPointInfo}
+}

+ 21 - 0
app/service/youngee_talent_service/talent_info.go

@@ -29,6 +29,27 @@ func OnPostTalentInfo(r *ghttp.Request) *TalentHttpResult {
 	return &TalentHttpResult{Code: 0, Msg: "success"}
 }
 
+func IsSecCollection(r *ghttp.Request) *TalentHttpResult {
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
+	}
+	selectionId := r.GetQueryString("selection_id")
+	collectionInfo := []youngee_talent_model.SelectionCollection{}
+	err = g.DB().Model("younggee_selection_collect_info").Where("selection_id=? and talent_id = ?", selectionId, tid).Scan(&collectionInfo)
+	if err != nil {
+		return &TalentHttpResult{Code: -1, Msg: err.Error()}
+	}
+	//已被收藏
+	if len(collectionInfo) != 0 && collectionInfo[0].Deleted == 0 { //有数据  且   没取消收藏
+		return &TalentHttpResult{Code: 0, Msg: "此选品已被收藏", Data: 0}
+	} else {
+		return &TalentHttpResult{Code: 0, Msg: "此选品没有被收藏", Data: 1} //没数据  或  有数据但取消了收藏
+	}
+	//返回的data作为收藏接口的is_collect字段传入
+
+}
+
 func OnUpdateTalentInfo(r *ghttp.Request) *TalentHttpResult {
 	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
 	if err != nil {

+ 100 - 6
app/service/youngee_talent_service/talent_ks_auth.go

@@ -12,6 +12,7 @@ import (
 	"github.com/lin-jim-leon/kuaishou/open/merchant"
 	"github.com/lin-jim-leon/kuaishou/open/user"
 	"log"
+	"strings"
 	"sync"
 	"time"
 	"youngmini_server/app/model/youngee_talent_model"
@@ -136,7 +137,7 @@ func GetKsEcomQrcode(r *ghttp.Request) *TalentHttpResult {
 	var text string
 	var ok bool
 	var tasks chromedp.Tasks
-	//快手
+	//快手小店授权码
 	tasks = chromedp.Tasks{
 		chromedp.Navigate(urlstr),
 		//点击出现二维码
@@ -154,15 +155,93 @@ func GetKsEcomQrcode(r *ghttp.Request) *TalentHttpResult {
 	println("ok----->", ok)
 	println("url----->", urlstr)
 	fmt.Println("代码运行时间:", time.Since(startTime))
-
-	// 在300秒后取消上下文
-	//time.AfterFunc(300*time.Second, func() {
-	//	cancel()
-	//})
 	// 返回二维码的操作已经完成,后续操作(go fun)在后台继续进行
+	// 启动后台 goroutine 监听重定向并处理
+	go HandleAfterRedirect(r)
+
 	return &TalentHttpResult{Code: 0, Msg: "二维码已生成", Data: text}
 }
 
+// 此函数执行完毕后
+func HandleAfterRedirect(r *ghttp.Request) *TalentHttpResult {
+	fmt.Println("HandleAfterRedirect-----")
+	//达人id获取
+	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+	fmt.Println("tid:", tid, "err:", err)
+	var isChecked1, isChecked2 bool
+	//var isChecked1 bool
+	var currentURL string
+	authURL := fmt.Sprintf("https://open.kwaixiaodian.com/oauth/authorize?app_id=ks651333097154138217&redirectUri=https://younggee.com/kuaishouauth&scope=merchant_distribution,merchant_refund,merchant_item,merchant_order,user_info,merchant_servicemarket,merchant_user,merchant_logistics&state=%s", tid)
+	// 执行任务
+	err = chromedp.Run(ctx, chromedp.Tasks{
+		// 等待用户扫码并跳转后,点击“立即购买”按钮,在这识别用户是否扫码完成
+		chromedp.WaitVisible(`#main_root > div > div.yPXHTHq9cx_6vEhWohw_ > div.Jb15b0XMeXvmyWfEfrvq > div.m5IIGVbmvqsfZdb00GFO > div.JktibAFTihy_wzOaJXHl > div.Cbz2c2xjrwvEPJnVK4iA > div.KY1LeQ_L_xVgT9RzkLow.cgxWbYdA4fs28QuNN36F > button`),
+		chromedp.Click(`#main_root > div > div.yPXHTHq9cx_6vEhWohw_ > div.Jb15b0XMeXvmyWfEfrvq > div.m5IIGVbmvqsfZdb00GFO > div.JktibAFTihy_wzOaJXHl > div.Cbz2c2xjrwvEPJnVK4iA > div.KY1LeQ_L_xVgT9RzkLow.cgxWbYdA4fs28QuNN36F > button`),
+		// 等待第一个 checkbox 元素可见
+		chromedp.WaitVisible(`#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input`),
+
+		// 检查第一个 checkbox 是否已选中
+		chromedp.EvaluateAsDevTools(`document.querySelector('#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input').checked`, &isChecked1),
+	})
+	if err != nil {
+		log.Fatalf("任务1执行失败:%v", err)
+	}
+	fmt.Println("*****")
+	// 如果第一个 checkbox 没有选中,则点击选中
+	if !isChecked1 {
+		fmt.Println("第一个 Checkbox 未选中。现在选中...")
+		err = chromedp.Run(ctx, chromedp.Click(`#app > div > section > main > div.cart-container > div.price-content > div.checkbox > label > span.ant-checkbox > input`))
+		if err != nil {
+			log.Fatalf("点击第一个 checkbox 失败:%v", err)
+		}
+	} else {
+		fmt.Println("第一个 Checkbox 已经选中。")
+	}
+
+	err = chromedp.Run(ctx, chromedp.Tasks{
+		// 点击提交订单按钮
+		chromedp.Click(`#app > div > section > main > div.cart-container > div.price-content > div.checkout > button`),
+		chromedp.Sleep(2 * time.Second),
+		//服务已购买,进行授权
+		chromedp.Navigate(authURL),
+		chromedp.Sleep(5 * time.Second),
+	})
+	//获取url
+	err = chromedp.Run(ctx, chromedp.Location(&currentURL))
+	//期望含code
+	fmt.Println("currentURL-----:", currentURL)
+
+	// 检查当前 URL 是否包含指定字符串 "https://open.kwaixiaodian.com/oauth/authorize"
+	if strings.Contains(currentURL, "https://open.kwaixiaodian.com/oauth/authorize") {
+		// 等待第二个 checkbox 元素可见
+		err = chromedp.Run(ctx, chromedp.WaitVisible(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input`, chromedp.ByQuery))
+		// 检查第二个 checkbox 获得选中情况
+		err = chromedp.Run(ctx, chromedp.EvaluateAsDevTools(`document.querySelector('#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input').checked`, &isChecked2))
+		if err != nil {
+			log.Fatalf("检查第二个 checkbox 状态失败:%v", err)
+		}
+
+		// 如果第二个 checkbox 没有选中,则点击选中
+		if !isChecked2 {
+			//选中同意
+			err = chromedp.Run(ctx, chromedp.Click(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > div > div:nth-child(2) > label > span.ant-checkbox > input`))
+			//点击授权按钮,肯定重定向过去了
+		} else {
+			fmt.Println("第二个 Checkbox 已经选中。")
+		}
+		//点击后授权成功
+		err = chromedp.Run(ctx, chromedp.Click(`#root > div > div > div > div > div.flex.f-jc-c.UcUNDIrRp1R3a9EnEbQE > div > div.f-1.f-fs-0.Zcms9k6vZGxKICWMIrdG > div.wNrvV7C_9L5FB2oxmyLe > button`))
+	} else {
+		fmt.Println("已经被后端API捕捉。")
+		fmt.Println("currentURL-----:", currentURL)
+	}
+
+	// 输出执行完成的日志
+	fmt.Println("授权完成")
+
+	return &TalentHttpResult{Code: 0, Msg: "已重定向到kuaishouauth接口", Data: nil}
+}
+
 // 检查数据库表中是否有达人对应的数据 且 token未过期
 func CheckAccount(r *ghttp.Request) *TalentHttpResult {
 	fmt.Println("into check")
@@ -493,6 +572,11 @@ func AddWindowWithKsAccount(r *ghttp.Request) *TalentHttpResult {
 	tid, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
 	pId := r.GetString("product_id")
 	openId := r.GetString("open_id")
+	selectionDetail := youngee_talent_model.SelectionDetail{}
+	err2 := g.DB().Model("younggee_selection_info").Where("selection_id=?", selectionDetail.SelectionId).Scan(&selectionDetail)
+	if err2 != nil {
+		fmt.Println("err--", err2.Error())
+	}
 	value, err := g.DB().Model("platform_kuaishou_user_info").Fields("open_id").Where("talent_id=? AND open_id = ?", tid, openId).Value()
 	if err != nil {
 		fmt.Println("query db fail")
@@ -504,6 +588,15 @@ func AddWindowWithKsAccount(r *ghttp.Request) *TalentHttpResult {
 	//res_info, err := merchant.AddItemsToShelf(ClientKey, SignSecret, accessToken, pIdSlice)
 	httpResult := youngee_sectask_service.IsCreateSecTask(r)
 	if httpResult.Code == 1 { //存在报名信息,仅添加橱窗
+		updateData := g.Map{
+			"enroll_num": selectionDetail.EnrollNum + 1, // enroll_num + 1
+		}
+		// 执行更新操作
+		_, err = g.DB().Model("younggee_selection_info").Where("selection_id=?", selectionDetail.SelectionId).Data(updateData).Update()
+		if err != nil {
+			// 错误处理
+			fmt.Println(err.Error())
+		}
 		_, err := merchant.AddItemsToShelf(ClientKey, SignSecret, accessToken, pIdSlice)
 		if err != nil {
 			//表示添加失敗,沒有開通
@@ -512,6 +605,7 @@ func AddWindowWithKsAccount(r *ghttp.Request) *TalentHttpResult {
 		// 查询成功,返回成功结果和数据
 		return &TalentHttpResult{Code: 0, Msg: "无需创建任务,加入橱窗成功", Data: nil}
 	} else { //不存在报名信息
+
 		//创建并插入报名信息
 		code := youngee_sectask_service.SignUpSecTaskFromWindow(r).Code
 		if code != 0 {

+ 140 - 69
app/service/youngee_task_service/project_info.go

@@ -6,8 +6,8 @@ import (
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gconv"
 	"reflect"
+	"sort"
 	"strconv"
-	"strings"
 	"youngmini_server/app/dao"
 	"youngmini_server/app/model"
 	"youngmini_server/app/model/youngee_talent_model"
@@ -16,7 +16,6 @@ import (
 
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/net/ghttp"
-	"github.com/wxnacy/wgo/arrays"
 )
 
 type projectStatus int
@@ -39,24 +38,34 @@ func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
 	fmt.Println("进入种草主页")
 	pageIndex := r.GetQueryInt("idx", -1)
 	cntPerPage := r.GetQueryInt("cnt", -1)
-	platform := r.Get("platform")
-	projectForm := r.Get("projectform")
-	feeForm := r.Get("feeform")
+	//组合筛选
+	platform := r.Get("platform", "")         //抖音、快手、红Book、B站、微博
+	projectForm := r.Get("projectform")       //1.商品寄拍、3.虚拟产品评测、2.素材分发
+	contentType := r.Get("contenttype", "")   //图文形式、视频形式
+	createTime := r.Get("createTime", "")     //任务上线时间
+	categoryForm := r.Get("categoryform", "") ////商品类目 智能家居、食品饮料等20种
+
+	//排根据浏览量排序
+	viewOrder := r.GetQueryInt("pageViewOrder", -1) //根据哪个字段排序
+
+	//仅稿费”+“稿费+赠品"。这个在recruit表中,得到列表之后进行排序
+	feeForm := r.Get("feeform", nil)
+
 	searchValue := r.Get("searchvalue")
 	if pageIndex == -1 || cntPerPage == -1 || cntPerPage == 0 {
 		return &TalentHttpResult{Code: -1, Msg: "参数错误"}
 	}
 
 	// 如果有稿费形式的过滤条件,则将过滤条件保存于taskModeList
-	var feeFormList []interface{}
-	if feeForm != nil {
-		if reflect.TypeOf(feeForm).Kind() != reflect.Slice {
-			return &TalentHttpResult{Code: -2, Msg: "搜索条件稿费形式错误"}
-		}
-
-		feeFormList = make([]interface{}, 0)
-		feeFormList = feeForm.([]interface{})
-	}
+	//var feeFormList []interface{}
+	//if feeForm != nil {
+	//	if reflect.TypeOf(feeForm).Kind() != reflect.Slice {
+	//		return &TalentHttpResult{Code: -2, Msg: "搜索条件稿费形式错误"}
+	//	}
+	//
+	//	feeFormList = make([]interface{}, 0)
+	//	feeFormList = feeForm.([]interface{})
+	//}
 
 	// 如果有任务形式的过滤条件,则将过滤条件保存于taskModeList
 	var projectFormList []interface{}
@@ -80,6 +89,42 @@ func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
 		platformList = platform.([]interface{})
 	}
 
+	// 如果有内容形式的过滤条件,则将过滤条件保存于taskModeList
+	var contentTypeList []interface{}
+	if contentType != nil {
+		if reflect.TypeOf(projectForm).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+
+		contentTypeList = make([]interface{}, 0)
+		contentTypeList = contentType.([]interface{})
+	}
+
+	// 上线时间
+	var createTimeList []interface{}
+	if createTime != nil {
+		if reflect.TypeOf(createTime).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+		createTimeList = make([]interface{}, 0)
+		createTimeList = createTime.([]interface{})
+	}
+
+	// 如果有商品类目的过滤条件,则将过滤条件保存于categoryFormList
+	var categoryFormList []interface{}
+	if categoryForm != nil {
+		if reflect.TypeOf(categoryForm).Kind() != reflect.Slice {
+			return &TalentHttpResult{Code: -2, Msg: "搜索条件任务形式错误"}
+		}
+
+		categoryFormList = make([]interface{}, 0)
+		categoryFormList = categoryForm.([]interface{})
+	}
+	if len(categoryFormList) > 0 {
+		// 使用 categoryFormList 进行某些操作
+		fmt.Println("Filtered categoryFormList:", categoryFormList)
+	}
+
 	// 构造查询的条件
 	startId := pageIndex * cntPerPage
 	// whereStr := fmt.Sprintf("(project_status >= %d and project_status <> %d and project_type = 1)", projectStatusRecruiting, projectStatusInvalid)
@@ -94,6 +139,44 @@ func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
 		whereStr += ")"
 	}
 
+	if contentTypeList != nil {
+		whereStr = whereStr + " and content_type in ("
+		for _, v := range contentTypeList {
+			whereStr += v.(string) + ", "
+		}
+
+		whereStr = whereStr[0 : len(whereStr)-2]
+		whereStr += ")"
+	}
+
+	// 处理 selectionFormList (创建时间的过滤条件)
+	if createTimeList != nil {
+		whereStr += " AND created_at >= (NOW() - INTERVAL "
+		for _, v := range createTimeList {
+			switch v.(string) {
+			case "1": // 近7天
+				whereStr += "7 DAY"
+			case "2": // 近30天
+				whereStr += "30 DAY"
+			case "3": // 近90天
+				whereStr += "90 DAY"
+			default:
+				continue // 无效的过滤条件,跳过
+			}
+		}
+		whereStr += ")"
+	}
+
+	if platformList != nil {
+		whereStr = whereStr + " and project_platform in ("
+		for _, v := range platformList {
+			whereStr += v.(string) + ", "
+		}
+
+		whereStr = whereStr[0 : len(whereStr)-2]
+		whereStr += ")"
+	}
+
 	if projectFormList != nil {
 		whereStr += " and project_form in ("
 		for _, v := range projectFormList {
@@ -107,46 +190,14 @@ func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
 		whereStr += " and project_name like '%" + searchValue.(string) + "%'"
 	}
 
+	fmt.Println("whereStr:-----》 ", whereStr)
+
 	// 查询所有project
 	var projectList = []model.ProjectInfo{}
-	var projectIdList []string
 	err := g.Model(dao.ProjectInfo.Table).Where(whereStr).Scan(&projectList)
 	if err != nil {
 		return &TalentHttpResult{Code: -3, Msg: "查询数据库失败"}
 	}
-	fmt.Println("searchValue:", searchValue)
-	fmt.Println("feeFormList:", feeFormList)
-	// 筛选出满足稿费形式条件的项目id列表
-	for _, v := range projectList {
-		string_slice := strings.Split(v.FeeForm, ",")
-		// fmt.Println("str:", string_slice)
-		tmp := 0
-		for _, w := range feeFormList {
-			i := arrays.ContainsString(string_slice, w.(string))
-			if i < 0 {
-				tmp = 0
-				break
-			}
-			tmp = 1
-		}
-		if tmp == 1 {
-			projectIdList = append(projectIdList, v.ProjectId)
-		}
-	}
-
-	if projectIdList != nil {
-		whereStr += " and project_id in ("
-		for _, v := range projectIdList {
-			whereStr += v + ", "
-		}
-
-		whereStr = whereStr[0 : len(whereStr)-2]
-		whereStr += ")"
-	} else if feeForm != nil {
-		return &TalentHttpResult{Code: -4, Msg: "has no fullproject", Data: nil}
-	}
-
-	fmt.Println("whereStr: ", whereStr)
 
 	// 判断请求页面是否超过最大页面
 	c, err := g.DB().Model(dao.ProjectInfo.Table).Fields("project_id").Where(whereStr).Count()
@@ -184,23 +235,37 @@ func GetProjectInfoList(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: 0, Msg: "Redis error"}
 		}
 		projectInfoList.ProjectInfos[i].WatchedNum = viewCount.Int()
-		// 如果 enterprise_id 有值,查询 Enterprise 信息并关联,服务商的任务不会出现在首页
-		//if project.EnterpriseId != "" {
-		//	var enterprise *youngee_talent_model.Enterprise
-		//	err := g.DB().Model("enterprise").Where("enterprise_id", project.EnterpriseId).Scan(&enterprise)
-		//	if err != nil {
-		//		fmt.Println("查询失败")
-		//		continue // 如果查询失败,跳过当前 project 继续处理下一个
-		//	}
-		//
-		//	fmt.Println("查询结果---", enterprise)
-		//
-		//	// 将查询到的 Enterprise 赋值给 projectInfo 的 Enterprise 字段
-		//	projectInfoList.ProjectInfos[i].Enterprise = enterprise
-		//}
-
+		// 根据 WatchedNum 从高到低排序
+		if viewOrder != -1 {
+			sort.Slice(projectInfoList.ProjectInfos, func(i, j int) bool {
+				return projectInfoList.ProjectInfos[i].WatchedNum > projectInfoList.ProjectInfos[j].WatchedNum
+			})
+		}
 	}
 	projectInfoList.MaxPage = maxPage
+	var filteredProjects []*youngee_talent_model.ProjectInfo
+	//筛选出“仅稿费”+“稿费+赠品”任务,
+	//只要策略中有 无费置换 之外的fee_form就是有稿费,projectform是 商品寄拍 和 虚拟产品测评 ,就是有赠品
+	if feeForm != nil {
+
+		for _, project := range projectInfoList.ProjectInfos {
+			// 条件1:筛选出所有 project_form 为 1 或 3 的项目
+			if project.ProjectForm == 1 || project.ProjectForm == 3 {
+				filteredProjects = append(filteredProjects, project)
+				continue // 如果满足条件1,直接跳过后续条件判断
+			}
+
+			// 条件2:RecruitStrategy 中存在 fee_form 不等于 1 的数据
+			for _, strategy := range project.RecruitStrategys {
+				if strategy.FeeForm != 1 {
+					filteredProjects = append(filteredProjects, project)
+					break // 找到符合条件的策略,跳出当前循环,避免重复添加
+				}
+			}
+		}
+		projectInfoList.ProjectInfos = filteredProjects
+
+	}
 
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: projectInfoList}
 }
@@ -229,10 +294,16 @@ func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
 		glog.Error(err)
 		return &TalentHttpResult{Code: 0, Msg: "Redis error"}
 	}
+	var ProjectDetail *youngee_talent_model.ProjectDetail
+	err = g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
+	if err != nil {
+		return &TalentHttpResult{Code: -3, Msg: err.Error()}
+	}
 
 	if viewed.IsNil() {
 		// User hasn't viewed this product yet, increase the view count
 		_, err = g.Redis().Do("INCR", projectViewKey)
+
 		if err != nil {
 			glog.Error(err)
 			return &TalentHttpResult{Code: 0, Msg: "Redis error"}
@@ -244,6 +315,11 @@ func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: 0, Msg: "Redis error"}
 		}
 	}
+	viewNum, err := g.Redis().DoVar("GET", projectViewKey)
+	if err != nil {
+		fmt.Println("获取浏览量失败")
+	}
+	ProjectDetail.ViewNum = viewNum.Int()
 
 	//浏览历史
 	currentDate := gtime.Now().Format("Ymd")
@@ -261,12 +337,6 @@ func GetProjectDetail(r *ghttp.Request) *TalentHttpResult {
 		return &TalentHttpResult{Code: 0, Msg: "Redis 设置过期时间失败"}
 	}
 
-	var ProjectDetail *youngee_talent_model.ProjectDetail
-	err = g.DB().Model("project_info").WithAll().Where("project_id", pid).Scan(&ProjectDetail)
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: err.Error()}
-	}
-
 	if enterprise_id != "" { //project来自商家
 		var enterprise *youngee_talent_model.Enterprise
 		err = g.DB().Model("enterprise").WithAll().Where("enterprise_id", enterprise_id).Scan(&enterprise)
@@ -340,5 +410,6 @@ func SignUpProjKuaishouList(r *ghttp.Request) *TalentHttpResult {
 		}
 
 	}
+
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: resInfo}
 }

+ 202 - 87
app/service/youngee_task_service/task_data.go

@@ -13,27 +13,20 @@ import (
 	"github.com/gogf/gf/os/gtime"
 )
 
-// 添加数据service
+// 添加数据service  14
 func AddTaskData(r *ghttp.Request) *TalentHttpResult {
 	var DataInfoReq *youngee_talent_model.AddTaskDataRequest
 	err := r.ParseForm(&DataInfoReq)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
-	// 查询该任务id是否有未提交数据
-	// 查询该任务是否有未提交脚本,无则插入,有则更新
-	unSubmitData, err := g.DB().Model(model.YounggeeDataInfo{}).Where("task_id = ? and is_submit = 0", DataInfoReq.TaskId).One()
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: "YounggeeDataInfo find failed"}
-	}
-	if unSubmitData != nil {
-		_, err = g.DB().Model(model.YounggeeDataInfo{}).Where("Data_id = ?", unSubmitData[dao.YounggeeDataInfo.Columns.DataId]).Delete()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeDataInfo delete failed"}
-		}
-	}
-
-	// 如果无未提交数据,则直接插入
+	taskDataInfo := []model.YounggeeDataInfo{}
+	err = g.DB().Model(model.YounggeeLinkInfo{}).Where("task_id = ? ", DataInfoReq.TaskId).OrderDesc("create_at").Scan(&taskDataInfo)
+	//上传过但是被拒了
+	var condition1 bool = len(taskDataInfo) != 0 && taskDataInfo[0].IsReview == 1 && taskDataInfo[0].IsOk == 0
+	//没有上传过初稿
+	var condition2 bool = len(taskDataInfo) == 0
+	//最新sketch数据
 	DataInfo := model.YounggeeDataInfo{
 		TaskId:        DataInfoReq.TaskId,
 		LikeNumber:    DataInfoReq.LikeNumber,
@@ -47,12 +40,27 @@ func AddTaskData(r *ghttp.Request) *TalentHttpResult {
 		IsOk:          0,
 	}
 
-	//todo:  修改taskstage为  14:数据待审
-	//todo 留痕而不是updata
+	if condition1 || condition2 {
+		//插入新数据
+		DataId, err := g.DB().Model(model.YounggeeDataInfo{}).Data(DataInfo).InsertAndGetId()
+		if err != nil {
+			return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo insert failed"}
+		}
+		//上传过,把旧的删掉
+		if condition1 {
+			_, err := g.DB().Model(model.YounggeeDataInfo{}).Where("data_id=?", DataId).Delete()
+			if err != nil {
+				fmt.Println("err:", err.Error())
+			}
+		}
 
-	_, err = g.DB().Model(model.YounggeeDataInfo{}).Data(DataInfo).Insert()
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: "YounggeeDataInfo insert failed"}
+	} else { //有数据,但是,还没有被审核,更新
+		dataId := taskDataInfo[0].DataId
+		// 使用主键 ID 更新记录
+		_, err := g.DB().Model(model.YounggeeDataInfo{}).Where("data_id = ?", dataId).Data(DataInfo).Update()
+		if err != nil {
+			return &TalentHttpResult{Code: -4, Msg: "YounggeeSketchInfo update failed"}
+		}
 	}
 
 	DataStatus, err := g.DB().Model(model.YoungeeTaskInfo{}).Fields("data_status").Where("task_id = ?", DataInfoReq.TaskId).Value()
@@ -70,80 +78,135 @@ func AddTaskData(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: -6, Msg: "YoungeeTaskInfo update failed"}
 		}
 	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 提交数据service
-func SubmitTaskData(r *ghttp.Request) *TalentHttpResult {
-	taskId, _ := r.Get("task_id").(string)
 	taskInfo := model.YoungeeTaskInfo{}
 	// 查询是否处于违约状态
-	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
+	err = g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", DataInfoReq.TaskId).Scan(&taskInfo)
+	//修改task表的属性
+	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", DataInfoReq.TaskId).Scan(&taskInfo)
 	if err1 != nil {
 		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
 	}
 	if taskInfo.CurDefaultType == 7 || taskInfo.CurDefaultType == 9 {
 		// 若处于违约状态则解除并更新企业应支付金额
-		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", taskId).Update()
+		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", DataInfoReq.TaskId).Update()
 		if err1 != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeTaskInfo update failed"}
 		}
 
 		// 更新违约记录表
-		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", taskId, g.Slice{1, 3, 4}).Update()
+		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", DataInfoReq.TaskId, g.Slice{1, 3, 4}).Update()
 		if err1 != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeContractInfo update failed"}
 		}
 	}
 
-	// 查询该任务是否有已添加或已修改数据
-	res, err := g.DB().Model(model.YounggeeDataInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+	//设置为数据待审
+	_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "14"}).Where("task_id = ?", DataInfoReq.TaskId).Update()
 	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "YounggeeDataInfo find failed"}
+		return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
 	}
-	if res == 1 && (taskInfo.DataStatus == 2 || taskInfo.DataStatus == 4) {
-		_, err = g.DB().Model(model.YounggeeDataInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeDataInfo update failed"}
-		}
-		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "14"}).Where("task_id = ?", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
-		}
-		// 记录任务日志-上传数据
-		taskLog := model.YounggeeTaskLog{
-			TaskId:  taskId,
-			Content: "上传数据",
-			LogAt:   gtime.Now(),
-		}
-		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
-		}
-		projectInfo := model.ProjectInfo{}
-		err1 := g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
-		if err1 != nil {
-			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
-		}
-		messageInfo := model.YounggeeMessageInfo{
-			MessageId:   13,
-			MessageType: 2,
-			CreatedAt:   gtime.Now(),
-			TalentId:    taskInfo.TalentId,
-			ProjectName: projectInfo.ProjectName,
-			IsReaded:    0,
-			IsDeleted:   0,
-		}
-		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
-		}
+	// 记录任务日志-上传数据
+	taskLog := model.YounggeeTaskLog{
+		TaskId:  DataInfoReq.TaskId,
+		Content: "上传数据",
+		LogAt:   gtime.Now(),
+	}
+	_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
+	if err != nil {
+		return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
+	}
+	projectInfo := model.ProjectInfo{}
+	err = g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+	if err != nil {
+		return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+	}
+	messageInfo := model.YounggeeMessageInfo{
+		MessageId:   13,
+		MessageType: 2,
+		CreatedAt:   gtime.Now(),
+		TalentId:    taskInfo.TalentId,
+		ProjectName: projectInfo.ProjectName,
+		IsReaded:    0,
+		IsDeleted:   0,
+	}
+	_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+	if err != nil {
+		return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
 	}
 
 	return &TalentHttpResult{Code: 0, Msg: "success"}
 }
 
+// 提交数据service
+//func SubmitTaskData(r *ghttp.Request) *TalentHttpResult {
+//	taskId, _ := r.Get("task_id").(string)
+//	taskInfo := model.YoungeeTaskInfo{}
+//	// 查询是否处于违约状态
+//	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
+//	if err1 != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
+//	}
+//	if taskInfo.CurDefaultType == 7 || taskInfo.CurDefaultType == 9 {
+//		// 若处于违约状态则解除并更新企业应支付金额
+//		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", taskId).Update()
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -2, Msg: "YoungeeTaskInfo update failed"}
+//		}
+//
+//		// 更新违约记录表
+//		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", taskId, g.Slice{1, 3, 4}).Update()
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -2, Msg: "YoungeeContractInfo update failed"}
+//		}
+//	}
+//
+//	// 查询该任务是否有已添加或已修改数据
+//	res, err := g.DB().Model(model.YounggeeDataInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+//	if err != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YounggeeDataInfo find failed"}
+//	}
+//	if res == 1 && (taskInfo.DataStatus == 2 || taskInfo.DataStatus == 4) {
+//		_, err = g.DB().Model(model.YounggeeDataInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -3, Msg: "YounggeeDataInfo update failed"}
+//		}
+//		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "14"}).Where("task_id = ?", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
+//		}
+//		// 记录任务日志-上传数据
+//		taskLog := model.YounggeeTaskLog{
+//			TaskId:  taskId,
+//			Content: "上传数据",
+//			LogAt:   gtime.Now(),
+//		}
+//		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
+//		}
+//		projectInfo := model.ProjectInfo{}
+//		err1 := g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+//		}
+//		messageInfo := model.YounggeeMessageInfo{
+//			MessageId:   13,
+//			MessageType: 2,
+//			CreatedAt:   gtime.Now(),
+//			TalentId:    taskInfo.TalentId,
+//			ProjectName: projectInfo.ProjectName,
+//			IsReaded:    0,
+//			IsDeleted:   0,
+//		}
+//		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
+//		}
+//	}
+//
+//	return &TalentHttpResult{Code: 0, Msg: "success"}
+//}
+
 // 查询数据提交审阅记录service
 func GetTaskData(r *ghttp.Request) *TalentHttpResult {
 	taskId := r.Get("task_id")
@@ -205,39 +268,91 @@ func ProjectCollection(r *ghttp.Request) *TalentHttpResult {
 }
 
 // 收藏带货项目
+//func SelectionCollection(r *ghttp.Request) *TalentHttpResult {
+//	tId, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
+//	selectionId := r.GetQueryString("selection_id")
+//	productionId := r.GetQueryString("production_id")
+//	record, err := g.DB().Model("younggee_selection_collect_info").Where("talent_id = ? and selection_id = ?", tId, selectionId).One()
+//	if err != nil {
+//		return &TalentHttpResult{Code: -1, Msg: err.Error()}
+//	}
+//	if record == nil {
+//		collectionInfo := youngee_talent_model.SelectionCollection{
+//			TalentId:    tId,
+//			SelectionId: selectionId,
+//			ProductId:   productionId,
+//			CreateTime:  gtime.Now(),
+//			Deleted:     0,
+//		}
+//		_, err = g.DB().Model("younggee_selection_collect_info").Data(collectionInfo).Insert()
+//
+//	} else {
+//		// 如果记录存在,更新 Delete 字段的值 和 收藏时间
+//		fmt.Println("*******", record)
+//		currentDeleteValue := gconv.Int(record["deleted"])
+//		newDeleteValue := 1 - currentDeleteValue // 0 改成 1,1 改成 0
+//		_, err = g.DB().Model("younggee_selection_collect_info").
+//			Where("talent_id = ? and selection_id = ?", tId, selectionId).
+//			Data(g.Map{
+//				"deleted":     newDeleteValue,
+//				"create_time": gtime.Now(),
+//			}).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -1, Msg: err.Error()}
+//		}
+//	}
+//	return &TalentHttpResult{Code: 0, Data: record["deleted"], Msg: "collection success"}
+//}
+
 func SelectionCollection(r *ghttp.Request) *TalentHttpResult {
 	tId, _ := utils.SessionTalentInfo.GetTalentIdFromSession(r)
 	selectionId := r.GetQueryString("selection_id")
 	productionId := r.GetQueryString("production_id")
-	record, err := g.DB().Model("younggee_selection_collect_info").Where("talent_id = ? and selection_id = ?", tId, selectionId).One()
+	collectionRes := []youngee_talent_model.SelectionCollection{}
+	err := g.DB().Model("younggee_selection_collect_info").Where("talent_id = ? and selection_id = ?", tId, selectionId).Scan(&collectionRes)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
-	if record == nil {
-		collectionInfo := youngee_talent_model.SelectionCollection{
+	// 1. 没有数据,插入新记录
+	if len(collectionRes) == 0 {
+		collectInfo := &youngee_talent_model.SelectionCollection{
 			TalentId:    tId,
 			SelectionId: selectionId,
 			ProductId:   productionId,
 			CreateTime:  gtime.Now(),
-			Deleted:     0,
+			Deleted:     0, // 默认未删除状态
 		}
+		_, err := g.DB().Model("younggee_selection_collect_info").Data(collectInfo).Insert()
+		if err != nil {
+			return &TalentHttpResult{Code: -1, Msg: err.Error()}
+		}
+		return &TalentHttpResult{Code: 0, Msg: "收藏成功", Data: 0} //收藏
+	}
 
-		_, err = g.DB().Model("younggee_selection_collect_info").Data(collectionInfo).Insert()
+	// 2. 有数据,且 Deleted == 0,更新 Deleted 为 1(取消收藏)
+	if len(collectionRes) != 0 && collectionRes[0].Deleted == 0 {
+		_, err := g.DB().Model("younggee_selection_collect_info").Where("collection_id = ?", collectionRes[0].CollectionId).Data(g.Map{
+			"Deleted":    1,
+			"UpdateTime": gtime.Now(),
+		}).Update()
+		if err != nil {
+			return &TalentHttpResult{Code: -1, Msg: err.Error()}
+		}
+		return &TalentHttpResult{Code: 0, Msg: "取消收藏成功", Data: 1} //取消收藏
+	}
 
-	} else {
-		// 如果记录存在,更新 Delete 字段的值 和 收藏时间
-		fmt.Println("*******", record)
-		currentDeleteValue := gconv.Int(record["deleted"])
-		newDeleteValue := 1 - currentDeleteValue // 0 改成 1,1 改成 0
-		_, err = g.DB().Model("younggee_selection_collect_info").
-			Where("talent_id = ? and selection_id = ?", tId, selectionId).
-			Data(g.Map{
-				"deleted":     newDeleteValue,
-				"create_time": gtime.Now(),
-			}).Update()
+	// 3. 有数据,且 Deleted == 1,更新 Deleted 为 0(重新收藏)
+	if len(collectionRes) != 0 && collectionRes[0].Deleted == 1 {
+		_, err := g.DB().Model("younggee_selection_collect_info").Where("collection_id = ?", collectionRes[0].CollectionId).Data(g.Map{
+			"Deleted":    0,
+			"UpdateTime": gtime.Now(),
+		}).Update()
 		if err != nil {
 			return &TalentHttpResult{Code: -1, Msg: err.Error()}
 		}
+		return &TalentHttpResult{Code: 0, Msg: "重新收藏成功"}
 	}
-	return &TalentHttpResult{Code: 0, Msg: "collection success"}
+
+	return &TalentHttpResult{Code: 0, Msg: "操作成功"}
+
 }

+ 21 - 19
app/service/youngee_task_service/task_info.go

@@ -242,6 +242,7 @@ func IsSignUpTask(r *ghttp.Request) *TalentHttpResult {
 
 // 查询所有任务
 func GetTaskBriefList(r *ghttp.Request) *TalentHttpResult {
+	fmt.Println("getTaskBriefList-----")
 	tid, err := utils.SessionTalentInfo.GetTalentIdFromSession(r)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: "Get talent info failed"}
@@ -250,7 +251,6 @@ func GetTaskBriefList(r *ghttp.Request) *TalentHttpResult {
 	// 构造查询条件
 	whereStr := fmt.Sprintf("talent_id = '%s'", tid)
 
-	fmt.Print(whereStr)
 	// 获取任务列表
 	var taskList []*youngee_talent_model.YoungeeTaskInfo
 	//此达人下,所有快手账号的任务都展示
@@ -259,7 +259,7 @@ func GetTaskBriefList(r *ghttp.Request) *TalentHttpResult {
 		return &TalentHttpResult{Code: -1, Msg: "Get task list failed"}
 	}
 
-	//便后续根据 PlatformId 快速查找平台信息。platformMap的key是PlatformId,value是平台具体描述
+	//后续根据 PlatformId 快速查找平台信息。platformMap的key是PlatformId,value是平台具体描述
 	platformMap := make(map[string]model.InfoThirdPlatform)
 	platformInfo := []*model.InfoThirdPlatform{}
 	if len(taskList) != 0 {
@@ -273,9 +273,10 @@ func GetTaskBriefList(r *ghttp.Request) *TalentHttpResult {
 		}
 	}
 
-	// 为每个任务根据项目id查询项目名称和主图
+	//为每个任务根据项目id查询项目名称和主图
 	//taskBriefList存了各个阶段的tasklist
 	taskBriefList := youngee_talent_model.TaskInfoBriefList{}
+	fmt.Println("taskList----的长度为:", len(taskList))
 	for _, v := range taskList { //taskList含所有任务
 		//获取具体的招募策略,taskInfo中
 		var projectDetail *youngee_talent_model.ProjectDetail
@@ -285,6 +286,7 @@ func GetTaskBriefList(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: -1, Msg: "Get fullproject info failed"}
 		}
 		var account *youngee_talent_model.KuaishouUserInfo
+		fmt.Println("openid---->", v.OpenId)
 		err = g.Model("platform_kuaishou_user_info").Where("platform_id = ? and talent_id = ? and open_id = ?", 8, tid, v.OpenId).Scan(&account)
 		//拿快手平台验证是否过期
 		expired := youngee_talent_service.CheckKuaishouTokenExp(account.OpenId)
@@ -630,28 +632,28 @@ func SignUpTaskWithKsAccount(r *ghttp.Request) *TalentHttpResult {
 			TaskId:                 newTaskId,
 			ProjectId:              signTaskInfo.ProjectId,
 			TalentId:               tid,
-			OpenId:                 accountInfo.OpenId,
+			OpenId:                 signTaskInfo.OpenID,
 			TalentPlatformInfoSnap: string(accountSnap),
 			TalentPersonalInfoSnap: string(talentSnap),
 			TalentPostAddrSnap:     string(addrSnap),
 			StrategyId:             signTaskInfo.StrategyId,
 			TaskStage:              1,
 			FeeForm:                strategy.FeeForm,
-			//ServiceCharge:          serviceCharge,
-			//ServiceRate:            serviceRate,
-			CreateDate:      gtime.Now(),
-			TaskStatus:      1,
-			LogisticsStatus: 1,
-			LinkStatus:      1,
-			DataStatus:      1,
-			ScriptStatus:    1,
-			SketchStatus:    1,
-			CompleteStatus:  1,
-			CurDefaultType:  0,
-			WithdrawStatus:  1,
-			SettleStatus:    1,
-			DraftFee:        signTaskInfo.Offer, //商家或者服务商可以看到的稿费价格,无非置换为空,一口价为策略表中的t_offer,自报价是达人添加的,
-			SettleAmount:    signTaskInfo.Offer,
+			ServiceCharge:          strategy.ServiceCharge,          //  服务费
+			ServiceRate:            projectDetail.ServiceChargeRate, //公开服务费率
+			CreateDate:             gtime.Now(),
+			TaskStatus:             1,
+			LogisticsStatus:        1,
+			LinkStatus:             1,
+			DataStatus:             1,
+			ScriptStatus:           1,
+			SketchStatus:           1,
+			CompleteStatus:         1,
+			CurDefaultType:         0,
+			WithdrawStatus:         1,
+			SettleStatus:           1,
+			DraftFee:               signTaskInfo.Offer, //商家或者服务商可以看到的稿费价格,无非置换为空,一口价为策略表中的t_offer,自报价是达人添加的,
+			SettleAmount:           signTaskInfo.Offer,
 		}
 	}
 	err = g.DB().Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {

+ 141 - 82
app/service/youngee_task_service/task_link.go

@@ -1,6 +1,7 @@
 package youngee_task_service
 
 import (
+	"fmt"
 	"youngmini_server/app/dao"
 	"youngmini_server/app/model"
 	"youngmini_server/app/model/youngee_talent_model"
@@ -17,35 +18,43 @@ func AddTaskLink(r *ghttp.Request) *TalentHttpResult {
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
-	// 查询该任务id是否有未提交链接
-	// 查询该任务是否有未提交脚本,无则插入,有则更新
-	unSubmitLink, err := g.DB().Model(model.YounggeeLinkInfo{}).Where("task_id = ? and is_submit = 0", LinkInfoReq.TaskId).One()
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: "YounggeeLinkInfo find failed"}
-	}
-	if unSubmitLink != nil {
-		_, err = g.DB().Model(model.YounggeeLinkInfo{}).Where("link_id = ?", unSubmitLink[dao.YounggeeLinkInfo.Columns.LinkId]).Delete()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo delete failed"}
-		}
-	}
-
-	// 如果无未提交链接,则直接插入
-	LinkInfo := model.YounggeeLinkInfo{
+	taskLinkInfo := []model.YounggeeLinkInfo{}
+	err = g.DB().Model(model.YounggeeLinkInfo{}).Where("task_id = ? ", LinkInfoReq.TaskId).OrderDesc("create_at").Scan(&taskLinkInfo)
+	//上传过但是被拒了
+	var condition1 bool = len(taskLinkInfo) != 0 && taskLinkInfo[0].IsReview == 1 && taskLinkInfo[0].IsOk == 0
+	//没有上传过初稿
+	var condition2 bool = len(taskLinkInfo) == 0
+	//最新sketch数据
+	linkInfo := model.YounggeeLinkInfo{
 		TaskId:   LinkInfoReq.TaskId,
 		LinkUrl:  LinkInfoReq.LinkUrl,
 		PhotoUrl: LinkInfoReq.PhotoUrl,
 		CreateAt: gtime.Now(),
 		IsReview: 0,
-		IsSubmit: 0,
+		IsSubmit: 0, //忽略
 		IsOk:     0,
 	}
+	if condition1 || condition2 {
+		//插入新数据
+		LinkId, err := g.DB().Model(model.YounggeeLinkInfo{}).Data(linkInfo).InsertAndGetId()
+		if err != nil {
+			return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo insert failed"}
+		}
+		//上传过,把旧的删掉
+		if condition1 {
+			_, err := g.DB().Model(model.YounggeeLinkInfo{}).Where("link_id=?", LinkId).Delete()
+			if err != nil {
+				fmt.Println("err:", err.Error())
+			}
+		}
 
-	//todo : task表中task stage 12:链接待审
-
-	_, err = g.DB().Model(model.YounggeeLinkInfo{}).Data(LinkInfo).Insert()
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo insert failed"}
+	} else { //有数据,但是,还没有被审核,更新
+		linkId := taskLinkInfo[0].LinkId
+		// 使用主键 ID 更新记录
+		_, err := g.DB().Model(model.YounggeeLinkInfo{}).Where("link_id = ?", linkId).Data(linkInfo).Update()
+		if err != nil {
+			return &TalentHttpResult{Code: -4, Msg: "YounggeeSketchInfo update failed"}
+		}
 	}
 
 	LinkStatus, err := g.DB().Model(model.YoungeeTaskInfo{}).Fields("link_status").Where("task_id = ?", LinkInfoReq.TaskId).Value()
@@ -63,100 +72,150 @@ func AddTaskLink(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: -6, Msg: "YoungeeTaskInfo update failed"}
 		}
 	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 提交链接service
-func SubmitTaskLink(r *ghttp.Request) *TalentHttpResult {
-	taskId, _ := r.Get("task_id").(string)
+	//修改task表,插入log和message
 	taskInfo := model.YoungeeTaskInfo{}
 	// 查询是否处于违约状态
-	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
-	if err1 != nil {
-		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
-	}
+	err = g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", LinkInfoReq.TaskId).Scan(&taskInfo)
 	if taskInfo.CurDefaultType == 5 || taskInfo.CurDefaultType == 9 {
 		// 若处于违约状态则解除并更新企业应支付金额
-		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", taskId).Update()
-		if err1 != nil {
+		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "err_break_rate": 0}).Where("task_id = ?", LinkInfoReq.TaskId).Update()
+		if err != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeTaskInfo update failed"}
 		}
 
 		// 更新违约记录表
-		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", taskId, g.Slice{1, 3, 4}).Update()
-		if err1 != nil {
+		_, err = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", LinkInfoReq.TaskId, g.Slice{1, 3, 4}).Update()
+		if err != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeContractInfo update failed"}
 		}
 	}
 
-	// 查询该任务是否有已添加或已修改链接
-	res, err := g.DB().Model(model.YounggeeLinkInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+	//task设置为链接待审
+	_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "12"}).Where("task_id = ?", LinkInfoReq.TaskId).Update()
 	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "YounggeeLinkInfo find failed"}
+		return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
 	}
-	if res == 1 && (taskInfo.LinkStatus == 2 || taskInfo.LinkStatus == 4) {
-		_, err = g.DB().Model(model.YounggeeLinkInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo update failed"}
-		}
-		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "12"}).Where("task_id = ?", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
-		}
-		// 记录任务日志-上传链接
-		taskLog := model.YounggeeTaskLog{
-			TaskId:  taskId,
-			Content: "上传链接",
-			LogAt:   gtime.Now(),
-		}
-		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
-		}
-		projectInfo := model.ProjectInfo{}
-		err1 = g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
-		if err1 != nil {
-			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
-		}
-		messageInfo := model.YounggeeMessageInfo{
-			MessageId:   12,
-			MessageType: 2,
-			CreatedAt:   gtime.Now(),
-			TalentId:    taskInfo.TalentId,
-			ProjectName: projectInfo.ProjectName,
-			IsReaded:    0,
-			IsDeleted:   0,
-		}
-		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
-		}
+	// 记录任务日志-上传链接
+	taskLog := model.YounggeeTaskLog{
+		TaskId:  LinkInfoReq.TaskId,
+		Content: "上传链接",
+		LogAt:   gtime.Now(),
+	}
+	_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
+	if err != nil {
+		return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
+	}
+	projectInfo := model.ProjectInfo{}
+	err = g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+	if err != nil {
+		return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+	}
+	messageInfo := model.YounggeeMessageInfo{
+		MessageId:   12,
+		MessageType: 2,
+		CreatedAt:   gtime.Now(),
+		TalentId:    taskInfo.TalentId,
+		ProjectName: projectInfo.ProjectName,
+		IsReaded:    0,
+		IsDeleted:   0,
+	}
+	_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+	if err != nil {
+		return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
 	}
 
 	return &TalentHttpResult{Code: 0, Msg: "success"}
 }
 
+// 提交链接service
+//func SubmitTaskLink(r *ghttp.Request) *TalentHttpResult {
+//	taskId, _ := r.Get("task_id").(string)
+//	taskInfo := model.YoungeeTaskInfo{}
+//	// 查询是否处于违约状态
+//	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
+//	if err1 != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
+//	}
+//	if taskInfo.CurDefaultType == 5 || taskInfo.CurDefaultType == 9 {
+//		// 若处于违约状态则解除并更新企业应支付金额
+//		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", taskId).Update()
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -2, Msg: "YoungeeTaskInfo update failed"}
+//		}
+//
+//		// 更新违约记录表
+//		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", taskId, g.Slice{1, 3, 4}).Update()
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -2, Msg: "YoungeeContractInfo update failed"}
+//		}
+//	}
+//
+//	// 查询该任务是否有已添加或已修改链接
+//	res, err := g.DB().Model(model.YounggeeLinkInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+//	if err != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YounggeeLinkInfo find failed"}
+//	}
+//	if res == 1 && (taskInfo.LinkStatus == 2 || taskInfo.LinkStatus == 4) {
+//		_, err = g.DB().Model(model.YounggeeLinkInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -3, Msg: "YounggeeLinkInfo update failed"}
+//		}
+//		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "12"}).Where("task_id = ?", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
+//		}
+//		// 记录任务日志-上传链接
+//		taskLog := model.YounggeeTaskLog{
+//			TaskId:  taskId,
+//			Content: "上传链接",
+//			LogAt:   gtime.Now(),
+//		}
+//		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
+//		}
+//		projectInfo := model.ProjectInfo{}
+//		err1 = g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+//		}
+//		messageInfo := model.YounggeeMessageInfo{
+//			MessageId:   12,
+//			MessageType: 2,
+//			CreatedAt:   gtime.Now(),
+//			TalentId:    taskInfo.TalentId,
+//			ProjectName: projectInfo.ProjectName,
+//			IsReaded:    0,
+//			IsDeleted:   0,
+//		}
+//		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
+//		}
+//	}
+//
+//	return &TalentHttpResult{Code: 0, Msg: "success"}
+//}
+
 // 查询链接提交审阅记录service
 func GetTaskLink(r *ghttp.Request) *TalentHttpResult {
 	taskId := r.Get("task_id")
-
-	res, err := g.DB().Model(dao.YounggeeLinkInfo.Table).Where("is_submit = 1 and is_review = 1 and task_id = ?", taskId).OrderAsc("submit_at").All()
+	res, err := g.DB().Model(dao.YounggeeLinkInfo.Table).Where("is_review = 1 and task_id = ?", taskId).OrderDesc("create_at").All()
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
-
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: res}
 }
 
 // 查询未提交链接service
 func GetUnSubmitTaskLink(r *ghttp.Request) *TalentHttpResult {
 	taskId := r.Get("task_id")
-
-	res, err := g.DB().Model(dao.YounggeeLinkInfo.Table).Where("is_review = 0 and task_id = ?", taskId).One()
+	res, err := g.DB().Model(dao.YounggeeLinkInfo.Table).Where("is_review = 0 and task_id = ?", taskId).OrderDesc("create_at").One()
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
-
+	if res == nil {
+		return &TalentHttpResult{Code: 0, Msg: "success", Data: nil}
+	}
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: res}
 }

+ 170 - 98
app/service/youngee_task_service/task_sketch.go

@@ -1,6 +1,7 @@
 package youngee_task_service
 
 import (
+	"fmt"
 	"strings"
 	"youngmini_server/app/dao"
 	"youngmini_server/app/model"
@@ -11,33 +12,27 @@ import (
 	"github.com/gogf/gf/os/gtime"
 )
 
-// 添加初稿service
+// 添加初稿service done
 func AddTaskSketch(r *ghttp.Request) *TalentHttpResult {
 	var sketchInfoReq *youngee_talent_model.AddTaskSketchRequest
+	//解析添加初稿的图文
 	err := r.ParseForm(&sketchInfoReq)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
 	photoUrl := strings.Split(sketchInfoReq.PhotoUrl, ",")
-	// 查询该任务id是否有未提交初稿
-	// 查询该任务是否有未提交脚本,无则插入,有则更新
-	unSubmitSketch, err := g.DB().Model(model.YounggeeSketchInfo{}).Where("task_id = ? and is_submit = 0", sketchInfoReq.TaskId).One()
+
+	taskSketchInfo := []youngee_talent_model.TaskSketchInfo{}
+
+	err = g.DB().Model(model.YounggeeSketchInfo{}).Where("task_id = ? ", sketchInfoReq.TaskId).OrderDesc("create_at").Scan(&taskSketchInfo)
 	if err != nil {
 		return &TalentHttpResult{Code: -2, Msg: "YounggeeSketchInfo find failed"}
 	}
-	if unSubmitSketch != nil {
-		// 如果有未提交初稿,则删除并重新添加
-		_, err := g.DB().Model(model.YounggeeSketchPhoto{}).Where("sketch_id = ?", unSubmitSketch[dao.YounggeeSketchInfo.Columns.SketchId]).Delete()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchPhoto delete failed"}
-		}
-
-		_, err = g.DB().Model(model.YounggeeSketchInfo{}).Where("sketch_id = ?", unSubmitSketch[dao.YounggeeSketchInfo.Columns.SketchId]).Delete()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchInfo delete failed"}
-		}
-	}
-	// 如果无未提交初稿,则直接插入
+	//上传过但是被拒了
+	var condition1 bool = len(taskSketchInfo) != 0 && taskSketchInfo[0].IsReview == 1 && taskSketchInfo[0].IsOk == 0
+	//没有上传过初稿
+	var condition2 bool = len(taskSketchInfo) == 0
+	//最新sketch数据
 	sketchInfo := model.YounggeeSketchInfo{
 		TaskId:   sketchInfoReq.TaskId,
 		Title:    sketchInfoReq.Title,
@@ -45,23 +40,52 @@ func AddTaskSketch(r *ghttp.Request) *TalentHttpResult {
 		Content:  sketchInfoReq.Content,
 		CreateAt: gtime.Now(),
 		IsReview: 0,
-		IsSubmit: 0,
+		IsSubmit: 0, //忽略
 		IsOk:     0,
 	}
+	if condition1 || condition2 {
+		//插入新数据
+		sketchId, err := g.DB().Model(model.YounggeeSketchInfo{}).Data(sketchInfo).InsertAndGetId()
+		if err != nil {
+			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchInfo insert failed"}
+		}
+		//上传过,把旧的删掉
+		if condition1 {
+			_, err := g.DB().Model(model.YounggeeSketchPhoto{}).Where("sketch_id=?", sketchId).Delete()
+			if err != nil {
+				fmt.Println("err:", err.Error())
+			}
+		}
+		//插入新的
+		for _, v := range photoUrl {
+			_, err := g.DB().Model(model.YounggeeSketchPhoto{}).Data(g.Map{"sketch_id": sketchId, "photo_url": v, "symbol": sketchInfoReq.Type, "create_at": gtime.Now()}).Insert()
+			if err != nil {
+				return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchPhoto insert failed"}
+			}
+		}
 
-	sketchId, err := g.DB().Model(model.YounggeeSketchInfo{}).Data(sketchInfo).InsertAndGetId()
-	if err != nil {
-		return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchInfo insert failed"}
-	}
-	for _, v := range photoUrl {
-		_, err := g.DB().Model(model.YounggeeSketchPhoto{}).Data(g.Map{"sketch_id": sketchId, "photo_url": v, "symbol": sketchInfoReq.Type, "create_at": gtime.Now()}).Insert()
+	} else { //有数据,但是,还没有被审核,更新
+		sketchId := taskSketchInfo[0].SketchId
+		// 使用主键 ID 更新记录
+		_, err := g.DB().Model(model.YounggeeSketchInfo{}).Where("sketch_id = ?", sketchId).Data(sketchInfo).Update()
+		//上传过,把旧的删掉
+		_, err = g.DB().Model(model.YounggeeSketchPhoto{}).Where("sketch_id=?", sketchId).Delete()
+		if err != nil {
+			fmt.Println("err:", err.Error())
+		}
+		//插入新的
+		for _, v := range photoUrl {
+			_, err := g.DB().Model(model.YounggeeSketchPhoto{}).Data(g.Map{"sketch_id": sketchId, "photo_url": v, "symbol": sketchInfoReq.Type, "create_at": gtime.Now()}).Insert()
+			if err != nil {
+				return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchPhoto insert failed"}
+			}
+		}
 		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchPhoto insert failed"}
+			return &TalentHttpResult{Code: -4, Msg: "YounggeeSketchInfo update failed"}
 		}
 	}
-	//todo :task_stage改成10 初稿待审
-	//todo: 再次提交,之前的也要保留,不能仅仅updata
 
+	//修改task表中的字段待添加变成已添加,待修改变成已修改
 	sketchStatus, err := g.DB().Model(model.YoungeeTaskInfo{}).Fields("sketch_status").Where("task_id = ?", sketchInfoReq.TaskId).Value()
 	if err != nil {
 		return &TalentHttpResult{Code: -5, Msg: "Get task info failed"}
@@ -77,86 +101,130 @@ func AddTaskSketch(r *ghttp.Request) *TalentHttpResult {
 			return &TalentHttpResult{Code: -6, Msg: "YoungeeTaskInfo update failed"}
 		}
 	}
-
-	return &TalentHttpResult{Code: 0, Msg: "success"}
-}
-
-// 提交初稿service
-func SubmitTaskSketch(r *ghttp.Request) *TalentHttpResult {
-	taskId, _ := r.Get("task_id").(string) // 查询是否处于违约状态
-	taskInfo := model.YoungeeTaskInfo{}
-	// 查询是否处于违约状态
-	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
-	if err1 != nil {
-		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
-	}
+	taskInfo := youngee_talent_model.YoungeeTaskInfo{}
+	//task设置为初稿待审核
+	_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "10"}).Where("task_id = ?", sketchInfoReq.TaskId).Update()
+	// 若处于违约状态则解除
 	if taskInfo.CurDefaultType == 3 || taskInfo.CurDefaultType == 9 {
-		// 若处于违约状态则解除并更新企业应支付金额
-		_, err1 = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "real_payment": taskInfo.AllPayment, "err_break_rate": 0}).Where("task_id = ?", taskId).Update()
-		if err1 != nil {
+		//将task设置为位违约
+		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"cur_default_type": "0", "err_break_rate": 0}).Where("task_id = ?", sketchInfoReq.TaskId).Update()
+		if err != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeTaskInfo update failed"}
 		}
 
-		// 更新违约记录表
-		_, err1 = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", taskId, g.Slice{1, 3, 4}).Update()
-		if err1 != nil {
+		// 更新违约记录表,default_status设置为已重新上传
+		_, err = g.DB().Model(model.YoungeeContractInfo{}).Data(g.Map{"default_status": 2}).Where("task_id = ? and default_status in (?)", sketchInfoReq.TaskId, g.Slice{1, 3, 4}).Update()
+		if err != nil {
 			return &TalentHttpResult{Code: -2, Msg: "YoungeeContractInfo update failed"}
 		}
 	}
-
-	// 查询该任务是否有已添加或已修改初稿
-	res, err := g.DB().Model(model.YounggeeSketchInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+	// 记录任务日志-上传初稿
+	taskLog := model.YounggeeTaskLog{
+		TaskId:  sketchInfoReq.TaskId,
+		Content: "上传初稿",
+		LogAt:   gtime.Now(),
+	}
+	//上传日志,用于详情页判断上一个状态是什么
+	_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
 	if err != nil {
-		return &TalentHttpResult{Code: -1, Msg: "YounggeeSketchInfo find failed"}
+		return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
 	}
-	if res == 1 && (taskInfo.SketchStatus == 2 || taskInfo.SketchStatus == 4) {
-		_, err = g.DB().Model(model.YounggeeSketchInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchInfo update failed"}
-		}
-		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "10"}).Where("task_id = ?", taskId).Update()
-		if err != nil {
-			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
-		}
-		// 记录任务日志-上传初稿
-		taskLog := model.YounggeeTaskLog{
-			TaskId:  taskId,
-			Content: "上传初稿",
-			LogAt:   gtime.Now(),
-		}
-		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
-		}
-		projectInfo := model.ProjectInfo{}
-		err1 := g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
-		if err1 != nil {
-			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
-		}
-		messageInfo := model.YounggeeMessageInfo{
-			MessageId:   11,
-			MessageType: 2,
-			CreatedAt:   gtime.Now(),
-			TalentId:    taskInfo.TalentId,
-			ProjectName: projectInfo.ProjectName,
-			IsReaded:    0,
-			IsDeleted:   0,
-		}
-		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
-		if err != nil {
-			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
-		}
+	//插入一条消息
+	projectInfo := model.ProjectInfo{}
+	err1 := g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+	if err1 != nil {
+		return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+	}
+	messageInfo := model.YounggeeMessageInfo{
+		MessageId:   11,
+		MessageType: 2,
+		CreatedAt:   gtime.Now(),
+		TalentId:    taskInfo.TalentId,
+		ProjectName: projectInfo.ProjectName,
+		IsReaded:    0,
+		IsDeleted:   0,
+	}
+	_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+	if err != nil {
+		return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
 	}
 
 	return &TalentHttpResult{Code: 0, Msg: "success"}
 }
 
-// 查询脚本提交审阅记录service
+// 提交初稿service
+//func SubmitTaskSketch(r *ghttp.Request) *TalentHttpResult {
+//	taskId, _ := r.Get("task_id").(string) // 查询是否处于违约状态
+//	taskInfo := model.YoungeeTaskInfo{}
+//	// 查询是否处于违约状态
+//	err1 := g.DB().Model(model.YoungeeTaskInfo{}).Where("task_id = ?", taskId).Scan(&taskInfo)
+//	if err1 != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YoungeeTaskInfo find failed"}
+//	}
+//	//若当前是违约状态
+//
+//	//如果有提交过,且被拒绝
+//
+//	// 查询该任务是否有已添加或已修改初稿
+//	//add之后is_submit就是0 && sketch_status变成已添加/已修改
+//	//
+//	res, err := g.DB().Model(model.YounggeeSketchInfo{}).Where("task_id = ? and is_submit = 0", taskId).Count()
+//	if err != nil {
+//		return &TalentHttpResult{Code: -1, Msg: "YounggeeSketchInfo find failed"}
+//	}
+//	// add之后一定会满足此条件
+//	if res == 1 && (taskInfo.SketchStatus == 2 || taskInfo.SketchStatus == 4) {
+//		//将这条task改成已提交并修改提交时间
+//		_, err = g.DB().Model(model.YounggeeSketchInfo{}).Data(g.Map{"is_submit": "1", "submit_at": gtime.Now()}).Where("task_id = ? and is_submit = 0", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -3, Msg: "YounggeeSketchInfo update failed"}
+//		}
+//		//将这条task_stage改成10(初稿待审)
+//		_, err = g.DB().Model(model.YoungeeTaskInfo{}).Data(g.Map{"task_stage": "10"}).Where("task_id = ?", taskId).Update()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -4, Msg: "YoungeeTaskInfo update failed"}
+//		}
+//		// 记录任务日志-上传初稿
+//		taskLog := model.YounggeeTaskLog{
+//			TaskId:  taskId,
+//			Content: "上传初稿",
+//			LogAt:   gtime.Now(),
+//		}
+//		//上传日志,用于详情页判断上一个状态是什么
+//		_, err = g.DB().Model(dao.YounggeeTaskLog.Table).Data(&taskLog).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -5, Msg: "YounggeeTaskLog insert failed"}
+//		}
+//		//插入一条消息
+//		projectInfo := model.ProjectInfo{}
+//		err1 := g.DB().Model(model.ProjectInfo{}).Where("project_id = ?", taskInfo.ProjectId).Scan(&projectInfo)
+//		if err1 != nil {
+//			return &TalentHttpResult{Code: -8, Msg: "ProjectInfo find failed"}
+//		}
+//		messageInfo := model.YounggeeMessageInfo{
+//			MessageId:   11,
+//			MessageType: 2,
+//			CreatedAt:   gtime.Now(),
+//			TalentId:    taskInfo.TalentId,
+//			ProjectName: projectInfo.ProjectName,
+//			IsReaded:    0,
+//			IsDeleted:   0,
+//		}
+//		_, err = g.DB().Model(dao.YounggeeMessageInfo.Table).Data(&messageInfo).Insert()
+//		if err != nil {
+//			return &TalentHttpResult{Code: -9, Msg: "YounggeeMessageInfo insert failed"}
+//		}
+//	}
+//
+//	return &TalentHttpResult{Code: 0, Msg: "success"}
+//}
+
+// 查询初稿提交审阅记录service done
 func GetTaskSketch(r *ghttp.Request) *TalentHttpResult {
 	taskId := r.Get("task_id")
 
 	var sketchInfoList []*youngee_talent_model.TaskSketchInfo
-	err := g.DB().Model(dao.YounggeeSketchInfo.Table).Where("is_submit = 1 and is_review = 1 and task_id = ?", taskId).OrderAsc("submit_at").Scan(&sketchInfoList)
+	err := g.DB().Model(dao.YounggeeSketchInfo.Table).Where("is_review = 1 and task_id = ?", taskId).OrderAsc("create_at").Scan(&sketchInfoList)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
@@ -172,22 +240,26 @@ func GetTaskSketch(r *ghttp.Request) *TalentHttpResult {
 	return &TalentHttpResult{Code: 0, Msg: "success", Data: sketchInfoList}
 }
 
-// 查询未提交初稿service
+// 查询未提交初稿service,进入上传初稿页面时访问
 func GetUnSubmitTaskSketch(r *ghttp.Request) *TalentHttpResult {
 	taskId := r.Get("task_id")
 
-	var unSubmitSketch *youngee_talent_model.TaskSketchInfo
-	err := g.DB().Model(dao.YounggeeSketchInfo.Table).Where("is_review = 0 and task_id = ?", taskId).OrderAsc("submit_at").Scan(&unSubmitSketch)
+	var unSubmitSketch []*youngee_talent_model.TaskSketchInfo
+	err := g.DB().Model(dao.YounggeeSketchInfo.Table).Where("is_review = 0 and task_id = ?", taskId).OrderDesc("create_at").Scan(&unSubmitSketch)
 	if err != nil {
 		return &TalentHttpResult{Code: -1, Msg: err.Error()}
 	}
+	if len(unSubmitSketch) == 0 {
+		return &TalentHttpResult{Code: 0, Msg: "success", Data: nil}
+	} else {
+		var sketchPhotoList []*youngee_talent_model.YounggeeSketchPhoto
+		err = g.DB().Model(dao.YounggeeSketchPhoto.Table).Where("sketch_id = ?", unSubmitSketch[0].SketchId).Scan(&sketchPhotoList)
+		if err != nil {
+			return &TalentHttpResult{Code: -2, Msg: err.Error()}
+		}
+		unSubmitSketch[0].Photo = sketchPhotoList
 
-	var sketchPhotoList []*youngee_talent_model.YounggeeSketchPhoto
-	err = g.DB().Model(dao.YounggeeSketchPhoto.Table).Where("sketch_id = ?", unSubmitSketch.SketchId).Scan(&sketchPhotoList)
-	if err != nil {
-		return &TalentHttpResult{Code: -2, Msg: err.Error()}
+		return &TalentHttpResult{Code: 0, Msg: "success", Data: unSubmitSketch[0]}
 	}
-	unSubmitSketch.Photo = sketchPhotoList
 
-	return &TalentHttpResult{Code: 0, Msg: "success", Data: unSubmitSketch}
 }

BIN
bin/main


BIN
bin/v3.7.3/linux_amd64/.DS_Store


BIN
bin/v3.7.3/windows_amd64/youngmini_server.exe


BIN
bin/v3.7.4/linux_amd64/.DS_Store


BIN
bin/v3.7.4/windows_amd64/youngmini_server.exe


+ 1 - 1
config/config.toml

@@ -19,7 +19,7 @@ name = "youngmini_server"
 output = "./bin"
 pack = ""
 system = "linux,windows"
-version = "v3.7.1"
+version = "v3.7.4"
 [gfcli.gen.dao]
 jsonCase = "Snake"
 link = "mysql:talent:talentDB_123@tcp(139.9.53.143:3306)/youngmini"

+ 11 - 4
go.mod

@@ -10,11 +10,11 @@ require (
 	github.com/chromedp/chromedp v0.9.5
 	github.com/gogf/gcache-adapter v0.1.2
 	github.com/gogf/gf v1.16.6
+	github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.118
 	github.com/lin-jim-leon/douyin v0.1.0
 	github.com/lin-jim-leon/kuaishou v0.3.0
 	github.com/satori/go.uuid v1.2.0
 	github.com/wechatpay-apiv3/wechatpay-go v0.2.18
-	github.com/wxnacy/wgo v1.0.4
 	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 )
 
@@ -33,17 +33,24 @@ require (
 	github.com/gorilla/websocket v1.4.2 // indirect
 	github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf // indirect
 	github.com/josharian/intern v1.0.0 // indirect
+	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.8 // indirect
 	github.com/mattn/go-isatty v0.0.12 // indirect
 	github.com/mattn/go-runewidth v0.0.10 // indirect
+	github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
+	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/olekukonko/tablewriter v0.0.5 // indirect
 	github.com/rivo/uniseg v0.1.0 // indirect
+	github.com/tjfoc/gmsm v1.4.1 // indirect
+	go.mongodb.org/mongo-driver v1.12.0 // indirect
 	go.opentelemetry.io/otel v1.0.0-RC2 // indirect
 	go.opentelemetry.io/otel/trace v1.0.0-RC2 // indirect
-	golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 // indirect
-	golang.org/x/sys v0.19.0 // indirect
-	golang.org/x/text v0.3.6 // indirect
+	golang.org/x/crypto v0.23.0 // indirect
+	golang.org/x/net v0.21.0 // indirect
+	golang.org/x/sys v0.20.0 // indirect
+	golang.org/x/text v0.15.0 // indirect
 	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
+	gopkg.in/ini.v1 v1.67.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 126 - 7
go.sum

@@ -1,7 +1,9 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
 github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/chromedp/cdproto v0.0.0-20240202021202-6d0b6a386732/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
 github.com/chromedp/cdproto v0.0.0-20240421230201-ab917191657d h1:x9d0XwRV3aWw1gAZtv0LrI39U+Efjp0mtyXRyikGb9Y=
 github.com/chromedp/cdproto v0.0.0-20240421230201-ab917191657d/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
@@ -11,9 +13,14 @@ github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3I
 github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
 github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4=
 github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
 github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
@@ -32,19 +39,42 @@ github.com/gogf/gcache-adapter v0.1.2/go.mod h1:LGkbo4Jp+23kEuPWiagDs+bpg93n1EZl
 github.com/gogf/gf v1.15.3/go.mod h1:K3FG9L4JBUeNLxQR/jCzDgB9+G9sayn49uQwx2zAn4A=
 github.com/gogf/gf v1.16.6 h1:Yp5YfwnGz41d1tiVqxcWXiPXyuzjTb7ax4SnPSXxDE8=
 github.com/gogf/gf v1.16.6/go.mod h1:4LoHfEBl2jbVmZpVx+qk2La3zWr1V315FtF2PVZuyQ8=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
 github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
 github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA=
 github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.118 h1:YHcixaT7Le4PxuxN07KQ5j9nPeH4ZdyXtMTSgA+Whh8=
+github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.118/go.mod h1:JWz2ujO9X3oU5wb6kXp+DpR2UuDj2SldDbX8T0FSuhI=
 github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
 github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kULo2bwGEkFvCePZ3qHDDTC3/J9Swo=
 github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
 github.com/lin-jim-leon/douyin v0.1.0 h1:WHCD5//i+rpKL6/+gZinTB3F9dbCFYJAK+BUGbKRU+4=
@@ -60,6 +90,11 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
 github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
@@ -67,6 +102,7 @@ github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhA
 github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
 github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
@@ -74,17 +110,26 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho=
+github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE=
 github.com/wechatpay-apiv3/wechatpay-go v0.2.18 h1:vj5tvSmnEIz3ZsnFNNUzg+3Z46xgNMJbrO4aD4wP15w=
 github.com/wechatpay-apiv3/wechatpay-go v0.2.18/go.mod h1:A254AUBVB6R+EqQFo3yTgeh7HtyqRRtN2w9hQSOrd4Q=
-github.com/wxnacy/wgo v1.0.4 h1:UEkzjlW3pMAXcTUCgMekrCvFYLKKwc0p5GAQrMIphs8=
-github.com/wxnacy/wgo v1.0.4/go.mod h1:8hqUwCgvMGgAIr4MLIeFur2YXS/Ns3vbyx5abx0e8iM=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
+github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+go.mongodb.org/mongo-driver v1.12.0 h1:aPx33jmn/rQuJXPQLZQ8NtfPQG8CaqgLThFtqRb0PiE=
+go.mongodb.org/mongo-driver v1.12.0/go.mod h1:AZkxhPnFJUoH7kZlFkVKucV20K387miPfm7oimrSmK0=
 go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA=
 go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg=
 go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM=
@@ -94,10 +139,41 @@ go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1
 go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
+golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
+golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
+golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -106,26 +182,69 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
-golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
+golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
+golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
+golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 73 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/LICENSE

@@ -0,0 +1,73 @@
+Copyright (c) Huawei Technologies Co., Ltd. 2020-present. All rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Copyright of core/signer/escape.go
+
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+Copyright of core/signer/signer.go
+
+Copyright (c) 2014, Xianjie
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 353 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic/basic_icredential.go

@@ -0,0 +1,353 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package basic
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/cache"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"io/ioutil"
+	"os"
+	"strings"
+	"time"
+)
+
+const (
+	ProjectIdInHeader     = "X-Project-Id"
+	SecurityTokenInHeader = "X-Security-Token"
+	AuthTokenInHeader     = "X-Auth-Token"
+	emptyAk               = "EMPTY_AK"
+	emptySK               = "EMPTY_SK"
+)
+
+var DefaultDerivedPredicate = auth.GetDefaultDerivedPredicate()
+
+type Credentials struct {
+	IamEndpoint      string
+	AK               string
+	SK               string
+	ProjectId        string
+	SecurityToken    string
+	IdpId            string
+	IdTokenFile      string
+	DerivedPredicate func(*request.DefaultHttpRequest) bool
+
+	derivedAuthServiceName string
+	regionId               string
+	authToken              string
+	expiredAt              int64
+}
+
+// ProcessAuthParams This function may panic under certain circumstances.
+func (s *Credentials) ProcessAuthParams(client *impl.DefaultHttpClient, region string) auth.ICredential {
+	if s.ProjectId != "" {
+		return s
+	}
+
+	authCache := cache.GetCache()
+	akWithName := s.AK + region
+	if projectId, ok := authCache.GetAuth(akWithName); ok {
+		s.ProjectId = projectId
+		return s
+	}
+
+	derivedPredicate := s.DerivedPredicate
+	s.DerivedPredicate = nil
+	r := internal.GetKeystoneListProjectsRequest(s.IamEndpoint, region, client.GetHttpConfig())
+	req, err := s.ProcessAuthRequest(client, r)
+	if err != nil {
+		panic(fmt.Errorf("failed to get project id of region '%s' automatically: %s", region, err.Error()))
+	}
+
+	resp, err := internal.KeystoneListProjects(client, req)
+	if err != nil {
+		panic(fmt.Errorf("failed to get project id of region '%s' automatically, X-IAM-Trace-Id=%s, %s",
+			region, resp.TraceId, err.Error()))
+	}
+	projects := *resp.Projects
+	if len(projects) < 1 {
+		panic(fmt.Errorf("failed to get project id of region '%s' automatically, X-IAM-Trace-Id=%s,"+
+			" confirm that the project exists in your account, or set project id manually:"+
+			" basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectId).SafeBuild()", region, resp.TraceId))
+	} else if len(projects) > 1 {
+		projectIds := make([]string, 0, len(projects))
+		for _, project := range projects {
+			projectIds = append(projectIds, project.Id)
+		}
+		panic(fmt.Errorf("multiple project ids found: [%s], X-IAM-Trace-Id=%s, please select one when initializing the credentials:"+
+			" basic.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithProjectId(projectId).SafeBuild()", strings.Join(projectIds, ","), resp.TraceId))
+	}
+
+	id := projects[0].Id
+	s.ProjectId = id
+	_ = authCache.PutAuth(akWithName, id)
+
+	s.DerivedPredicate = derivedPredicate
+
+	return s
+}
+
+func (s *Credentials) ProcessAuthRequest(client *impl.DefaultHttpClient, req *request.DefaultHttpRequest) (*request.DefaultHttpRequest, error) {
+	if s.needUpdateAuthToken() {
+		err := s.updateAuthTokenByIdToken(client)
+		if err != nil {
+			return nil, err
+		}
+	} else if s.needUpdateSecurityToken() {
+		err := s.UpdateSecurityTokenFromMetadata()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	reqBuilder := req.Builder()
+	if s.ProjectId != "" {
+		reqBuilder = reqBuilder.AddAutoFilledPathParam("project_id", s.ProjectId).AddHeaderParam(ProjectIdInHeader, s.ProjectId)
+	}
+
+	if s.authToken != "" {
+		req := reqBuilder.Build()
+		req.AddHeaderParam(AuthTokenInHeader, s.authToken)
+		return req, nil
+	}
+
+	if s.SecurityToken != "" {
+		reqBuilder.AddHeaderParam(SecurityTokenInHeader, s.SecurityToken)
+	}
+
+	var additionalHeaders map[string]string
+	var err error
+	if s.IsDerivedAuth(req) {
+		additionalHeaders, err = signer.GetDerivedSigner().Sign(reqBuilder.Build(), s.AK, s.SK, s.derivedAuthServiceName, s.regionId)
+	} else {
+		sn, err := signer.GetSigner(req.GetSigningAlgorithm())
+		if err != nil {
+			return nil, err
+		}
+		additionalHeaders, err = sn.Sign(reqBuilder.Build(), s.AK, s.SK)
+	}
+
+	if err != nil {
+		return nil, err
+	}
+
+	for key, value := range additionalHeaders {
+		req.AddHeaderParam(key, value)
+	}
+	return req, nil
+}
+
+func (s *Credentials) ProcessDerivedAuthParams(derivedAuthServiceName, regionId string) auth.ICredential {
+	if s.derivedAuthServiceName == "" {
+		s.derivedAuthServiceName = derivedAuthServiceName
+	}
+
+	if s.regionId == "" {
+		s.regionId = regionId
+	}
+
+	return s
+}
+
+func (s *Credentials) IsDerivedAuth(httpRequest *request.DefaultHttpRequest) bool {
+	if s.DerivedPredicate == nil {
+		return false
+	}
+
+	return s.DerivedPredicate(httpRequest)
+}
+
+func (s *Credentials) needUpdateSecurityToken() bool {
+	if s.authToken != "" {
+		return false
+	}
+	if s.AK == "" && s.SK == "" {
+		return true
+	}
+	if s.expiredAt == 0 || s.SecurityToken == "" {
+		return false
+	}
+	return s.expiredAt-time.Now().Unix() < 60
+}
+
+func (s *Credentials) UpdateSecurityTokenFromMetadata() error {
+	credential, err := internal.GetCredentialFromMetadata()
+	if err != nil {
+		return err
+	}
+
+	s.AK = credential.Access
+	s.SK = credential.Secret
+	s.SecurityToken = credential.Securitytoken
+	location, err := time.ParseInLocation(`2006-01-02T15:04:05Z`, credential.ExpiresAt, time.UTC)
+	if err != nil {
+		return err
+	}
+	s.expiredAt = location.Unix()
+
+	return nil
+}
+
+func (s *Credentials) needUpdateAuthToken() bool {
+	if s.IdpId == "" || s.IdTokenFile == "" {
+		return false
+	}
+	if s.authToken == "" {
+		return true
+	}
+	return s.expiredAt-time.Now().Unix() < 60
+}
+
+func (s *Credentials) updateAuthTokenByIdToken(client *impl.DefaultHttpClient) error {
+	idToken, err := s.getIdToken()
+	if err != nil {
+		return err
+	}
+
+	req := internal.GetProjectTokenWithIdTokenRequest(s.IamEndpoint, s.IdpId, idToken, s.ProjectId, client.GetHttpConfig())
+	resp, err := internal.CreateTokenWithIdToken(client, req)
+	if err != nil {
+		return err
+	}
+
+	location, err := time.ParseInLocation(`2006-01-02T15:04:05Z`, resp.Token.ExpiresAt, time.UTC)
+	if err != nil {
+		return err
+	}
+	s.expiredAt = location.Unix()
+	s.authToken = resp.XSubjectToken
+	return nil
+}
+
+func (s *Credentials) getIdToken() (string, error) {
+	_, err := os.Stat(s.IdTokenFile)
+	if err != nil {
+		return "", err
+	}
+
+	bytes, err := ioutil.ReadFile(s.IdTokenFile)
+	if err != nil {
+		return "", err
+	}
+	idToken := string(bytes)
+	if idToken == "" {
+		return "", sdkerr.NewCredentialsTypeError("id token is empty")
+	}
+	return idToken, nil
+}
+
+type CredentialsBuilder struct {
+	Credentials *Credentials
+	errMap      map[string]string
+}
+
+func NewCredentialsBuilder() *CredentialsBuilder {
+	return &CredentialsBuilder{
+		Credentials: &Credentials{IamEndpoint: internal.GetIamEndpoint()},
+		errMap:      make(map[string]string),
+	}
+}
+
+func (builder *CredentialsBuilder) WithIamEndpointOverride(endpoint string) *CredentialsBuilder {
+	builder.Credentials.IamEndpoint = endpoint
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithAk(ak string) *CredentialsBuilder {
+	if ak == "" {
+		builder.errMap[emptyAk] = "input ak cannot be an empty string"
+	} else {
+		builder.Credentials.AK = ak
+		delete(builder.errMap, emptyAk)
+	}
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithSk(sk string) *CredentialsBuilder {
+	if sk == "" {
+		builder.errMap[emptySK] = "input sk cannot be an empty string"
+	} else {
+		builder.Credentials.SK = sk
+		delete(builder.errMap, emptySK)
+	}
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithProjectId(projectId string) *CredentialsBuilder {
+	builder.Credentials.ProjectId = projectId
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithSecurityToken(token string) *CredentialsBuilder {
+	builder.Credentials.SecurityToken = token
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithDerivedPredicate(derivedPredicate func(*request.DefaultHttpRequest) bool) *CredentialsBuilder {
+	builder.Credentials.DerivedPredicate = derivedPredicate
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithIdpId(idpId string) *CredentialsBuilder {
+	builder.Credentials.IdpId = idpId
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithIdTokenFile(idTokenFile string) *CredentialsBuilder {
+	builder.Credentials.IdTokenFile = idTokenFile
+	return builder
+}
+
+// Deprecated: This function may panic under certain circumstances. Use SafeBuild instead.
+func (builder *CredentialsBuilder) Build() *Credentials {
+	credentials, err := builder.SafeBuild()
+	if err != nil {
+		panic(err)
+	}
+	return credentials
+}
+
+func (builder *CredentialsBuilder) SafeBuild() (*Credentials, error) {
+	if builder.errMap != nil && len(builder.errMap) != 0 {
+		errMsg := "build credentials failed: "
+		for _, msg := range builder.errMap {
+			errMsg += msg + "; "
+		}
+		return nil, sdkerr.NewCredentialsTypeError(errMsg)
+	}
+
+	if builder.Credentials.IdpId != "" || builder.Credentials.IdTokenFile != "" {
+		if builder.Credentials.IdpId == "" {
+			return nil, sdkerr.NewCredentialsTypeError("IdpId is required when using IdpId&IdTokenFile")
+		}
+		if builder.Credentials.IdTokenFile == "" {
+			return nil, sdkerr.NewCredentialsTypeError("IdTokenFile is required when using IdpId&IdTokenFile")
+		}
+		if builder.Credentials.ProjectId == "" {
+			return nil, sdkerr.NewCredentialsTypeError("ProjectId is required when using IdpId&IdTokenFile")
+		}
+	}
+	return builder.Credentials, nil
+}

+ 58 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/cache/auth_cache.go

@@ -0,0 +1,58 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package cache
+
+import (
+	"sync"
+)
+
+var (
+	c    *Cache
+	m    sync.RWMutex
+	once sync.Once
+)
+
+type Cache struct {
+	value map[string]string
+}
+
+func GetCache() *Cache {
+	once.Do(func() {
+		c = &Cache{
+			value: make(map[string]string),
+		}
+	})
+
+	return c
+}
+
+func (c *Cache) PutAuth(key string, value string) error {
+	m.Lock()
+	defer m.Unlock()
+	c.value[key] = value
+	return nil
+}
+
+func (c *Cache) GetAuth(key string) (string, bool) {
+	m.RLock()
+	defer m.RUnlock()
+	value, ok := c.value[key]
+	return value, ok
+}

+ 45 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/derived_icredential.go

@@ -0,0 +1,45 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"regexp"
+	"strings"
+)
+
+const DefaultEndpointReg = "^[a-z][a-z0-9-]+(\\.[a-z]{2,}-[a-z]+-\\d{1,2})?\\.(my)?(huaweicloud|myhwclouds).(com|cn)"
+
+type IDerivedCredential interface {
+	ProcessDerivedAuthParams(derivedAuthServiceName, regionId string) ICredential
+	IsDerivedAuth(httpRequest *request.DefaultHttpRequest) bool
+	ICredential
+}
+
+func GetDefaultDerivedPredicate() func(*request.DefaultHttpRequest) bool {
+	return func(httpRequest *request.DefaultHttpRequest) bool {
+		matched, err := regexp.MatchString(DefaultEndpointReg, strings.Replace(httpRequest.GetEndpoint(), "https://", "", 1))
+		if err != nil {
+			return true
+		} else {
+			return !matched
+		}
+	}
+}

+ 344 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global/global_icredential.go

@@ -0,0 +1,344 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package global
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/cache"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"io/ioutil"
+	"os"
+	"time"
+)
+
+const (
+	DomainIdInHeader      = "X-Domain-Id"
+	SecurityTokenInHeader = "X-Security-Token"
+	GlobalRegionId        = "globe"
+	AuthTokenInHeader     = "X-Auth-Token"
+	emptyAk               = "EMPTY_AK"
+	emptySK               = "EMPTY_SK"
+)
+
+var DefaultDerivedPredicate = auth.GetDefaultDerivedPredicate()
+
+type Credentials struct {
+	IamEndpoint      string
+	AK               string
+	SK               string
+	DomainId         string
+	SecurityToken    string
+	IdpId            string
+	IdTokenFile      string
+	DerivedPredicate func(*request.DefaultHttpRequest) bool
+
+	derivedAuthServiceName string
+	regionId               string
+	authToken              string
+	expiredAt              int64
+}
+
+// ProcessAuthParams This function may panic under certain circumstances.
+func (s *Credentials) ProcessAuthParams(client *impl.DefaultHttpClient, region string) auth.ICredential {
+	if s.DomainId != "" {
+		return s
+	}
+
+	authCache := cache.GetCache()
+	if domainId, ok := authCache.GetAuth(s.AK); ok {
+		s.DomainId = domainId
+		return s
+	}
+
+	derivedPredicate := s.DerivedPredicate
+	s.DerivedPredicate = nil
+
+	req, err := s.ProcessAuthRequest(client, internal.GetKeystoneListAuthDomainsRequest(s.IamEndpoint, client.GetHttpConfig()))
+	if err != nil {
+		panic(fmt.Errorf("failed to get domain id automatically, %w", err))
+	}
+
+	resp, err := internal.KeystoneListAuthDomains(client, req)
+	if err != nil {
+		panic(fmt.Errorf("failed to get domain id automatically, X-IAM-Trace-Id=%s, %w", resp.TraceId, err))
+	}
+	domains := *resp.Domains
+	if len(domains) == 0 {
+		panic(fmt.Errorf("failed to get domain id automatically, X-IAM-Trace-Id=%s,"+
+			" please confirm that you have 'iam:users:getUser' permission, or set domain id manually:"+
+			" global.NewCredentialsBuilder().WithAk(ak).WithSk(sk).WithDomainId(domainId).SafeBuild()", resp.TraceId))
+	}
+
+	id := domains[0].Id
+	s.DomainId = id
+	_ = authCache.PutAuth(s.AK, id)
+
+	s.DerivedPredicate = derivedPredicate
+
+	return s
+}
+
+func (s *Credentials) ProcessAuthRequest(client *impl.DefaultHttpClient, req *request.DefaultHttpRequest) (*request.DefaultHttpRequest, error) {
+	if s.needUpdateAuthToken() {
+		err := s.updateAuthTokenByIdToken(client)
+		if err != nil {
+			return nil, err
+		}
+	} else if s.needUpdateSecurityToken() {
+		err := s.UpdateSecurityTokenFromMetadata()
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	reqBuilder := req.Builder()
+	if s.DomainId != "" {
+		reqBuilder = reqBuilder.AddAutoFilledPathParam("domain_id", s.DomainId).AddHeaderParam(DomainIdInHeader, s.DomainId)
+	}
+
+	if s.authToken != "" {
+		req := reqBuilder.Build()
+		req.AddHeaderParam(AuthTokenInHeader, s.authToken)
+		return req, nil
+	}
+
+	if s.SecurityToken != "" {
+		reqBuilder.AddHeaderParam(SecurityTokenInHeader, s.SecurityToken)
+	}
+
+	var additionalHeaders map[string]string
+	var err error
+	if s.IsDerivedAuth(req) {
+		additionalHeaders, err = signer.GetDerivedSigner().Sign(reqBuilder.Build(), s.AK, s.SK, s.derivedAuthServiceName, s.regionId)
+	} else {
+		sn, err := signer.GetSigner(req.GetSigningAlgorithm())
+		if err != nil {
+			return nil, err
+		}
+		additionalHeaders, err = sn.Sign(reqBuilder.Build(), s.AK, s.SK)
+	}
+
+	if err != nil {
+		return nil, err
+	}
+
+	for key, value := range additionalHeaders {
+		req.AddHeaderParam(key, value)
+	}
+	return req, nil
+}
+
+func (s *Credentials) ProcessDerivedAuthParams(derivedAuthServiceName, regionId string) auth.ICredential {
+	if s.derivedAuthServiceName == "" {
+		s.derivedAuthServiceName = derivedAuthServiceName
+	}
+
+	if s.regionId == "" {
+		s.regionId = GlobalRegionId
+	}
+
+	return s
+}
+
+func (s *Credentials) IsDerivedAuth(httpRequest *request.DefaultHttpRequest) bool {
+	if s.DerivedPredicate == nil {
+		return false
+	}
+
+	return s.DerivedPredicate(httpRequest)
+}
+
+func (s *Credentials) needUpdateSecurityToken() bool {
+	if s.authToken != "" {
+		return false
+	}
+	if s.AK == "" && s.SK == "" {
+		return true
+	}
+	if s.expiredAt == 0 || s.SecurityToken == "" {
+		return false
+	}
+	return s.expiredAt-time.Now().Unix() < 60
+}
+
+func (s *Credentials) needUpdateAuthToken() bool {
+	if s.IdpId == "" || s.IdTokenFile == "" {
+		return false
+	}
+	if s.authToken == "" {
+		return true
+	}
+	return s.expiredAt-time.Now().Unix() < 60
+}
+
+func (s *Credentials) getIdToken() (string, error) {
+	_, err := os.Stat(s.IdTokenFile)
+	if err != nil {
+		return "", err
+	}
+
+	bytes, err := ioutil.ReadFile(s.IdTokenFile)
+	if err != nil {
+		return "", err
+	}
+	idToken := string(bytes)
+	if idToken == "" {
+		return "", sdkerr.NewCredentialsTypeError("id token is empty")
+	}
+	return idToken, nil
+}
+
+func (s *Credentials) UpdateSecurityTokenFromMetadata() error {
+	credential, err := internal.GetCredentialFromMetadata()
+	if err != nil {
+		return err
+	}
+
+	s.AK = credential.Access
+	s.SK = credential.Secret
+	s.SecurityToken = credential.Securitytoken
+	location, err := time.ParseInLocation(`2006-01-02T15:04:05Z`, credential.ExpiresAt, time.UTC)
+	if err != nil {
+		return err
+	}
+	s.expiredAt = location.Unix()
+
+	return nil
+}
+
+func (s *Credentials) updateAuthTokenByIdToken(client *impl.DefaultHttpClient) error {
+	idToken, err := s.getIdToken()
+	if err != nil {
+		return err
+	}
+
+	req := internal.GetDomainTokenWithIdTokenRequest(s.IamEndpoint, s.IdpId, idToken, s.DomainId, client.GetHttpConfig())
+	resp, err := internal.CreateTokenWithIdToken(client, req)
+	if err != nil {
+		return err
+	}
+
+	location, err := time.ParseInLocation(`2006-01-02T15:04:05Z`, resp.Token.ExpiresAt, time.UTC)
+	if err != nil {
+		return err
+	}
+	s.expiredAt = location.Unix()
+	s.authToken = resp.XSubjectToken
+	return nil
+}
+
+type CredentialsBuilder struct {
+	Credentials *Credentials
+	errMap      map[string]string
+}
+
+func NewCredentialsBuilder() *CredentialsBuilder {
+	return &CredentialsBuilder{
+		Credentials: &Credentials{IamEndpoint: internal.GetIamEndpoint()},
+		errMap:      make(map[string]string),
+	}
+}
+
+func (builder *CredentialsBuilder) WithAk(ak string) *CredentialsBuilder {
+	if ak == "" {
+		builder.errMap[emptyAk] = "input ak cannot be an empty string"
+	} else {
+		builder.Credentials.AK = ak
+		delete(builder.errMap, emptyAk)
+	}
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithSk(sk string) *CredentialsBuilder {
+	if sk == "" {
+		builder.errMap[emptySK] = "input sk cannot be an empty string"
+	} else {
+		builder.Credentials.SK = sk
+		delete(builder.errMap, emptySK)
+	}
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithDomainId(domainId string) *CredentialsBuilder {
+	builder.Credentials.DomainId = domainId
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithSecurityToken(token string) *CredentialsBuilder {
+	builder.Credentials.SecurityToken = token
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithIamEndpointOverride(endpoint string) *CredentialsBuilder {
+	builder.Credentials.IamEndpoint = endpoint
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithDerivedPredicate(derivedPredicate func(*request.DefaultHttpRequest) bool) *CredentialsBuilder {
+	builder.Credentials.DerivedPredicate = derivedPredicate
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithIdpId(idpId string) *CredentialsBuilder {
+	builder.Credentials.IdpId = idpId
+	return builder
+}
+
+func (builder *CredentialsBuilder) WithIdTokenFile(idTokenFile string) *CredentialsBuilder {
+	builder.Credentials.IdTokenFile = idTokenFile
+	return builder
+}
+
+// Deprecated: This function may panic under certain circumstances. Use SafeBuild instead.
+func (builder *CredentialsBuilder) Build() *Credentials {
+	credentials, err := builder.SafeBuild()
+	if err != nil {
+		panic(err)
+	}
+	return credentials
+}
+
+func (builder *CredentialsBuilder) SafeBuild() (*Credentials, error) {
+	if builder.errMap != nil && len(builder.errMap) != 0 {
+		errMsg := "build credentials failed: "
+		for _, msg := range builder.errMap {
+			errMsg += msg + "; "
+		}
+		return nil, sdkerr.NewCredentialsTypeError(errMsg)
+	}
+
+	if builder.Credentials.IdpId != "" || builder.Credentials.IdTokenFile != "" {
+		if builder.Credentials.IdpId == "" {
+			return nil, sdkerr.NewCredentialsTypeError("IdpId is required when using IdpId&IdTokenFile")
+		}
+		if builder.Credentials.IdTokenFile == "" {
+			return nil, sdkerr.NewCredentialsTypeError("IdTokenFile is required when using IdpId&IdTokenFile")
+		}
+		if builder.Credentials.DomainId == "" {
+			return nil, sdkerr.NewCredentialsTypeError("DomainId is required when using IdpId&IdTokenFile")
+		}
+	}
+	return builder.Credentials, nil
+}

+ 30 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/icredential.go

@@ -0,0 +1,30 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package auth
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+)
+
+type ICredential interface {
+	ProcessAuthParams(httpClient *impl.DefaultHttpClient, region string) ICredential
+	ProcessAuthRequest(httpClient *impl.DefaultHttpClient, httpRequest *request.DefaultHttpRequest) (*request.DefaultHttpRequest, error)
+}

+ 325 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal/iam_service.go

@@ -0,0 +1,325 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+	"errors"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+	"os"
+	"reflect"
+	"strings"
+)
+
+const (
+	DefaultIamEndpoint         = "https://iam.myhuaweicloud.com"
+	KeystoneListProjectsUri    = "/v3/projects"
+	KeystoneListAuthDomainsUri = "/v3/auth/domains"
+	IamEndpointEnv             = "HUAWEICLOUD_SDK_IAM_ENDPOINT"
+	CreateTokenWithIdTokenUri  = "/v3.0/OS-AUTH/id-token/tokens"
+	IamTraceId                 = "X-IAM-Trace-Id"
+)
+
+type IamResponse struct {
+	TraceId string
+}
+
+type KeystoneListProjectsResponse struct {
+	IamResponse
+	Projects *[]ProjectResult `json:"projects,omitempty"`
+}
+
+type ProjectResult struct {
+	Id   string `json:"id"`
+	Name string `json:"name"`
+}
+
+func GetIamEndpoint() string {
+	if endpoint := os.Getenv(IamEndpointEnv); endpoint != "" {
+		https := "https://"
+		if !strings.HasPrefix(endpoint, https) {
+			endpoint = https + endpoint
+		}
+		return endpoint
+	}
+	return DefaultIamEndpoint
+}
+
+func GetKeystoneListProjectsRequest(iamEndpoint string, regionId string, httpConfig config.HttpConfig) *request.DefaultHttpRequest {
+	return request.NewHttpRequestBuilder().
+		WithEndpoint(iamEndpoint).
+		WithPath(KeystoneListProjectsUri).
+		WithMethod("GET").
+		WithSigningAlgorithm(httpConfig.SigningAlgorithm).
+		AddQueryParam("name", reflect.ValueOf(regionId)).
+		Build()
+}
+
+func KeystoneListProjects(client *impl.DefaultHttpClient, req *request.DefaultHttpRequest) (*KeystoneListProjectsResponse, error) {
+	resp, err := client.SyncInvokeHttp(req)
+	if err != nil {
+		return nil, err
+	}
+
+	data, err := handleErrAndGetRespData(req, resp)
+	if err != nil {
+		return nil, err
+	}
+
+	keystoneListProjectResponse := new(KeystoneListProjectsResponse)
+	err = utils.Unmarshal(data, keystoneListProjectResponse)
+	if err != nil {
+		return nil, err
+	}
+	keystoneListProjectResponse.TraceId = resp.GetHeader(IamTraceId)
+
+	return keystoneListProjectResponse, nil
+}
+
+type KeystoneListAuthDomainsResponse struct {
+	IamResponse
+	Domains *[]Domains `json:"domains,omitempty"`
+}
+
+type Domains struct {
+	Id   string `json:"id"`
+	Name string `json:"name"`
+}
+
+func GetKeystoneListAuthDomainsRequest(iamEndpoint string, httpConfig config.HttpConfig) *request.DefaultHttpRequest {
+	return request.NewHttpRequestBuilder().
+		WithEndpoint(iamEndpoint).
+		WithPath(KeystoneListAuthDomainsUri).
+		WithMethod("GET").
+		WithSigningAlgorithm(httpConfig.SigningAlgorithm).
+		Build()
+}
+
+func KeystoneListAuthDomains(client *impl.DefaultHttpClient, req *request.DefaultHttpRequest) (*KeystoneListAuthDomainsResponse, error) {
+	resp, err := client.SyncInvokeHttp(req)
+	if err != nil {
+		return nil, err
+	}
+
+	data, err := handleErrAndGetRespData(req, resp)
+	if err != nil {
+		return nil, err
+	}
+
+	keystoneListAuthDomainsResponse := new(KeystoneListAuthDomainsResponse)
+	err = utils.Unmarshal(data, keystoneListAuthDomainsResponse)
+	if err != nil {
+		return nil, err
+	}
+	keystoneListAuthDomainsResponse.TraceId = resp.GetHeader(IamTraceId)
+
+	return keystoneListAuthDomainsResponse, nil
+}
+
+func handleErrAndGetRespData(req *request.DefaultHttpRequest, resp *response.DefaultHttpResponse) ([]byte, error) {
+	if err := (sdkerr.DefaultErrorHandler{}).HandleError(req, resp); err != nil {
+		return nil, err
+	}
+
+	return resp.GetBodyAsBytes()
+}
+
+type CreateTokenWithIdTokenRequest struct {
+	XIdpId string                 `json:"X-Idp-Id"`
+	Body   *GetIdTokenRequestBody `json:"body,omitempty"`
+}
+
+type GetIdTokenRequestBody struct {
+	Auth *GetIdTokenAuthParams `json:"auth"`
+}
+
+type GetIdTokenAuthParams struct {
+	IdToken *GetIdTokenIdTokenBody `json:"id_token"`
+
+	Scope *GetIdTokenIdScopeBody `json:"scope,omitempty"`
+}
+
+type GetIdTokenIdTokenBody struct {
+	Id string `json:"id"`
+}
+
+type GetIdTokenIdScopeBody struct {
+	Domain *GetIdTokenScopeDomainOrProjectBody `json:"domain,omitempty"`
+
+	Project *GetIdTokenScopeDomainOrProjectBody `json:"project,omitempty"`
+}
+
+type GetIdTokenScopeDomainOrProjectBody struct {
+	Id   *string `json:"id,omitempty"`
+	Name *string `json:"name,omitempty"`
+}
+
+type CreateTokenWithIdTokenResponse struct {
+	IamResponse
+	Token          *ScopedTokenInfo `json:"token"`
+	XSubjectToken  string           `json:"X-Subject-Token"`
+	XRequestId     string           `json:"X-Request-Id"`
+	HttpStatusCode int              `json:"-"`
+}
+
+type ScopedTokenInfo struct {
+	ExpiresAt string                     `json:"expires_at"`
+	Methods   []string                   `json:"methods"`
+	IssuedAt  string                     `json:"issued_at"`
+	User      *FederationUserBody        `json:"user"`
+	Domain    *DomainInfo                `json:"domain,omitempty"`
+	Project   *ProjectInfo               `json:"project,omitempty"`
+	Roles     []ScopedTokenInfoRoles     `json:"roles"`
+	Catalog   []UnscopedTokenInfoCatalog `json:"catalog"`
+}
+
+type FederationUserBody struct {
+	OsFederation *OsFederationInfo `json:"OS-FEDERATION"`
+	Domain       *DomainInfo       `json:"domain"`
+	Id           *string           `json:"id,omitempty"`
+	Name         *string           `json:"name,omitempty"`
+}
+
+type OsFederationInfo struct {
+	IdentityProvider *IdpIdInfo      `json:"identity_provider"`
+	Protocol         *ProtocolIdInfo `json:"protocol"`
+	Groups           []interface{}   `json:"groups"`
+}
+
+type IdpIdInfo struct {
+	Id string `json:"id"`
+}
+
+type ProtocolIdInfo struct {
+	Id string `json:"id"`
+}
+
+type DomainInfo struct {
+	Id   *string `json:"id,omitempty"`
+	Name string  `json:"name"`
+}
+
+type ProjectInfo struct {
+	Domain *DomainInfo `json:"domain,omitempty"`
+	Id     *string     `json:"id,omitempty"`
+	Name   string      `json:"name"`
+}
+
+type ScopedTokenInfoRoles struct {
+	Id   *string `json:"id,omitempty"`
+	Name *string `json:"name,omitempty"`
+}
+
+type UnscopedTokenInfoCatalog struct {
+	Id        *string `json:"id,omitempty"`
+	Interface *string `json:"interface,omitempty"`
+	Region    *string `json:"region,omitempty"`
+	RegionId  *string `json:"region_id,omitempty"`
+	Url       *string `json:"url,omitempty"`
+}
+
+func getCreateTokenWithIdTokenRequestBody(idToken string, scope *GetIdTokenIdScopeBody) *GetIdTokenRequestBody {
+	idTokenAuth := &GetIdTokenIdTokenBody{
+		Id: idToken,
+	}
+	authbody := &GetIdTokenAuthParams{
+		IdToken: idTokenAuth,
+		Scope:   scope,
+	}
+	body := &GetIdTokenRequestBody{
+		Auth: authbody,
+	}
+	return body
+}
+
+func getCreateTokenWithIdTokenRequest(iamEndpoint string, idpId string, body *GetIdTokenRequestBody, httpConfig config.HttpConfig) *request.DefaultHttpRequest {
+	req := request.NewHttpRequestBuilder().
+		WithEndpoint(iamEndpoint).
+		WithPath(CreateTokenWithIdTokenUri).
+		WithMethod("POST").
+		WithSigningAlgorithm(httpConfig.SigningAlgorithm).
+		WithBody("body", body).
+		Build()
+	req.AddHeaderParam("X-Idp-Id", idpId)
+	req.AddHeaderParam("Content-Type", "application/json;charset=UTF-8")
+	return req
+}
+
+func GetProjectTokenWithIdTokenRequest(iamEndpoint, idpId, idToken, projectId string, httpConfig config.HttpConfig) *request.DefaultHttpRequest {
+	projectScope := &GetIdTokenScopeDomainOrProjectBody{
+		Id: &projectId,
+	}
+	scopeAuth := &GetIdTokenIdScopeBody{
+		Project: projectScope,
+	}
+	body := getCreateTokenWithIdTokenRequestBody(idToken, scopeAuth)
+	return getCreateTokenWithIdTokenRequest(iamEndpoint, idpId, body, httpConfig)
+}
+
+func GetDomainTokenWithIdTokenRequest(iamEndpoint, idpId, idToken, domainId string, httpConfig config.HttpConfig) *request.DefaultHttpRequest {
+	domainScope := &GetIdTokenScopeDomainOrProjectBody{
+		Id: &domainId,
+	}
+	scopeAuth := &GetIdTokenIdScopeBody{
+		Domain: domainScope,
+	}
+	body := getCreateTokenWithIdTokenRequestBody(idToken, scopeAuth)
+	return getCreateTokenWithIdTokenRequest(iamEndpoint, idpId, body, httpConfig)
+}
+
+func CreateTokenWithIdToken(client *impl.DefaultHttpClient, req *request.DefaultHttpRequest) (*CreateTokenWithIdTokenResponse, error) {
+	resp, err := client.SyncInvokeHttp(req)
+	if err != nil {
+		return nil, err
+	}
+
+	data, err := handleErrAndGetRespData(req, resp)
+	if err != nil {
+		return nil, err
+	}
+
+	createTokenWithIdTokenResponse := new(CreateTokenWithIdTokenResponse)
+	err = utils.Unmarshal(data, createTokenWithIdTokenResponse)
+	if err != nil {
+		return nil, err
+	}
+
+	if createTokenWithIdTokenResponse.Token.ExpiresAt == "" {
+		return nil, errors.New("[CreateTokenWithIdTokenError] failed to get the expiration time of X-Auth-Token")
+	}
+	requestId := resp.GetHeader("X-Request-Id")
+	if requestId == "" {
+		return nil, errors.New("[CreateTokenWithIdTokenError] failed to get X-Request-Id")
+	}
+	authToken := resp.GetHeader("X-Subject-Token")
+	if authToken == "" {
+		return nil, errors.New("[CreateTokenWithIdTokenError] failed to get X-Auth-Token")
+	}
+	createTokenWithIdTokenResponse.HttpStatusCode = resp.GetStatusCode()
+	createTokenWithIdTokenResponse.XRequestId = requestId
+	createTokenWithIdTokenResponse.XSubjectToken = authToken
+	createTokenWithIdTokenResponse.TraceId = resp.GetHeader(IamTraceId)
+
+	return createTokenWithIdTokenResponse, nil
+}

+ 73 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/internal/metadata.go

@@ -0,0 +1,73 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package internal
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+	"io/ioutil"
+	"net/http"
+	"time"
+)
+
+type GetTemporaryCredentialFromMetadataResponse struct {
+	Credential *Credential `json:"credential,omitempty"`
+}
+
+type Credential struct {
+	ExpiresAt string `json:"expires_at"`
+
+	Access string `json:"access"`
+
+	Secret string `json:"secret"`
+
+	Securitytoken string `json:"securitytoken"`
+}
+
+func GetCredentialFromMetadata() (*Credential, error) {
+	client := &http.Client{
+		Timeout: 3 * time.Second,
+	}
+	resp, err := client.Get("http://169.254.169.254/openstack/latest/securitykey")
+
+	if err != nil {
+		return nil, err
+	}
+
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	if resp.StatusCode >= 400 {
+		return nil, &sdkerr.ServiceResponseError{
+			StatusCode:   resp.StatusCode,
+			ErrorMessage: string(body),
+		}
+	}
+
+	respModel := &GetTemporaryCredentialFromMetadataResponse{}
+	err = utils.Unmarshal(body, respModel)
+	if err != nil {
+		return nil, err
+	}
+	return respModel.Credential, nil
+}

+ 80 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/credential_provider.go

@@ -0,0 +1,80 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package provider
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"reflect"
+)
+
+const (
+	basicCredentialType  = "basic"
+	globalCredentialType = "global"
+
+	credentialsAttr   = "Credentials"
+	akAttr            = "AK"
+	skAttr            = "SK"
+	securityTokenAttr = "SecurityToken"
+	idpIdAttr         = "IdpId"
+	idTokenFileAttr   = "IdTokenFile"
+	iamEndpointAttr   = "IamEndpoint"
+)
+
+type ICredentialProvider interface {
+	GetCredentials() (auth.ICredential, error)
+}
+
+type commonAttrs struct {
+	ak            string
+	sk            string
+	securityToken string
+	idpId         string
+	idTokenFile   string
+	iamEndpoint   string
+}
+
+func fillCommonAttrs(builder interface{}, common commonAttrs) error {
+	v := reflect.ValueOf(builder)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+	v = v.FieldByName(credentialsAttr)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	if common.iamEndpoint != "" {
+		v.FieldByName(iamEndpointAttr).SetString(common.iamEndpoint)
+	}
+	if common.idpId != "" && common.idTokenFile != "" {
+		v.FieldByName(idpIdAttr).SetString(common.idpId)
+		v.FieldByName(idTokenFileAttr).SetString(common.idTokenFile)
+		return nil
+	} else if common.ak != "" && common.sk != "" {
+		v.FieldByName(akAttr).SetString(common.ak)
+		v.FieldByName(skAttr).SetString(common.sk)
+		v.FieldByName(securityTokenAttr).SetString(common.securityToken)
+		return nil
+	}
+	return sdkerr.NewCredentialsTypeError(fmt.Sprintf("%s&%s or %s&%s does not exist",
+		akAttr, skAttr, idpIdAttr, idTokenFileAttr))
+}

+ 94 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/env_provider.go

@@ -0,0 +1,94 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package provider
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"os"
+	"strings"
+)
+
+const (
+	akEnvName            = "HUAWEICLOUD_SDK_AK"
+	skEnvName            = "HUAWEICLOUD_SDK_SK"
+	projectIdEnvName     = "HUAWEICLOUD_SDK_PROJECT_ID"
+	domainIdEnvName      = "HUAWEICLOUD_SDK_DOMAIN_ID"
+	securityTokenEnvName = "HUAWEICLOUD_SDK_SECURITY_TOKEN"
+	idpIdEnvName         = "HUAWEICLOUD_SDK_IDP_ID"
+	idTokenFileEnvName   = "HUAWEICLOUD_SDK_ID_TOKEN_FILE"
+)
+
+type EnvCredentialProvider struct {
+	credentialType string
+}
+
+// NewEnvCredentialProvider return a env credential provider
+// Supported credential types: basic, global
+func NewEnvCredentialProvider(credentialType string) *EnvCredentialProvider {
+	return &EnvCredentialProvider{credentialType: strings.ToLower(credentialType)}
+}
+
+// BasicCredentialEnvProvider return a env provider for basic.Credentials
+func BasicCredentialEnvProvider() *EnvCredentialProvider {
+	return NewEnvCredentialProvider(basicCredentialType)
+}
+
+// GlobalCredentialEnvProvider return a env provider for global.Credentials
+func GlobalCredentialEnvProvider() *EnvCredentialProvider {
+	return NewEnvCredentialProvider(globalCredentialType)
+}
+
+// GetCredentials get basic.Credentials or global.Credentials from environment variables
+func (p *EnvCredentialProvider) GetCredentials() (auth.ICredential, error) {
+	if p.credentialType == "" {
+		return nil, sdkerr.NewCredentialsTypeError("credential type is empty")
+	}
+
+	if strings.HasPrefix(p.credentialType, basicCredentialType) {
+		builder := basic.NewCredentialsBuilder().WithProjectId(os.Getenv(projectIdEnvName))
+		err := fillCommonAttrs(builder, getCommonAttrsFromEnv())
+		if err != nil {
+			return nil, err
+		}
+		return builder.Build(), nil
+	} else if strings.HasPrefix(p.credentialType, globalCredentialType) {
+		builder := global.NewCredentialsBuilder().WithDomainId(os.Getenv(domainIdEnvName))
+		err := fillCommonAttrs(builder, getCommonAttrsFromEnv())
+		if err != nil {
+			return nil, err
+		}
+		return builder.Build(), nil
+	}
+
+	return nil, sdkerr.NewCredentialsTypeError("unsupported credential type: " + p.credentialType)
+}
+
+func getCommonAttrsFromEnv() commonAttrs {
+	return commonAttrs{
+		ak:            os.Getenv(akEnvName),
+		sk:            os.Getenv(skEnvName),
+		securityToken: os.Getenv(securityTokenEnvName),
+		idpId:         os.Getenv(idpIdEnvName),
+		idTokenFile:   os.Getenv(idTokenFileEnvName),
+	}
+}

+ 73 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/metadata_provider.go

@@ -0,0 +1,73 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package provider
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"strings"
+)
+
+type MetadataCredentialProvider struct {
+	credentialType string
+}
+
+// NewMetadataCredentialProvider return a metadata credential provider
+// Supported credential types: basic, global
+func NewMetadataCredentialProvider(credentialType string) *MetadataCredentialProvider {
+	return &MetadataCredentialProvider{credentialType: strings.ToLower(credentialType)}
+}
+
+// BasicCredentialMetadataProvider return a metadata provider for basic.Credentials
+func BasicCredentialMetadataProvider() *MetadataCredentialProvider {
+	return NewMetadataCredentialProvider(basicCredentialType)
+}
+
+// GlobalCredentialMetadataProvider return a metadata provider for global.Credentials
+func GlobalCredentialMetadataProvider() *MetadataCredentialProvider {
+	return NewMetadataCredentialProvider(globalCredentialType)
+}
+
+// GetCredentials get basic.Credentials or global.Credentials from the instance's metadata
+func (p *MetadataCredentialProvider) GetCredentials() (auth.ICredential, error) {
+	if p.credentialType == "" {
+		return nil, sdkerr.NewCredentialsTypeError("credential type is empty")
+	}
+
+	if strings.HasPrefix(p.credentialType, basicCredentialType) {
+		credentials := basic.NewCredentialsBuilder().Build()
+		err := credentials.UpdateSecurityTokenFromMetadata()
+		if err != nil {
+			return nil, err
+		}
+		return credentials, nil
+	} else if strings.HasPrefix(p.credentialType, globalCredentialType) {
+		credentials := global.NewCredentialsBuilder().Build()
+		err := credentials.UpdateSecurityTokenFromMetadata()
+		if err != nil {
+			return nil, err
+		}
+		return credentials, nil
+	}
+
+	return nil, sdkerr.NewCredentialsTypeError("unsupported credential type: " + p.credentialType)
+}

+ 125 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/profile_provider.go

@@ -0,0 +1,125 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package provider
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/global"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"gopkg.in/ini.v1"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+const (
+	credentialsFileEnvName = "HUAWEICLOUD_SDK_CREDENTIALS_FILE"
+	defaultDir             = ".huaweicloud"
+	defaultFile            = "credentials"
+
+	akName            = "ak"
+	skName            = "sk"
+	projectIdName     = "project_id"
+	domainIdName      = "domain_id"
+	securityTokenName = "security_token"
+	iamEndpointName   = "iam_endpoint"
+	idpIdName         = "idp_id"
+	idTokenFileName   = "id_token_file"
+)
+
+type ProfileCredentialProvider struct {
+	credentialType string
+}
+
+// NewProfileCredentialProvider return a profile credential provider
+// Supported credential types: basic, global
+func NewProfileCredentialProvider(credentialType string) *ProfileCredentialProvider {
+	return &ProfileCredentialProvider{credentialType: strings.ToLower(credentialType)}
+}
+
+// BasicCredentialProfileProvider return a profile provider for basic.Credentials
+func BasicCredentialProfileProvider() *ProfileCredentialProvider {
+	return NewProfileCredentialProvider(basicCredentialType)
+}
+
+// GlobalCredentialProfileProvider return a profile provider for global.Credentials
+func GlobalCredentialProfileProvider() *ProfileCredentialProvider {
+	return NewProfileCredentialProvider(globalCredentialType)
+}
+
+// GetCredentials get basic.Credentials or global.Credentials from profile
+func (p *ProfileCredentialProvider) GetCredentials() (auth.ICredential, error) {
+	filePath, err := getCredentialsFilePath()
+	if err != nil {
+		return nil, err
+	}
+	file, err := ini.Load(filePath)
+	if err != nil {
+		return nil, err
+	}
+
+	section := file.Section(p.credentialType)
+	if section == nil {
+		return nil, sdkerr.NewCredentialsTypeError(fmt.Sprintf("credential type '%s' does not exist in '%s'", p.credentialType, filePath))
+	}
+
+	if strings.HasPrefix(p.credentialType, basicCredentialType) {
+		builder := basic.NewCredentialsBuilder().WithProjectId(section.Key(projectIdName).String())
+		err := fillCommonAttrs(builder, getCommonAttrsFromProfile(section))
+		if err != nil {
+			return nil, err
+		}
+		return builder.Build(), nil
+	} else if strings.HasPrefix(p.credentialType, globalCredentialType) {
+		builder := global.NewCredentialsBuilder().WithDomainId(section.Key(domainIdName).String())
+		err := fillCommonAttrs(builder, getCommonAttrsFromProfile(section))
+		if err != nil {
+			return nil, err
+		}
+		return builder.Build(), nil
+	}
+	return nil, sdkerr.NewCredentialsTypeError("unsupported credential type: " + p.credentialType)
+}
+
+func getCredentialsFilePath() (string, error) {
+	if path := os.Getenv(credentialsFileEnvName); path != "" {
+		return path, nil
+	}
+
+	dir, err := os.UserHomeDir()
+	if err != nil {
+		return "", err
+	}
+
+	return filepath.Join(dir, defaultDir, defaultFile), nil
+}
+
+func getCommonAttrsFromProfile(section *ini.Section) commonAttrs {
+	return commonAttrs{
+		ak:            section.Key(akName).String(),
+		sk:            section.Key(skName).String(),
+		securityToken: section.Key(securityTokenName).String(),
+		idpId:         section.Key(idpIdName).String(),
+		idTokenFile:   section.Key(idTokenFileName).String(),
+		iamEndpoint:   section.Key(iamEndpointName).String(),
+	}
+}

+ 82 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider/provider_chain.go

@@ -0,0 +1,82 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package provider
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"strings"
+)
+
+type CredentialProviderChain struct {
+	providers []ICredentialProvider
+}
+
+// NewCredentialProviderChain return a credential provider chain
+func NewCredentialProviderChain(providers []ICredentialProvider) *CredentialProviderChain {
+	return &CredentialProviderChain{providers: providers}
+}
+
+// DefaultCredentialProviderChain return a default credential provider chain
+// Supported credential types: basic, global
+// Default order: environment variables -> profile -> metadata
+func DefaultCredentialProviderChain(credentialType string) *CredentialProviderChain {
+	providers := []ICredentialProvider{
+		NewEnvCredentialProvider(credentialType),
+		NewProfileCredentialProvider(credentialType),
+		NewMetadataCredentialProvider(credentialType),
+	}
+	return NewCredentialProviderChain(providers)
+}
+
+// BasicCredentialProviderChain return a provider chain for basic.Credentials
+func BasicCredentialProviderChain() *CredentialProviderChain {
+	providers := []ICredentialProvider{
+		BasicCredentialEnvProvider(),
+		BasicCredentialProfileProvider(),
+		BasicCredentialMetadataProvider(),
+	}
+	return NewCredentialProviderChain(providers)
+}
+
+// GlobalCredentialProviderChain return a provider chain for global.Credentials
+func GlobalCredentialProviderChain() *CredentialProviderChain {
+	providers := []ICredentialProvider{
+		GlobalCredentialEnvProvider(),
+		GlobalCredentialProfileProvider(),
+		GlobalCredentialMetadataProvider(),
+	}
+	return NewCredentialProviderChain(providers)
+}
+
+// GetCredentials get basic.Credentials or global.Credentials in providers
+// In the order of providers, return the first found credentials
+// If credentials not found in every providers, return a error of all providers
+func (p *CredentialProviderChain) GetCredentials() (auth.ICredential, error) {
+	var errs []string
+	for _, provider := range p.providers {
+		credential, err := provider.GetCredentials()
+		if err == nil {
+			return credential, nil
+		}
+		errs = append(errs, err.Error())
+	}
+	return nil, sdkerr.NewCredentialsTypeError("unable to get credential in providers:\n" + strings.Join(errs, "\n"))
+}

+ 33 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm/signing_algorithm.go

@@ -0,0 +1,33 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package algorithm
+
+type SigningAlgorithm string
+
+const (
+	HmacSHA256      = "HmacSHA256"
+	HmacSM3         = "HmacSM3"
+	EcdsaP256SHA256 = "EcdsaP256SHA256"
+	SM2SM3          = "SM2SM3"
+)
+
+func GetDefaultSigningAlgorithm() SigningAlgorithm {
+	return HmacSHA256
+}

+ 121 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/derived_signer.go

@@ -0,0 +1,121 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"crypto/sha256"
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"golang.org/x/crypto/hkdf"
+	"io"
+	"strings"
+	"time"
+)
+
+const (
+	DerivedDateFormat = "20060102"
+	AlgorithmV11      = "V11-HMAC-SHA256"
+)
+
+func SignDerived(r *request.DefaultHttpRequest, ak string, sk string, derivedAuthServiceName string, regionId string) (map[string]string, error) {
+	return DerivedSigner{}.Sign(r, ak, sk, derivedAuthServiceName, regionId)
+}
+
+type DerivedSigner struct {
+}
+
+// Sign SignRequest set Authorization header
+func (s DerivedSigner) Sign(r *request.DefaultHttpRequest, ak, sk, derivedAuthServiceName, regionId string) (map[string]string, error) {
+	err := checkAKSK(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+	if derivedAuthServiceName == "" {
+		return nil, errors.New("DerivedAuthServiceName is required in credentials when using derived auth")
+	}
+	if regionId == "" {
+		return nil, errors.New("RegionId is required in credentials when using derived auth")
+	}
+
+	originalHeaders := r.GetHeaderParams()
+	t := extractTime(originalHeaders)
+	headerDate := t.UTC().Format(BasicDateFormat)
+	originalHeaders[HeaderXDate] = headerDate
+	additionalHeaders := map[string]string{HeaderXDate: headerDate}
+
+	signedHeaders := extractSignedHeaders(originalHeaders)
+	cr, err := canonicalRequest(r, signedHeaders, xSdkContentSha256, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+	info := t.UTC().Format(DerivedDateFormat) + "/" + regionId + "/" + derivedAuthServiceName
+	sts, err := s.stringToSign(cr, info, t)
+	if err != nil {
+		return nil, err
+	}
+	derivationKey, err := s.getDerivationKey(ak, sk, info)
+	if err != nil {
+		return nil, err
+	}
+	sig, err := s.signStringToSign(sts, []byte(derivationKey))
+	if err != nil {
+		return nil, err
+	}
+	additionalHeaders[HeaderAuthorization] = s.authHeaderValue(sig, ak, info, signedHeaders)
+	return additionalHeaders, nil
+}
+
+// signStringToSign Create the Signature.
+func (s DerivedSigner) signStringToSign(stringToSign string, signingKey []byte) (string, error) {
+	hm, err := sha256HasherInst.hmac([]byte(stringToSign), signingKey)
+	return fmt.Sprintf("%x", hm), err
+}
+
+// authHeaderValue Get the finalized value for the "Authorization" header.
+// The signature parameter is the output from signStringToSign
+func (s DerivedSigner) authHeaderValue(signature, accessKey, info string, signedHeaders []string) string {
+	return fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s",
+		AlgorithmV11,
+		accessKey,
+		info,
+		strings.Join(signedHeaders, ";"),
+		signature)
+}
+
+// getDerivationKey Get the derivation key for derived credential.
+func (s DerivedSigner) getDerivationKey(accessKey, secretKey, info string) (string, error) {
+	hash := sha256.New
+	derivationKeyReader := hkdf.New(hash, []byte(secretKey), []byte(accessKey), []byte(info))
+	derivationKey := make([]byte, 32)
+	_, err := io.ReadFull(derivationKeyReader, derivationKey)
+	return hex.EncodeToString(derivationKey), err
+}
+
+// stringToSign Create a "String to Sign".
+func (s DerivedSigner) stringToSign(canonicalRequest, info string, t time.Time) (string, error) {
+	canonicalRequestHash, err := sha256HasherInst.hashHexString([]byte(canonicalRequest))
+	if err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf("%s\n%s\n%s\n%s", AlgorithmV11, t.UTC().Format(BasicDateFormat), info, canonicalRequestHash), nil
+}

+ 89 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/hasher.go

@@ -0,0 +1,89 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	chmac "crypto/hmac"
+	"crypto/sha256"
+	"encoding/hex"
+	"github.com/tjfoc/gmsm/sm3"
+)
+
+type iHasher interface {
+	hash(data []byte) ([]byte, error)
+	hashHexString(data []byte) (string, error)
+	hmac(data []byte, key []byte) ([]byte, error)
+}
+
+type sm3Hasher struct {
+}
+
+func (h sm3Hasher) hash(data []byte) ([]byte, error) {
+	hash := sm3.New()
+	_, err := hash.Write(data)
+	if err != nil {
+		return nil, err
+	}
+	return hash.Sum(nil), nil
+}
+
+func (h sm3Hasher) hashHexString(data []byte) (string, error) {
+	hash, err := h.hash(data)
+	if err != nil {
+		return "", err
+	}
+	return hex.EncodeToString(hash), nil
+}
+
+func (h sm3Hasher) hmac(data []byte, key []byte) ([]byte, error) {
+	hash := chmac.New(sm3.New, key)
+	if _, err := hash.Write(data); err != nil {
+		return nil, err
+	}
+	return hash.Sum(nil), nil
+}
+
+type sha256Hasher struct {
+}
+
+func (h sha256Hasher) hash(data []byte) ([]byte, error) {
+	hash := sha256.New()
+	_, err := hash.Write(data)
+	if err != nil {
+		return nil, err
+	}
+	return hash.Sum(nil), nil
+}
+
+func (h sha256Hasher) hashHexString(data []byte) (string, error) {
+	hash, err := h.hash(data)
+	if err != nil {
+		return "", err
+	}
+	return hex.EncodeToString(hash), nil
+}
+
+func (h sha256Hasher) hmac(data []byte, key []byte) ([]byte, error) {
+	hash := chmac.New(sha256.New, key)
+	if _, err := hash.Write(data); err != nil {
+		return nil, err
+	}
+	return hash.Sum(nil), nil
+}

+ 45 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/iaksksigner.go

@@ -0,0 +1,45 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"errors"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+)
+
+type IAKSKSigner interface {
+	Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error)
+}
+
+func GetSigner(alg algorithm.SigningAlgorithm) (IAKSKSigner, error) {
+	switch alg {
+	case algorithm.HmacSHA256:
+		return signerInst, nil
+	case algorithm.HmacSM3:
+		return sm3SignerInst, nil
+	case algorithm.EcdsaP256SHA256:
+		return p256sha256SignerInst, nil
+	case algorithm.SM2SM3:
+		return sm2sm3SignerInst, nil
+	default:
+		return nil, errors.New("unsupported signing algorithm: " + string(alg))
+	}
+}

+ 44 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/init.go

@@ -0,0 +1,44 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+var (
+	sha256HasherInst     sha256Hasher
+	sm3HasherInst        sm3Hasher
+	signerInst           Signer
+	derivedSignerInst    DerivedSigner
+	sm3SignerInst        SM3Signer
+	p256sha256SignerInst P256SHA256Signer
+	sm2sm3SignerInst     SM2SM3Signer
+)
+
+func init() {
+	sha256HasherInst = sha256Hasher{}
+	sm3HasherInst = sm3Hasher{}
+	signerInst = Signer{}
+	derivedSignerInst = DerivedSigner{}
+	sm3SignerInst = SM3Signer{}
+	p256sha256SignerInst = P256SHA256Signer{}
+	sm2sm3SignerInst = SM2SM3Signer{}
+}
+
+func GetDerivedSigner() DerivedSigner {
+	return derivedSignerInst
+}

+ 140 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/p256_sha256_signer.go

@@ -0,0 +1,140 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"bytes"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"encoding/hex"
+	"errors"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"math/big"
+)
+
+const (
+	sdkEcdsaP256Sha256 = "SDK-ECDSA-P256-SHA256"
+)
+
+var (
+	one           = big.NewInt(1)
+	curveP256     = elliptic.P256()
+	p256nMinusTwo = new(big.Int).Sub(new(big.Int).Set(curveP256.Params().N), big.NewInt(2))
+)
+
+type P256SHA256Signer struct {
+}
+
+func (s P256SHA256Signer) Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error) {
+	err := checkAKSK(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	processContentHeader(req, xSdkContentSha256)
+	originalHeaders := req.GetHeaderParams()
+	t := extractTime(originalHeaders)
+	headerDate := t.UTC().Format(BasicDateFormat)
+	originalHeaders[HeaderXDate] = headerDate
+	additionalHeaders := map[string]string{HeaderXDate: headerDate}
+
+	signedHeaders := extractSignedHeaders(originalHeaders)
+
+	cr, err := canonicalRequest(req, signedHeaders, xSdkContentSha256, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sts, err := stringToSign(sdkEcdsaP256Sha256, cr, t, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	signingKey, err := s.GetSigningKey(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	sig, err := signStringToSign(sts, signingKey)
+	if err != nil {
+		return nil, err
+	}
+
+	additionalHeaders[HeaderAuthorization] = authHeaderValue(sdkEcdsaP256Sha256, sig, ak, signedHeaders)
+	return additionalHeaders, nil
+}
+
+// GetSigningKey get the derived key based on ak and sk.
+func (s P256SHA256Signer) GetSigningKey(ak, sk string) (ISigningKey, error) {
+	privInt, err := derivePrivateInt(sdkEcdsaP256Sha256, ak, sk, p256nMinusTwo, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.deriveSigningKey(privInt), nil
+}
+
+func (s P256SHA256Signer) deriveSigningKey(priv *big.Int) ISigningKey {
+	privateKey := new(ecdsa.PrivateKey)
+	privateKey.PublicKey.Curve = curveP256
+	privateKey.D = priv
+	privateKey.PublicKey.X, privateKey.PublicKey.Y = curveP256.ScalarBaseMult(priv.Bytes())
+	return P256SigningKey{privateKey: privateKey}
+}
+
+func derivePrivateInt(alg, ak, sk string, nMinusTwo *big.Int, hasher iHasher) (*big.Int, error) {
+	context := bytes.NewBuffer(make([]byte, 0, len(ak)+1))
+	data := bytes.NewBuffer(nil)
+
+	for counter := 0; counter <= 0xff; counter++ {
+		context.Reset()
+		data.Reset()
+
+		context.WriteString(ak)
+		context.WriteByte(byte(counter))
+
+		data.Write([]byte{0x00, 0x00, 0x00, 0x01})
+		data.WriteString(alg)
+		data.WriteByte(0x00)
+		data.Write(context.Bytes())
+		data.Write([]byte{0x00, 0x00, 0x01, 0x00})
+
+		hmacBytes, err := hasher.hmac(data.Bytes(), []byte(sk))
+		if err != nil {
+			return nil, err
+		}
+
+		candidate := new(big.Int).SetBytes(hmacBytes)
+		if candidate.Cmp(nMinusTwo) <= 0 {
+			return candidate.Add(candidate, one), nil
+		}
+	}
+	return nil, errors.New("derive candidate failed, counter out of range")
+}
+
+// signStringToSign Create the Signature.
+func signStringToSign(stringToSign string, signingKey ISigningKey) (string, error) {
+	sig, err := signingKey.Sign([]byte(stringToSign))
+	if err != nil {
+		return "", err
+	}
+
+	return hex.EncodeToString(sig), nil
+}

+ 312 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/signer.go

@@ -0,0 +1,312 @@
+// HWS API Gateway Signature
+// based on https://github.com/datastream/aws/blob/master/signv4.go
+// Copyright (c) 2014, Xianjie
+// License that can be found in the LICENSE file
+
+package signer
+
+import (
+	"encoding/hex"
+	"errors"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"net/url"
+	"reflect"
+	"sort"
+	"strings"
+	"time"
+)
+
+const (
+	sdkHmacSha256     = "SDK-HMAC-SHA256"
+	xSdkContentSha256 = "X-Sdk-Content-Sha256"
+)
+
+func Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error) {
+	return Signer{}.Sign(req, ak, sk)
+}
+
+type Signer struct {
+}
+
+// Sign SignRequest set Authorization header
+func (s Signer) Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error) {
+	err := checkAKSK(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	processContentHeader(req, xSdkContentSha256)
+	originalHeaders := req.GetHeaderParams()
+	t := extractTime(originalHeaders)
+	headerDate := t.UTC().Format(BasicDateFormat)
+	originalHeaders[HeaderXDate] = headerDate
+	additionalHeaders := map[string]string{HeaderXDate: headerDate}
+
+	signedHeaders := extractSignedHeaders(originalHeaders)
+
+	cr, err := canonicalRequest(req, signedHeaders, xSdkContentSha256, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sts, err := stringToSign(sdkHmacSha256, cr, t, sha256HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sig, err := s.signStringToSign(sts, []byte(sk))
+	if err != nil {
+		return nil, err
+	}
+
+	additionalHeaders[HeaderAuthorization] = authHeaderValue(sdkHmacSha256, sig, ak, signedHeaders)
+	return additionalHeaders, nil
+}
+
+// signStringToSign Create the Signature.
+func (s Signer) signStringToSign(stringToSign string, signingKey []byte) (string, error) {
+	hmac, err := sha256HasherInst.hmac([]byte(stringToSign), signingKey)
+	if err != nil {
+		return "", err
+	}
+	return hex.EncodeToString(hmac), nil
+}
+
+const (
+	BasicDateFormat     = "20060102T150405Z"
+	HeaderXDate         = "X-Sdk-Date"
+	HeaderHost          = "host"
+	HeaderAuthorization = "Authorization"
+)
+
+func checkAKSK(ak, sk string) error {
+	if ak == "" {
+		return errors.New("ak is required in credentials")
+	}
+	if sk == "" {
+		return errors.New("sk is required in credentials")
+	}
+
+	return nil
+}
+
+// stringToSign Create a "String to Sign".
+func stringToSign(alg, canonicalRequest string, t time.Time, hasher iHasher) (string, error) {
+	canonicalRequestHash, err := hasher.hashHexString([]byte(canonicalRequest))
+	if err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf("%s\n%s\n%s", alg, t.UTC().Format(BasicDateFormat), canonicalRequestHash), nil
+}
+
+// authHeaderValue Get the finalized value for the "Authorization" header.
+// The signature parameter is the output from stringToSign
+func authHeaderValue(alg, sig, ak string, signedHeaders []string) string {
+	return fmt.Sprintf("%s Access=%s, SignedHeaders=%s, Signature=%s",
+		alg,
+		ak,
+		strings.Join(signedHeaders, ";"),
+		sig)
+}
+
+func processContentHeader(req *request.DefaultHttpRequest, contentHeader string) {
+	if contentType, ok := req.GetHeaderParams()["Content-Type"]; ok && (!strings.Contains(contentType, "application/json") &&
+		!strings.Contains(contentType, "application/bson")) {
+		req.AddHeaderParam(contentHeader, "UNSIGNED-PAYLOAD")
+	}
+}
+
+func canonicalRequest(req *request.DefaultHttpRequest, signedHeaders []string, contentHeader string, hasher iHasher) (string, error) {
+	hexEncode, err := getContentHash(req, contentHeader, hasher)
+	if err != nil {
+		return "", err
+	}
+
+	return fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s",
+		req.GetMethod(),
+		canonicalURI(req),
+		canonicalQueryString(req),
+		canonicalHeaders(req, signedHeaders),
+		strings.Join(signedHeaders, ";"), hexEncode), nil
+}
+
+func getContentHash(req *request.DefaultHttpRequest, contentHeader string, hasher iHasher) (string, error) {
+	if content, ok := req.GetHeaderParams()[contentHeader]; ok {
+		return content, nil
+	}
+
+	buffer, err := req.GetBodyToBytes()
+	if err != nil {
+		return "", err
+	}
+
+	data := buffer.Bytes()
+	hexEncode, err := hasher.hashHexString(data)
+	if err != nil {
+		return "", err
+	}
+	return hexEncode, nil
+}
+
+func extractTime(headers map[string]string) time.Time {
+	if date, ok := headers[HeaderXDate]; ok {
+		t, err := time.Parse(BasicDateFormat, date)
+		if date == "" || err != nil {
+			return time.Now()
+		}
+		return t
+	}
+	return time.Now()
+}
+
+// canonicalURI returns request uri
+func canonicalURI(r *request.DefaultHttpRequest) string {
+	pattens := strings.Split(r.GetPath(), "/")
+
+	var uri []string
+	for _, v := range pattens {
+		uri = append(uri, escape(v))
+	}
+
+	urlPath := strings.Join(uri, "/")
+	if len(urlPath) == 0 || urlPath[len(urlPath)-1] != '/' {
+		urlPath = urlPath + "/"
+	}
+
+	return urlPath
+}
+
+func canonicalQueryString(r *request.DefaultHttpRequest) string {
+	var query = make(map[string][]string, 0)
+	for key, value := range r.GetQueryParams() {
+		valueWithType, ok := value.(reflect.Value)
+		if !ok {
+			continue
+		}
+
+		if valueWithType.Kind() == reflect.Slice {
+			params := r.CanonicalSliceQueryParamsToMulti(valueWithType)
+			for _, param := range params {
+				if _, ok := query[key]; !ok {
+					query[key] = make([]string, 0)
+				}
+				query[key] = append(query[key], param)
+			}
+		} else if valueWithType.Kind() == reflect.Map {
+			params := r.CanonicalMapQueryParams(key, valueWithType)
+			for _, param := range params {
+				for k, v := range param {
+					if _, ok := query[k]; !ok {
+						query[k] = make([]string, 0)
+					}
+					query[k] = append(query[k], v)
+				}
+			}
+		} else {
+			if _, ok := query[key]; !ok {
+				query[key] = make([]string, 0)
+			}
+			query[key] = append(query[key], r.CanonicalStringQueryParams(valueWithType))
+		}
+	}
+
+	var keys []string
+	for key := range query {
+		keys = append(keys, key)
+	}
+	sort.Strings(keys)
+
+	var a []string
+	for _, key := range keys {
+		k := escape(key)
+		sort.Strings(query[key])
+		for _, v := range query[key] {
+			kv := fmt.Sprintf("%s=%s", k, escape(v))
+			a = append(a, kv)
+		}
+	}
+	queryStr := strings.Join(a, "&")
+
+	return queryStr
+}
+
+func canonicalHeaders(r *request.DefaultHttpRequest, signerHeaders []string) string {
+	var a []string
+	header := make(map[string][]string)
+	userHeaders := r.GetHeaderParams()
+
+	for k, v := range userHeaders {
+		if _, ok := header[strings.ToLower(k)]; !ok {
+			header[strings.ToLower(k)] = make([]string, 0)
+		}
+		header[strings.ToLower(k)] = append(header[strings.ToLower(k)], v)
+	}
+
+	for _, key := range signerHeaders {
+		value := header[key]
+		if strings.EqualFold(key, HeaderHost) {
+			if u, err := url.Parse(r.GetEndpoint()); err == nil {
+				header[HeaderHost] = []string{u.Host}
+			}
+		}
+
+		sort.Strings(value)
+		for _, v := range value {
+			a = append(a, key+":"+strings.TrimSpace(v))
+		}
+	}
+
+	return fmt.Sprintf("%s\n", strings.Join(a, "\n"))
+}
+
+func extractSignedHeaders(headers map[string]string) []string {
+	var sh []string
+	for key := range headers {
+		if strings.HasPrefix(strings.ToLower(key), "content-type") || strings.Contains(key, "_") {
+			continue
+		}
+		sh = append(sh, strings.ToLower(key))
+	}
+	sort.Strings(sh)
+
+	return sh
+}
+
+func shouldEscape(c byte) bool {
+	if 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c == '-' || c == '~' || c == '.' {
+		return false
+	}
+	return true
+}
+
+func escape(s string) string {
+	hexCount := 0
+	for i := 0; i < len(s); i++ {
+		c := s[i]
+		if shouldEscape(c) {
+			hexCount++
+		}
+	}
+
+	if hexCount == 0 {
+		return s
+	}
+
+	t := make([]byte, len(s)+2*hexCount)
+	j := 0
+	for i := 0; i < len(s); i++ {
+		switch c := s[i]; {
+		case shouldEscape(c):
+			t[j] = '%'
+			t[j+1] = "0123456789ABCDEF"[c>>4]
+			t[j+2] = "0123456789ABCDEF"[c&15]
+			j += 3
+		default:
+			t[j] = s[i]
+			j++
+		}
+	}
+	return string(t)
+}

+ 110 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/signing_key.go

@@ -0,0 +1,110 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"crypto/ecdsa"
+	"crypto/rand"
+	"encoding/asn1"
+	"github.com/tjfoc/gmsm/sm2"
+	"math/big"
+)
+
+type ISigningKey interface {
+	Sign(data []byte) ([]byte, error)
+	Verify(signature, data []byte) bool
+}
+
+type ecSignature struct {
+	R *big.Int
+	S *big.Int
+}
+
+type P256SigningKey struct {
+	privateKey *ecdsa.PrivateKey
+}
+
+func (k P256SigningKey) Sign(data []byte) ([]byte, error) {
+	hashed, err := sha256HasherInst.hash(data)
+	if err != nil {
+		return nil, err
+	}
+	r, s, err := ecdsa.Sign(rand.Reader, k.privateKey, hashed)
+	if err != nil {
+		return nil, err
+	}
+
+	ecSig := ecSignature{
+		R: r,
+		S: s,
+	}
+	sig, err := asn1.Marshal(ecSig)
+	if err != nil {
+		return nil, err
+	}
+	return sig, nil
+}
+
+func (k P256SigningKey) Verify(signature, data []byte) bool {
+	ecSig := ecSignature{}
+	_, err := asn1.Unmarshal(signature, &ecSig)
+	if err != nil {
+		return false
+	}
+
+	hashed, err := sha256HasherInst.hash(data)
+	if err != nil {
+		return false
+	}
+
+	publicKey := &k.privateKey.PublicKey
+	return ecdsa.Verify(publicKey, hashed, ecSig.R, ecSig.S)
+}
+
+type SM2SigningKey struct {
+	privateKey *sm2.PrivateKey
+}
+
+func (k SM2SigningKey) Sign(data []byte) ([]byte, error) {
+	r, s, err := sm2.Sm2Sign(k.privateKey, data, []byte{}, rand.Reader)
+	if err != nil {
+		return nil, err
+	}
+
+	ecSig := ecSignature{
+		R: r,
+		S: s,
+	}
+	sig, err := asn1.Marshal(ecSig)
+	if err != nil {
+		return nil, err
+	}
+	return sig, nil
+}
+
+func (k SM2SigningKey) Verify(signature, data []byte) bool {
+	ecSig := ecSignature{}
+	_, err := asn1.Unmarshal(signature, &ecSig)
+	if err != nil {
+		return false
+	}
+
+	return sm2.Sm2Verify(&k.privateKey.PublicKey, data, []byte{}, ecSig.R, ecSig.S)
+}

+ 94 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/sm2_sm3_signer.go

@@ -0,0 +1,94 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/tjfoc/gmsm/sm2"
+	"math/big"
+)
+
+const (
+	sdkSm2Sm3 = "SDK-SM2-SM3"
+)
+
+var (
+	curveSm2     = sm2.P256Sm2()
+	sm2nMinusTwo = new(big.Int).Sub(new(big.Int).Set(curveSm2.Params().N), big.NewInt(2))
+)
+
+type SM2SM3Signer struct {
+}
+
+func (s SM2SM3Signer) Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error) {
+	err := checkAKSK(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	processContentHeader(req, xSdkContentSm3)
+	originalHeaders := req.GetHeaderParams()
+	t := extractTime(originalHeaders)
+	headerDate := t.UTC().Format(BasicDateFormat)
+	originalHeaders[HeaderXDate] = headerDate
+	additionalHeaders := map[string]string{HeaderXDate: headerDate}
+
+	signedHeaders := extractSignedHeaders(originalHeaders)
+
+	cr, err := canonicalRequest(req, signedHeaders, xSdkContentSm3, sm3HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sts, err := stringToSign(sdkSm2Sm3, cr, t, sm3HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	signingKey, err := s.GetSigningKey(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	sig, err := signStringToSign(sts, signingKey)
+	if err != nil {
+		return nil, err
+	}
+
+	additionalHeaders[HeaderAuthorization] = authHeaderValue(sdkSm2Sm3, sig, ak, signedHeaders)
+	return additionalHeaders, nil
+}
+
+func (s SM2SM3Signer) GetSigningKey(ak, sk string) (ISigningKey, error) {
+	privInt, err := derivePrivateInt(sdkSm2Sm3, ak, sk, sm2nMinusTwo, sm3HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	return s.deriveSigningKey(privInt), nil
+}
+
+func (s SM2SM3Signer) deriveSigningKey(priv *big.Int) ISigningKey {
+	privateKey := new(sm2.PrivateKey)
+	privateKey.PublicKey.Curve = curveSm2
+	privateKey.D = priv
+	privateKey.PublicKey.X, privateKey.PublicKey.Y = curveSm2.ScalarBaseMult(priv.Bytes())
+	return SM2SigningKey{privateKey: privateKey}
+}

+ 75 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/sm3_signer.go

@@ -0,0 +1,75 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package signer
+
+import (
+	"encoding/hex"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+)
+
+const (
+	sdkHmacSm3     = "SDK-HMAC-SM3"
+	xSdkContentSm3 = "X-Sdk-Content-Sm3"
+)
+
+type SM3Signer struct {
+}
+
+func (s SM3Signer) Sign(req *request.DefaultHttpRequest, ak, sk string) (map[string]string, error) {
+	err := checkAKSK(ak, sk)
+	if err != nil {
+		return nil, err
+	}
+
+	processContentHeader(req, xSdkContentSm3)
+	originalHeaders := req.GetHeaderParams()
+	t := extractTime(originalHeaders)
+	headerDate := t.UTC().Format(BasicDateFormat)
+	originalHeaders[HeaderXDate] = headerDate
+	additionalHeaders := map[string]string{HeaderXDate: headerDate}
+
+	signedHeaders := extractSignedHeaders(originalHeaders)
+
+	cr, err := canonicalRequest(req, signedHeaders, xSdkContentSm3, sm3HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sts, err := stringToSign(sdkHmacSm3, cr, t, sm3HasherInst)
+	if err != nil {
+		return nil, err
+	}
+
+	sig, err := s.signStringToSign(sts, []byte(sk))
+	if err != nil {
+		return nil, err
+	}
+
+	additionalHeaders[HeaderAuthorization] = authHeaderValue(sdkHmacSm3, sig, ak, signedHeaders)
+	return additionalHeaders, nil
+}
+
+func (s SM3Signer) signStringToSign(stringToSign string, signingKey []byte) (string, error) {
+	hmac, err := sm3HasherInst.hmac([]byte(stringToSign), signingKey)
+	if err != nil {
+		return "", err
+	}
+	return hex.EncodeToString(hmac), nil
+}

+ 182 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config/http_config.go

@@ -0,0 +1,182 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package config
+
+import (
+	"context"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/httphandler"
+	"net"
+	"net/http"
+	"time"
+)
+
+const (
+	DefaultTimeout                        = 120 * time.Second
+	DefaultRetries                        = 0
+	DefaultIgnoreSSLVerification          = false
+	DefaultIgnoreContentTypeForGetRequest = false
+)
+
+type DialContext func(ctx context.Context, network string, addr string) (net.Conn, error)
+
+type HttpConfig struct {
+	DialContext           DialContext
+	Timeout               time.Duration
+	Retries               int
+	HttpProxy             *Proxy
+	IgnoreSSLVerification bool
+	// AllowRedirects Experimental configuration, the default value is false.
+	// Automatic redirection is allowed when turns on, which may cause some request exceptions.
+	AllowRedirects bool
+	HttpHandler    *httphandler.HttpHandler
+	// HttpTransport This configuration has the highest priority,
+	// which means specifying the HttpTransport will invalidate other configurations,
+	// such as DialContext, HttpProxy, IgnoreSSLVerification.
+	HttpTransport *http.Transport
+	RoundTripper  http.RoundTripper
+	// IgnoreContentTypeForGetRequest Ignore the request header Content-Type when sending a GET request,
+	// the default value is false
+	IgnoreContentTypeForGetRequest bool
+	SigningAlgorithm               algorithm.SigningAlgorithm
+}
+
+func DefaultHttpConfig() *HttpConfig {
+	return &HttpConfig{
+		Timeout:                        DefaultTimeout,
+		Retries:                        DefaultRetries,
+		IgnoreSSLVerification:          DefaultIgnoreSSLVerification,
+		IgnoreContentTypeForGetRequest: DefaultIgnoreContentTypeForGetRequest,
+		SigningAlgorithm:               algorithm.GetDefaultSigningAlgorithm(),
+	}
+}
+
+func (config *HttpConfig) WithSigningAlgorithm(signingAlgorithm algorithm.SigningAlgorithm) *HttpConfig {
+	config.SigningAlgorithm = signingAlgorithm
+	return config
+}
+
+func (config *HttpConfig) WithDialContext(dial DialContext) *HttpConfig {
+	config.DialContext = dial
+	return config
+}
+
+func (config *HttpConfig) WithTimeout(timeout time.Duration) *HttpConfig {
+	config.Timeout = timeout
+	return config
+}
+
+func (config *HttpConfig) WithRetries(retries int) *HttpConfig {
+	config.Retries = retries
+	return config
+}
+
+func (config *HttpConfig) WithIgnoreSSLVerification(ignore bool) *HttpConfig {
+	config.IgnoreSSLVerification = ignore
+	return config
+}
+
+// WithAllowRedirects Experimental configuration, the default value is false.
+// Automatic redirection is allowed when turns on, which may cause some request exceptions.
+func (config *HttpConfig) WithAllowRedirects(allowRedirects bool) *HttpConfig {
+	config.AllowRedirects = allowRedirects
+	return config
+}
+
+func (config *HttpConfig) WithHttpHandler(handler *httphandler.HttpHandler) *HttpConfig {
+	config.HttpHandler = handler
+	return config
+}
+
+// WithHttpTransport This configuration has the highest priority,
+// which means specifying the HttpTransport will invalidate other configurations,
+// such as DialContext, HttpProxy, IgnoreSSLVerification.
+func (config *HttpConfig) WithHttpTransport(transport *http.Transport) *HttpConfig {
+	config.HttpTransport = transport
+	return config
+}
+
+func (config *HttpConfig) WithHttpRoundTripper(roundTripper http.RoundTripper) *HttpConfig {
+	config.RoundTripper = roundTripper
+	return config
+}
+
+func (config *HttpConfig) WithProxy(proxy *Proxy) *HttpConfig {
+	config.HttpProxy = proxy
+	return config
+}
+
+// WithIgnoreContentTypeForGetRequest Ignore the request header Content-Type when sending a GET request,
+// the default value is false
+func (config *HttpConfig) WithIgnoreContentTypeForGetRequest(ignoreContentTypeForGetRequest bool) *HttpConfig {
+	config.IgnoreContentTypeForGetRequest = ignoreContentTypeForGetRequest
+	return config
+}
+
+type Proxy struct {
+	Schema   string
+	Host     string
+	Port     int
+	Username string
+	Password string
+}
+
+func NewProxy() *Proxy {
+	return &Proxy{}
+}
+
+func (p *Proxy) WithSchema(schema string) *Proxy {
+	p.Schema = schema
+	return p
+}
+
+func (p *Proxy) WithHost(host string) *Proxy {
+	p.Host = host
+	return p
+}
+
+func (p *Proxy) WithPort(port int) *Proxy {
+	p.Port = port
+	return p
+}
+
+func (p *Proxy) WithUsername(name string) *Proxy {
+	p.Username = name
+	return p
+}
+
+func (p *Proxy) WithPassword(pwd string) *Proxy {
+	p.Password = pwd
+	return p
+}
+
+func (p *Proxy) GetProxyUrl() string {
+	var proxyUrl string
+	if p.Username != "" {
+		proxyUrl = fmt.Sprintf("%s://%s:%s@%s", p.Schema, p.Username, p.Password, p.Host)
+	} else {
+		proxyUrl = fmt.Sprintf("%s://%s", p.Schema, p.Host)
+	}
+	if p.Port != 0 {
+		proxyUrl = fmt.Sprintf("%s:%d", proxyUrl, p.Port)
+	}
+	return proxyUrl
+}

+ 96 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter/converters.go

@@ -0,0 +1,96 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package converter
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+type Converter interface {
+	CovertStringToInterface(value string) (interface{}, error)
+	CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error
+}
+
+func StringConverterFactory(vType string) Converter {
+	switch vType {
+	case "string":
+		return StringConverter{}
+	case "int32":
+		return Int32Converter{}
+	case "int64":
+		return Int64Converter{}
+	case "float32":
+		return Float32Converter{}
+	case "float64":
+		return Float32Converter{}
+	case "bool":
+		return BooleanConverter{}
+	default:
+		return nil
+	}
+}
+
+func ConvertInterfaceToString(value interface{}) string {
+	if value == nil {
+		return ""
+	}
+	switch value.(type) {
+	case float64:
+		return strconv.FormatFloat(value.(float64), 'f', -1, 64)
+	case float32:
+		return strconv.FormatFloat(float64(value.(float32)), 'f', -1, 64)
+	case int:
+		return strconv.Itoa(value.(int))
+	case uint:
+		return strconv.Itoa(int(value.(uint)))
+	case int8:
+		return strconv.Itoa(int(value.(int8)))
+	case uint8:
+		return strconv.Itoa(int(value.(uint8)))
+	case int16:
+		return strconv.Itoa(int(value.(int16)))
+	case uint16:
+		return strconv.Itoa(int(value.(uint16)))
+	case int32:
+		return strconv.Itoa(int(value.(int32)))
+	case uint32:
+		return strconv.Itoa(int(value.(uint32)))
+	case int64:
+		return strconv.FormatInt(value.(int64), 10)
+	case uint64:
+		return strconv.FormatUint(value.(uint64), 10)
+	case bool:
+		return strconv.FormatBool(value.(bool))
+	case string:
+		return value.(string)
+	case []byte:
+		return string(value.([]byte))
+	default:
+		b, err := utils.Marshal(value)
+		if err != nil {
+			return ""
+		}
+		return strings.Trim(string(b[:]), "\"")
+	}
+}

+ 183 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter/types.go

@@ -0,0 +1,183 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package converter
+
+import (
+	"fmt"
+	"reflect"
+	"strconv"
+)
+
+type Int32Converter struct{}
+
+func (i Int32Converter) CovertStringToInterface(value string) (interface{}, error) {
+	i64, err := strconv.ParseInt(value, 10, 32)
+	if err == nil {
+		return int32(i64), nil
+	}
+	return int32(0), err
+}
+
+func (i Int32Converter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	v, err := i.CovertStringToInterface(value)
+	if err != nil {
+		return err
+	}
+	val, ok := v.(int32)
+	if !ok {
+		return fmt.Errorf("failed to convert string (%s) to int32", value)
+	}
+
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}
+
+type Int64Converter struct{}
+
+func (i Int64Converter) CovertStringToInterface(value string) (interface{}, error) {
+	i64, err := strconv.ParseInt(value, 10, 64)
+	if err == nil {
+		return i64, nil
+	}
+	return int64(0), err
+}
+
+func (i Int64Converter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	v, err := i.CovertStringToInterface(value)
+	if err != nil {
+		return err
+	}
+	val, ok := v.(int64)
+	if !ok {
+		return fmt.Errorf("failed to convert string (%s) to int64", value)
+	}
+
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}
+
+type Float32Converter struct{}
+
+func (i Float32Converter) CovertStringToInterface(value string) (interface{}, error) {
+	f64, err := strconv.ParseFloat(value, 32)
+	if err == nil {
+		return float32(f64), nil
+	}
+	return float32(0), err
+}
+
+func (i Float32Converter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	v, err := i.CovertStringToInterface(value)
+	if err != nil {
+		return err
+	}
+	val, ok := v.(float32)
+	if !ok {
+		return fmt.Errorf("failed to convert string (%s) to float32", value)
+	}
+
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}
+
+type Float64Converter struct{}
+
+func (i Float64Converter) CovertStringToInterface(value string) (interface{}, error) {
+	f64, err := strconv.ParseFloat(value, 32)
+	if err == nil {
+		return f64, nil
+	}
+	return float64(0), err
+}
+
+func (i Float64Converter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	v, err := i.CovertStringToInterface(value)
+	if err != nil {
+		return err
+	}
+	val, ok := v.(float64)
+	if !ok {
+		return fmt.Errorf("failed to convert string (%s) to float64", value)
+	}
+
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}
+
+type BooleanConverter struct{}
+
+func (i BooleanConverter) CovertStringToInterface(value string) (interface{}, error) {
+	boolean, err := strconv.ParseBool(value)
+	if err == nil {
+		return boolean, nil
+	}
+	return false, err
+}
+
+func (i BooleanConverter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	v, err := i.CovertStringToInterface(value)
+	if err != nil {
+		return err
+	}
+
+	val, ok := v.(bool)
+	if !ok {
+		return fmt.Errorf("failed to convert string (%s) to bool", value)
+	}
+
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}
+
+type StringConverter struct{}
+
+func (i StringConverter) CovertStringToInterface(value string) (interface{}, error) {
+	return value, nil
+}
+
+func (i StringConverter) CovertStringToPrimitiveTypeAndSetField(field reflect.Value, value string, isPtr bool) error {
+	val := value
+	if isPtr {
+		field.Set(reflect.ValueOf(&val))
+	} else {
+		field.Set(reflect.ValueOf(val))
+	}
+	return nil
+}

+ 62 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/field.go

@@ -0,0 +1,62 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package def
+
+type LocationType int32
+
+const (
+	Header LocationType = 1 << iota
+	Path
+	Query
+	Body
+	Form
+	Cname
+)
+
+type FieldDef struct {
+	LocationType LocationType
+	Name         string
+	JsonTag      string
+	KindName     string
+}
+
+func NewFieldDef() *FieldDef {
+	return &FieldDef{}
+}
+
+func (field *FieldDef) WithLocationType(locationType LocationType) *FieldDef {
+	field.LocationType = locationType
+	return field
+}
+
+func (field *FieldDef) WithName(name string) *FieldDef {
+	field.Name = name
+	return field
+}
+
+func (field *FieldDef) WithJsonTag(tag string) *FieldDef {
+	field.JsonTag = tag
+	return field
+}
+
+func (field *FieldDef) WithKindName(kindName string) *FieldDef {
+	field.KindName = kindName
+	return field
+}

+ 78 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/http_request_def.go

@@ -0,0 +1,78 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package def
+
+type HttpRequestDef struct {
+	Method         string
+	Path           string
+	ContentType    string
+	RequestFields  []*FieldDef
+	ResponseFields []*FieldDef
+	Response       interface{}
+}
+
+type HttpRequestDefBuilder struct {
+	httpRequestDef *HttpRequestDef
+}
+
+func NewHttpRequestDefBuilder() *HttpRequestDefBuilder {
+	httpRequestDef := &HttpRequestDef{
+		RequestFields:  []*FieldDef{},
+		ResponseFields: []*FieldDef{},
+	}
+	HttpRequestDefBuilder := &HttpRequestDefBuilder{
+		httpRequestDef: httpRequestDef,
+	}
+	return HttpRequestDefBuilder
+}
+
+func (builder *HttpRequestDefBuilder) WithPath(path string) *HttpRequestDefBuilder {
+	builder.httpRequestDef.Path = path
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) WithMethod(method string) *HttpRequestDefBuilder {
+	builder.httpRequestDef.Method = method
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) WithContentType(contentType string) *HttpRequestDefBuilder {
+	builder.httpRequestDef.ContentType = contentType
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) WithResponse(response interface{}) *HttpRequestDefBuilder {
+	builder.httpRequestDef.Response = response
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) WithRequestField(field *FieldDef) *HttpRequestDefBuilder {
+	builder.httpRequestDef.RequestFields = append(builder.httpRequestDef.RequestFields, field)
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) WithResponseField(field *FieldDef) *HttpRequestDefBuilder {
+	builder.httpRequestDef.ResponseFields = append(builder.httpRequestDef.ResponseFields, field)
+	return builder
+}
+
+func (builder *HttpRequestDefBuilder) Build() *HttpRequestDef {
+	return builder.httpRequestDef
+}

+ 108 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def/multipart.go

@@ -0,0 +1,108 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package def
+
+import (
+	"errors"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter"
+	"io"
+	"mime/multipart"
+	"net/textproto"
+	"os"
+	"path/filepath"
+	"strings"
+)
+
+var quoteEscape = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
+
+func escapeQuotes(s string) string {
+	return quoteEscape.Replace(s)
+}
+
+type FilePart struct {
+	Headers textproto.MIMEHeader
+	Content *os.File
+}
+
+func NewFilePart(content *os.File) *FilePart {
+	return &FilePart{
+		Content: content,
+	}
+}
+
+func NewFilePartWithContentType(content *os.File, contentType string) *FilePart {
+	var headers = make(textproto.MIMEHeader)
+	headers.Set("Content-Type", contentType)
+
+	return &FilePart{
+		Headers: headers,
+		Content: content,
+	}
+}
+
+func (f FilePart) Write(w *multipart.Writer, name string) error {
+	var h textproto.MIMEHeader
+	if f.Headers != nil {
+		h = f.Headers
+	} else {
+		h = make(textproto.MIMEHeader)
+	}
+
+	filename := filepath.Base(f.Content.Name())
+	if filename == "" {
+		return errors.New("failed to obtain filename from: " + f.Content.Name())
+	}
+
+	h.Set("Content-Disposition",
+		fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
+			escapeQuotes(name), escapeQuotes(filename)))
+
+	if f.Headers.Get("Content-Type") == "" {
+		h.Set("Content-Type", "application/octet-stream")
+	}
+
+	writer, err := w.CreatePart(h)
+	if err != nil {
+		return err
+	}
+
+	_, err = io.Copy(writer, f.Content)
+	return err
+}
+
+type MultiPart struct {
+	Content interface{}
+}
+
+func NewMultiPart(content interface{}) *MultiPart {
+	return &MultiPart{
+		Content: content,
+	}
+}
+
+func (m MultiPart) Write(w *multipart.Writer, name string) error {
+	err := w.WriteField(name, converter.ConvertInterfaceToString(m.Content))
+	return err
+}
+
+type FormData interface {
+	Write(*multipart.Writer, string) error
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange/exchange.go

@@ -0,0 +1,25 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package exchange
+
+type SdkExchange struct {
+	ApiReference *ApiReference
+	Attributes   map[string]interface{}
+}

+ 35 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange/reference.go

@@ -0,0 +1,35 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package exchange
+
+import "time"
+
+type ApiReference struct {
+	Host          string
+	Method        string
+	Path          string
+	Raw           string
+	UserAgent     string
+	StartedTime   time.Time
+	DurationMs    time.Duration
+	RequestId     string
+	StatusCode    int
+	ContentLength int64
+}

+ 521 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/hc_http_client.go

@@ -0,0 +1,521 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package core
+
+import (
+	"encoding/json"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+	"go.mongodb.org/mongo-driver/bson"
+	"net"
+	"net/url"
+	"reflect"
+	"strings"
+	"sync/atomic"
+)
+
+const (
+	userAgent       = "User-Agent"
+	xRequestId      = "X-Request-Id"
+	contentType     = "Content-Type"
+	applicationXml  = "application/xml"
+	applicationBson = "application/bson"
+)
+
+type HcHttpClient struct {
+	endpoints     []string
+	endpointIndex int32
+	credential    auth.ICredential
+	extraHeaders  map[string]string
+	httpClient    *impl.DefaultHttpClient
+	errorHandler  sdkerr.ErrorHandler
+}
+
+func NewHcHttpClient(httpClient *impl.DefaultHttpClient) *HcHttpClient {
+	return &HcHttpClient{httpClient: httpClient}
+}
+
+func (hc *HcHttpClient) WithEndpoints(endpoints []string) *HcHttpClient {
+	hc.endpoints = endpoints
+	return hc
+}
+
+func (hc *HcHttpClient) WithCredential(credential auth.ICredential) *HcHttpClient {
+	hc.credential = credential
+	return hc
+}
+
+func (hc *HcHttpClient) WithErrorHandler(errorHandler sdkerr.ErrorHandler) *HcHttpClient {
+	hc.errorHandler = errorHandler
+	return hc
+}
+
+func (hc *HcHttpClient) WithExtraHeaders(extraHeaders map[string]string) *HcHttpClient {
+	hc.extraHeaders = extraHeaders
+	return hc
+}
+
+func (hc *HcHttpClient) GetCredential() auth.ICredential {
+	return hc.credential
+}
+
+// Deprecated: This function will be removed in the future version. Use WithExtraHeaders instead.
+func (hc *HcHttpClient) PreInvoke(headers map[string]string) *HcHttpClient {
+	return hc.WithExtraHeaders(headers)
+}
+
+func (hc *HcHttpClient) Sync(req interface{}, reqDef *def.HttpRequestDef) (interface{}, error) {
+	exg := &exchange.SdkExchange{
+		ApiReference: &exchange.ApiReference{},
+		Attributes:   make(map[string]interface{}),
+	}
+	return hc.SyncInvoke(req, reqDef, exg)
+}
+
+func (hc *HcHttpClient) SyncInvoke(req interface{}, reqDef *def.HttpRequestDef,
+	exchange *exchange.SdkExchange) (interface{}, error) {
+	return hc.SyncInvokeWithExtraHeaders(req, reqDef, exchange, hc.extraHeaders)
+}
+
+func (hc *HcHttpClient) SyncInvokeWithExtraHeaders(req interface{}, reqDef *def.HttpRequestDef,
+	exchange *exchange.SdkExchange, extraHeaders map[string]string) (interface{}, error) {
+	var (
+		httpRequest *request.DefaultHttpRequest
+		resp        *response.DefaultHttpResponse
+		err         error
+	)
+
+	for {
+		httpRequest, err = hc.buildRequest(req, reqDef, extraHeaders)
+		if err != nil {
+			return nil, err
+		}
+
+		resp, err = hc.httpClient.SyncInvokeHttpWithExchange(httpRequest, exchange)
+		if err == nil {
+			break
+		}
+
+		var dnsErr *net.DNSError
+		if errors.As(err, &dnsErr) && atomic.LoadInt32(&hc.endpointIndex) < int32(len(hc.endpoints)-1) {
+			atomic.AddInt32(&hc.endpointIndex, 1)
+		} else {
+			return nil, err
+		}
+	}
+
+	return hc.extractResponse(httpRequest, resp, reqDef)
+}
+
+func (hc *HcHttpClient) extractEndpoint(req interface{}, reqDef *def.HttpRequestDef, attrMaps map[string]string) (string, error) {
+	var endpoint string
+	for _, v := range reqDef.RequestFields {
+		if v.LocationType == def.Cname {
+			u, err := url.Parse(hc.endpoints[atomic.LoadInt32(&hc.endpointIndex)])
+			if err != nil {
+				return "", err
+			}
+			value, err := hc.getFieldValueByName(v.Name, attrMaps, req)
+			if err != nil {
+				return "", err
+			}
+			endpoint = fmt.Sprintf("%s://%s.%s", u.Scheme, value, u.Host)
+		}
+	}
+
+	if endpoint == "" {
+		endpoint = hc.endpoints[hc.endpointIndex]
+	}
+
+	return endpoint, nil
+}
+
+func (hc *HcHttpClient) buildRequest(req interface{}, reqDef *def.HttpRequestDef, extraHeaders map[string]string) (*request.DefaultHttpRequest, error) {
+	t := reflect.TypeOf(req)
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	attrMaps := hc.getFieldJsonTags(t)
+
+	endpoint, err := hc.extractEndpoint(req, reqDef, attrMaps)
+	if err != nil {
+		return nil, err
+	}
+
+	builder := request.NewHttpRequestBuilder().WithEndpoint(endpoint).WithMethod(reqDef.Method).WithPath(reqDef.Path).
+		WithSigningAlgorithm(hc.httpClient.GetHttpConfig().SigningAlgorithm)
+
+	if pq, ok := req.(progress.Request); ok {
+		builder.WithProgressListener(pq.GetProgressListener()).WithProgressInterval(pq.GetProgressInterval())
+	}
+
+	hc.fillExtraHeaders(builder, extraHeaders)
+
+	builder, err = hc.fillParamsFromReq(req, t, reqDef, attrMaps, builder)
+	if err != nil {
+		return nil, err
+	}
+
+	var httpRequest = builder.Build()
+
+	currentHeaderParams := httpRequest.GetHeaderParams()
+	if _, ok := currentHeaderParams["Authorization"]; !ok {
+		httpRequest, err = hc.credential.ProcessAuthRequest(hc.httpClient, httpRequest)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return httpRequest, err
+}
+
+func (hc *HcHttpClient) fillExtraHeaders(builder *request.HttpRequestBuilder, extraHeaders map[string]string) {
+	headers := make(map[string]string)
+
+	// client-level headers
+	if hc.extraHeaders != nil {
+		for k, v := range hc.extraHeaders {
+			headers[k] = v
+		}
+	}
+
+	// request-level headers
+	if extraHeaders != nil {
+		for k, v := range extraHeaders {
+			headers[k] = v
+		}
+	}
+
+	// user-agent
+	uaValue := "huaweicloud-usdk-go/3.0"
+	for k, v := range headers {
+		if strings.ToLower(k) == strings.ToLower(userAgent) {
+			uaValue = uaValue + ";" + v
+		} else {
+			builder.AddHeaderParam(k, v)
+		}
+	}
+	builder.AddHeaderParam(userAgent, uaValue)
+}
+
+func (hc *HcHttpClient) fillParamsFromReq(req interface{}, t reflect.Type, reqDef *def.HttpRequestDef,
+	attrMaps map[string]string, builder *request.HttpRequestBuilder) (*request.HttpRequestBuilder, error) {
+	hasBody := false
+	for _, fieldDef := range reqDef.RequestFields {
+		value, err := hc.getFieldValueByName(fieldDef.Name, attrMaps, req)
+		if err != nil {
+			return nil, err
+		}
+
+		if !value.IsValid() {
+			continue
+		}
+
+		v, err := flattenEnumStruct(value)
+		if err != nil {
+			return nil, err
+		}
+
+		switch fieldDef.LocationType {
+		case def.Header:
+			builder.AddHeaderParam(fieldDef.JsonTag, fmt.Sprintf("%v", v))
+		case def.Path:
+			builder.AddPathParam(fieldDef.JsonTag, fmt.Sprintf("%v", v))
+		case def.Query:
+			builder.AddQueryParam(fieldDef.JsonTag, v)
+		case def.Body:
+			if body, ok := t.FieldByName("Body"); ok {
+				builder.WithBody(body.Tag.Get("type"), value.Interface())
+			} else {
+				builder.WithBody("", value.Interface())
+			}
+			hasBody = true
+		case def.Form:
+			builder.AddFormParam(fieldDef.JsonTag, value.Interface().(def.FormData))
+		}
+	}
+
+	if reqDef.ContentType != "" && !(hc.httpClient.GetHttpConfig().IgnoreContentTypeForGetRequest && reqDef.Method == "GET" && !hasBody) {
+		builder.AddHeaderParam(contentType, reqDef.ContentType)
+	}
+
+	return builder, nil
+}
+
+func (hc *HcHttpClient) getFieldJsonTags(t reflect.Type) map[string]string {
+	attrMaps := make(map[string]string)
+
+	fieldNum := t.NumField()
+	for i := 0; i < fieldNum; i++ {
+		jsonTag := t.Field(i).Tag.Get("json")
+		if jsonTag != "" {
+			attrMaps[t.Field(i).Name] = jsonTag
+		}
+	}
+
+	return attrMaps
+}
+
+func (hc *HcHttpClient) getFieldValueByName(name string, jsonTag map[string]string,
+	structName interface{}) (reflect.Value, error) {
+	v := reflect.ValueOf(structName)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	value := v.FieldByName(name)
+	if value.Kind() == reflect.Ptr {
+		if value.IsNil() {
+			if strings.Contains(jsonTag[name], "omitempty") {
+				return reflect.ValueOf(nil), nil
+			}
+			return reflect.ValueOf(nil), errors.New("request field " + name + " read null value")
+		}
+		return value.Elem(), nil
+	}
+
+	return value, nil
+}
+
+func flattenEnumStruct(value reflect.Value) (reflect.Value, error) {
+	if value.Kind() == reflect.Struct {
+		if method := value.MethodByName("Value"); method.IsValid() {
+			return method.Call(nil)[0], nil
+		}
+
+		v, e := utils.Marshal(value.Interface())
+		if e == nil {
+			str := string(v)
+			if strings.HasSuffix(str, "\n") {
+				str = strings.Trim(str, "\n")
+			}
+			if strings.HasPrefix(str, "\"") {
+				str = strings.Trim(str, "\"")
+			}
+			return reflect.ValueOf(str), nil
+		}
+		return reflect.ValueOf(nil), e
+	}
+	return value, nil
+}
+
+func (hc *HcHttpClient) extractResponse(req *request.DefaultHttpRequest, resp *response.DefaultHttpResponse, reqDef *def.HttpRequestDef) (interface{},
+	error) {
+	if hc.errorHandler == nil {
+		hc.errorHandler = sdkerr.DefaultErrorHandler{}
+	}
+	err := hc.errorHandler.HandleError(req, resp)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = hc.deserializeResponse(resp, reqDef); err != nil {
+		return nil, err
+	}
+
+	return reqDef.Response, nil
+}
+
+func (hc *HcHttpClient) deserializeResponse(resp *response.DefaultHttpResponse, reqDef *def.HttpRequestDef) error {
+	t := reflect.TypeOf(reqDef.Response)
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+
+	v := reflect.ValueOf(reqDef.Response)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	addStatusCode := func() {
+		field := v.FieldByName("HttpStatusCode")
+		field.Set(reflect.ValueOf(resp.GetStatusCode()))
+	}
+
+	// Return directly without reading the stream
+	if body, ok := t.FieldByName("Body"); ok && body.Type.Name() == "ReadCloser" {
+		v.FieldByName("Body").Set(reflect.ValueOf(resp.Response.Body))
+		addStatusCode()
+		return nil
+	}
+
+	err := hc.deserializeResponseFields(resp, reqDef)
+	if err != nil {
+		return err
+	}
+
+	addStatusCode()
+	return nil
+}
+
+func (hc *HcHttpClient) deserializeResponseFields(resp *response.DefaultHttpResponse, reqDef *def.HttpRequestDef) error {
+	data, err := resp.GetBodyAsBytes()
+	if err != nil {
+		return err
+	}
+
+	processError := func(err error) error {
+		return &sdkerr.ServiceResponseError{
+			StatusCode:   resp.GetStatusCode(),
+			RequestId:    resp.GetHeader(xRequestId),
+			ErrorMessage: err.Error(),
+		}
+	}
+
+	hasBody := false
+	for _, item := range reqDef.ResponseFields {
+		if item.LocationType == def.Header {
+			headerErr := hc.deserializeResponseHeaders(resp, reqDef, item)
+			if headerErr != nil {
+				return processError(headerErr)
+			}
+		}
+
+		if item.LocationType == def.Body {
+			hasBody = true
+
+			bodyErr := hc.deserializeResponseBody(reqDef, data)
+			if bodyErr != nil {
+				return processError(bodyErr)
+			}
+		}
+	}
+
+	if len(data) != 0 && !hasBody {
+		if strings.Contains(resp.Response.Header.Get(contentType), applicationXml) {
+			err = xml.Unmarshal(data, &reqDef.Response)
+		} else if strings.Contains(resp.Response.Header.Get(contentType), applicationBson) {
+			err = bson.Unmarshal(data, reqDef.Response)
+		} else {
+			err = utils.Unmarshal(data, &reqDef.Response)
+		}
+
+		if err != nil {
+			return processError(err)
+		}
+	}
+
+	return nil
+}
+
+func (hc *HcHttpClient) deserializeResponseBody(reqDef *def.HttpRequestDef, data []byte) error {
+	dataStr := string(data)
+
+	v := reflect.ValueOf(reqDef.Response)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	t := reflect.TypeOf(reqDef.Response)
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+
+	if body, ok := t.FieldByName("Body"); ok {
+		if body.Type.Kind() == reflect.Ptr && body.Type.Elem().Kind() == reflect.String {
+			v.FieldByName("Body").Set(reflect.ValueOf(&dataStr))
+		} else if body.Type.Kind() == reflect.String {
+			v.FieldByName("Body").Set(reflect.ValueOf(dataStr))
+		} else {
+			var bodyIns interface{}
+			if body.Type.Kind() == reflect.Ptr {
+				bodyIns = reflect.New(body.Type.Elem()).Interface()
+			} else {
+				bodyIns = reflect.New(body.Type).Interface()
+			}
+			var err error
+			if reqDef.ContentType == applicationBson {
+				err = bson.Unmarshal(data, bodyIns)
+			} else {
+				err = json.Unmarshal(data, bodyIns)
+			}
+			if err != nil {
+				return err
+			}
+
+			if body.Type.Kind() == reflect.Ptr {
+				v.FieldByName("Body").Set(reflect.ValueOf(bodyIns))
+			} else {
+				v.FieldByName("Body").Set(reflect.ValueOf(bodyIns).Elem())
+			}
+		}
+	}
+
+	return nil
+}
+
+func (hc *HcHttpClient) deserializeResponseHeaders(resp *response.DefaultHttpResponse, reqDef *def.HttpRequestDef,
+	item *def.FieldDef) error {
+	isPtr, fieldKind := hc.getFieldInfo(reqDef, item)
+	v := reflect.ValueOf(reqDef.Response)
+	if v.Kind() == reflect.Ptr {
+		v = v.Elem()
+	}
+
+	fieldValue := v.FieldByName(item.Name)
+	headerValue := resp.GetHeader(item.JsonTag)
+	if headerValue == "" {
+		return nil
+	}
+
+	sdkConverter := converter.StringConverterFactory(fieldKind)
+	if sdkConverter == nil {
+		return fmt.Errorf("failed to convert %s", item.JsonTag)
+	}
+
+	if err := sdkConverter.CovertStringToPrimitiveTypeAndSetField(fieldValue, headerValue, isPtr); err != nil {
+
+		return err
+	}
+
+	return nil
+}
+
+func (hc *HcHttpClient) getFieldInfo(reqDef *def.HttpRequestDef, item *def.FieldDef) (bool, string) {
+
+	var isPtr = false
+	var fieldKind string
+
+	t := reflect.TypeOf(reqDef.Response)
+	if t.Kind() == reflect.Ptr {
+		isPtr = true
+		t = t.Elem()
+	}
+
+	field, _ := t.FieldByName(item.Name)
+	if field.Type.Kind() == reflect.Ptr {
+		fieldKind = field.Type.Elem().Kind().String()
+	} else {
+		fieldKind = field.Type.Kind().String()
+	}
+
+	return isPtr, fieldKind
+}

+ 155 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/hc_http_client_builder.go

@@ -0,0 +1,155 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package core
+
+import (
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/provider"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr"
+	"reflect"
+	"strings"
+)
+
+type HcHttpClientBuilder struct {
+	CredentialsType        []string
+	derivedAuthServiceName string
+	credentials            auth.ICredential
+	endpoints              []string
+	httpConfig             *config.HttpConfig
+	region                 *region.Region
+	errorHandler           sdkerr.ErrorHandler
+}
+
+func NewHcHttpClientBuilder() *HcHttpClientBuilder {
+	hcHttpClientBuilder := &HcHttpClientBuilder{
+		CredentialsType: []string{"basic.Credentials"},
+		errorHandler:    sdkerr.DefaultErrorHandler{},
+	}
+	return hcHttpClientBuilder
+}
+
+func (builder *HcHttpClientBuilder) WithCredentialsType(credentialsType string) *HcHttpClientBuilder {
+	builder.CredentialsType = strings.Split(credentialsType, ",")
+	return builder
+}
+
+func (builder *HcHttpClientBuilder) WithDerivedAuthServiceName(derivedAuthServiceName string) *HcHttpClientBuilder {
+	builder.derivedAuthServiceName = derivedAuthServiceName
+	return builder
+}
+
+// Deprecated: As of 0.1.27, because of the support of the multi-endpoint feature, use WithEndpoints instead
+func (builder *HcHttpClientBuilder) WithEndpoint(endpoint string) *HcHttpClientBuilder {
+	return builder.WithEndpoints([]string{endpoint})
+}
+
+func (builder *HcHttpClientBuilder) WithEndpoints(endpoints []string) *HcHttpClientBuilder {
+	builder.endpoints = endpoints
+	return builder
+}
+
+func (builder *HcHttpClientBuilder) WithRegion(region *region.Region) *HcHttpClientBuilder {
+	builder.region = region
+	return builder
+}
+
+func (builder *HcHttpClientBuilder) WithHttpConfig(httpConfig *config.HttpConfig) *HcHttpClientBuilder {
+	builder.httpConfig = httpConfig
+	return builder
+}
+
+func (builder *HcHttpClientBuilder) WithCredential(iCredential auth.ICredential) *HcHttpClientBuilder {
+	builder.credentials = iCredential
+	return builder
+}
+
+func (builder *HcHttpClientBuilder) WithErrorHandler(errorHandler sdkerr.ErrorHandler) *HcHttpClientBuilder {
+	builder.errorHandler = errorHandler
+	return builder
+}
+
+// Deprecated: This function may panic under certain circumstances. Use SafeBuild instead.
+func (builder *HcHttpClientBuilder) Build() *HcHttpClient {
+	if builder.httpConfig == nil {
+		builder.httpConfig = config.DefaultHttpConfig()
+	}
+
+	defaultHttpClient := impl.NewDefaultHttpClient(builder.httpConfig)
+
+	if builder.credentials == nil {
+		p := provider.DefaultCredentialProviderChain(builder.CredentialsType[0])
+		credentials, err := p.GetCredentials()
+		if err != nil {
+			panic(err)
+		}
+		builder.credentials = credentials
+	}
+
+	t := reflect.TypeOf(builder.credentials)
+	if t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+	givenCredentialsType := t.String()
+	match := false
+	for _, credentialsType := range builder.CredentialsType {
+		if credentialsType == givenCredentialsType {
+			match = true
+			break
+		}
+	}
+	if !match {
+		panic(fmt.Errorf("need credential type is %s, actually is %s", builder.CredentialsType, givenCredentialsType))
+	}
+
+	if builder.region != nil {
+		builder.endpoints = builder.region.Endpoints
+		builder.credentials.ProcessAuthParams(defaultHttpClient, builder.region.Id)
+
+		if credential, ok := builder.credentials.(auth.IDerivedCredential); ok {
+			credential.ProcessDerivedAuthParams(builder.derivedAuthServiceName, builder.region.Id)
+		}
+	}
+
+	for index, endpoint := range builder.endpoints {
+		if !strings.HasPrefix(endpoint, "http") {
+			builder.endpoints[index] = "https://" + endpoint
+		}
+	}
+
+	hcHttpClient := NewHcHttpClient(defaultHttpClient).
+		WithEndpoints(builder.endpoints).
+		WithCredential(builder.credentials).
+		WithErrorHandler(builder.errorHandler)
+	return hcHttpClient
+}
+
+func (builder *HcHttpClientBuilder) SafeBuild() (client *HcHttpClient, err error) {
+	defer func() {
+		if r := recover(); r != nil {
+			err = fmt.Errorf("%v", r)
+		}
+	}()
+	client = builder.Build()
+	return
+}

+ 64 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/httphandler/http_handler.go

@@ -0,0 +1,64 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package httphandler
+
+import (
+	"net/http"
+	"time"
+)
+
+type MonitorMetric struct {
+	Host          string
+	Path          string
+	Method        string
+	Raw           string
+	UserAgent     string
+	RequestId     string
+	StatusCode    int
+	ContentLength int64
+	Latency       time.Duration
+	Attributes    map[string]interface{}
+}
+
+type HttpHandler struct {
+	RequestHandlers  func(http.Request)
+	ResponseHandlers func(http.Response)
+	MonitorHandlers  func(*MonitorMetric)
+}
+
+func NewHttpHandler() *HttpHandler {
+	handler := HttpHandler{}
+	return &handler
+}
+
+func (handler *HttpHandler) AddRequestHandler(requestHandler func(http.Request)) *HttpHandler {
+	handler.RequestHandlers = requestHandler
+	return handler
+}
+
+func (handler *HttpHandler) AddResponseHandler(responseHandler func(response http.Response)) *HttpHandler {
+	handler.ResponseHandlers = responseHandler
+	return handler
+}
+
+func (handler *HttpHandler) AddMonitorHandler(monitorHandler func(*MonitorMetric)) *HttpHandler {
+	handler.MonitorHandlers = monitorHandler
+	return handler
+}

+ 251 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/impl/default_http_client.go

@@ -0,0 +1,251 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package impl
+
+import (
+	"bytes"
+	"crypto/tls"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/config"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/httphandler"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response"
+	"io/ioutil"
+	"net/http"
+	"net/url"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type DefaultHttpClient struct {
+	httpHandler  *httphandler.HttpHandler
+	httpConfig   *config.HttpConfig
+	roundTripper http.RoundTripper
+	goHttpClient *http.Client
+}
+
+func NewDefaultHttpClient(httpConfig *config.HttpConfig) *DefaultHttpClient {
+	var roundTripper http.RoundTripper
+	if httpConfig.HttpTransport != nil {
+		roundTripper = httpConfig.HttpTransport
+	} else if httpConfig.RoundTripper != nil {
+		roundTripper = httpConfig.RoundTripper
+	} else {
+		defaultTrans := &http.Transport{
+			TLSClientConfig: &tls.Config{InsecureSkipVerify: httpConfig.IgnoreSSLVerification},
+		}
+
+		if httpConfig.DialContext != nil {
+			defaultTrans.DialContext = httpConfig.DialContext
+		}
+
+		if httpConfig.HttpProxy != nil {
+			proxyUrl := httpConfig.HttpProxy.GetProxyUrl()
+			proxy, err := url.Parse(proxyUrl)
+			if err == nil {
+				defaultTrans.Proxy = http.ProxyURL(proxy)
+			}
+		}
+
+		roundTripper = defaultTrans
+	}
+
+	client := &DefaultHttpClient{
+		roundTripper: roundTripper,
+		httpConfig:   httpConfig,
+	}
+
+	client.goHttpClient = &http.Client{
+		Transport: client.roundTripper,
+		Timeout:   httpConfig.Timeout,
+	}
+
+	if !httpConfig.AllowRedirects {
+		client.goHttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
+			return http.ErrUseLastResponse
+		}
+	}
+
+	client.httpHandler = httpConfig.HttpHandler
+
+	return client
+}
+
+func (client *DefaultHttpClient) GetHttpConfig() config.HttpConfig {
+	return *client.httpConfig
+}
+
+func (client *DefaultHttpClient) SyncInvokeHttp(request *request.DefaultHttpRequest) (*response.DefaultHttpResponse,
+	error) {
+	exch := &exchange.SdkExchange{
+		ApiReference: &exchange.ApiReference{},
+		Attributes:   make(map[string]interface{}),
+	}
+	return client.SyncInvokeHttpWithExchange(request, exch)
+}
+
+func (client *DefaultHttpClient) SyncInvokeHttpWithExchange(request *request.DefaultHttpRequest,
+	exch *exchange.SdkExchange) (*response.DefaultHttpResponse, error) {
+	req, err := request.ConvertRequest()
+	if err != nil {
+		return nil, err
+	}
+
+	if lnErr := client.listenRequest(req); lnErr != nil {
+		return nil, lnErr
+	}
+
+	client.recordRequestInfo(exch, req)
+	resp, err := client.goHttpClient.Do(req)
+	if err != nil {
+		return nil, err
+	}
+
+	processProgressResponse(request, resp)
+	client.recordResponseInfo(exch, resp)
+
+	if lnErr := client.listenResponse(resp); lnErr != nil {
+		return nil, lnErr
+	}
+	client.monitorHttp(exch, resp)
+
+	return response.NewDefaultHttpResponse(resp), nil
+}
+
+func (client *DefaultHttpClient) recordRequestInfo(exch *exchange.SdkExchange, req *http.Request) {
+	exch.ApiReference.Host = req.URL.Host
+	exch.ApiReference.Method = req.Method
+	exch.ApiReference.Path = req.URL.Path
+	exch.ApiReference.Raw = req.URL.RawQuery
+	exch.ApiReference.UserAgent = req.UserAgent()
+	exch.ApiReference.StartedTime = time.Now()
+}
+
+func (client *DefaultHttpClient) recordResponseInfo(exch *exchange.SdkExchange, resp *http.Response) {
+	exch.ApiReference.RequestId = resp.Header.Get("X-Request-Id")
+	exch.ApiReference.StatusCode = resp.StatusCode
+	exch.ApiReference.ContentLength = resp.ContentLength
+	exch.ApiReference.DurationMs = time.Since(exch.ApiReference.StartedTime)
+}
+
+func (client *DefaultHttpClient) listenRequest(req *http.Request) error {
+	if client.httpHandler == nil || client.httpHandler.RequestHandlers == nil || req == nil {
+		return nil
+	}
+
+	reqClone := req.Clone(req.Context())
+	if req.Body != nil {
+		if isStream(req.Header) {
+			reqClone.Body = ioutil.NopCloser(strings.NewReader("{stream: *****}"))
+		} else {
+			bodyBytes, err := ioutil.ReadAll(req.Body)
+			if err != nil {
+				return err
+			}
+			req.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
+			reqClone.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
+		}
+		defer reqClone.Body.Close()
+	}
+
+	client.httpHandler.RequestHandlers(*reqClone)
+	return nil
+}
+
+func (client *DefaultHttpClient) listenResponse(resp *http.Response) error {
+	if client.httpHandler == nil || client.httpHandler.ResponseHandlers == nil || resp == nil {
+		return nil
+	}
+
+	respClone := http.Response{
+		Status:           resp.Status,
+		StatusCode:       resp.StatusCode,
+		Proto:            resp.Proto,
+		ProtoMajor:       resp.ProtoMajor,
+		ProtoMinor:       resp.ProtoMinor,
+		Header:           resp.Header,
+		ContentLength:    resp.ContentLength,
+		TransferEncoding: resp.TransferEncoding,
+		Close:            resp.Close,
+		Uncompressed:     resp.Uncompressed,
+		Trailer:          resp.Trailer,
+	}
+
+	if resp.Body != nil {
+		if isStream(resp.Header) {
+			respClone.Body = ioutil.NopCloser(strings.NewReader("{stream: *****}"))
+		} else {
+			bodyBytes, err := ioutil.ReadAll(resp.Body)
+			if err != nil {
+				return err
+			}
+			resp.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
+			respClone.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
+		}
+
+		defer respClone.Body.Close()
+	}
+
+	client.httpHandler.ResponseHandlers(respClone)
+	return nil
+}
+
+func (client *DefaultHttpClient) monitorHttp(exch *exchange.SdkExchange, resp *http.Response) {
+	if client.httpHandler != nil && client.httpHandler.MonitorHandlers != nil {
+		metric := &httphandler.MonitorMetric{
+			Host:          exch.ApiReference.Host,
+			Method:        exch.ApiReference.Method,
+			Path:          exch.ApiReference.Path,
+			Raw:           exch.ApiReference.Raw,
+			UserAgent:     exch.ApiReference.UserAgent,
+			Latency:       exch.ApiReference.DurationMs,
+			RequestId:     exch.ApiReference.RequestId,
+			StatusCode:    exch.ApiReference.StatusCode,
+			ContentLength: exch.ApiReference.ContentLength,
+			Attributes:    exch.Attributes,
+		}
+
+		client.httpHandler.MonitorHandlers(metric)
+	}
+}
+
+func isStream(header http.Header) bool {
+	contentType := header.Get("Content-Type")
+	if contentType == "" {
+		return false
+	}
+	return strings.Contains(contentType, "octet-stream")
+}
+
+func processProgressResponse(request *request.DefaultHttpRequest, response *http.Response) {
+	if request.GetProgressListener() == nil || !isStream(response.Header) {
+		return
+	}
+	contentLength := int64(-1)
+	if value := response.Header.Get("Content-Length"); value != "" {
+		i, err := strconv.ParseInt(value, 10, 64)
+		if err == nil {
+			contentLength = i
+		}
+	}
+	response.Body = progress.NewTeeReader(response.Body, nil, contentLength, request.GetProgressListener(), request.GetProgressInterval())
+}

+ 113 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/invoker.go

@@ -0,0 +1,113 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package invoker
+
+import (
+	"time"
+
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/exchange"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry"
+)
+
+type RetryChecker func(interface{}, error) bool
+
+type BaseInvoker struct {
+	Exchange *exchange.SdkExchange
+
+	client  *core.HcHttpClient
+	request interface{}
+	meta    *def.HttpRequestDef
+	headers map[string]string
+
+	retryTimes      int
+	retryChecker    RetryChecker
+	backoffStrategy retry.Strategy
+}
+
+func NewBaseInvoker(client *core.HcHttpClient, request interface{}, meta *def.HttpRequestDef) *BaseInvoker {
+	exch := &exchange.SdkExchange{
+		ApiReference: &exchange.ApiReference{
+			Method: meta.Method,
+			Path:   meta.Path,
+		},
+		Attributes: make(map[string]interface{}),
+	}
+
+	return &BaseInvoker{
+		Exchange: exch,
+		client:   client,
+		request:  request,
+		meta:     meta,
+		headers:  make(map[string]string),
+	}
+}
+
+func (b *BaseInvoker) ReplaceCredentialWhen(fun func(auth.ICredential) auth.ICredential) *BaseInvoker {
+	b.client.WithCredential(fun(b.client.GetCredential()))
+	return b
+}
+
+// Deprecated: This function will be removed in the future version, use AddHeaders instead.
+func (b *BaseInvoker) AddHeader(headers map[string]string) *BaseInvoker {
+	return b.AddHeaders(headers)
+}
+
+func (b *BaseInvoker) AddHeaders(headers map[string]string) *BaseInvoker {
+	if headers != nil {
+		for k, v := range headers {
+			b.headers[k] = v
+		}
+	}
+	return b
+}
+
+func (b *BaseInvoker) WithRetry(retryTimes int, checker RetryChecker, backoffStrategy retry.Strategy) *BaseInvoker {
+	b.retryTimes = retryTimes
+	b.retryChecker = checker
+	b.backoffStrategy = backoffStrategy
+	return b
+}
+
+func (b *BaseInvoker) Invoke() (interface{}, error) {
+	if b.retryTimes == 0 || b.retryChecker == nil {
+		return b.client.SyncInvokeWithExtraHeaders(b.request, b.meta, b.Exchange, b.headers)
+	}
+
+	var execTimes int
+	var resp interface{}
+	var err error
+	for {
+		resp, err = b.client.SyncInvokeWithExtraHeaders(b.request, b.meta, b.Exchange, b.headers)
+		execTimes++
+
+		if execTimes > b.retryTimes || !b.retryChecker(resp, err) {
+			break
+		}
+
+		delay := b.backoffStrategy.ComputeDelayBeforeNextRetry(int32(execTimes))
+		if delay > 0 {
+			time.Sleep(time.Duration(delay) * time.Millisecond)
+		}
+	}
+	return resp, err
+}

+ 37 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/decorrelated_jitter.go

@@ -0,0 +1,37 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+// DecorRelatedJitter 去相关抖动退避 delay = min(最大等待时间, random(基础等待时间, 基础等待时间 * 3);
+type DecorRelatedJitter struct {
+	*strategyBase
+}
+
+func NewDecorRelatedJitter() *DecorRelatedJitter {
+	return &DecorRelatedJitter{strategyBase: newStrategyBase()}
+}
+
+func (d *DecorRelatedJitter) ComputeDelayBeforeNextRetry(int32) int32 {
+	return utils.Min32(MaxDelay, utils.RandInt32(d.GetBaseDelay(), d.GetBaseDelay()*3))
+}

+ 38 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/equal_jitter.go

@@ -0,0 +1,38 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+// EqualJitter 等抖动指数退避 delay = Exponential/2 + random(0, Exponential/2)
+type EqualJitter struct {
+	*strategyBase
+}
+
+func NewEqualJitter() *EqualJitter {
+	return &EqualJitter{strategyBase: newStrategyBase()}
+}
+
+func (e *EqualJitter) ComputeDelayBeforeNextRetry(retryTimes int32) int32 {
+	expoDelay := getExponentialDelay(e.GetBaseDelay(), retryTimes)
+	return expoDelay/2 + utils.RandInt32(1, expoDelay/2)
+}

+ 42 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/exponential.go

@@ -0,0 +1,42 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+// Exponential 指数退避 delay = min(最大等待时间, 基础等待时间 * (2^已重试次数))
+type Exponential struct {
+	*strategyBase
+}
+
+func NewExponential() *Exponential {
+	return &Exponential{strategyBase: newStrategyBase()}
+}
+
+func (e *Exponential) ComputeDelayBeforeNextRetry(retryTimes int32) int32 {
+	return getExponentialDelay(e.GetBaseDelay(), retryTimes)
+}
+
+// getExponentialDelay 等于 min(最大等待时间, 基础等待时间 * (2^已重试次数))
+func getExponentialDelay(baseDelay, retryTimes int32) int32 {
+	return utils.Min32(MaxDelay, baseDelay*(utils.Pow32(2, retryTimes)))
+}

+ 28 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/none.go

@@ -0,0 +1,28 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+type None struct{}
+
+func (n None) SetBaseDelay(int32) {}
+
+func (n None) ComputeDelayBeforeNextRetry(int32) int32 {
+	return 0
+}

+ 38 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/random_jitter.go

@@ -0,0 +1,38 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+// RandomJitter 全抖动指数退避 delay = random(0, Exponential)
+type RandomJitter struct {
+	*strategyBase
+}
+
+func NewRandomJitter() *RandomJitter {
+	return &RandomJitter{strategyBase: newStrategyBase()}
+}
+
+func (r *RandomJitter) ComputeDelayBeforeNextRetry(retryTimes int32) int32 {
+	expoDelay := getExponentialDelay(r.GetBaseDelay(), retryTimes)
+	return utils.RandInt32(1, expoDelay)
+}

+ 52 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker/retry/strategy.go

@@ -0,0 +1,52 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package retry
+
+const (
+	BaseDelay = 10        // base delay is 10ms
+	MaxDelay  = 60 * 1000 // max delay is 60s
+)
+
+type strategyBase struct {
+	baseDelay int32
+}
+
+// newStrategyBase new struct with default base delay: BaseDelay
+func newStrategyBase() *strategyBase {
+	return &strategyBase{baseDelay: BaseDelay}
+}
+
+func (s *strategyBase) SetBaseDelay(baseDelay int32) {
+	if s != nil {
+		s.baseDelay = baseDelay
+	}
+}
+
+func (s *strategyBase) GetBaseDelay() int32 {
+	if s != nil {
+		return s.baseDelay
+	}
+	return BaseDelay
+}
+
+type Strategy interface {
+	SetBaseDelay(int32)
+	ComputeDelayBeforeNextRetry(int32) int32
+}

+ 45 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/event.go

@@ -0,0 +1,45 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package progress
+
+type EventType int
+
+const (
+	TransferStartedEvent EventType = iota
+	TransferDataEvent
+	TransferCompletedEvent
+	TransferFailedEvent
+)
+
+type Event struct {
+	Type             EventType
+	TransferredBytes int64
+	TotalBytes       int64
+	Err              error
+}
+
+func NewEvent(eventType EventType, transferredBytes int64, totalBytes int64, err error) *Event {
+	return &Event{
+		Type:             eventType,
+		TransferredBytes: transferredBytes,
+		TotalBytes:       totalBytes,
+		Err:              err,
+	}
+}

+ 24 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/listener.go

@@ -0,0 +1,24 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package progress
+
+type Listener interface {
+	ProgressChanged(event *Event)
+}

+ 95 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/reader.go

@@ -0,0 +1,95 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package progress
+
+import (
+	"io"
+)
+
+const defaultProgressInterval = int64(102400)
+
+func NewTeeReader(reader io.Reader, writer io.Writer, totalBytes int64, progressListener Listener, progressInterval int64) *TeeReader {
+	if progressInterval <= 0 {
+		progressInterval = defaultProgressInterval
+	}
+
+	return &TeeReader{
+		reader:           reader,
+		writer:           writer,
+		progressInterval: progressInterval,
+		totalBytes:       totalBytes,
+		listener:         progressListener,
+	}
+}
+
+type TeeReader struct {
+	reader           io.Reader
+	writer           io.Writer
+	cacheBytes       int64
+	progressInterval int64
+	transferredBytes int64
+	totalBytes       int64
+	listener         Listener
+}
+
+func (r *TeeReader) Read(p []byte) (int, error) {
+	if r.transferredBytes == 0 {
+		event := NewEvent(TransferStartedEvent, r.transferredBytes, r.totalBytes, nil)
+		r.listener.ProgressChanged(event)
+	}
+
+	n, err := r.reader.Read(p)
+	if err != nil && err != io.EOF {
+		event := NewEvent(TransferFailedEvent, r.transferredBytes, r.totalBytes, err)
+		r.listener.ProgressChanged(event)
+	}
+
+	if n > 0 {
+		n64 := int64(n)
+		r.transferredBytes += n64
+		if r.writer != nil {
+			if n, err := r.writer.Write(p[:n]); err != nil {
+				return n, err
+			}
+		}
+
+		r.cacheBytes += n64
+		if r.cacheBytes >= r.progressInterval || r.transferredBytes == r.totalBytes {
+			r.cacheBytes = 0
+			event := NewEvent(TransferDataEvent, r.transferredBytes, r.totalBytes, nil)
+			r.listener.ProgressChanged(event)
+		}
+	}
+
+	if err == io.EOF {
+		r.cacheBytes = 0
+		event := NewEvent(TransferCompletedEvent, r.transferredBytes, r.totalBytes, nil)
+		r.listener.ProgressChanged(event)
+	}
+
+	return n, err
+}
+
+func (r *TeeReader) Close() error {
+	if closer, ok := r.reader.(io.ReadCloser); ok {
+		return closer.Close()
+	}
+	return nil
+}

+ 27 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress/request.go

@@ -0,0 +1,27 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package progress
+
+type Request interface {
+	SetProgressListener(progressListener Listener)
+	GetProgressListener() Listener
+	SetProgressInterval(progressInterval int64)
+	GetProgressInterval() int64
+}

+ 73 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/env_region.go

@@ -0,0 +1,73 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package region
+
+import (
+	"fmt"
+	"os"
+	"strings"
+	"sync"
+)
+
+const (
+	regionEnvPrefix = "HUAWEICLOUD_SDK_REGION"
+)
+
+var (
+	envOnce  sync.Once
+	envCache *EnvCache
+)
+
+type EnvCache struct {
+	value map[string]*Region
+}
+
+func getEnvCache() *EnvCache {
+	envOnce.Do(func() {
+		envCache = &EnvCache{value: make(map[string]*Region)}
+	})
+
+	return envCache
+}
+
+type EnvProvider struct {
+	serviceName string
+}
+
+func NewEnvProvider(serviceName string) *EnvProvider {
+	return &EnvProvider{serviceName: strings.ToUpper(serviceName)}
+}
+
+func (p *EnvProvider) GetRegion(regionId string) *Region {
+	if reg, ok := getEnvCache().value[p.serviceName+regionId]; ok {
+		return reg
+	}
+
+	envName := fmt.Sprintf("%s_%s_%s", regionEnvPrefix, p.serviceName, strings.ToUpper(strings.Replace(regionId, "-", "_", -1)))
+	endpoint := os.Getenv(envName)
+	if endpoint == "" {
+		return nil
+	}
+
+	endpoints := strings.Split(endpoint, ",")
+	reg := NewRegion(regionId, endpoints...)
+	getEnvCache().value[p.serviceName+regionId] = reg
+	return reg
+}

+ 136 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/profile_region.go

@@ -0,0 +1,136 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package region
+
+import (
+	"fmt"
+	"gopkg.in/yaml.v3"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"strings"
+	"sync"
+)
+
+const (
+	regionsFileEnv            = "HUAWEICLOUD_SDK_REGIONS_FILE"
+	defaultRegionsFileDirName = ".huaweicloud"
+	defaultRegionsFileName    = "regions.yaml"
+)
+
+var (
+	profileOnce  sync.Once
+	profileCache *ProfileCache
+)
+
+type ProfileCache struct {
+	value map[string]*Region
+}
+
+type regionInfo struct {
+	Id        string   `yaml:"id"`
+	Endpoint  string   `yaml:"endpoint"`
+	Endpoints []string `yaml:"endpoints"`
+}
+
+func getProfileCache() *ProfileCache {
+	profileOnce.Do(func() {
+		profileCache = &ProfileCache{value: resolveProfile()}
+	})
+
+	return profileCache
+}
+
+func getRegionsFilePath() string {
+	if path := os.Getenv(regionsFileEnv); path != "" {
+		return path
+	}
+
+	dir, err := os.UserHomeDir()
+	if err != nil {
+		return ""
+	}
+
+	return filepath.Join(dir, defaultRegionsFileDirName, defaultRegionsFileName)
+}
+
+func isPathExist(path string) bool {
+	_, err := os.Stat(path)
+	if err == nil {
+		return true
+	}
+	return false
+}
+
+func resolveProfile() map[string]*Region {
+	result := make(map[string]*Region)
+
+	path := getRegionsFilePath()
+	if !isPathExist(path) {
+		return result
+	}
+
+	bytes, err := ioutil.ReadFile(path)
+	if err != nil {
+		panic(fmt.Errorf("failed to read file: '%s'\n%w", path, err))
+	}
+
+	var servReg map[string][]*regionInfo
+	err = yaml.Unmarshal(bytes, &servReg)
+	if err != nil {
+		panic(fmt.Errorf("failed to resolve file: '%s'\n%w", path, err))
+	}
+
+	for serv, regInfos := range servReg {
+		for _, regInfo := range regInfos {
+			if regInfo.Id == "" {
+				continue
+			}
+
+			endpoints := make([]string, 0)
+			if regInfo.Endpoint != "" {
+				endpoints = append(endpoints, regInfo.Endpoint)
+			}
+			if regInfo.Endpoints != nil {
+				endpoints = append(endpoints, regInfo.Endpoints...)
+			}
+
+			if len(endpoints) != 0 {
+				result[strings.ToUpper(serv)+regInfo.Id] = NewRegion(regInfo.Id, endpoints...)
+			}
+		}
+	}
+	return result
+}
+
+type ProfileProvider struct {
+	serviceName string
+}
+
+func NewProfileProvider(serviceName string) *ProfileProvider {
+
+	return &ProfileProvider{
+		serviceName: strings.ToUpper(serviceName),
+	}
+}
+
+func (p *ProfileProvider) GetRegion(regionId string) *Region {
+	return getProfileCache().value[p.serviceName+regionId]
+}

+ 42 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region.go

@@ -0,0 +1,42 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package region
+
+type Region struct {
+	Id        string
+	Endpoints []string
+}
+
+func NewRegion(id string, endpoints ...string) *Region {
+	return &Region{
+		Id:        id,
+		Endpoints: endpoints,
+	}
+}
+
+// Deprecated: As of 0.1.27, because of the support of the multi-endpoint feature, use WithEndpointsOverride instead
+func (r *Region) WithEndpointOverride(endpoint string) *Region {
+	return r.WithEndpointsOverride([]string{endpoint})
+}
+
+func (r *Region) WithEndpointsOverride(endpoints []string) *Region {
+	r.Endpoints = endpoints
+	return r
+}

+ 39 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region_chain.go

@@ -0,0 +1,39 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package region
+
+type ProviderChain struct {
+	providers []IRegionProvider
+}
+
+func DefaultProviderChain(serviceName string) *ProviderChain {
+	providers := []IRegionProvider{NewEnvProvider(serviceName), NewProfileProvider(serviceName)}
+	return &ProviderChain{providers: providers}
+}
+
+func (p *ProviderChain) GetRegion(regionId string) *Region {
+	for _, provider := range p.providers {
+		reg := provider.GetRegion(regionId)
+		if reg != nil {
+			return reg
+		}
+	}
+	return nil
+}

+ 24 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/region/region_provider.go

@@ -0,0 +1,24 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package region
+
+type IRegionProvider interface {
+	GetRegion(regionId string) *Region
+}

+ 423 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request/default_http_request.go

@@ -0,0 +1,423 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package request
+
+import (
+	"bytes"
+	"encoding/json"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/converter"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress"
+	"go.mongodb.org/mongo-driver/bson"
+	"io"
+	"mime/multipart"
+	"net/http"
+	"net/url"
+	"os"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
+)
+
+type DefaultHttpRequest struct {
+	endpoint string
+	path     string
+	method   string
+
+	queryParams  map[string]interface{}
+	pathParams   map[string]string
+	headerParams map[string]string
+	formParams   map[string]def.FormData
+	body         interface{}
+
+	autoFilledPathParams map[string]string
+	progressListener     progress.Listener
+	progressInterval     int64
+	signingAlgorithm     algorithm.SigningAlgorithm
+}
+
+func (httpRequest *DefaultHttpRequest) fillParamsInPath() *DefaultHttpRequest {
+	for key, value := range httpRequest.pathParams {
+		httpRequest.path = strings.ReplaceAll(httpRequest.path, "{"+key+"}", value)
+	}
+	for key, value := range httpRequest.autoFilledPathParams {
+		httpRequest.path = strings.ReplaceAll(httpRequest.path, "{"+key+"}", value)
+	}
+	return httpRequest
+}
+
+func (httpRequest *DefaultHttpRequest) Builder() *HttpRequestBuilder {
+	httpRequestBuilder := HttpRequestBuilder{httpRequest: httpRequest}
+	return &httpRequestBuilder
+}
+
+func (httpRequest *DefaultHttpRequest) GetEndpoint() string {
+	return httpRequest.endpoint
+}
+
+func (httpRequest *DefaultHttpRequest) GetPath() string {
+	return httpRequest.path
+}
+
+func (httpRequest *DefaultHttpRequest) GetSigningAlgorithm() algorithm.SigningAlgorithm {
+	return httpRequest.signingAlgorithm
+}
+
+func (httpRequest *DefaultHttpRequest) GetMethod() string {
+	return httpRequest.method
+}
+
+func (httpRequest *DefaultHttpRequest) GetQueryParams() map[string]interface{} {
+	return httpRequest.queryParams
+}
+
+func (httpRequest *DefaultHttpRequest) GetHeaderParams() map[string]string {
+	return httpRequest.headerParams
+}
+
+func (httpRequest *DefaultHttpRequest) GetPathPrams() map[string]string {
+	return httpRequest.pathParams
+}
+
+func (httpRequest *DefaultHttpRequest) GetFormPrams() map[string]def.FormData {
+	return httpRequest.formParams
+}
+
+func (httpRequest *DefaultHttpRequest) GetBody() interface{} {
+	return httpRequest.body
+}
+
+func (httpRequest *DefaultHttpRequest) GetBodyToBytes() (*bytes.Buffer, error) {
+	buf := &bytes.Buffer{}
+
+	if httpRequest.body != nil {
+		v := reflect.ValueOf(httpRequest.body)
+		if v.Kind() == reflect.Ptr {
+			v = v.Elem()
+		}
+
+		if v.Kind() == reflect.String {
+			buf.WriteString(v.Interface().(string))
+		} else {
+			var err error
+			if httpRequest.headerParams["Content-Type"] == "application/xml" {
+				encoder := xml.NewEncoder(buf)
+				err = encoder.Encode(httpRequest.body)
+			} else if httpRequest.headerParams["Content-Type"] == "application/bson" {
+				buffer, err := bson.Marshal(httpRequest.body)
+				if err != nil {
+					return nil, err
+				}
+				buf.Write(buffer)
+			} else {
+				encoder := json.NewEncoder(buf)
+				encoder.SetEscapeHTML(false)
+				err = encoder.Encode(httpRequest.body)
+			}
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return buf, nil
+}
+
+func (httpRequest *DefaultHttpRequest) GetProgressListener() progress.Listener {
+	return httpRequest.progressListener
+}
+
+func (httpRequest *DefaultHttpRequest) GetProgressInterval() int64 {
+	return httpRequest.progressInterval
+}
+
+func (httpRequest *DefaultHttpRequest) AddQueryParam(key string, value string) {
+	httpRequest.queryParams[key] = value
+}
+
+func (httpRequest *DefaultHttpRequest) AddPathParam(key string, value string) {
+	httpRequest.pathParams[key] = value
+}
+
+func (httpRequest *DefaultHttpRequest) AddHeaderParam(key string, value string) {
+	httpRequest.headerParams[key] = value
+}
+
+func (httpRequest *DefaultHttpRequest) AddFormParam(key string, value def.FormData) {
+	httpRequest.formParams[key] = value
+}
+
+func (httpRequest *DefaultHttpRequest) ConvertRequest() (*http.Request, error) {
+	t := reflect.TypeOf(httpRequest.body)
+	if t != nil && t.Kind() == reflect.Ptr {
+		t = t.Elem()
+	}
+
+	var req *http.Request
+	var err error
+	if httpRequest.body != nil && t != nil && t.Name() == "File" {
+		req, err = httpRequest.convertStreamBody(err, req)
+		if err != nil {
+			return nil, err
+		}
+	} else if len(httpRequest.GetFormPrams()) != 0 {
+		if httpRequest.headerParams["Content-Type"] == "application/x-www-form-urlencoded" {
+			req, err = httpRequest.covertFormUrlencodedBody()
+		} else {
+			req, err = httpRequest.covertFormDataBody()
+		}
+		if err != nil {
+			return nil, err
+		}
+	} else {
+		var buf *bytes.Buffer
+
+		buf, err = httpRequest.GetBodyToBytes()
+		if err != nil {
+			return nil, err
+		}
+
+		req, err = http.NewRequest(httpRequest.GetMethod(), httpRequest.GetEndpoint(), buf)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	httpRequest.fillPath(req)
+	httpRequest.fillQueryParams(req)
+	httpRequest.fillHeaderParams(req)
+
+	return req, nil
+}
+
+func (httpRequest *DefaultHttpRequest) covertFormUrlencodedBody() (*http.Request, error) {
+	form := url.Values{}
+	for k, v := range httpRequest.GetFormPrams() {
+		if part, ok := v.(*def.MultiPart); ok {
+			form.Add(k, converter.ConvertInterfaceToString(part.Content))
+		} else {
+			return nil, errors.New("failed to encode form field: " + k)
+		}
+	}
+
+	return http.NewRequest(httpRequest.GetMethod(), httpRequest.GetEndpoint(), bytes.NewBufferString(form.Encode()))
+}
+
+func (httpRequest *DefaultHttpRequest) covertFormDataBody() (*http.Request, error) {
+	bodyBuffer := &bytes.Buffer{}
+	bodyWriter := multipart.NewWriter(bodyBuffer)
+
+	sortedKeys := make([]string, 0, len(httpRequest.GetFormPrams()))
+	for k, v := range httpRequest.GetFormPrams() {
+		if _, ok := v.(*def.FilePart); ok {
+			sortedKeys = append(sortedKeys, k)
+		} else {
+			sortedKeys = append([]string{k}, sortedKeys...)
+		}
+	}
+
+	for _, k := range sortedKeys {
+		if err := httpRequest.GetFormPrams()[k].Write(bodyWriter, k); err != nil {
+			return nil, err
+		}
+	}
+
+	contentType := bodyWriter.FormDataContentType()
+	if err := bodyWriter.Close(); err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest(httpRequest.GetMethod(), httpRequest.GetEndpoint(), bodyBuffer)
+	if err != nil {
+		return nil, err
+	}
+
+	req.Header.Set("Content-type", contentType)
+	return req, nil
+}
+
+func (httpRequest *DefaultHttpRequest) getContentLength() int64 {
+	contentLength := int64(-1)
+	if value, ok := httpRequest.GetHeaderParams()["Content-Length"]; ok {
+		parseInt, err := strconv.ParseInt(value, 10, 64)
+		if err == nil {
+			contentLength = parseInt
+		}
+	}
+
+	if contentLength == -1 {
+		if value, ok := httpRequest.GetBody().(os.File); ok {
+			if stat, err := value.Stat(); err == nil {
+				contentLength = stat.Size()
+			}
+		}
+	}
+
+	return contentLength
+}
+
+func (httpRequest *DefaultHttpRequest) convertStreamBody(err error, req *http.Request) (*http.Request, error) {
+	if f, ok := httpRequest.body.(os.File); !ok {
+		return nil, errors.New("failed to get stream request body")
+	} else {
+		var reader io.Reader
+		if httpRequest.progressListener != nil {
+			reader = progress.NewTeeReader(&f, nil, httpRequest.getContentLength(), httpRequest.progressListener, httpRequest.progressInterval)
+		} else {
+			reader = &f
+		}
+
+		req, err = http.NewRequest(httpRequest.GetMethod(), httpRequest.GetEndpoint(), reader)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return req, nil
+}
+
+func (httpRequest *DefaultHttpRequest) fillHeaderParams(req *http.Request) {
+	if len(httpRequest.GetHeaderParams()) == 0 {
+		return
+	}
+
+	for key, value := range httpRequest.GetHeaderParams() {
+		if strings.EqualFold(key, "Content-type") && req.Header.Get("Content-type") != "" {
+			continue
+		}
+		req.Header.Add(key, value)
+	}
+}
+
+func (httpRequest *DefaultHttpRequest) fillQueryParams(req *http.Request) {
+	if len(httpRequest.GetQueryParams()) == 0 {
+		return
+	}
+
+	q := req.URL.Query()
+	for key, value := range httpRequest.GetQueryParams() {
+		valueWithType, ok := value.(reflect.Value)
+		if !ok {
+			continue
+		}
+
+		if valueWithType.Kind() == reflect.Slice {
+			params := httpRequest.CanonicalSliceQueryParamsToMulti(valueWithType)
+			for _, param := range params {
+				q.Add(key, param)
+			}
+		} else if valueWithType.Kind() == reflect.Map {
+			params := httpRequest.CanonicalMapQueryParams(key, valueWithType)
+			for _, param := range params {
+				for k, v := range param {
+					q.Add(k, v)
+				}
+			}
+		} else {
+			q.Add(key, httpRequest.CanonicalStringQueryParams(valueWithType))
+		}
+	}
+
+	req.URL.RawQuery = strings.ReplaceAll(strings.ReplaceAll(strings.Trim(q.Encode(), "="), "=&", "&"), "+", "%20")
+}
+
+func (httpRequest *DefaultHttpRequest) CanonicalStringQueryParams(value reflect.Value) string {
+	return fmt.Sprintf("%v", value)
+}
+
+func (httpRequest *DefaultHttpRequest) CanonicalSliceQueryParamsToMulti(value reflect.Value) []string {
+	params := make([]string, 0)
+
+	for i := 0; i < value.Len(); i++ {
+		if value.Index(i).Kind() == reflect.Struct {
+			methodByName := value.Index(i).MethodByName("Value")
+			if methodByName.IsValid() {
+				value := converter.ConvertInterfaceToString(methodByName.Call([]reflect.Value{})[0].Interface())
+				params = append(params, value)
+			} else {
+				v, e := json.Marshal(value.Interface())
+				if e == nil {
+					if strings.HasPrefix(string(v), "\"") {
+						params = append(params, strings.Trim(string(v), "\""))
+					} else {
+						params = append(params, string(v))
+					}
+				}
+			}
+		} else {
+			params = append(params, httpRequest.CanonicalStringQueryParams(value.Index(i)))
+		}
+	}
+
+	return params
+}
+
+func (httpRequest *DefaultHttpRequest) CanonicalMapQueryParams(key string, value reflect.Value) []map[string]string {
+	queryParams := make([]map[string]string, 0)
+
+	for _, k := range value.MapKeys() {
+		if value.MapIndex(k).Kind() == reflect.Struct {
+			v, e := json.Marshal(value.Interface())
+			if e == nil {
+				if strings.HasPrefix(string(v), "\"") {
+					queryParams = append(queryParams, map[string]string{
+						key: strings.Trim(string(v), "\""),
+					})
+				} else {
+					queryParams = append(queryParams, map[string]string{
+						key: string(v),
+					})
+				}
+			}
+		} else if value.MapIndex(k).Kind() == reflect.Slice {
+			params := httpRequest.CanonicalSliceQueryParamsToMulti(value.MapIndex(k))
+			if len(params) == 0 {
+				queryParams = append(queryParams, map[string]string{
+					fmt.Sprintf("%s[%s]", key, k): "",
+				})
+				continue
+			}
+			for _, paramValue := range httpRequest.CanonicalSliceQueryParamsToMulti(value.MapIndex(k)) {
+				queryParams = append(queryParams, map[string]string{
+					fmt.Sprintf("%s[%s]", key, k): paramValue,
+				})
+			}
+		} else if value.MapIndex(k).Kind() == reflect.Map {
+			queryParams = append(queryParams, httpRequest.CanonicalMapQueryParams(fmt.Sprintf("%s[%s]", key, k), value.MapIndex(k))...)
+		} else {
+			queryParams = append(queryParams, map[string]string{
+				fmt.Sprintf("%s[%s]", key, k): httpRequest.CanonicalStringQueryParams(value.MapIndex(k)),
+			})
+		}
+	}
+
+	return queryParams
+}
+
+func (httpRequest *DefaultHttpRequest) fillPath(req *http.Request) {
+	if "" != httpRequest.GetPath() {
+		req.URL.Path = httpRequest.GetPath()
+	}
+}

+ 136 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request/http_request_builder.go

@@ -0,0 +1,136 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package request
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/signer/algorithm"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/progress"
+	"reflect"
+	"strings"
+)
+
+type HttpRequestBuilder struct {
+	httpRequest *DefaultHttpRequest
+}
+
+func NewHttpRequestBuilder() *HttpRequestBuilder {
+	httpRequest := &DefaultHttpRequest{
+		queryParams:          make(map[string]interface{}),
+		headerParams:         make(map[string]string),
+		pathParams:           make(map[string]string),
+		autoFilledPathParams: make(map[string]string),
+		formParams:           make(map[string]def.FormData),
+	}
+	httpRequestBuilder := &HttpRequestBuilder{
+		httpRequest: httpRequest,
+	}
+	return httpRequestBuilder
+}
+
+func (builder *HttpRequestBuilder) WithEndpoint(endpoint string) *HttpRequestBuilder {
+	builder.httpRequest.endpoint = endpoint
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithPath(path string) *HttpRequestBuilder {
+	builder.httpRequest.path = path
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithMethod(method string) *HttpRequestBuilder {
+	builder.httpRequest.method = method
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithSigningAlgorithm(signingAlgorithm algorithm.SigningAlgorithm) *HttpRequestBuilder {
+	builder.httpRequest.signingAlgorithm = signingAlgorithm
+	return builder
+}
+
+func (builder *HttpRequestBuilder) AddQueryParam(key string, value interface{}) *HttpRequestBuilder {
+	builder.httpRequest.queryParams[key] = value
+	return builder
+}
+
+func (builder *HttpRequestBuilder) AddPathParam(key string, value string) *HttpRequestBuilder {
+	builder.httpRequest.pathParams[key] = value
+	return builder
+}
+
+func (builder *HttpRequestBuilder) AddAutoFilledPathParam(key string, value string) *HttpRequestBuilder {
+	builder.httpRequest.autoFilledPathParams[key] = value
+	return builder
+}
+
+func (builder *HttpRequestBuilder) AddHeaderParam(key string, value string) *HttpRequestBuilder {
+	builder.httpRequest.headerParams[key] = value
+	return builder
+}
+
+func (builder *HttpRequestBuilder) AddFormParam(key string, value def.FormData) *HttpRequestBuilder {
+	builder.httpRequest.formParams[key] = value
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithBody(kind string, body interface{}) *HttpRequestBuilder {
+	if kind == "multipart" {
+		v := reflect.ValueOf(body)
+		if v.Kind() == reflect.Ptr {
+			v = v.Elem()
+		}
+
+		t := reflect.TypeOf(body)
+		if t.Kind() == reflect.Ptr {
+			t = t.Elem()
+		}
+
+		fieldNum := t.NumField()
+		for i := 0; i < fieldNum; i++ {
+			jsonTag := t.Field(i).Tag.Get("json")
+			if jsonTag != "" {
+				if v.FieldByName(t.Field(i).Name).IsNil() && strings.Contains(jsonTag, "omitempty") {
+					continue
+				}
+				builder.AddFormParam(strings.Split(jsonTag, ",")[0], v.FieldByName(t.Field(i).Name).Interface().(def.FormData))
+			} else {
+				builder.AddFormParam(t.Field(i).Name, v.FieldByName(t.Field(i).Name).Interface().(def.FormData))
+			}
+		}
+	} else {
+		builder.httpRequest.body = body
+	}
+
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithProgressListener(progressListener progress.Listener) *HttpRequestBuilder {
+	builder.httpRequest.progressListener = progressListener
+	return builder
+}
+
+func (builder *HttpRequestBuilder) WithProgressInterval(progressInterval int64) *HttpRequestBuilder {
+	builder.httpRequest.progressInterval = progressInterval
+	return builder
+}
+
+func (builder *HttpRequestBuilder) Build() *DefaultHttpRequest {
+	return builder.httpRequest.fillParamsInPath()
+}

+ 82 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response/default_http_response.go

@@ -0,0 +1,82 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package response
+
+import (
+	"bytes"
+	"io/ioutil"
+	"net/http"
+)
+
+type DefaultHttpResponse struct {
+	Response *http.Response
+}
+
+func NewDefaultHttpResponse(response *http.Response) *DefaultHttpResponse {
+	return &DefaultHttpResponse{Response: response}
+}
+
+func (r *DefaultHttpResponse) GetStatusCode() int {
+	return r.Response.StatusCode
+}
+
+func (r *DefaultHttpResponse) GetHeaders() map[string]string {
+	headerParams := map[string]string{}
+	for key, values := range r.Response.Header {
+		if values == nil || len(values) <= 0 {
+			continue
+		}
+		headerParams[key] = values[0]
+	}
+	return headerParams
+}
+
+func (r *DefaultHttpResponse) GetBody() string {
+	body, err := ioutil.ReadAll(r.Response.Body)
+	if err != nil {
+		return ""
+	}
+	if err := r.Response.Body.Close(); err == nil {
+		r.Response.Body = ioutil.NopCloser(bytes.NewBuffer(body))
+	}
+	return string(body)
+}
+
+func (r *DefaultHttpResponse) GetHeader(key string) string {
+	header := r.Response.Header
+	return header.Get(key)
+}
+
+func (r *DefaultHttpResponse) GetBodyAsString() (string, error) {
+	b, err := r.GetBodyAsBytes()
+	if err != nil {
+		return "", err
+	}
+	return string(b), nil
+}
+
+func (r *DefaultHttpResponse) GetBodyAsBytes() ([]byte, error) {
+	defer r.Response.Body.Close()
+	data, err := ioutil.ReadAll(r.Response.Body)
+	if err != nil {
+		return nil, err
+	}
+	return data, nil
+}

+ 39 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr/error_handler.go

@@ -0,0 +1,39 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package sdkerr
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/request"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/response"
+)
+
+type ErrorHandler interface {
+	HandleError(req *request.DefaultHttpRequest, resp *response.DefaultHttpResponse) error
+}
+
+type DefaultErrorHandler struct {
+}
+
+func (h DefaultErrorHandler) HandleError(req *request.DefaultHttpRequest, resp *response.DefaultHttpResponse) error {
+	if resp.GetStatusCode() < 400 {
+		return nil
+	}
+	return NewServiceResponseError(resp.Response)
+}

+ 175 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/sdkerr/errors.go

@@ -0,0 +1,175 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package sdkerr
+
+import (
+	"fmt"
+	"go.mongodb.org/mongo-driver/bson"
+	"io/ioutil"
+	"net/http"
+
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+)
+
+const (
+	xRequestId                  = "X-Request-Id"
+	code                        = "code"
+	message                     = "message"
+	errorCode                   = "error_code"
+	errorMsg                    = "error_msg"
+	encodedAuthorizationMessage = "encoded_authorization_message"
+)
+
+type CredentialsTypeError struct {
+	ErrorMessage string
+}
+
+func NewCredentialsTypeError(msg string) *CredentialsTypeError {
+	c := &CredentialsTypeError{
+		ErrorMessage: msg,
+	}
+	return c
+}
+
+func (c *CredentialsTypeError) Error() string {
+	return fmt.Sprintf("{\"ErrorMessage\": \"%s\"}", c.ErrorMessage)
+}
+
+type ConnectionError struct {
+	ErrorMessage string
+}
+
+func NewConnectionError(msg string) *ConnectionError {
+	c := &ConnectionError{
+		ErrorMessage: msg,
+	}
+	return c
+}
+
+func (c *ConnectionError) Error() string {
+	return fmt.Sprintf("{\"ErrorMessage\": \"%s\"}", c.ErrorMessage)
+}
+
+type RequestTimeoutError struct {
+	ErrorMessage string
+}
+
+func NewRequestTimeoutError(msg string) *RequestTimeoutError {
+	rt := &RequestTimeoutError{
+		ErrorMessage: msg,
+	}
+	return rt
+}
+
+func (rt *RequestTimeoutError) Error() string {
+	return fmt.Sprintf("{\"ErrorMessage\": \"%s\"}", rt.ErrorMessage)
+}
+
+type errMap map[string]interface{}
+
+func (m errMap) getStringValue(key string) string {
+	var result string
+
+	value, isExist := m[key]
+	if !isExist {
+		return result
+	}
+
+	if strVal, ok := value.(string); ok {
+		result = strVal
+	}
+
+	return result
+}
+
+type ServiceResponseError struct {
+	StatusCode                  int    `json:"status_code"`
+	RequestId                   string `json:"request_id"`
+	ErrorCode                   string `json:"error_code" bson:"errorCode"`
+	ErrorMessage                string `json:"error_message" bson:"errorMsg"`
+	EncodedAuthorizationMessage string `json:"encoded_authorization_message"`
+}
+
+func NewServiceResponseError(resp *http.Response) *ServiceResponseError {
+	sr := &ServiceResponseError{}
+
+	defer resp.Body.Close()
+	data, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		sr.ErrorMessage = err.Error()
+		return sr
+	}
+
+	dataBuf := errMap{}
+	if resp.Header.Get("Content-Type") == "application/bson" {
+		err = bson.Unmarshal(data, &sr)
+	} else {
+		err = utils.Unmarshal(data, &dataBuf)
+	}
+	if err != nil {
+		sr.ErrorMessage = string(data)
+	} else {
+		processServiceResponseError(dataBuf, sr)
+		if sr.ErrorMessage == "" {
+			sr.ErrorMessage = string(data)
+		}
+	}
+	sr.StatusCode = resp.StatusCode
+	sr.RequestId = resp.Header.Get(xRequestId)
+
+	return sr
+}
+
+func processServiceResponseError(m errMap, sr *ServiceResponseError) {
+	if value := m.getStringValue(encodedAuthorizationMessage); value != "" {
+		sr.EncodedAuthorizationMessage = value
+	}
+
+	_code := m.getStringValue(errorCode)
+	msg := m.getStringValue(errorMsg)
+	if _code != "" && msg != "" {
+		sr.ErrorCode = _code
+		sr.ErrorMessage = msg
+		return
+	}
+
+	_code = m.getStringValue(code)
+	msg = m.getStringValue(message)
+	if _code != "" && msg != "" {
+		sr.ErrorCode = _code
+		sr.ErrorMessage = msg
+		return
+	}
+
+	for _, v := range m {
+		if val, ok := v.(map[string]interface{}); ok {
+			processServiceResponseError(val, sr)
+		}
+	}
+}
+
+func (sr ServiceResponseError) Error() string {
+	data, err := utils.Marshal(sr)
+	if err != nil {
+		return fmt.Sprintf("{\"ErrorMessage\": \"%s\",\"ErrorCode\": \"%s\",\"EncodedAuthorizationMessage\": \"%s\"}",
+			sr.ErrorMessage, sr.ErrorCode, sr.EncodedAuthorizationMessage)
+	}
+	return fmt.Sprintf(string(data))
+}

+ 40 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/json_utils.go

@@ -0,0 +1,40 @@
+// Copyright 2023 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package utils
+
+import (
+	"bytes"
+	jsoniter "github.com/json-iterator/go"
+)
+
+func Marshal(i interface{}) ([]byte, error) {
+	buffer := bytes.NewBuffer([]byte{})
+	encoder := jsoniter.NewEncoder(buffer)
+	encoder.SetEscapeHTML(false)
+	err := encoder.Encode(i)
+	return buffer.Bytes(), err
+}
+
+func Unmarshal(data []byte, i interface{}) error {
+	reader := bytes.NewReader(data)
+	decoder := jsoniter.NewDecoder(reader)
+	decoder.UseNumber()
+	return decoder.Decode(i)
+}

+ 64 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/math_utils.go

@@ -0,0 +1,64 @@
+// Copyright 2022 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package utils
+
+import (
+	"crypto/rand"
+	"math/big"
+)
+
+var reader = rand.Reader
+
+func Max32(x, y int32) int32 {
+	if x > y {
+		return x
+	}
+	return y
+}
+
+func Min32(x, y int32) int32 {
+	if x > y {
+		return y
+	}
+	return x
+}
+
+// RandInt32 生成一个随机数,有效区间是: [min, max), 其中要求 min > 0 & max > min
+func RandInt32(min, max int32) int32 {
+	if min <= 0 || max <= min {
+		return max
+	}
+
+	limit := big.NewInt(int64(max - min))
+	r, err := rand.Int(reader, limit)
+	if err != nil {
+		return max
+	}
+	return int32(r.Int64()) + min
+}
+
+func Pow32(x, y int32) int32 {
+	var ans int32 = 1
+	for y != 0 {
+		ans *= x
+		y--
+	}
+	return ans
+}

+ 28 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils/string_utils.go

@@ -0,0 +1,28 @@
+// Copyright 2020 Huawei Technologies Co.,Ltd.
+//
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+package utils
+
+import "strings"
+
+func UnderscoreToCamel(name string) string {
+	name = strings.Replace(name, "_", " ", -1)
+	name = strings.Title(name)
+	return strings.Replace(name, " ", "", -1)
+}

+ 146 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_client.go

@@ -0,0 +1,146 @@
+package v2
+
+import (
+	httpclient "github.com/huaweicloud/huaweicloud-sdk-go-v3/core"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model"
+)
+
+type IvsClient struct {
+	HcClient *httpclient.HcHttpClient
+}
+
+func NewIvsClient(hcClient *httpclient.HcHttpClient) *IvsClient {
+	return &IvsClient{HcClient: hcClient}
+}
+
+func IvsClientBuilder() *httpclient.HcHttpClientBuilder {
+	builder := httpclient.NewHcHttpClientBuilder()
+	return builder
+}
+
+// DetectExtentionByIdCardImage 人证核身证件版(二要素)
+//
+// 使用姓名、身份证号码二要素进行身份审核。身份验证时,传入的数据为身份证信息。提取身份证信息时,可以使用身份证正反面图片,也可以直接输入姓名、身份证号文本。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectExtentionByIdCardImage(request *model.DetectExtentionByIdCardImageRequest) (*model.DetectExtentionByIdCardImageResponse, error) {
+	requestDef := GenReqDefForDetectExtentionByIdCardImage()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectExtentionByIdCardImageResponse), nil
+	}
+}
+
+// DetectExtentionByIdCardImageInvoker 人证核身证件版(二要素)
+func (c *IvsClient) DetectExtentionByIdCardImageInvoker(request *model.DetectExtentionByIdCardImageRequest) *DetectExtentionByIdCardImageInvoker {
+	requestDef := GenReqDefForDetectExtentionByIdCardImage()
+	return &DetectExtentionByIdCardImageInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}
+
+// DetectExtentionByNameAndId 人证核身证件版(二要素)
+//
+// 使用姓名、身份证号码二要素进行身份审核。身份验证时,传入的数据为身份证信息。提取身份证信息时,可以使用身份证正反面图片,也可以直接输入姓名、身份证号文本。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectExtentionByNameAndId(request *model.DetectExtentionByNameAndIdRequest) (*model.DetectExtentionByNameAndIdResponse, error) {
+	requestDef := GenReqDefForDetectExtentionByNameAndId()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectExtentionByNameAndIdResponse), nil
+	}
+}
+
+// DetectExtentionByNameAndIdInvoker 人证核身证件版(二要素)
+func (c *IvsClient) DetectExtentionByNameAndIdInvoker(request *model.DetectExtentionByNameAndIdRequest) *DetectExtentionByNameAndIdInvoker {
+	requestDef := GenReqDefForDetectExtentionByNameAndId()
+	return &DetectExtentionByNameAndIdInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}
+
+// DetectStandardByIdCardImage 人证核身标准版(三要素)
+//
+// 使用身份证正反面图片提取姓名和身份证号码,与人脸图片进行三要素身份审核。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectStandardByIdCardImage(request *model.DetectStandardByIdCardImageRequest) (*model.DetectStandardByIdCardImageResponse, error) {
+	requestDef := GenReqDefForDetectStandardByIdCardImage()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectStandardByIdCardImageResponse), nil
+	}
+}
+
+// DetectStandardByIdCardImageInvoker 人证核身标准版(三要素)
+func (c *IvsClient) DetectStandardByIdCardImageInvoker(request *model.DetectStandardByIdCardImageRequest) *DetectStandardByIdCardImageInvoker {
+	requestDef := GenReqDefForDetectStandardByIdCardImage()
+	return &DetectStandardByIdCardImageInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}
+
+// DetectStandardByNameAndId 人证核身标准版(三要素)
+//
+// 使用姓名、身份证号文本和人脸图片进行三要素身份审核。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectStandardByNameAndId(request *model.DetectStandardByNameAndIdRequest) (*model.DetectStandardByNameAndIdResponse, error) {
+	requestDef := GenReqDefForDetectStandardByNameAndId()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectStandardByNameAndIdResponse), nil
+	}
+}
+
+// DetectStandardByNameAndIdInvoker 人证核身标准版(三要素)
+func (c *IvsClient) DetectStandardByNameAndIdInvoker(request *model.DetectStandardByNameAndIdRequest) *DetectStandardByNameAndIdInvoker {
+	requestDef := GenReqDefForDetectStandardByNameAndId()
+	return &DetectStandardByNameAndIdInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}
+
+// DetectStandardByVideoAndIdCardImage 人证核身标准版(三要素)
+//
+// 从身份证正反面图片中提取姓名和身份证号码,并对视频做活体检测后提取人脸图片,以此进行三要素身份审核。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectStandardByVideoAndIdCardImage(request *model.DetectStandardByVideoAndIdCardImageRequest) (*model.DetectStandardByVideoAndIdCardImageResponse, error) {
+	requestDef := GenReqDefForDetectStandardByVideoAndIdCardImage()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectStandardByVideoAndIdCardImageResponse), nil
+	}
+}
+
+// DetectStandardByVideoAndIdCardImageInvoker 人证核身标准版(三要素)
+func (c *IvsClient) DetectStandardByVideoAndIdCardImageInvoker(request *model.DetectStandardByVideoAndIdCardImageRequest) *DetectStandardByVideoAndIdCardImageInvoker {
+	requestDef := GenReqDefForDetectStandardByVideoAndIdCardImage()
+	return &DetectStandardByVideoAndIdCardImageInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}
+
+// DetectStandardByVideoAndNameAndId 人证核身标准版(三要素)
+//
+// 使用姓名、身份证号文本,并对视频做活体检测后提取人脸图片,以此进行三要素身份审核。
+//
+// Please refer to HUAWEI cloud API Explorer for details.
+func (c *IvsClient) DetectStandardByVideoAndNameAndId(request *model.DetectStandardByVideoAndNameAndIdRequest) (*model.DetectStandardByVideoAndNameAndIdResponse, error) {
+	requestDef := GenReqDefForDetectStandardByVideoAndNameAndId()
+
+	if resp, err := c.HcClient.Sync(request, requestDef); err != nil {
+		return nil, err
+	} else {
+		return resp.(*model.DetectStandardByVideoAndNameAndIdResponse), nil
+	}
+}
+
+// DetectStandardByVideoAndNameAndIdInvoker 人证核身标准版(三要素)
+func (c *IvsClient) DetectStandardByVideoAndNameAndIdInvoker(request *model.DetectStandardByVideoAndNameAndIdRequest) *DetectStandardByVideoAndNameAndIdInvoker {
+	requestDef := GenReqDefForDetectStandardByVideoAndNameAndId()
+	return &DetectStandardByVideoAndNameAndIdInvoker{invoker.NewBaseInvoker(c.HcClient, request, requestDef)}
+}

+ 102 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_invoker.go

@@ -0,0 +1,102 @@
+package v2
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/invoker"
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model"
+)
+
+type DetectExtentionByIdCardImageInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectExtentionByIdCardImageInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectExtentionByIdCardImageInvoker) Invoke() (*model.DetectExtentionByIdCardImageResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectExtentionByIdCardImageResponse), nil
+	}
+}
+
+type DetectExtentionByNameAndIdInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectExtentionByNameAndIdInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectExtentionByNameAndIdInvoker) Invoke() (*model.DetectExtentionByNameAndIdResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectExtentionByNameAndIdResponse), nil
+	}
+}
+
+type DetectStandardByIdCardImageInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectStandardByIdCardImageInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectStandardByIdCardImageInvoker) Invoke() (*model.DetectStandardByIdCardImageResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectStandardByIdCardImageResponse), nil
+	}
+}
+
+type DetectStandardByNameAndIdInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectStandardByNameAndIdInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectStandardByNameAndIdInvoker) Invoke() (*model.DetectStandardByNameAndIdResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectStandardByNameAndIdResponse), nil
+	}
+}
+
+type DetectStandardByVideoAndIdCardImageInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectStandardByVideoAndIdCardImageInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectStandardByVideoAndIdCardImageInvoker) Invoke() (*model.DetectStandardByVideoAndIdCardImageResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectStandardByVideoAndIdCardImageResponse), nil
+	}
+}
+
+type DetectStandardByVideoAndNameAndIdInvoker struct {
+	*invoker.BaseInvoker
+}
+
+func (i *DetectStandardByVideoAndNameAndIdInvoker) GetBaseInvoker() *invoker.BaseInvoker {
+	return i.BaseInvoker
+}
+
+func (i *DetectStandardByVideoAndNameAndIdInvoker) Invoke() (*model.DetectStandardByVideoAndNameAndIdResponse, error) {
+	if result, err := i.BaseInvoker.Invoke(); err != nil {
+		return nil, err
+	} else {
+		return result.(*model.DetectStandardByVideoAndNameAndIdResponse), nil
+	}
+}

+ 164 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/ivs_meta.go

@@ -0,0 +1,164 @@
+package v2
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
+
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model"
+	"net/http"
+)
+
+func GenReqDefForDetectExtentionByIdCardImage() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-idcard-extention").
+		WithResponse(new(model.DetectExtentionByIdCardImageResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}
+
+func GenReqDefForDetectExtentionByNameAndId() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-idcard-extention").
+		WithResponse(new(model.DetectExtentionByNameAndIdResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}
+
+func GenReqDefForDetectStandardByIdCardImage() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-standard").
+		WithResponse(new(model.DetectStandardByIdCardImageResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}
+
+func GenReqDefForDetectStandardByNameAndId() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-standard").
+		WithResponse(new(model.DetectStandardByNameAndIdResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}
+
+func GenReqDefForDetectStandardByVideoAndIdCardImage() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-standard").
+		WithResponse(new(model.DetectStandardByVideoAndIdCardImageResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}
+
+func GenReqDefForDetectStandardByVideoAndNameAndId() *def.HttpRequestDef {
+	reqDefBuilder := def.NewHttpRequestDefBuilder().
+		WithMethod(http.MethodPost).
+		WithPath("/v2.0/ivs-standard").
+		WithResponse(new(model.DetectStandardByVideoAndNameAndIdResponse)).
+		WithContentType("application/json")
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("EnterpriseProjectId").
+		WithJsonTag("Enterprise-Project-Id").
+		WithLocationType(def.Header))
+
+	reqDefBuilder.WithRequestField(def.NewFieldDef().
+		WithName("Body").
+		WithLocationType(def.Body))
+
+	reqDefBuilder.WithResponseField(def.NewFieldDef().
+		WithName("XRequestId").
+		WithJsonTag("X-Request-Id").
+		WithKindName("string").
+		WithLocationType(def.Header))
+
+	requestDef := reqDefBuilder.Build()
+	return requestDef
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_actions_list.go

@@ -0,0 +1,25 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+type ActionsList struct {
+
+	// 置信度,取值范围0~1。
+	Confidence float64 `json:"confidence"`
+
+	// 动作编号,取值范围:[1,2,3,4],其中: • 1:左摇头 • 2:右摇头 • 3:点头 • 4:嘴部动作
+	Action int32 `json:"action"`
+}
+
+func (o ActionsList) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "ActionsList struct{}"
+	}
+
+	return strings.Join([]string{"ActionsList", string(data)}, " ")
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_id_card_image_request.go

@@ -0,0 +1,25 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectExtentionByIdCardImageRequest Request Object
+type DetectExtentionByIdCardImageRequest struct {
+
+	// 企业项目ID。IVS支持通过企业项目管理(EPS)对不同用户组和用户的资源使用,进行分账。  获取方法:进入“[企业项目管理](https://console.huaweicloud.com/eps/?region=cn-north-4#/projects/list)”页面,单击企业项目名称,在企业项目详情页获取Enterprise-Project-Id(企业项目ID)。  企业项目创建步骤请参见用户指南。 > 说明: 创建企业项目后,在传参时,有以下三类场景。 - 携带正确的ID,正常使用IVS服务,账单的企业项目会被分类到企业ID对应的企业项目中。 - 携带格式正确但不存在的ID,正常使用IVS服务,账单的企业项目会显示对应不存在的企业项目ID。 - 不携带ID或格式错误ID(包含特殊字符等),正常使用IVS服务,账单的企业项目会被分类到\"default\"中。
+	EnterpriseProjectId *string `json:"Enterprise-Project-Id,omitempty"`
+
+	Body *IvsExtentionByIdCardImageRequestBody `json:"body,omitempty"`
+}
+
+func (o DetectExtentionByIdCardImageRequest) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectExtentionByIdCardImageRequest struct{}"
+	}
+
+	return strings.Join([]string{"DetectExtentionByIdCardImageRequest", string(data)}, " ")
+}

+ 26 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_id_card_image_response.go

@@ -0,0 +1,26 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectExtentionByIdCardImageResponse Response Object
+type DetectExtentionByIdCardImageResponse struct {
+	Meta *Meta `json:"meta,omitempty"`
+
+	Result *IvsExtentionByIdCardImageResponseBodyResult `json:"result,omitempty"`
+
+	XRequestId     *string `json:"X-Request-Id,omitempty"`
+	HttpStatusCode int     `json:"-"`
+}
+
+func (o DetectExtentionByIdCardImageResponse) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectExtentionByIdCardImageResponse struct{}"
+	}
+
+	return strings.Join([]string{"DetectExtentionByIdCardImageResponse", string(data)}, " ")
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_name_and_id_request.go

@@ -0,0 +1,25 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectExtentionByNameAndIdRequest Request Object
+type DetectExtentionByNameAndIdRequest struct {
+
+	// 企业项目ID。IVS支持通过企业项目管理(EPS)对不同用户组和用户的资源使用,进行分账。  获取方法:进入“[企业项目管理](https://console.huaweicloud.com/eps/?region=cn-north-4#/projects/list)”页面,单击企业项目名称,在企业项目详情页获取Enterprise-Project-Id(企业项目ID)。  企业项目创建步骤请参见用户指南。 > 说明: 创建企业项目后,在传参时,有以下三类场景。 - 携带正确的ID,正常使用IVS服务,账单的企业项目会被分类到企业ID对应的企业项目中。 - 携带格式正确但不存在的ID,正常使用IVS服务,账单的企业项目会显示对应不存在的企业项目ID。 - 不携带ID或格式错误ID(包含特殊字符等),正常使用IVS服务,账单的企业项目会被分类到\"default\"中。
+	EnterpriseProjectId *string `json:"Enterprise-Project-Id,omitempty"`
+
+	Body *IvsExtentionByNameAndIdRequestBody `json:"body,omitempty"`
+}
+
+func (o DetectExtentionByNameAndIdRequest) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectExtentionByNameAndIdRequest struct{}"
+	}
+
+	return strings.Join([]string{"DetectExtentionByNameAndIdRequest", string(data)}, " ")
+}

+ 26 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_extention_by_name_and_id_response.go

@@ -0,0 +1,26 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectExtentionByNameAndIdResponse Response Object
+type DetectExtentionByNameAndIdResponse struct {
+	Meta *Meta `json:"meta,omitempty"`
+
+	Result *IvsExtentionByNameAndIdResponseBodyResult `json:"result,omitempty"`
+
+	XRequestId     *string `json:"X-Request-Id,omitempty"`
+	HttpStatusCode int     `json:"-"`
+}
+
+func (o DetectExtentionByNameAndIdResponse) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectExtentionByNameAndIdResponse struct{}"
+	}
+
+	return strings.Join([]string{"DetectExtentionByNameAndIdResponse", string(data)}, " ")
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_id_card_image_request.go

@@ -0,0 +1,25 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectStandardByIdCardImageRequest Request Object
+type DetectStandardByIdCardImageRequest struct {
+
+	// 企业项目ID。IVS支持通过企业项目管理(EPS)对不同用户组和用户的资源使用,进行分账。  获取方法:进入“[企业项目管理](https://console.huaweicloud.com/eps/?region=cn-north-4#/projects/list)”页面,单击企业项目名称,在企业项目详情页获取Enterprise-Project-Id(企业项目ID)。  企业项目创建步骤请参见用户指南。 > 说明: 创建企业项目后,在传参时,有以下三类场景。 - 携带正确的ID,正常使用IVS服务,账单的企业项目会被分类到企业ID对应的企业项目中。 - 携带格式正确但不存在的ID,正常使用IVS服务,账单的企业项目会显示对应不存在的企业项目ID。 - 不携带ID或格式错误ID(包含特殊字符等),正常使用IVS服务,账单的企业项目会被分类到\"default\"中。
+	EnterpriseProjectId *string `json:"Enterprise-Project-Id,omitempty"`
+
+	Body *IvsStandardByIdCardImageRequestBody `json:"body,omitempty"`
+}
+
+func (o DetectStandardByIdCardImageRequest) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectStandardByIdCardImageRequest struct{}"
+	}
+
+	return strings.Join([]string{"DetectStandardByIdCardImageRequest", string(data)}, " ")
+}

+ 26 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_id_card_image_response.go

@@ -0,0 +1,26 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectStandardByIdCardImageResponse Response Object
+type DetectStandardByIdCardImageResponse struct {
+	Meta *Meta `json:"meta,omitempty"`
+
+	Result *IvsStandardByIdCardImageResponseBodyResult `json:"result,omitempty"`
+
+	XRequestId     *string `json:"X-Request-Id,omitempty"`
+	HttpStatusCode int     `json:"-"`
+}
+
+func (o DetectStandardByIdCardImageResponse) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectStandardByIdCardImageResponse struct{}"
+	}
+
+	return strings.Join([]string{"DetectStandardByIdCardImageResponse", string(data)}, " ")
+}

+ 25 - 0
vendor/github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ivs/v2/model/model_detect_standard_by_name_and_id_request.go

@@ -0,0 +1,25 @@
+package model
+
+import (
+	"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/utils"
+
+	"strings"
+)
+
+// DetectStandardByNameAndIdRequest Request Object
+type DetectStandardByNameAndIdRequest struct {
+
+	// 企业项目ID。IVS支持通过企业项目管理(EPS)对不同用户组和用户的资源使用,进行分账。  获取方法:进入“[企业项目管理](https://console.huaweicloud.com/eps/?region=cn-north-4#/projects/list)”页面,单击企业项目名称,在企业项目详情页获取Enterprise-Project-Id(企业项目ID)。  企业项目创建步骤请参见用户指南。 > 说明: 创建企业项目后,在传参时,有以下三类场景。 - 携带正确的ID,正常使用IVS服务,账单的企业项目会被分类到企业ID对应的企业项目中。 - 携带格式正确但不存在的ID,正常使用IVS服务,账单的企业项目会显示对应不存在的企业项目ID。 - 不携带ID或格式错误ID(包含特殊字符等),正常使用IVS服务,账单的企业项目会被分类到\"default\"中。
+	EnterpriseProjectId *string `json:"Enterprise-Project-Id,omitempty"`
+
+	Body *IvsStandardByNameAndIdRequestBody `json:"body,omitempty"`
+}
+
+func (o DetectStandardByNameAndIdRequest) String() string {
+	data, err := utils.Marshal(o)
+	if err != nil {
+		return "DetectStandardByNameAndIdRequest struct{}"
+	}
+
+	return strings.Join([]string{"DetectStandardByNameAndIdRequest", string(data)}, " ")
+}

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff