feat: able to set top up link now

This commit is contained in:
JustSong 2023-04-27 16:32:21 +08:00
parent 54b1e4adef
commit f97c2b4c22
6 changed files with 53 additions and 13 deletions

View File

@ -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. 支持为新用户设置初始配额。
8. 支持发布公告,在线修改关于页面,设置充值链接,自定义页脚。
9. 支持通过系统访问令牌访问管理 API。
10. 多种用户登录注册方式:
+ 邮箱登录注册以及通过邮箱进行密码重置。 + 邮箱登录注册以及通过邮箱进行密码重置。
+ [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))。
7. 支持用户管理。 11. 支持用户管理。
8. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。 12. 未来其他大模型开放 API 后,将第一时间支持,并将其封装成同样的 API 访问方式。
## 部署 ## 部署
### 基于 Docker 进行部署 ### 基于 Docker 进行部署

View File

@ -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

View File

@ -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

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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