Sfoglia il codice sorgente

feat: able to fix channels

CaIon 2 anni fa
parent
commit
6a24e8953f
4 ha cambiato i file con 80 aggiunte e 0 eliminazioni
  1. 16 0
      controller/channel.go
  2. 43 0
      model/ability.go
  3. 1 0
      router/api-router.go
  4. 20 0
      web/src/components/ChannelsTable.js

+ 16 - 0
controller/channel.go

@@ -35,6 +35,22 @@ func GetAllChannels(c *gin.Context) {
 	return
 	return
 }
 }
 
 
+func FixChannelsAbilities(c *gin.Context) {
+	count, err := model.FixAbility()
+	if err != nil {
+		c.JSON(http.StatusOK, gin.H{
+			"success": false,
+			"message": err.Error(),
+		})
+		return
+	}
+	c.JSON(http.StatusOK, gin.H{
+		"success": true,
+		"message": "",
+		"data":    count,
+	})
+}
+
 func SearchChannels(c *gin.Context) {
 func SearchChannels(c *gin.Context) {
 	keyword := c.Query("keyword")
 	keyword := c.Query("keyword")
 	group := c.Query("group")
 	group := c.Query("group")

+ 43 - 0
model/ability.go

@@ -1,6 +1,7 @@
 package model
 package model
 
 
 import (
 import (
+	"fmt"
 	"one-api/common"
 	"one-api/common"
 	"strings"
 	"strings"
 )
 )
@@ -118,3 +119,45 @@ func (channel *Channel) UpdateAbilities() error {
 func UpdateAbilityStatus(channelId int, status bool) error {
 func UpdateAbilityStatus(channelId int, status bool) error {
 	return DB.Model(&Ability{}).Where("channel_id = ?", channelId).Select("enabled").Update("enabled", status).Error
 	return DB.Model(&Ability{}).Where("channel_id = ?", channelId).Select("enabled").Update("enabled", status).Error
 }
 }
+
+func FixAbility() (int, error) {
+	var channelIds []int
+	count := 0
+	// Find all channel ids from channel table
+	err := DB.Model(&Channel{}).Pluck("id", &channelIds).Error
+	if err != nil {
+		common.SysError(fmt.Sprintf("Get channel ids from channel table failed: %s", err.Error()))
+		return 0, err
+	}
+	// Delete abilities of channels that are not in channel table
+	err = DB.Where("channel_id NOT IN (?)", channelIds).Delete(&Ability{}).Error
+	if err != nil {
+		common.SysError(fmt.Sprintf("Delete abilities of channels that are not in channel table failed: %s", err.Error()))
+		return 0, err
+	}
+	common.SysLog(fmt.Sprintf("Delete abilities of channels that are not in channel table successfully, ids: %v", channelIds))
+	count += len(channelIds)
+
+	// Use channelIds to find channel not in abilities table
+	var abilityChannelIds []int
+	err = DB.Model(&Ability{}).Pluck("channel_id", &abilityChannelIds).Error
+	if err != nil {
+		common.SysError(fmt.Sprintf("Get channel ids from abilities table failed: %s", err.Error()))
+		return 0, err
+	}
+	var channels []Channel
+	err = DB.Where("id NOT IN (?)", abilityChannelIds).Find(&channels).Error
+	if err != nil {
+		return 0, err
+	}
+	for _, channel := range channels {
+		err := channel.UpdateAbilities()
+		if err != nil {
+			common.SysError(fmt.Sprintf("Update abilities of channel %d failed: %s", channel.Id, err.Error()))
+		} else {
+			common.SysLog(fmt.Sprintf("Update abilities of channel %d successfully", channel.Id))
+			count++
+		}
+	}
+	return count, nil
+}

+ 1 - 0
router/api-router.go

@@ -84,6 +84,7 @@ func SetApiRouter(router *gin.Engine) {
 			channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel)
 			channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel)
 			channelRoute.DELETE("/:id", controller.DeleteChannel)
 			channelRoute.DELETE("/:id", controller.DeleteChannel)
 			channelRoute.POST("/batch", controller.DeleteChannelBatch)
 			channelRoute.POST("/batch", controller.DeleteChannelBatch)
+			channelRoute.POST("/fix", controller.FixChannelsAbilities)
 		}
 		}
 		tokenRoute := apiRouter.Group("/token")
 		tokenRoute := apiRouter.Group("/token")
 		tokenRoute.Use(middleware.UserAuth())
 		tokenRoute.Use(middleware.UserAuth())

+ 20 - 0
web/src/components/ChannelsTable.js

@@ -531,6 +531,17 @@ const ChannelsTable = () => {
         setLoading(false);
         setLoading(false);
     }
     }
 
 
+    const fixChannelsAbilities = async () => {
+        const res = await API.post(`/api/channel/fix`);
+        const {success, message, data} = res.data;
+        if (success) {
+            showSuccess(`已修复 ${data} 个通道!`);
+            await refresh();
+        } else {
+            showError(message);
+        }
+    }
+
     const sortChannel = (key) => {
     const sortChannel = (key) => {
         if (channels.length === 0) return;
         if (channels.length === 0) return;
         setLoading(true);
         setLoading(true);
@@ -722,6 +733,15 @@ const ChannelsTable = () => {
                     >
                     >
                         <Button disabled={!enableBatchDelete} theme='light' type='danger' style={{marginRight: 8}}>删除所选通道</Button>
                         <Button disabled={!enableBatchDelete} theme='light' type='danger' style={{marginRight: 8}}>删除所选通道</Button>
                     </Popconfirm>
                     </Popconfirm>
+                    <Popconfirm
+                        title="确定是否要修复数据库一致性?"
+                        content="进行该操作时,可能导致渠道访问错误,请仅在数据库出现问题时使用"
+                        okType={'warning'}
+                        onConfirm={fixChannelsAbilities}
+                        position={'top'}
+                    >
+                        <Button theme='light' type='secondary' style={{marginRight: 8}}>修复数据库一致性</Button>
+                    </Popconfirm>
                 </Space>
                 </Space>
             </div>
             </div>
         </>
         </>