// Package handler provides HTTP handlers for various endpoints. package handler import ( "net/http" "modelRT/constants" "modelRT/logger" "modelRT/model" "modelRT/network" "github.com/gin-gonic/gin" ) // MeasurementRecommendHandler define measurement recommend API // @Summary 测量点推荐(搜索框自动补全) // @Description 根据用户输入的字符串,从 Redis 中查询可能的测量点或结构路径,并提供推荐列表。 // @Tags Measurement Recommend // @Accept json // @Produce json // @Param input query string true "推荐关键词,例如 'grid1' 或 'grid1.'" Example("grid1") // @Success 200 {object} network.SuccessResponse{payload=network.MeasurementRecommendPayload} "返回推荐列表成功" // // @Example 200 { // "code": 200, // "msg": "success", // "payload": { // "input": "grid1.zone1.station1.ns1.tag1.bay.", // "offset": 21, // "recommended_list": [ // "I11_A_rms", // "I11_B_rms.", // "I11_C_rms.", // ] // } // } // // @Failure 400 {object} network.FailureResponse "返回推荐列表失败" // // @Example 400 { // "code": 400, // "msg": "failed to get recommend data from redis", // } // // @Router /measurement/recommend [get] func MeasurementRecommendHandler(c *gin.Context) { ctx := c.Request.Context() var request network.MeasurementRecommendRequest if err := c.ShouldBindQuery(&request); err != nil { logger.Error(ctx, "failed to bind measurement recommend request", "error", err) c.JSON(http.StatusOK, network.FailureResponse{ Code: http.StatusBadRequest, Msg: err.Error(), }) return } recommendResults := model.RedisSearchRecommend(ctx, request.Input) payload := network.MeasurementRecommendPayload{ Input: request.Input, RecommendedList: make([]string, 0), } seen := make(map[string]struct{}) orderedResults := orderedRecommendResults(recommendResults) for _, recommendResult := range orderedResults { if recommendResult.Err != nil { err := recommendResult.Err logger.Error(ctx, "failed to get recommend data from redis", "input", request.Input, "error", err) c.JSON(http.StatusOK, network.FailureResponse{ Code: http.StatusInternalServerError, Msg: err.Error(), Payload: map[string]any{ "input": request.Input, }, }) return } if recommendResult.Offset > payload.Offset { payload.Offset = recommendResult.Offset } } for _, recommendResult := range orderedResults { for _, recommend := range recommendResult.QueryDatas { if _, exists := seen[recommend]; !exists { seen[recommend] = struct{}{} payload.RecommendedList = append(payload.RecommendedList, recommend) } } } c.JSON(http.StatusOK, network.SuccessResponse{ Code: http.StatusOK, Msg: "success", Payload: payload, }) } func orderedRecommendResults(recommendResults map[string]model.SearchResult) []model.SearchResult { orderedTypes := []string{ constants.CompNSPathRecommendHierarchyType.String(), constants.GridRecommendHierarchyType.String(), constants.ZoneRecommendHierarchyType.String(), constants.StationRecommendHierarchyType.String(), constants.CompTagRecommendHierarchyType.String(), constants.ConfigRecommendHierarchyType.String(), constants.MeasTagRecommendHierarchyType.String(), } results := make([]model.SearchResult, 0, len(recommendResults)) for _, recommendType := range orderedTypes { result, ok := recommendResults[recommendType] if !ok { continue } results = append(results, result) } return results }