mirror of
https://github.com/songquanpeng/one-api.git
synced 2025-11-02 14:53:41 +08:00
Compare commits
6 Commits
v0.2.5-alp
...
v0.2.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2cdc718fde | ||
|
|
57cb150177 | ||
|
|
6167e20b34 | ||
|
|
8835d8302e | ||
|
|
224bebe67a | ||
|
|
cf6883778e |
15
README.md
15
README.md
@@ -43,8 +43,8 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
|
|||||||
## 功能
|
## 功能
|
||||||
1. 支持多种 API 访问渠道,欢迎 PR 或提 issue 添加更多渠道:
|
1. 支持多种 API 访问渠道,欢迎 PR 或提 issue 添加更多渠道:
|
||||||
+ [x] OpenAI 官方通道
|
+ [x] OpenAI 官方通道
|
||||||
+ [x] [API2D](https://api2d.com/r/197971)
|
|
||||||
+ [x] Azure OpenAI API
|
+ [x] Azure OpenAI API
|
||||||
|
+ [x] [API2D](https://api2d.com/r/197971)
|
||||||
+ [x] [CloseAI](https://console.openai-asia.com)
|
+ [x] [CloseAI](https://console.openai-asia.com)
|
||||||
+ [x] [OpenAI-SB](https://openai-sb.com)
|
+ [x] [OpenAI-SB](https://openai-sb.com)
|
||||||
+ [x] [OpenAI Max](https://openaimax.com)
|
+ [x] [OpenAI Max](https://openaimax.com)
|
||||||
@@ -55,15 +55,16 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
|
|||||||
4. 支持 HTTP SSE,可以通过流式传输实现打字机效果。
|
4. 支持 HTTP SSE,可以通过流式传输实现打字机效果。
|
||||||
5. 支持设置令牌的过期时间和使用次数。
|
5. 支持设置令牌的过期时间和使用次数。
|
||||||
6. 支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
|
6. 支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
|
||||||
7. 支持为新用户设置初始配额。
|
7. 支持批量创建通道。
|
||||||
8. 支持自定义首页,发布公告,自定义关于页面,设置充值链接,自定义页脚。
|
8. 支持发布公告,自定义关于页面,设置充值链接,自定义页脚。
|
||||||
9. 支持通过系统访问令牌访问管理 API。
|
9. 支持自定义首页,可以选择使用 HTML & Markdown 代码进行自定义,或者使用一个单独的网页通过 iframe 嵌入。
|
||||||
10. 多种用户登录注册方式:
|
10. 支持通过系统访问令牌访问管理 API。
|
||||||
|
11. 多种用户登录注册方式:
|
||||||
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
||||||
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
||||||
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
||||||
11. 支持用户管理。
|
12. 支持用户管理,支持为新用户设置初始配额。。
|
||||||
12. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
|
13. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
|
||||||
|
|
||||||
## 部署
|
## 部署
|
||||||
### 基于 Docker 进行部署
|
### 基于 Docker 进行部署
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ func relayHelper(c *gin.Context) error {
|
|||||||
select {
|
select {
|
||||||
case data := <-dataChan:
|
case data := <-dataChan:
|
||||||
if strings.HasPrefix(data, "data: [DONE]") {
|
if strings.HasPrefix(data, "data: [DONE]") {
|
||||||
data = "data: [DONE]"
|
data = data[:12]
|
||||||
}
|
}
|
||||||
c.Render(-1, common.CustomEvent{Data: data})
|
c.Render(-1, common.CustomEvent{Data: data})
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -117,18 +117,18 @@ const OtherSetting = () => {
|
|||||||
<Form.Group widths='equal'>
|
<Form.Group widths='equal'>
|
||||||
<Form.TextArea
|
<Form.TextArea
|
||||||
label='首页内容'
|
label='首页内容'
|
||||||
placeholder='在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示'
|
placeholder='在此输入首页内容,支持 Markdown & HTML 代码,设置后首页的状态信息将不再显示。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为首页。'
|
||||||
value={inputs.HomePageContent}
|
value={inputs.HomePageContent}
|
||||||
name='HomePageContent'
|
name='HomePageContent'
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
style={{ minHeight: 300, fontFamily: 'JetBrains Mono, Consolas' }}
|
style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Form.Button onClick={()=>submitOption('HomePageContent')}>保存首页内容</Form.Button>
|
<Form.Button onClick={()=>submitOption('HomePageContent')}>保存首页内容</Form.Button>
|
||||||
<Form.Group widths='equal'>
|
<Form.Group widths='equal'>
|
||||||
<Form.TextArea
|
<Form.TextArea
|
||||||
label='关于'
|
label='关于'
|
||||||
placeholder='在此输入新的关于内容,支持 Markdown & HTML 代码'
|
placeholder='在此输入新的关于内容,支持 Markdown & HTML 代码。如果输入的是一个链接,则会使用该链接作为 iframe 的 src 属性,这允许你设置任意网页作为关于页面。'
|
||||||
value={inputs.About}
|
value={inputs.About}
|
||||||
name='About'
|
name='About'
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ body {
|
|||||||
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, "Microsoft YaHei", sans-serif;
|
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, "Microsoft YaHei", sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
|
|||||||
@@ -5,18 +5,24 @@ import { marked } from 'marked';
|
|||||||
|
|
||||||
const About = () => {
|
const About = () => {
|
||||||
const [about, setAbout] = useState('');
|
const [about, setAbout] = useState('');
|
||||||
|
const [aboutLoaded, setAboutLoaded] = useState(false);
|
||||||
|
|
||||||
const displayAbout = async () => {
|
const displayAbout = async () => {
|
||||||
|
setAbout(localStorage.getItem('about') || '');
|
||||||
const res = await API.get('/api/about');
|
const res = await API.get('/api/about');
|
||||||
const { success, message, data } = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
let HTMLAbout = marked.parse(data);
|
let aboutContent = data;
|
||||||
localStorage.setItem('about', HTMLAbout);
|
if (!data.startsWith('https://')) {
|
||||||
setAbout(HTMLAbout);
|
aboutContent = marked.parse(data);
|
||||||
|
}
|
||||||
|
setAbout(aboutContent);
|
||||||
|
localStorage.setItem('about', aboutContent);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
setAbout('加载关于内容失败...');
|
setAbout('加载关于内容失败...');
|
||||||
}
|
}
|
||||||
|
setAboutLoaded(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -25,20 +31,27 @@ const About = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Segment>
|
{
|
||||||
{
|
aboutLoaded && about === '' ? <>
|
||||||
about === '' ? <>
|
<Segment>
|
||||||
<Header as='h3'>关于</Header>
|
<Header as='h3'>关于</Header>
|
||||||
<p>可在设置页面设置关于内容,支持 HTML & Markdown</p>
|
<p>可在设置页面设置关于内容,支持 HTML & Markdown</p>
|
||||||
项目仓库地址:
|
项目仓库地址:
|
||||||
<a href="https://github.com/songquanpeng/one-api">
|
<a href='https://github.com/songquanpeng/one-api'>
|
||||||
https://github.com/songquanpeng/one-api
|
https://github.com/songquanpeng/one-api
|
||||||
</a>
|
</a>
|
||||||
</> : <>
|
</Segment>
|
||||||
<div dangerouslySetInnerHTML={{ __html: about}}></div>
|
</> : <>
|
||||||
</>
|
{
|
||||||
}
|
about.startsWith('https://') ? <iframe
|
||||||
</Segment>
|
src={about}
|
||||||
|
style={{ width: '100%', height: '100vh', border: 'none' }}
|
||||||
|
/> : <Segment>
|
||||||
|
<div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: about }}></div>
|
||||||
|
</Segment>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { marked } from 'marked';
|
|||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const [statusState, statusDispatch] = useContext(StatusContext);
|
const [statusState, statusDispatch] = useContext(StatusContext);
|
||||||
|
const [homePageContentLoaded, setHomePageContentLoaded] = useState(false);
|
||||||
const [homePageContent, setHomePageContent] = useState('');
|
const [homePageContent, setHomePageContent] = useState('');
|
||||||
|
|
||||||
const displayNotice = async () => {
|
const displayNotice = async () => {
|
||||||
@@ -23,16 +24,21 @@ const Home = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const displayHomePageContent = async () => {
|
const displayHomePageContent = async () => {
|
||||||
|
setHomePageContent(localStorage.getItem('home_page_content') || '');
|
||||||
const res = await API.get('/api/home_page_content');
|
const res = await API.get('/api/home_page_content');
|
||||||
const { success, message, data } = res.data;
|
const { success, message, data } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
let HTMLContent = marked.parse(data);
|
let content = data;
|
||||||
localStorage.setItem('home_page_content', HTMLContent);
|
if (!data.startsWith('https://')) {
|
||||||
setHomePageContent(HTMLContent);
|
content = marked.parse(data);
|
||||||
|
}
|
||||||
|
setHomePageContent(content);
|
||||||
|
localStorage.setItem('home_page_content', content);
|
||||||
} else {
|
} else {
|
||||||
showError(message);
|
showError(message);
|
||||||
setHomePageContent('加载首页内容失败...');
|
setHomePageContent('加载首页内容失败...');
|
||||||
}
|
}
|
||||||
|
setHomePageContentLoaded(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getStartTimeString = () => {
|
const getStartTimeString = () => {
|
||||||
@@ -46,73 +52,79 @@ const Home = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Segment>
|
{
|
||||||
{
|
homePageContentLoaded && homePageContent === '' ? <>
|
||||||
homePageContent === '' ? <>
|
<Segment>
|
||||||
<Header as='h3'>系统状况</Header>
|
<Header as='h3'>系统状况</Header>
|
||||||
<Grid columns={2} stackable>
|
<Grid columns={2} stackable>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Card fluid>
|
<Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>系统信息</Card.Header>
|
<Card.Header>系统信息</Card.Header>
|
||||||
<Card.Meta>系统信息总览</Card.Meta>
|
<Card.Meta>系统信息总览</Card.Meta>
|
||||||
<Card.Description>
|
<Card.Description>
|
||||||
<p>名称:{statusState?.status?.system_name}</p>
|
<p>名称:{statusState?.status?.system_name}</p>
|
||||||
<p>版本:{statusState?.status?.version}</p>
|
<p>版本:{statusState?.status?.version}</p>
|
||||||
<p>
|
<p>
|
||||||
源码:
|
源码:
|
||||||
<a
|
<a
|
||||||
href='https://github.com/songquanpeng/one-api'
|
href='https://github.com/songquanpeng/one-api'
|
||||||
target='_blank'
|
target='_blank'
|
||||||
>
|
>
|
||||||
https://github.com/songquanpeng/one-api
|
https://github.com/songquanpeng/one-api
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<p>启动时间:{getStartTimeString()}</p>
|
<p>启动时间:{getStartTimeString()}</p>
|
||||||
</Card.Description>
|
</Card.Description>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
<Grid.Column>
|
<Grid.Column>
|
||||||
<Card fluid>
|
<Card fluid>
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Card.Header>系统配置</Card.Header>
|
<Card.Header>系统配置</Card.Header>
|
||||||
<Card.Meta>系统配置总览</Card.Meta>
|
<Card.Meta>系统配置总览</Card.Meta>
|
||||||
<Card.Description>
|
<Card.Description>
|
||||||
<p>
|
<p>
|
||||||
邮箱验证:
|
邮箱验证:
|
||||||
{statusState?.status?.email_verification === true
|
{statusState?.status?.email_verification === true
|
||||||
? '已启用'
|
? '已启用'
|
||||||
: '未启用'}
|
: '未启用'}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
GitHub 身份验证:
|
GitHub 身份验证:
|
||||||
{statusState?.status?.github_oauth === true
|
{statusState?.status?.github_oauth === true
|
||||||
? '已启用'
|
? '已启用'
|
||||||
: '未启用'}
|
: '未启用'}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
微信身份验证:
|
微信身份验证:
|
||||||
{statusState?.status?.wechat_login === true
|
{statusState?.status?.wechat_login === true
|
||||||
? '已启用'
|
? '已启用'
|
||||||
: '未启用'}
|
: '未启用'}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Turnstile 用户校验:
|
Turnstile 用户校验:
|
||||||
{statusState?.status?.turnstile_check === true
|
{statusState?.status?.turnstile_check === true
|
||||||
? '已启用'
|
? '已启用'
|
||||||
: '未启用'}
|
: '未启用'}
|
||||||
</p>
|
</p>
|
||||||
</Card.Description>
|
</Card.Description>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
</Grid.Column>
|
</Grid.Column>
|
||||||
</Grid>
|
</Grid>
|
||||||
</> : <>
|
</Segment>
|
||||||
<div dangerouslySetInnerHTML={{ __html: homePageContent}}></div>
|
</> : <>
|
||||||
</>
|
{
|
||||||
}
|
homePageContent.startsWith('https://') ? <iframe
|
||||||
</Segment>
|
src={homePageContent}
|
||||||
|
style={{ width: '100%', height: '100vh', border: 'none' }}
|
||||||
|
/> : <div style={{ fontSize: 'larger' }} dangerouslySetInnerHTML={{ __html: homePageContent }}></div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user