diff --git a/controller/channel.go b/controller/channel.go index 40b9cde4..83755333 100644 --- a/controller/channel.go +++ b/controller/channel.go @@ -168,18 +168,40 @@ func SearchChannels(c *gin.Context) { group := c.Query("group") modelKeyword := c.Query("model") idSort, _ := strconv.ParseBool(c.Query("id_sort")) - channels, err := model.SearchChannels(keyword, group, modelKeyword, idSort) - if err != nil { - c.JSON(http.StatusOK, gin.H{ - "success": false, - "message": err.Error(), - }) - return + enableTagMode, _ := strconv.ParseBool(c.Query("tag_mode")) + channelData := make([]*model.Channel, 0) + if enableTagMode { + tags, err := model.SearchTags(keyword, group, modelKeyword, idSort) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return + } + for _, tag := range tags { + if tag != nil && *tag != "" { + tagChannel, err := model.GetChannelsByTag(*tag) + if err == nil { + channelData = append(channelData, tagChannel...) + } + } + } + } else { + channels, err := model.SearchChannels(keyword, group, modelKeyword, idSort) + if err != nil { + c.JSON(http.StatusOK, gin.H{ + "success": false, + "message": err.Error(), + }) + return + } + channelData = channels } c.JSON(http.StatusOK, gin.H{ "success": true, "message": "", - "data": channels, + "data": channelData, }) return } diff --git a/model/channel.go b/model/channel.go index 9d59579f..48408f1d 100644 --- a/model/channel.go +++ b/model/channel.go @@ -410,3 +410,55 @@ func GetPaginatedTags(offset int, limit int) ([]*string, error) { err := DB.Model(&Channel{}).Select("DISTINCT tag").Where("tag != ''").Offset(offset).Limit(limit).Find(&tags).Error return tags, err } + +func SearchTags(keyword string, group string, model string, idSort bool) ([]*string, error) { + var tags []*string + keyCol := "`key`" + groupCol := "`group`" + modelsCol := "`models`" + + // 如果是 PostgreSQL,使用双引号 + if common.UsingPostgreSQL { + keyCol = `"key"` + groupCol = `"group"` + modelsCol = `"models"` + } + + order := "priority desc" + if idSort { + order = "id desc" + } + + // 构造基础查询 + baseQuery := DB.Model(&Channel{}).Omit(keyCol) + + // 构造WHERE子句 + var whereClause string + var args []interface{} + if group != "" && group != "null" { + var groupCondition string + if common.UsingMySQL { + groupCondition = `CONCAT(',', ` + groupCol + `, ',') LIKE ?` + } else { + // sqlite, PostgreSQL + groupCondition = `(',' || ` + groupCol + ` || ',') LIKE ?` + } + whereClause = "(id = ? OR name LIKE ? OR " + keyCol + " = ?) AND " + modelsCol + ` LIKE ? AND ` + groupCondition + args = append(args, common.String2Int(keyword), "%"+keyword+"%", keyword, "%"+model+"%", "%,"+group+",%") + } else { + whereClause = "(id = ? OR name LIKE ? OR " + keyCol + " = ?) AND " + modelsCol + " LIKE ?" + args = append(args, common.String2Int(keyword), "%"+keyword+"%", keyword, "%"+model+"%") + } + + err := baseQuery.Where(whereClause, args...). + Select("DISTINCT tag"). + Where("tag != ''"). + Order(order). + Find(&tags).Error + + if err != nil { + return nil, err + } + + return tags, nil +} diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js index 0139030f..61dd45a2 100644 --- a/web/src/components/ChannelsTable.js +++ b/web/src/components/ChannelsTable.js @@ -768,7 +768,7 @@ const ChannelsTable = () => { } }; - const searchChannels = async (searchKeyword, searchGroup, searchModel) => { + const searchChannels = async (searchKeyword, searchGroup, searchModel, enableTagMode) => { if (searchKeyword === '' && searchGroup === '' && searchModel === '') { await loadChannels(0, pageSize, idSort, enableTagMode); setActivePage(1); @@ -982,7 +982,7 @@ const ChannelsTable = () => { />
{ - searchChannels(searchKeyword, searchGroup, searchModel); + searchChannels(searchKeyword, searchGroup, searchModel, enableTagMode); }} labelPosition="left" > @@ -1015,7 +1015,7 @@ const ChannelsTable = () => { initValue={null} onChange={(v) => { setSearchGroup(v); - searchChannels(searchKeyword, v, searchModel); + searchChannels(searchKeyword, v, searchModel, enableTagMode); }} />