feat: able to set top up link now
This commit is contained in:
parent
54b1e4adef
commit
f97c2b4c22
20
README.md
20
README.md
@ -52,14 +52,18 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
|
|||||||
+ [x] 自定义渠道
|
+ [x] 自定义渠道
|
||||||
2. 支持通过负载均衡的方式访问多个渠道。
|
2. 支持通过负载均衡的方式访问多个渠道。
|
||||||
3. 支持单个访问渠道设置多个 API Key,利用起来你的多个 API Key。
|
3. 支持单个访问渠道设置多个 API Key,利用起来你的多个 API Key。
|
||||||
4. 支持设置令牌的过期时间和使用次数。
|
4. 支持 HTTP SSE,可以通过流式传输实现打字机效果。
|
||||||
5. 支持 HTTP SSE。
|
5. 支持设置令牌的过期时间和使用次数。
|
||||||
6. 多种用户登录注册方式:
|
6. 支持批量生成和导出兑换码,可使用兑换码为令牌进行充值。
|
||||||
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
7. 支持为新用户设置初始配额。
|
||||||
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
8. 支持发布公告,在线修改关于页面,设置充值链接,自定义页脚。
|
||||||
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
9. 支持通过系统访问令牌访问管理 API。
|
||||||
7. 支持用户管理。
|
10. 多种用户登录注册方式:
|
||||||
8. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
|
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
||||||
|
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
|
||||||
|
+ 微信公众号授权(需要额外部署 [WeChat Server](https://github.com/songquanpeng/wechat-server))。
|
||||||
|
11. 支持用户管理。
|
||||||
|
12. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
|
||||||
|
|
||||||
## 部署
|
## 部署
|
||||||
### 基于 Docker 进行部署
|
### 基于 Docker 进行部署
|
||||||
|
@ -11,6 +11,7 @@ var Version = "v0.0.0" // this hard coding will be replaced automatic
|
|||||||
var SystemName = "One API"
|
var SystemName = "One API"
|
||||||
var ServerAddress = "http://localhost:3000"
|
var ServerAddress = "http://localhost:3000"
|
||||||
var Footer = ""
|
var Footer = ""
|
||||||
|
var TopUpLink = ""
|
||||||
|
|
||||||
var UsingSQLite = false
|
var UsingSQLite = false
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ func GetStatus(c *gin.Context) {
|
|||||||
"server_address": common.ServerAddress,
|
"server_address": common.ServerAddress,
|
||||||
"turnstile_check": common.TurnstileCheckEnabled,
|
"turnstile_check": common.TurnstileCheckEnabled,
|
||||||
"turnstile_site_key": common.TurnstileSiteKey,
|
"turnstile_site_key": common.TurnstileSiteKey,
|
||||||
|
"top_up_link": common.TopUpLink,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -47,6 +47,7 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["TurnstileSiteKey"] = ""
|
common.OptionMap["TurnstileSiteKey"] = ""
|
||||||
common.OptionMap["TurnstileSecretKey"] = ""
|
common.OptionMap["TurnstileSecretKey"] = ""
|
||||||
common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser)
|
common.OptionMap["QuotaForNewUser"] = strconv.Itoa(common.QuotaForNewUser)
|
||||||
|
common.OptionMap["TopUpLink"] = common.TopUpLink
|
||||||
common.OptionMapRWMutex.Unlock()
|
common.OptionMapRWMutex.Unlock()
|
||||||
options, _ := AllOption()
|
options, _ := AllOption()
|
||||||
for _, option := range options {
|
for _, option := range options {
|
||||||
@ -134,5 +135,7 @@ func updateOptionMap(key string, value string) {
|
|||||||
common.TurnstileSecretKey = value
|
common.TurnstileSecretKey = value
|
||||||
case "QuotaForNewUser":
|
case "QuotaForNewUser":
|
||||||
common.QuotaForNewUser, _ = strconv.Atoi(value)
|
common.QuotaForNewUser, _ = strconv.Atoi(value)
|
||||||
|
case "TopUpLink":
|
||||||
|
common.TopUpLink = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ const SystemSetting = () => {
|
|||||||
TurnstileSecretKey: '',
|
TurnstileSecretKey: '',
|
||||||
RegisterEnabled: '',
|
RegisterEnabled: '',
|
||||||
QuotaForNewUser: 0,
|
QuotaForNewUser: 0,
|
||||||
|
TopUpLink: ''
|
||||||
});
|
});
|
||||||
let originInputs = {};
|
let originInputs = {};
|
||||||
let [loading, setLoading] = useState(false);
|
let [loading, setLoading] = useState(false);
|
||||||
@ -65,7 +66,7 @@ const SystemSetting = () => {
|
|||||||
}
|
}
|
||||||
const res = await API.put('/api/option', {
|
const res = await API.put('/api/option', {
|
||||||
key,
|
key,
|
||||||
value,
|
value
|
||||||
});
|
});
|
||||||
const { success, message } = res.data;
|
const { success, message } = res.data;
|
||||||
if (success) {
|
if (success) {
|
||||||
@ -88,7 +89,8 @@ const SystemSetting = () => {
|
|||||||
name === 'WeChatAccountQRCodeImageURL' ||
|
name === 'WeChatAccountQRCodeImageURL' ||
|
||||||
name === 'TurnstileSiteKey' ||
|
name === 'TurnstileSiteKey' ||
|
||||||
name === 'TurnstileSecretKey' ||
|
name === 'TurnstileSecretKey' ||
|
||||||
name === 'QuotaForNewUser'
|
name === 'QuotaForNewUser' ||
|
||||||
|
name === 'TopUpLink'
|
||||||
) {
|
) {
|
||||||
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
setInputs((inputs) => ({ ...inputs, [name]: value }));
|
||||||
} else {
|
} else {
|
||||||
@ -101,6 +103,15 @@ const SystemSetting = () => {
|
|||||||
await updateOption('ServerAddress', ServerAddress);
|
await updateOption('ServerAddress', ServerAddress);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitOperationConfig = async () => {
|
||||||
|
if (originInputs['QuotaForNewUser'] !== inputs.QuotaForNewUser) {
|
||||||
|
await updateOption('QuotaForNewUser', inputs.QuotaForNewUser);
|
||||||
|
}
|
||||||
|
if (originInputs['TopUpLink'] !== inputs.TopUpLink) {
|
||||||
|
await updateOption('TopUpLink', inputs.TopUpLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const submitSMTP = async () => {
|
const submitSMTP = async () => {
|
||||||
if (originInputs['SMTPServer'] !== inputs.SMTPServer) {
|
if (originInputs['SMTPServer'] !== inputs.SMTPServer) {
|
||||||
await updateOption('SMTPServer', inputs.SMTPServer);
|
await updateOption('SMTPServer', inputs.SMTPServer);
|
||||||
@ -244,10 +255,17 @@ const SystemSetting = () => {
|
|||||||
min='0'
|
min='0'
|
||||||
placeholder='例如:100'
|
placeholder='例如:100'
|
||||||
/>
|
/>
|
||||||
|
<Form.Input
|
||||||
|
label='充值链接'
|
||||||
|
name='TopUpLink'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.TopUpLink}
|
||||||
|
type='link'
|
||||||
|
placeholder='例如发卡网站的购买链接'
|
||||||
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Form.Button onClick={()=>{
|
<Form.Button onClick={submitOperationConfig}>保存运营设置</Form.Button>
|
||||||
updateOption('QuotaForNewUser', inputs.QuotaForNewUser).then();
|
|
||||||
}}>保存运营设置</Form.Button>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
配置 SMTP
|
配置 SMTP
|
||||||
|
@ -37,6 +37,7 @@ const TokensTable = () => {
|
|||||||
const [showTopUpModal, setShowTopUpModal] = useState(false);
|
const [showTopUpModal, setShowTopUpModal] = useState(false);
|
||||||
const [targetTokenIdx, setTargetTokenIdx] = useState(0);
|
const [targetTokenIdx, setTargetTokenIdx] = useState(0);
|
||||||
const [redemptionCode, setRedemptionCode] = useState('');
|
const [redemptionCode, setRedemptionCode] = useState('');
|
||||||
|
const [topUpLink, setTopUpLink] = useState('');
|
||||||
|
|
||||||
const loadTokens = async (startIdx) => {
|
const loadTokens = async (startIdx) => {
|
||||||
const res = await API.get(`/api/token/?p=${startIdx}`);
|
const res = await API.get(`/api/token/?p=${startIdx}`);
|
||||||
@ -71,6 +72,13 @@ const TokensTable = () => {
|
|||||||
.catch((reason) => {
|
.catch((reason) => {
|
||||||
showError(reason);
|
showError(reason);
|
||||||
});
|
});
|
||||||
|
let status = localStorage.getItem('status');
|
||||||
|
if (status) {
|
||||||
|
status = JSON.parse(status);
|
||||||
|
if (status.top_up_link) {
|
||||||
|
setTopUpLink(status.top_up_link);
|
||||||
|
}
|
||||||
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const manageToken = async (id, action, idx) => {
|
const manageToken = async (id, action, idx) => {
|
||||||
@ -342,6 +350,11 @@ const TokensTable = () => {
|
|||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Modal.Description>
|
<Modal.Description>
|
||||||
{/*<Image src={status.wechat_qrcode} fluid />*/}
|
{/*<Image src={status.wechat_qrcode} fluid />*/}
|
||||||
|
{
|
||||||
|
topUpLink && <p>
|
||||||
|
<a target='_blank' href={topUpLink}>点击此处获取兑换码</a>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
<Form size='large'>
|
<Form size='large'>
|
||||||
<Form.Input
|
<Form.Input
|
||||||
fluid
|
fluid
|
||||||
|
Loading…
Reference in New Issue
Block a user