Просмотр исходного кода

Merge pull request #611 from Calcium-Ion/mobile

feat: 前端美化
Calcium-Ion 1 год назад
Родитель
Сommit
db84b26e2d

+ 3 - 3
relay/channel/gemini/constant.go

@@ -5,9 +5,9 @@ const (
 )
 
 var ModelList = []string{
-	"gemini-1.0-pro-latest", "gemini-1.0-pro-001", "gemini-1.5-pro-latest", "gemini-1.5-flash-latest", "gemini-ultra",
-	"gemini-1.0-pro-vision-latest", "gemini-1.0-pro-vision-001", "gemini-1.5-pro-exp-0827", "gemini-1.5-flash-exp-0827",
-	"gemini-exp-1114",
+	"gemini-1.5-pro-latest", "gemini-1.5-flash-latest", "gemini-ultra",
+	"gemini-1.5-pro-exp-0827", "gemini-1.5-flash-exp-0827",
+	"gemini-exp-1114", "gemini-exp-1206",
 }
 
 var ChannelName = "google gemini"

+ 14 - 1
relay/channel/vertex/adaptor.go

@@ -176,7 +176,20 @@ func (a *Adaptor) DoResponse(c *gin.Context, resp *http.Response, info *relaycom
 }
 
 func (a *Adaptor) GetModelList() []string {
-	return ModelList
+	var modelList []string
+	for i, s := range ModelList {
+		modelList = append(modelList, s)
+		ModelList[i] = s
+	}
+	for i, s := range claude.ModelList {
+		modelList = append(modelList, s)
+		claude.ModelList[i] = s
+	}
+	for i, s := range gemini.ModelList {
+		modelList = append(modelList, s)
+		gemini.ModelList[i] = s
+	}
+	return modelList
 }
 
 func (a *Adaptor) GetChannelName() string {

+ 5 - 5
relay/channel/vertex/constants.go

@@ -1,13 +1,13 @@
 package vertex
 
 var ModelList = []string{
-	"claude-3-sonnet-20240229",
-	"claude-3-opus-20240229",
-	"claude-3-haiku-20240307",
-	"claude-3-5-sonnet-20240620",
+	//"claude-3-sonnet-20240229",
+	//"claude-3-opus-20240229",
+	//"claude-3-haiku-20240307",
+	//"claude-3-5-sonnet-20240620",
 
 	//"gemini-1.5-pro-latest", "gemini-1.5-flash-latest",
-	"gemini-1.5-pro-001", "gemini-1.5-flash-001", "gemini-pro", "gemini-pro-vision",
+	//"gemini-1.5-pro-001", "gemini-1.5-flash-001", "gemini-pro", "gemini-pro-vision",
 
 	"meta/llama3-405b-instruct-maas",
 }

+ 7 - 10
web/src/components/LogsTable.js

@@ -25,7 +25,7 @@ import {
 import { ITEMS_PER_PAGE } from '../constants';
 import {
   renderAudioModelPrice,
-  renderModelPrice,
+  renderModelPrice, renderModelPriceSimple,
   renderNumber,
   renderQuota,
   stringToColor
@@ -386,14 +386,11 @@ const LogsTable = () => {
           );
         }
 
-        // let content = renderModelPrice(
-        //   record.prompt_tokens,
-        //   record.completion_tokens,
-        //   other.model_ratio,
-        //   other.model_price,
-        //   other.completion_ratio,
-        //   other.group_ratio,
-        // );
+        let content = renderModelPriceSimple(
+          other.model_ratio,
+          other.model_price,
+          other.group_ratio,
+        );
         return (
             <Paragraph
                 ellipsis={{
@@ -401,7 +398,7 @@ const LogsTable = () => {
                 }}
                 style={{ maxWidth: 240 }}
             >
-              调用消费
+              {content}
             </Paragraph>
         );
       },

+ 1 - 1
web/src/components/PageLayout.js

@@ -23,7 +23,7 @@ const PageLayout = () => {
         </Sider>
         <Layout>
           <Content
-            style={{ overflowY: 'auto', padding: '24px' }}
+            style={{ overflowY: 'auto', padding: styleState.isChatPage? '0': '24px' }}
           >
             <App />
           </Content>

+ 11 - 29
web/src/components/PersonalSetting.js

@@ -363,36 +363,18 @@ const PersonalSetting = () => {
                                     </Space>
                                 </>
                             }
-                            footer={
-                                <Descriptions row>
-                                    <Descriptions.Item itemKey='当前余额'>
-                                        {renderQuota(userState?.user?.quota)}
-                                    </Descriptions.Item>
-                                    <Descriptions.Item itemKey='历史消耗'>
-                                        {renderQuota(userState?.user?.used_quota)}
-                                    </Descriptions.Item>
-                                    <Descriptions.Item itemKey='请求次数'>
-                                        {userState.user?.request_count}
-                                    </Descriptions.Item>
-                                </Descriptions>
-                            }
                         >
-                            <Typography.Title heading={6}>可用模型</Typography.Title>
-                            <div style={{marginTop: 10}}>
-                                <Space wrap>
-                                    {models.map((model) => (
-                                        <Tag
-                                            key={model}
-                                            color='cyan'
-                                            onClick={() => {
-                                                copyText(model);
-                                            }}
-                                        >
-                                            {model}
-                                        </Tag>
-                                    ))}
-                                </Space>
-                            </div>
+                            <Descriptions row>
+                                <Descriptions.Item itemKey='当前余额'>
+                                    {renderQuota(userState?.user?.quota)}
+                                </Descriptions.Item>
+                                <Descriptions.Item itemKey='历史消耗'>
+                                    {renderQuota(userState?.user?.used_quota)}
+                                </Descriptions.Item>
+                                <Descriptions.Item itemKey='请求次数'>
+                                    {userState.user?.request_count}
+                                </Descriptions.Item>
+                            </Descriptions>
                         </Card>
                         <Card
                             style={{marginTop: 10}}

+ 5 - 0
web/src/components/SiderBar.js

@@ -279,6 +279,11 @@ const SiderBar = () => {
         }}
         items={headerButtons}
         onSelect={(key) => {
+          if (key.itemKey.toString().startsWith('chat')) {
+            styleDispatch({ type: 'SET_CHAT_PAGE', payload: true });
+          } else {
+            styleDispatch({ type: 'SET_CHAT_PAGE', payload: false });
+          }
           setSelectedKeys([key.itemKey]);
         }}
         footer={

+ 4 - 0
web/src/context/Style/index.js

@@ -11,6 +11,7 @@ export const StyleProvider = ({ children }) => {
   const [state, setState] = useState({
     isMobile: false,
     showSider: false,
+    isChatPage: false,
   });
 
   const dispatch = (action) => {
@@ -25,6 +26,9 @@ export const StyleProvider = ({ children }) => {
         case 'SET_MOBILE':
           setState(prev => ({ ...prev, isMobile: action.payload }));
           break;
+        case 'SET_CHAT_PAGE':
+          setState(prev => ({ ...prev, isChatPage: action.payload }));
+          break;
         default:
           setState(prev => ({ ...prev, ...action }));
       }

+ 13 - 0
web/src/helpers/render.js

@@ -175,6 +175,19 @@ export function renderModelPrice(
   }
 }
 
+export function renderModelPriceSimple(
+  modelRatio,
+  modelPrice = -1,
+  groupRatio,
+) {
+  // 1 ratio = $0.002 / 1K tokens
+  if (modelPrice !== -1) {
+    return '价格:$' + modelPrice + ' * 分组:' + groupRatio;
+  } else {
+    return '模型: ' + modelRatio + ' * 分组: ' + groupRatio;
+  }
+}
+
 export function renderAudioModelPrice(
   inputTokens,
   completionTokens,

+ 2 - 0
web/src/pages/Channel/EditChannel.js

@@ -710,6 +710,8 @@ const EditChannel = (props) => {
             required
             multiple
             selection
+            filter
+            searchPosition='dropdown'
             onChange={(value) => {
               handleInputChange('models', value);
             }}

+ 49 - 0
web/src/pages/Channel/EditTagModal.js

@@ -16,6 +16,7 @@ const EditTagModal = (props) => {
   const [groupOptions, setGroupOptions] = useState([]);
   const [basicModels, setBasicModels] = useState([]);
   const [fullModels, setFullModels] = useState([]);
+  const [customModel, setCustomModel] = useState('');
   const originInputs = {
     tag: '',
     new_tag: null,
@@ -183,6 +184,40 @@ const EditTagModal = (props) => {
     fetchGroups().then();
   }, [visible]);
 
+  const addCustomModels = () => {
+    if (customModel.trim() === '') return;
+    // 使用逗号分隔字符串,然后去除每个模型名称前后的空格
+    const modelArray = customModel.split(',').map((model) => model.trim());
+
+    let localModels = [...inputs.models];
+    let localModelOptions = [...modelOptions];
+    let hasError = false;
+
+    modelArray.forEach((model) => {
+      // 检查模型是否已存在,且模型名称非空
+      if (model && !localModels.includes(model)) {
+        localModels.push(model); // 添加到模型列表
+        localModelOptions.push({
+          // 添加到下拉选项
+          key: model,
+          text: model,
+          value: model
+        });
+      } else if (model) {
+        showError('某些模型已存在!');
+        hasError = true;
+      }
+    });
+
+    if (hasError) return; // 如果有错误则终止操作
+
+    // 更新状态值
+    setModelOptions(localModelOptions);
+    setCustomModel('');
+    handleInputChange('models', localModels);
+  };
+
+
   return (
     <SideSheet
       title="编辑标签"
@@ -224,6 +259,8 @@ const EditTagModal = (props) => {
           required
           multiple
           selection
+          filter
+          searchPosition='dropdown'
           onChange={(value) => {
             handleInputChange('models', value);
           }}
@@ -231,6 +268,18 @@ const EditTagModal = (props) => {
           autoComplete="new-password"
           optionList={modelOptions}
         />
+        <Input
+          addonAfter={
+            <Button type="primary" onClick={addCustomModels}>
+              填入
+            </Button>
+          }
+          placeholder="输入自定义模型名称"
+          value={customModel}
+          onChange={(value) => {
+            setCustomModel(value.trim());
+          }}
+        />
         <div style={{ marginTop: 10 }}>
           <Typography.Text strong>分组,留空则不更改:</Typography.Text>
         </div>

+ 10 - 5
web/src/pages/Playground/Playground.js

@@ -103,11 +103,16 @@ const Playground = () => {
       // handleInputChange('group', localGroupOptions[0].value);
 
       if (localGroupOptions.length > 0) {
-        // set default group at first
-        localGroupOptions.unshift({
-          label: '用户分组',
-          value: '',
-        });
+        // set user group at first
+        if (userState.user && userState.user.group) {
+          let userGroup = userState.user.group;
+          // Find and move user's group to the front
+          const userGroupIndex = localGroupOptions.findIndex(g => g.value === userGroup);
+          if (userGroupIndex > -1) {
+            const userGroupOption = localGroupOptions.splice(userGroupIndex, 1)[0];
+            localGroupOptions.unshift(userGroupOption);
+          }
+        }
       } else {
         localGroupOptions = [{
           label: '用户分组',