host.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. package service
  2. import (
  3. "context"
  4. v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
  5. "github.com/go-nunu/nunu-layout-advanced/internal/model"
  6. "github.com/go-nunu/nunu-layout-advanced/internal/repository"
  7. "github.com/spf13/cast"
  8. "strconv"
  9. "strings"
  10. "time"
  11. )
  12. // HostService 接口定义
  13. type HostService interface {
  14. GetHost(ctx context.Context, id int64) (*model.Host, error)
  15. GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error)
  16. GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error)
  17. // 检查是否过期 到期false 未到期true
  18. CheckExpired(ctx context.Context, uid int64, hostId int64) (bool, error)
  19. }
  20. func NewHostService(
  21. service *Service,
  22. hostRepository repository.HostRepository,
  23. ) HostService {
  24. return &hostService{
  25. Service: service,
  26. hostRepository: hostRepository,
  27. }
  28. }
  29. // 常量定义,包含新增的配置项名称
  30. const (
  31. ConfigOnlineDevices = "在线设备数"
  32. ConfigRuleEntries = "规则条目"
  33. ConfigMaxBandwidth = "高带宽转发规则条目"
  34. ConfigSourceMachines = "支持源机"
  35. ConfigBps = "带宽"
  36. ConfigMaxProtection = "高防防护能力"
  37. ConfigPortCount = "防御端口数量"
  38. ConfigDomainCount = "防御域名(需要备案)"
  39. ConfigOperator = "高防线路"
  40. ConfigIpCount = "高防节点IP"
  41. NodeArea = "节点区域"
  42. IsBanUdp = "UDP协议"
  43. IsBanOverseas = "海外访问"
  44. )
  45. // unitSuffixMap 存储需要去除的单位后缀
  46. var unitSuffixMap = map[string]string{
  47. ConfigOnlineDevices: "个",
  48. ConfigRuleEntries: "个",
  49. ConfigMaxBandwidth: "条",
  50. ConfigIpCount: "个",
  51. }
  52. type hostService struct {
  53. *Service
  54. hostRepository repository.HostRepository
  55. }
  56. func (s *hostService) GetHost(ctx context.Context, id int64) (*model.Host, error) {
  57. return s.hostRepository.GetHost(ctx, id)
  58. }
  59. // GetHostConfig 保持不变,它是一个通用的底层数据获取方法。
  60. func (s *hostService) GetHostConfig(ctx context.Context, hostId int) ([]map[string]string, error) {
  61. configOptions, err := s.hostRepository.GetHostConfig(ctx, hostId)
  62. if err != nil {
  63. return nil, err
  64. }
  65. // 2. 收集ID和建立映射关系 (优化部分)
  66. var configIDs []int
  67. // 只收集那些我们需要查询详情的 option ID
  68. var optionIDsToFetch []int
  69. optionMap := make(map[int]int)
  70. qtyMap := make(map[int]int)
  71. for _, item := range configOptions {
  72. configIDs = append(configIDs, item.Configid)
  73. qtyMap[item.Configid] = item.Qty
  74. // 核心优化:只有当数量为0时,我们才需要Option的名称,
  75. // 因此才需要记录其ID用于后续查询,并建立 configID -> optionID 的映射。
  76. if item.Qty == 0 {
  77. optionIDsToFetch = append(optionIDsToFetch, item.Optionid)
  78. optionMap[item.Configid] = item.Optionid
  79. }
  80. }
  81. // 3. 获取配置和选项数据
  82. var configs []v1.ProductConfigOption
  83. if len(configIDs) > 0 {
  84. configs, err = s.hostRepository.GetProductConfigOption(ctx, configIDs)
  85. if err != nil {
  86. return nil, err
  87. }
  88. }
  89. // 只有在确实需要查询的情况下才执行
  90. var options []v1.ProductConfigOptionSub
  91. if len(optionIDsToFetch) > 0 {
  92. options, err = s.hostRepository.GetProductConfigOptionSub(ctx, optionIDsToFetch)
  93. if err != nil {
  94. return nil, err
  95. }
  96. }
  97. // 4. 转换选项为关联数组
  98. optionsByID := make(map[int]v1.ProductConfigOptionSub)
  99. for _, option := range options {
  100. optionsByID[option.ID] = option
  101. }
  102. // 5. 构建结果数据 (逻辑更清晰)
  103. var data []map[string]string
  104. for _, config := range configs {
  105. var optionName string
  106. // 直接通过qtyMap判断,逻辑更直接
  107. if qty := qtyMap[config.ID]; qty != 0 {
  108. // 如果数量不为0,直接使用数量作为名称
  109. optionName = strconv.Itoa(qty)
  110. } else {
  111. // 否则,我们知道它一定在 optionMap 和 optionsByID 中 (如果数据一致)
  112. optionID := optionMap[config.ID] // 这个查找现在是必要的
  113. if opt, ok := optionsByID[optionID]; ok {
  114. optionName = opt.OptionName
  115. }
  116. }
  117. data = append(data, map[string]string{
  118. "config_name": config.OptionName,
  119. "option_name": optionName,
  120. })
  121. }
  122. return data, nil
  123. }
  124. // cleanConfigOptionName 简化后的清理函数,直接返回清理后的字符串。
  125. func (s *hostService) cleanConfigOptionName(configName string, optionName string) string {
  126. // 根据配置名称去除相应的单位后缀
  127. if suffix, ok := unitSuffixMap[configName]; ok {
  128. optionName = strings.TrimSuffix(optionName, suffix)
  129. }
  130. return optionName
  131. }
  132. // getHostConfigsMap 新增的辅助函数,用于获取所有清理后的配置映射。
  133. func (s *hostService) getHostConfigsMap(ctx context.Context, hostId int) (map[string]string, error) {
  134. baseData, err := s.GetHostConfig(ctx, hostId)
  135. if err != nil {
  136. return nil, err
  137. }
  138. configsMap := make(map[string]string)
  139. for _, item := range baseData {
  140. configName := item["config_name"]
  141. optionName := item["option_name"]
  142. // 将清理后的值存储到 map 中
  143. configsMap[configName] = s.cleanConfigOptionName(configName, optionName)
  144. }
  145. return configsMap, nil
  146. }
  147. func (s *hostService) GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error) {
  148. // 调用新辅助函数获取处理好的配置映射
  149. configsMap, err := s.getHostConfigsMap(ctx, hostId)
  150. if err != nil {
  151. return v1.GameShieldHostBackendConfigResponse{}, err
  152. }
  153. var data v1.GameShieldHostBackendConfigResponse
  154. var parseErr error // 用于统一处理类型转换错误
  155. // 从映射中获取值并进行类型转换
  156. if val, ok := configsMap[ConfigOnlineDevices]; ok {
  157. data.OnlineDevicesCount, parseErr = cast.ToInt64E(val)
  158. if parseErr != nil {
  159. return data, parseErr
  160. }
  161. }
  162. if val, ok := configsMap[ConfigRuleEntries]; ok {
  163. data.RuleEntriesCount, parseErr = cast.ToInt64E(val)
  164. if parseErr != nil {
  165. return data, parseErr
  166. }
  167. }
  168. if val, ok := configsMap[ConfigMaxBandwidth]; ok {
  169. data.MaxBandwidthCount, parseErr = cast.ToInt64E(val)
  170. if parseErr != nil {
  171. return data, parseErr
  172. }
  173. }
  174. if val, ok := configsMap[ConfigSourceMachines]; ok {
  175. data.SourceMachinesCount, parseErr = cast.ToInt64E(val)
  176. if parseErr != nil {
  177. return data, parseErr
  178. }
  179. }
  180. return data, nil
  181. }
  182. func (s *hostService) GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error) {
  183. configsMap, err := s.getHostConfigsMap(ctx, hostId)
  184. if err != nil {
  185. return v1.GlobalLimitConfigResponse{}, err
  186. }
  187. data := v1.GlobalLimitConfigResponse{
  188. MaxBytesMonth: "0",
  189. Bps: "0",
  190. IpCount: 0,
  191. Operator: 0,
  192. NodeArea: "",
  193. ConfigMaxProtection: "",
  194. IsBanUdp: 0,
  195. }
  196. if val, ok := configsMap[ConfigBps]; ok {
  197. data.Bps = val
  198. }
  199. //if val, ok := configsMap[ConfigMaxBytesMonth]; ok {
  200. // data.MaxBytesMonth = val
  201. //}
  202. if val, ok := configsMap[ConfigPortCount]; ok {
  203. data.PortCount, err = cast.ToIntE(val)
  204. if err != nil {
  205. return data, err
  206. }
  207. }
  208. if val, ok := configsMap[ConfigDomainCount]; ok {
  209. data.DomainCount, err = cast.ToIntE(val)
  210. if err != nil {
  211. return data, err
  212. }
  213. }
  214. if val, ok := configsMap[ConfigOperator]; ok {
  215. if val == "电信" {
  216. data.IpCount = 1
  217. }
  218. if val == "BGP" {
  219. data.IpCount = 2
  220. }
  221. }
  222. if val, ok := configsMap[ConfigIpCount]; ok {
  223. data.Operator, err = cast.ToIntE(val)
  224. if err != nil {
  225. return data, err
  226. }
  227. }
  228. if val, ok := configsMap[NodeArea]; ok {
  229. data.NodeArea = val
  230. }
  231. if val, ok := configsMap[ConfigMaxProtection]; ok {
  232. data.ConfigMaxProtection = val
  233. }
  234. if val, ok := configsMap[IsBanUdp]; ok {
  235. if val == "开通" {
  236. data.IsBanUdp = 0
  237. }
  238. if val == "关闭" {
  239. data.IsBanUdp = 1
  240. }
  241. }
  242. if val, ok := configsMap[IsBanOverseas]; ok {
  243. if val == "开放" {
  244. data.IsBanOverseas = 0
  245. }
  246. if val == "封堵" {
  247. data.IsBanOverseas = 1
  248. }
  249. }
  250. return data, nil
  251. }
  252. // GetTcpLimitConfig 修正返回类型,并使用新的辅助函数
  253. // 检查是否过期 到期false 未到期true
  254. func (s *hostService) CheckExpired(ctx context.Context, uid int64, hostId int64) (bool, error) {
  255. var expireTime string
  256. expireTime, err := s.hostRepository.GetExpireTime(ctx, uid, hostId)
  257. if err != nil {
  258. return false, err
  259. }
  260. if expireTime == "" {
  261. return true, nil
  262. }
  263. unixTime, err := strconv.ParseInt(expireTime, 10, 64)
  264. if err != nil {
  265. return false, err
  266. }
  267. now := time.Now().Unix() // 当前时间戳(秒级)
  268. if now > unixTime {
  269. return false, nil
  270. }
  271. return true, nil
  272. }