Skip to content

Commit

Permalink
feat: 支持对接oneapi/newapi
Browse files Browse the repository at this point in the history
  • Loading branch information
nianhua99 committed Sep 19, 2024
1 parent 8adca7d commit 414fa43
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 26 deletions.
4 changes: 4 additions & 0 deletions data/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"apiUrl": "https://api-proxy.oaipro.com/v1/moderations",
"message": "您的消息包含不当内容,请修改后重试!"
},
"oneapi": {
"token": "",
"domain": ""
},
"log": {
"level": "info",
"encoding": "console",
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/api/services/accountService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum AccountApi {
search = '/account/search',
shareAccounts = '/share_accounts',
loginFree = '/login_free_account',
getOneApiChannel = '/account/oneapi/channels',
}

const getAccountList = () =>
Expand Down Expand Up @@ -43,6 +44,7 @@ export interface AccountAddReq {
sessionKey?: string;
refreshToken?: string;
accessToken?: string;
oneApiChannelId?: number;
}

interface ShareAccountListResp {
Expand All @@ -57,14 +59,23 @@ interface LoginFreeAccountResp {
SelectType?: string,
}

interface OneApiChannel {
id: number;
name: string;
group: string;
status: number;
}

const addAccount = (data: AccountAddReq) => apiClient.post({ url: AccountApi.add, data });
const updateAccount = (data: AccountAddReq) => apiClient.post({ url: AccountApi.update, data });
const deleteAccount = (id: number) => apiClient.post({ url: AccountApi.delete, data: { id } });
const refreshAccount = (id: number) => apiClient.post({ url: AccountApi.refresh, data: { id } });
const getShareAccountList = () => apiClient.post<ShareAccountListResp>({ url: AccountApi.shareAccounts });
const getOneApiChannelList = () => apiClient.post<OneApiChannel[]>({ url: AccountApi.getOneApiChannel });
const loginFreeAccount = (data: LoginFreeAccountResp) => apiClient.post({ url: AccountApi.loginFree, data });

export default {
getOneApiChannelList,
getAccountList,
searchAccountList,
addAccount,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/pages/token/account/chatgpt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export default function AccountPage() {
refreshToken: '',
accessToken: '',
shared: 0,
oneApiChannelId: undefined,
}

const [accountModalProps, setAccountModalProps] = useState<AccountModalProps>({
Expand All @@ -81,7 +82,6 @@ export default function AccountPage() {
show: false,
onOk: (values: AccountAddReq, callback) => {
if (values.id) {
console.log(values)
updateAccountMutation.mutate(values, {
onSuccess: () => {
setAccountModalProps((prev) => ({ ...prev, show: false }));
Expand Down Expand Up @@ -338,6 +338,7 @@ export default function AccountPage() {
shared: record.shared,
refreshToken: record.refreshToken,
accessToken: record.accessToken,
oneApiChannelId: record.oneApiChannelId,
},
}));
};
Expand Down
56 changes: 54 additions & 2 deletions frontend/src/pages/token/account/components/AccountModal.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import {AccountAddReq} from "@/api/services/accountService.ts";
import {Button, Form, Input, Modal, Space, Switch, Tooltip} from "antd";
import accountService, {AccountAddReq} from "@/api/services/accountService.ts";
import {
Button,
Form,
Input,
Modal,
Select,
Space,
Spin,
Switch,
Tag,
Tooltip,
Typography
} from "antd";
import {useEffect, useState} from "react";
import {useTranslation} from "react-i18next";
import Password from "antd/es/input/Password";
import {InfoCircleOutlined} from "@ant-design/icons";
import {useQuery} from "@tanstack/react-query";

export type AccountModalProps = {
formValue: AccountAddReq;
Expand All @@ -18,6 +31,13 @@ export function AccountModal({ title, show, formValue, onOk, onCancel }: Account
const [loading, setLoading] = useState(false);
const { t } = useTranslation();

const { data, isLoading } = useQuery({
queryKey: ['accounts', 'one-api-channel', formValue],
queryFn: () => accountService.getOneApiChannelList(),
enabled: show,
});


useEffect(() => {
if (show) {
form1.setFieldsValue(formValue)
Expand Down Expand Up @@ -96,6 +116,38 @@ export function AccountModal({ title, show, formValue, onOk, onCancel }: Account
>
<Switch />
</Form.Item>
{formValue.accountType === 'chatgpt' ? (
<Form.Item<AccountAddReq>
label={"OneAPI 渠道"}
name={"oneApiChannelId"}
>
<Select
placeholder={"对接OneApi/NewApi的渠道, 非必填"}
allowClear={true}
loading={isLoading}
notFoundContent={isLoading ? <Spin size={"small"} /> : null}
>
{data?.map((item) => (
<Select.Option key={item.id}>
<Space>
<Typography.Text>{item.name}</Typography.Text>
<div>
{
item.group.split(',').map((group) => {
const colors = ["volcano", "orange", "gold", "lime", "green", "cyan", "blue", "geekblue", "purple", "magenta", "red"];
// 根据group随机hash出不同颜色
return <Tag color={colors[group.charCodeAt(0) % colors.length]}
key={group}
>{group}</Tag>
})
}
</div>
</Space>
</Select.Option>
))}
</Select>
</Form.Item>
): null}
{formValue.accountType === 'chatgpt' ? (
<>
<Form.Item
Expand Down
18 changes: 12 additions & 6 deletions frontend/src/pages/token/account/components/ShareModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,17 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
};

const limitFormatter = (value: number | undefined) => {
console.log(value);
switch (value) {
case -1:
console.log(value, typeof value);
switch (`${value}`) {
case '-1':
return '无限制';
case 0:
case '0':
return '禁用';
default:
return `${value}`;
return value !== undefined ? String(value) : '';
}
}
};


const limitParser = (value: string | undefined) => {
switch (value) {
Expand Down Expand Up @@ -126,6 +127,7 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
style={{ width: '100%' }}
formatter={limitFormatter}
parser={limitParser}
min={-1}
/>
</Form.Item>
</Col>
Expand All @@ -135,6 +137,7 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
style={{ width: '100%' }}
formatter={limitFormatter}
parser={limitParser}
min={-1}
/>
</Form.Item>
</Col>
Expand All @@ -144,6 +147,7 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
style={{ width: '100%' }}
formatter={limitFormatter}
parser={limitParser}
min={-1}
/>
</Form.Item>
</Col>
Expand All @@ -153,6 +157,7 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
style={{ width: '100%' }}
formatter={limitFormatter}
parser={limitParser}
min={-1}
/>
</Form.Item>
</Col>
Expand All @@ -162,6 +167,7 @@ export function ShareModal({ title, show, formValue, onOk, onCancel }: ShareModa
style={{ width: '100%' }}
formatter={limitFormatter}
parser={limitParser}
min={-1}
/>
</Form.Item>
</Col>
Expand Down
1 change: 1 addition & 0 deletions frontend/types/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface Account {
export interface ChatGPTAccount extends Account {
refreshToken?: string;
accessToken?: string;
oneApiChannelId?: number;
}

export interface ClaudeAccount extends Account {
Expand Down
9 changes: 9 additions & 0 deletions internal/handler/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,12 @@ func (h *AccountHandler) LoginShareAccount(ctx *gin.Context) {
}
v1.HandleSuccess(ctx, url)
}

func (h *AccountHandler) GetOneApiChannelList(ctx *gin.Context) {
channels, err := h.accountService.GetOneApiChannelList(ctx)
if err != nil {
v1.HandleError(ctx, http.StatusInternalServerError, err, nil)
return
}
v1.HandleSuccess(ctx, channels)
}
25 changes: 13 additions & 12 deletions internal/model/account.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package model

type Account struct {
ID uint `json:"id" gorm:"primaryKey" gorm:"column:id"`
Email string `json:"email" gorm:"column:email"`
Password string `json:"password" gorm:"column:password"`
SessionToken string `json:"sessionToken" gorm:"column:session_token"`
AccessToken string `json:"accessToken" gorm:"column:access_token"`
CreateTime *LocalTime `json:"createTime" gorm:"autoCreateTime" gorm:"column:create_time"`
UpdateTime *LocalTime `json:"updateTime" gorm:"autoUpdateTime" gorm:"column:update_time"`
Shared int `json:"shared" gorm:"column:shared"`
RefreshToken string `json:"refreshToken" gorm:"column:refresh_token"`
AccountType string `json:"accountType" gorm:"column:account_type" gorm:"default:chatgpt"`
SessionKey string `json:"sessionKey" gorm:"column:session_key"`
Shares []Share `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE"` // 外键关系
ID uint `json:"id" gorm:"primaryKey" gorm:"column:id"`
Email string `json:"email" gorm:"column:email"`
Password string `json:"password" gorm:"column:password"`
SessionToken string `json:"sessionToken" gorm:"column:session_token"`
AccessToken string `json:"accessToken" gorm:"column:access_token"`
CreateTime *LocalTime `json:"createTime" gorm:"autoCreateTime" gorm:"column:create_time"`
UpdateTime *LocalTime `json:"updateTime" gorm:"autoUpdateTime" gorm:"column:update_time"`
Shared int `json:"shared" gorm:"column:shared"`
RefreshToken string `json:"refreshToken" gorm:"column:refresh_token"`
AccountType string `json:"accountType" gorm:"column:account_type" gorm:"default:chatgpt"`
SessionKey string `json:"sessionKey" gorm:"column:session_key"`
OneApiChannelId string `json:"oneApiChannelId" gorm:"column:one_api_channel_id;default:''"`
Shares []Share `gorm:"foreignKey:AccountID;constraint:OnDelete:CASCADE"` // 外键关系
}

func (m *Account) TableName() string {
Expand Down
27 changes: 27 additions & 0 deletions internal/model/oneApiChannel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package model

type OneApiChannel struct {
Id int `json:"id"`
Type int `json:"type" gorm:"default:0"`
Key string `json:"key" gorm:"not null"`
OpenAIOrganization string `json:"openai_organization"`
TestModel string `json:"test_model"`
Status int `json:"status" gorm:"default:1"`
Name string `json:"name" gorm:"index"`
Weight uint `json:"weight" gorm:"default:0"`
CreatedTime int64 `json:"created_time" gorm:"bigint"`
TestTime int64 `json:"test_time" gorm:"bigint"`
ResponseTime int `json:"response_time"` // in milliseconds
BaseURL string `json:"base_url" gorm:"column:base_url;default:''"`
Other string `json:"other"`
Balance float64 `json:"balance"` // in USD
BalanceUpdatedTime int64 `json:"balance_updated_time" gorm:"bigint"`
Models string `json:"models"`
Group string `json:"group" gorm:"type:varchar(64);default:'default'"`
UsedQuota int64 `json:"used_quota" gorm:"bigint;default:0"`
ModelMapping string `json:"model_mapping" gorm:"type:varchar(1024);default:''"`
StatusCodeMapping string `json:"status_code_mapping" gorm:"type:varchar(1024);default:''"`
Priority int64 `json:"priority" gorm:"bigint;default:0"`
AutoBan int `json:"auto_ban" gorm:"default:1"`
OtherInfo string `json:"other_info"`
}
10 changes: 5 additions & 5 deletions internal/model/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ type Share struct {
ExpiresIn int `json:"expiresIn" gorm:"column:expires_in"`
ExpiresAt string `json:"expiresAt" gorm:"column:expires_at"`
SiteLimit string `json:"siteLimit" gorm:"column:site_limit"`
Gpt4Limit int `json:"gpt4Limit" gorm:"column:gpt4_limit"`
Gpt4oLimit int `json:"gpt4oLimit" gorm:"column:gpt4o_limit"`
Gpt4oMiniLimit int `json:"gpt4oMiniLimit" gorm:"column:gpt4o_mini_limit"`
O1Limit int `json:"o1Limit" gorm:"column:o1_limit"`
O1MiniLimit int `json:"o1MiniLimit" gorm:"column:o1_mini_limit"`
Gpt4Limit int `json:"gpt4Limit" gorm:"column:gpt4_limit;default:-1"`
Gpt4oLimit int `json:"gpt4oLimit" gorm:"column:gpt4o_limit;default:-1"`
Gpt4oMiniLimit int `json:"gpt4oMiniLimit" gorm:"column:gpt4o_mini_limit;default:-1"`
O1Limit int `json:"o1Limit" gorm:"column:o1_limit;default:-1"`
O1MiniLimit int `json:"o1MiniLimit" gorm:"column:o1_mini_limit;default:-1"`
Gpt35Limit int `json:"gpt35Limit" gorm:"column:gpt35_limit"`
ShowUserinfo bool `json:"showUserinfo" gorm:"column:show_userinfo"`
ShowConversations bool `json:"showConversations" gorm:"column:show_conversations"`
Expand Down
1 change: 1 addition & 0 deletions internal/server/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ func NewHTTPServer(
accountAuthRouter.POST("/search", accountHandler.SearchAccount)
accountAuthRouter.POST("/delete", accountHandler.DeleteAccount)
accountAuthRouter.POST("/update", accountHandler.UpdateAccount)
accountAuthRouter.POST("/oneapi/channels", accountHandler.GetOneApiChannelList)
}
}

Expand Down
Loading

0 comments on commit 414fa43

Please sign in to comment.