Explorar el Código

feat: able to delete all manually disabled channels (close #539)

JustSong hace 2 años
padre
commit
8d34b7a77e

+ 4 - 3
common/constants.go

@@ -156,9 +156,10 @@ const (
 )
 
 const (
-	ChannelStatusUnknown  = 0
-	ChannelStatusEnabled  = 1 // don't use 0, 0 is the default value!
-	ChannelStatusDisabled = 2 // also don't use 0
+	ChannelStatusUnknown          = 0
+	ChannelStatusEnabled          = 1 // don't use 0, 0 is the default value!
+	ChannelStatusManuallyDisabled = 2 // also don't use 0
+	ChannelStatusAutoDisabled     = 3
 )
 
 const (

+ 1 - 1
controller/channel-test.go

@@ -141,7 +141,7 @@ func disableChannel(channelId int, channelName string, reason string) {
 	if common.RootUserEmail == "" {
 		common.RootUserEmail = model.GetRootUserEmail()
 	}
-	model.UpdateChannelStatusById(channelId, common.ChannelStatusDisabled)
+	model.UpdateChannelStatusById(channelId, common.ChannelStatusAutoDisabled)
 	subject := fmt.Sprintf("通道「%s」(#%d)已被禁用", channelName, channelId)
 	content := fmt.Sprintf("通道「%s」(#%d)已被禁用,原因:%s", channelName, channelId, reason)
 	err := common.SendEmail(subject, common.RootUserEmail, content)

+ 17 - 0
controller/channel.go

@@ -127,6 +127,23 @@ func DeleteChannel(c *gin.Context) {
 	return
 }
 
+func DeleteManuallyDisabledChannel(c *gin.Context) {
+	rows, err := model.DeleteChannelByStatus(common.ChannelStatusManuallyDisabled)
+	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":    rows,
+	})
+	return
+}
+
 func UpdateChannel(c *gin.Context) {
 	channel := model.Channel{}
 	err := c.ShouldBindJSON(&channel)

+ 5 - 0
model/channel.go

@@ -176,3 +176,8 @@ func updateChannelUsedQuota(id int, quota int) {
 		common.SysError("failed to update channel used quota: " + err.Error())
 	}
 }
+
+func DeleteChannelByStatus(status int64) (int64, error) {
+	result := DB.Where("status = ?", status).Delete(&Channel{})
+	return result.RowsAffected, result.Error
+}

+ 1 - 0
router/api-router.go

@@ -74,6 +74,7 @@ func SetApiRouter(router *gin.Engine) {
 			channelRoute.GET("/update_balance/:id", controller.UpdateChannelBalance)
 			channelRoute.POST("/", controller.AddChannel)
 			channelRoute.PUT("/", controller.UpdateChannel)
+			channelRoute.DELETE("/manually_disabled", controller.DeleteManuallyDisabledChannel)
 			channelRoute.DELETE("/:id", controller.DeleteChannel)
 		}
 		tokenRoute := apiRouter.Group("/token")

+ 73 - 24
web/src/components/ChannelsTable.js

@@ -1,5 +1,5 @@
 import React, { useEffect, useState } from 'react';
-import {Button, Form, Input, Label, Pagination, Popup, Table} from 'semantic-ui-react';
+import { Button, Form, Input, Label, Pagination, Popup, Table } from 'semantic-ui-react';
 import { Link } from 'react-router-dom';
 import { API, showError, showInfo, showNotice, showSuccess, timestamp2string } from '../helpers';
 
@@ -96,7 +96,7 @@ const ChannelsTable = () => {
       });
   }, []);
 
-  const manageChannel = async (id, action, idx, priority) => {
+  const manageChannel = async (id, action, idx, value) => {
     let data = { id };
     let res;
     switch (action) {
@@ -112,10 +112,20 @@ const ChannelsTable = () => {
         res = await API.put('/api/channel/', data);
         break;
       case 'priority':
-        if (priority === '') {
+        if (value === '') {
           return;
         }
-        data.priority = parseInt(priority);
+        data.priority = parseInt(value);
+        res = await API.put('/api/channel/', data);
+        break;
+      case 'weight':
+        if (value === '') {
+          return;
+        }
+        data.weight = parseInt(value);
+        if (data.weight < 0) {
+          data.weight = 0;
+        }
         res = await API.put('/api/channel/', data);
         break;
     }
@@ -142,9 +152,23 @@ const ChannelsTable = () => {
         return <Label basic color='green'>已启用</Label>;
       case 2:
         return (
-          <Label basic color='red'>
-            已禁用
-          </Label>
+          <Popup
+            trigger={<Label basic color='red'>
+              已禁用
+            </Label>}
+            content='本渠道被手动禁用'
+            basic
+          />
+        );
+      case 3:
+        return (
+          <Popup
+            trigger={<Label basic color='yellow'>
+              已禁用
+            </Label>}
+            content='本渠道被程序自动禁用'
+            basic
+          />
         );
       default:
         return (
@@ -202,7 +226,7 @@ const ChannelsTable = () => {
       showInfo(`通道 ${name} 测试成功,耗时 ${time.toFixed(2)} 秒。`);
     } else {
       showError(message);
-      showNotice("当前版本测试是通过按照 OpenAI API 格式使用 gpt-3.5-turbo 模型进行非流式请求实现的,因此测试报错并不一定代表通道不可用,该功能后续会修复。")
+      showNotice('当前版本测试是通过按照 OpenAI API 格式使用 gpt-3.5-turbo 模型进行非流式请求实现的,因此测试报错并不一定代表通道不可用,该功能后续会修复。');
     }
   };
 
@@ -216,6 +240,17 @@ const ChannelsTable = () => {
     }
   };
 
+  const deleteAllManuallyDisabledChannels = async () => {
+    const res = await API.delete(`/api/channel/manually_disabled`);
+    const { success, message, data } = res.data;
+    if (success) {
+      showSuccess(`已删除所有手动禁用渠道,共计 ${data} 个`);
+      await refresh();
+    } else {
+      showError(message);
+    }
+  };
+
   const updateChannelBalance = async (id, name, idx) => {
     const res = await API.get(`/api/channel/update_balance/${id}/`);
     const { success, message, balance } = res.data;
@@ -343,10 +378,10 @@ const ChannelsTable = () => {
               余额
             </Table.HeaderCell>
             <Table.HeaderCell
-                style={{ cursor: 'pointer' }}
-                onClick={() => {
-                  sortChannel('priority');
-                }}
+              style={{ cursor: 'pointer' }}
+              onClick={() => {
+                sortChannel('priority');
+              }}
             >
               优先级
             </Table.HeaderCell>
@@ -390,18 +425,18 @@ const ChannelsTable = () => {
                   </Table.Cell>
                   <Table.Cell>
                     <Popup
-                        trigger={<Input type="number"  defaultValue={channel.priority} onBlur={(event) => {
-                          manageChannel(
-                              channel.id,
-                              'priority',
-                              idx,
-                              event.target.value,
-                          );
-                        }}>
-                          <input style={{maxWidth:'60px'}} />
-                        </Input>}
-                        content='渠道选择优先级,越高越优先'
-                        basic
+                      trigger={<Input type='number' defaultValue={channel.priority} onBlur={(event) => {
+                        manageChannel(
+                          channel.id,
+                          'priority',
+                          idx,
+                          event.target.value
+                        );
+                      }}>
+                        <input style={{ maxWidth: '60px' }} />
+                      </Input>}
+                      content='渠道选择优先级,越高越优先'
+                      basic
                     />
                   </Table.Cell>
                   <Table.Cell>
@@ -481,6 +516,20 @@ const ChannelsTable = () => {
               </Button>
               <Button size='small' onClick={updateAllChannelsBalance}
                       loading={loading || updatingBalance}>更新所有已启用通道余额</Button>
+              <Popup
+                trigger={
+                  <Button size='small' loading={loading}>
+                    删除所有手动禁用渠道
+                  </Button>
+                }
+                on='click'
+                flowing
+                hoverable
+              >
+                <Button size='small' loading={loading} negative onClick={deleteAllManuallyDisabledChannels}>
+                  确认删除
+                </Button>
+              </Popup>
               <Pagination
                 floated='right'
                 activePage={activePage}