This commit is contained in:
wood 2023-11-08 00:19:46 +08:00
parent c5a271dec4
commit 6d9ae196d6
10 changed files with 336 additions and 199 deletions

View File

@ -6,7 +6,7 @@
- [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值; - [x] 用户管理界面,支持快速设置用户组,在`web\src\components\UsersTable.js`处修改相关值;
- [x] 令牌界面,删除无用的多种复制、聊天等按钮; - [x] 令牌界面,删除无用的多种复制、聊天等按钮;
- [x] 删除系统访问令牌; - [x] 删除系统访问令牌;
- [ ] 在个人设置页面显示分组 - [x] 在个人设置页面显示分组,使用信息等
- [ ] 渠道管理处,已启用渠道和禁用渠道,启用/禁用按钮改为不同颜色; - [ ] 渠道管理处,已启用渠道和禁用渠道,启用/禁用按钮改为不同颜色;
- [x] 等 - [x] 等
@ -18,7 +18,7 @@
<p align="center"> <p align="center">
<a href="https://github.com/songquanpeng/one-api"><img src="https://raw.githubusercontent.com/songquanpeng/one-api/main/web/publichttps://cdn-img-r2.czl.net/2023/06/20/649168ebc2b5d.png" width="150" height="150" alt="one-api logo"></a> <a href="https://github.com/songquanpeng/one-api"><img src="https://raw.githubusercontent.com/songquanpeng/one-api/main/web/public/logo.png" width="150" height="150" alt="one-api logo"></a>
</p> </p>
<div align="center"> <div align="center">

View File

@ -45,6 +45,7 @@ var ModelRatio = map[string]float64{
"text-moderation-stable": 0.1, "text-moderation-stable": 0.1,
"text-moderation-latest": 0.1, "text-moderation-latest": 0.1,
"dall-e": 8, "dall-e": 8,
"dall-e-3": 20,
"claude-instant-1": 0.815, // $1.63 / 1M tokens "claude-instant-1": 0.815, // $1.63 / 1M tokens
"claude-2": 5.51, // $11.02 / 1M tokens "claude-2": 5.51, // $11.02 / 1M tokens
"ERNIE-Bot": 0.8572, // ¥0.012 / 1k tokens "ERNIE-Bot": 0.8572, // ¥0.012 / 1k tokens

View File

@ -63,6 +63,15 @@ func init() {
Root: "dall-e", Root: "dall-e",
Parent: nil, Parent: nil,
}, },
{
Id: "dall-e-3",
Object: "model",
Created: 1677649963,
OwnedBy: "openai",
Permission: permission,
Root: "dall-e-3",
Parent: nil,
},
{ {
Id: "whisper-1", Id: "whisper-1",
Object: "model", Object: "model",

View File

@ -8,107 +8,241 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
// func SetApiRouter(router *gin.Engine) {
// apiRouter := router.Group("/api")
// apiRouter.Use(gzip.Gzip(gzip.DefaultCompression))
// apiRouter.Use(middleware.GlobalAPIRateLimit())
// {
// apiRouter.GET("/status", controller.GetStatus)
// apiRouter.GET("/notice", controller.GetNotice)
// apiRouter.GET("/about", controller.GetAbout)
// apiRouter.GET("/home_page_content", controller.GetHomePageContent)
// apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification)
// apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail)
// apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword)
// apiRouter.GET("/oauth/github", middleware.CriticalRateLimit(), controller.GitHubOAuth)
// apiRouter.GET("/oauth/state", middleware.CriticalRateLimit(), controller.GenerateOAuthCode)
// apiRouter.GET("/oauth/wechat", middleware.CriticalRateLimit(), controller.WeChatAuth)
// apiRouter.GET("/oauth/wechat/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.WeChatBind)
// apiRouter.GET("/oauth/email/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.EmailBind)
// userRoute := apiRouter.Group("/user")
// {
// userRoute.POST("/register", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.Register)
// userRoute.POST("/login", middleware.CriticalRateLimit(), controller.Login)
// userRoute.GET("/logout", controller.Logout)
// selfRoute := userRoute.Group("/")
// selfRoute.Use(middleware.UserAuth())
// {
// selfRoute.GET("/self", controller.GetSelf)
// selfRoute.PUT("/self", controller.UpdateSelf)
// selfRoute.DELETE("/self", controller.DeleteSelf)
// selfRoute.GET("/token", controller.GenerateAccessToken)
// selfRoute.GET("/aff", controller.GetAffCode)
// selfRoute.POST("/topup", controller.TopUp)
// }
// adminRoute := userRoute.Group("/")
// adminRoute.Use(middleware.AdminAuth())
// {
// adminRoute.GET("/", controller.GetAllUsers)
// adminRoute.GET("/search", controller.SearchUsers)
// adminRoute.GET("/:id", controller.GetUser)
// adminRoute.POST("/", controller.CreateUser)
// adminRoute.POST("/manage", controller.ManageUser)
// adminRoute.PUT("/", controller.UpdateUser)
// adminRoute.DELETE("/:id", controller.DeleteUser)
// }
// }
// optionRoute := apiRouter.Group("/option")
// optionRoute.Use(middleware.RootAuth())
// {
// optionRoute.GET("/", controller.GetOptions)
// optionRoute.PUT("/", controller.UpdateOption)
// }
// channelRoute := apiRouter.Group("/channel")
// channelRoute.Use(middleware.AdminAuth())
// {
// channelRoute.GET("/", controller.GetAllChannels)
// channelRoute.GET("/search", controller.SearchChannels)
// channelRoute.GET("/models", controller.ListModels)
// channelRoute.GET("/:id", controller.GetChannel)
// channelRoute.GET("/test", controller.TestAllChannels)
// channelRoute.GET("/test/:id", controller.TestChannel)
// channelRoute.GET("/update_balance", controller.UpdateAllChannelsBalance)
// channelRoute.GET("/update_balance/:id", controller.UpdateChannelBalance)
// channelRoute.POST("/", controller.AddChannel)
// channelRoute.PUT("/", controller.UpdateChannel)
// channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel)
// channelRoute.DELETE("/:id", controller.DeleteChannel)
// }
// tokenRoute := apiRouter.Group("/token")
// tokenRoute.Use(middleware.UserAuth())
// {
// tokenRoute.GET("/", controller.GetAllTokens)
// tokenRoute.GET("/search", controller.SearchTokens)
// tokenRoute.GET("/:id", controller.GetToken)
// tokenRoute.POST("/", controller.AddToken)
// tokenRoute.PUT("/", controller.UpdateToken)
// tokenRoute.DELETE("/:id", controller.DeleteToken)
// }
// redemptionRoute := apiRouter.Group("/redemption")
// redemptionRoute.Use(middleware.AdminAuth())
// {
// redemptionRoute.GET("/", controller.GetAllRedemptions)
// redemptionRoute.GET("/search", controller.SearchRedemptions)
// redemptionRoute.GET("/:id", controller.GetRedemption)
// redemptionRoute.POST("/", controller.AddRedemption)
// redemptionRoute.PUT("/", controller.UpdateRedemption)
// redemptionRoute.DELETE("/:id", controller.DeleteRedemption)
// }
// logRoute := apiRouter.Group("/log")
// logRoute.GET("/", middleware.AdminAuth(), controller.GetAllLogs)
// logRoute.DELETE("/", middleware.AdminAuth(), controller.DeleteHistoryLogs)
// logRoute.GET("/stat", middleware.AdminAuth(), controller.GetLogsStat)
// logRoute.GET("/self/stat", middleware.UserAuth(), controller.GetLogsSelfStat)
// logRoute.GET("/search", middleware.AdminAuth(), controller.SearchAllLogs)
// logRoute.GET("/self", middleware.UserAuth(), controller.GetUserLogs)
// logRoute.GET("/self/search", middleware.UserAuth(), controller.SearchUserLogs)
// groupRoute := apiRouter.Group("/group")
// groupRoute.Use(middleware.AdminAuth())
// {
// groupRoute.GET("/", controller.GetGroups)
// }
// }
// }
// 设置API路由
func SetApiRouter(router *gin.Engine) { func SetApiRouter(router *gin.Engine) {
apiRouter := router.Group("/api") // 创建API路由分组
apiRouter.Use(gzip.Gzip(gzip.DefaultCompression)) apiRouter := router.Group("/api")
apiRouter.Use(middleware.GlobalAPIRateLimit()) // 使用gzip压缩中间件
{ apiRouter.Use(gzip.Gzip(gzip.DefaultCompression))
apiRouter.GET("/status", controller.GetStatus) // 使用全局API速率限制中间件
apiRouter.GET("/notice", controller.GetNotice) apiRouter.Use(middleware.GlobalAPIRateLimit())
apiRouter.GET("/about", controller.GetAbout) {
apiRouter.GET("/home_page_content", controller.GetHomePageContent) // 设置GET请求的路由处理函数
apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification) apiRouter.GET("/status", controller.GetStatus)
apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail) apiRouter.GET("/notice", controller.GetNotice)
apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword) apiRouter.GET("/about", controller.GetAbout)
apiRouter.GET("/oauth/github", middleware.CriticalRateLimit(), controller.GitHubOAuth) apiRouter.GET("/home_page_content", controller.GetHomePageContent)
apiRouter.GET("/oauth/state", middleware.CriticalRateLimit(), controller.GenerateOAuthCode) apiRouter.GET("/verification", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendEmailVerification)
apiRouter.GET("/oauth/wechat", middleware.CriticalRateLimit(), controller.WeChatAuth) apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.SendPasswordResetEmail)
apiRouter.GET("/oauth/wechat/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.WeChatBind) apiRouter.POST("/user/reset", middleware.CriticalRateLimit(), controller.ResetPassword)
apiRouter.GET("/oauth/email/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.EmailBind) apiRouter.GET("/oauth/github", middleware.CriticalRateLimit(), controller.GitHubOAuth)
apiRouter.GET("/oauth/state", middleware.CriticalRateLimit(), controller.GenerateOAuthCode)
apiRouter.GET("/oauth/wechat", middleware.CriticalRateLimit(), controller.WeChatAuth)
apiRouter.GET("/oauth/wechat/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.WeChatBind)
apiRouter.GET("/oauth/email/bind", middleware.CriticalRateLimit(), middleware.UserAuth(), controller.EmailBind)
// 添加新的路由
userRoute := apiRouter.Group("/user") // 创建user路由分组
{ userRoute := apiRouter.Group("/user")
userRoute.POST("/register", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.Register) {
userRoute.POST("/login", middleware.CriticalRateLimit(), controller.Login) // 设置POST请求的路由处理函数
userRoute.GET("/logout", controller.Logout) userRoute.POST("/register", middleware.CriticalRateLimit(), middleware.TurnstileCheck(), controller.Register)
userRoute.POST("/login", middleware.CriticalRateLimit(), controller.Login)
userRoute.GET("/logout", controller.Logout)
selfRoute := userRoute.Group("/") // 创建self路由分组并使用用户认证中间件
selfRoute.Use(middleware.UserAuth()) selfRoute := userRoute.Group("/")
{ selfRoute.Use(middleware.UserAuth())
selfRoute.GET("/self", controller.GetSelf) {
selfRoute.PUT("/self", controller.UpdateSelf) // 设置GET请求的路由处理函数
selfRoute.DELETE("/self", controller.DeleteSelf) selfRoute.GET("/self", controller.GetSelf)
selfRoute.GET("/token", controller.GenerateAccessToken) selfRoute.PUT("/self", controller.UpdateSelf)
selfRoute.GET("/aff", controller.GetAffCode) selfRoute.DELETE("/self", controller.DeleteSelf)
selfRoute.POST("/topup", controller.TopUp) selfRoute.GET("/token", controller.GenerateAccessToken)
} selfRoute.GET("/aff", controller.GetAffCode)
selfRoute.POST("/topup", controller.TopUp)
}
adminRoute := userRoute.Group("/") // 创建admin路由分组并使用管理员认证中间件
adminRoute.Use(middleware.AdminAuth()) adminRoute := userRoute.Group("/")
{ adminRoute.Use(middleware.AdminAuth())
adminRoute.GET("/", controller.GetAllUsers) {
adminRoute.GET("/search", controller.SearchUsers) // 设置GET请求的路由处理函数
adminRoute.GET("/:id", controller.GetUser) adminRoute.GET("/", controller.GetAllUsers)
adminRoute.POST("/", controller.CreateUser) adminRoute.GET("/search", controller.SearchUsers)
adminRoute.POST("/manage", controller.ManageUser) adminRoute.GET("/:id", controller.GetUser)
adminRoute.PUT("/", controller.UpdateUser) adminRoute.POST("/", controller.CreateUser)
adminRoute.DELETE("/:id", controller.DeleteUser) adminRoute.POST("/manage", controller.ManageUser)
} adminRoute.PUT("/", controller.UpdateUser)
} adminRoute.DELETE("/:id", controller.DeleteUser)
optionRoute := apiRouter.Group("/option") }
optionRoute.Use(middleware.RootAuth()) }
{
optionRoute.GET("/", controller.GetOptions) // 创建option路由分组并使用根认证中间件
optionRoute.PUT("/", controller.UpdateOption) optionRoute := apiRouter.Group("/option")
} optionRoute.Use(middleware.RootAuth())
channelRoute := apiRouter.Group("/channel") {
channelRoute.Use(middleware.AdminAuth()) // 设置GET请求的路由处理函数
{ optionRoute.GET("/", controller.GetOptions)
channelRoute.GET("/", controller.GetAllChannels) optionRoute.PUT("/", controller.UpdateOption)
channelRoute.GET("/search", controller.SearchChannels) }
channelRoute.GET("/models", controller.ListModels)
channelRoute.GET("/:id", controller.GetChannel) // 创建channel路由分组并使用管理员认证中间件
channelRoute.GET("/test", controller.TestAllChannels) channelRoute := apiRouter.Group("/channel")
channelRoute.GET("/test/:id", controller.TestChannel) channelRoute.Use(middleware.AdminAuth())
channelRoute.GET("/update_balance", controller.UpdateAllChannelsBalance) {
channelRoute.GET("/update_balance/:id", controller.UpdateChannelBalance) // 设置GET请求的路由处理函数
channelRoute.POST("/", controller.AddChannel) channelRoute.GET("/", controller.GetAllChannels)
channelRoute.PUT("/", controller.UpdateChannel) channelRoute.GET("/search", controller.SearchChannels)
channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel) channelRoute.GET("/:id", controller.GetChannel)
channelRoute.DELETE("/:id", controller.DeleteChannel) channelRoute.GET("/test", controller.TestAllChannels)
} channelRoute.GET("/test/:id", controller.TestChannel)
tokenRoute := apiRouter.Group("/token") channelRoute.GET("/update_balance", controller.UpdateAllChannelsBalance)
tokenRoute.Use(middleware.UserAuth()) channelRoute.GET("/update_balance/:id", controller.UpdateChannelBalance)
{ channelRoute.POST("/", controller.AddChannel)
tokenRoute.GET("/", controller.GetAllTokens) channelRoute.PUT("/", controller.UpdateChannel)
tokenRoute.GET("/search", controller.SearchTokens) channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel)
tokenRoute.GET("/:id", controller.GetToken) channelRoute.DELETE("/:id", controller.DeleteChannel)
tokenRoute.POST("/", controller.AddToken) }
tokenRoute.PUT("/", controller.UpdateToken)
tokenRoute.DELETE("/:id", controller.DeleteToken) // 创建token路由分组并使用用户认证中间件
} tokenRoute := apiRouter.Group("/token")
redemptionRoute := apiRouter.Group("/redemption") tokenRoute.Use(middleware.UserAuth())
redemptionRoute.Use(middleware.AdminAuth()) {
{ // 设置GET请求的路由处理函数
redemptionRoute.GET("/", controller.GetAllRedemptions) tokenRoute.GET("/", controller.GetAllTokens)
redemptionRoute.GET("/search", controller.SearchRedemptions) tokenRoute.GET("/search", controller.SearchTokens)
redemptionRoute.GET("/:id", controller.GetRedemption) tokenRoute.GET("/:id", controller.GetToken)
redemptionRoute.POST("/", controller.AddRedemption) tokenRoute.POST("/", controller.AddToken)
redemptionRoute.PUT("/", controller.UpdateRedemption) tokenRoute.PUT("/", controller.UpdateToken)
redemptionRoute.DELETE("/:id", controller.DeleteRedemption) tokenRoute.DELETE("/:id", controller.DeleteToken)
} }
logRoute := apiRouter.Group("/log")
logRoute.GET("/", middleware.AdminAuth(), controller.GetAllLogs) // 创建redemption路由分组并使用管理员认证中间件
logRoute.DELETE("/", middleware.AdminAuth(), controller.DeleteHistoryLogs) redemptionRoute := apiRouter.Group("/redemption")
logRoute.GET("/stat", middleware.AdminAuth(), controller.GetLogsStat) redemptionRoute.Use(middleware.AdminAuth())
logRoute.GET("/self/stat", middleware.UserAuth(), controller.GetLogsSelfStat) {
logRoute.GET("/search", middleware.AdminAuth(), controller.SearchAllLogs) // 设置GET请求的路由处理函数
logRoute.GET("/self", middleware.UserAuth(), controller.GetUserLogs) redemptionRoute.GET("/", controller.GetAllRedemptions)
logRoute.GET("/self/search", middleware.UserAuth(), controller.SearchUserLogs) redemptionRoute.GET("/search", controller.SearchRedemptions)
groupRoute := apiRouter.Group("/group") redemptionRoute.GET("/:id", controller.GetRedemption)
groupRoute.Use(middleware.AdminAuth()) redemptionRoute.POST("/", controller.AddRedemption)
{ redemptionRoute.PUT("/", controller.UpdateRedemption)
groupRoute.GET("/", controller.GetGroups) redemptionRoute.DELETE("/:id", controller.DeleteRedemption)
} }
}
} // 创建log路由分组
logRoute := apiRouter.Group("/")
logRoute.GET("/", middleware.AdminAuth(), controller.GetAllLogs)
logRoute.DELETE("/", middleware.AdminAuth(), controller.DeleteHistoryLogs)
logRoute.GET("/stat", middleware.AdminAuth(), controller.GetLogsStat)
logRoute.GET("/self/stat", middleware.UserAuth(), controller.GetLogsSelfStat)
logRoute.GET("/search", middleware.AdminAuth(), controller.SearchAllLogs)
logRoute.GET("/self", middleware.UserAuth(), controller.GetUserLogs)
logRoute.GET("/self/search", middleware.UserAuth(), controller.SearchUserLogs)
// 创建group路由分组并使用管理员认证中间件
groupRoute := apiRouter.Group("/group")
groupRoute.Use(middleware.AdminAuth())
{
// 设置GET请求的路由处理函数
groupRoute.GET("/", controller.GetGroups)
}
}
}

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="icon" href="https://cdn-img-r2.czl.net/2023/06/20/649168ebc2b5d.png" /> <link rel="icon" href="/logo.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff" />
<meta name="description" <meta name="description"

View File

@ -55,15 +55,6 @@ function App() {
} else { } else {
localStorage.removeItem('chat_link'); localStorage.removeItem('chat_link');
} }
if (
data.version !== process.env.REACT_APP_VERSION &&
data.version !== 'v0.0.0' &&
process.env.REACT_APP_VERSION !== ''
) {
showNotice(
`新版本可用:${data.version},请使用快捷键 Shift + F5 刷新页面`
);
}
} else { } else {
showError('无法正常连接至服务器!'); showError('无法正常连接至服务器!');
} }

View File

@ -64,7 +64,7 @@ const PasswordResetConfirm = () => {
<Grid textAlign='center' style={{ marginTop: '48px' }}> <Grid textAlign='center' style={{ marginTop: '48px' }}>
<Grid.Column style={{ maxWidth: 450 }}> <Grid.Column style={{ maxWidth: 450 }}>
<Header as='h2' color='' textAlign='center'> <Header as='h2' color='' textAlign='center'>
<Image src='https://cdn-img-r2.czl.net/2023/06/20/649168ebc2b5d.png' /> 密码重置确认 <Image src='/logo.png' /> 密码重置确认
</Header> </Header>
<Form size='large'> <Form size='large'>
<Segment> <Segment>

View File

@ -59,7 +59,7 @@ const PasswordResetForm = () => {
<Grid textAlign='center' style={{ marginTop: '48px' }}> <Grid textAlign='center' style={{ marginTop: '48px' }}>
<Grid.Column style={{ maxWidth: 450 }}> <Grid.Column style={{ maxWidth: 450 }}>
<Header as='h2' color='' textAlign='center'> <Header as='h2' color='' textAlign='center'>
<Image src='https://cdn-img-r2.czl.net/2023/06/20/649168ebc2b5d.png' /> 密码重置 <Image src='/logo.png' /> 密码重置
</Header> </Header>
<Form size='large'> <Form size='large'>
<Segment> <Segment>

View File

@ -1,5 +1,5 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { Button, Divider, Form, Header, Image, Message, Modal } from 'semantic-ui-react'; import { Button, Divider, Form, Header, Image, Message, Modal, Label } from 'semantic-ui-react';
import { Link, useNavigate } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers'; import { API, copy, showError, showInfo, showNotice, showSuccess } from '../helpers';
import Turnstile from 'react-turnstile'; import Turnstile from 'react-turnstile';
@ -19,7 +19,6 @@ const PersonalSetting = () => {
const [status, setStatus] = useState({}); const [status, setStatus] = useState({});
const [showWeChatBindModal, setShowWeChatBindModal] = useState(false); const [showWeChatBindModal, setShowWeChatBindModal] = useState(false);
const [showEmailBindModal, setShowEmailBindModal] = useState(false); const [showEmailBindModal, setShowEmailBindModal] = useState(false);
const [showAccountDeleteModal, setShowAccountDeleteModal] = useState(false);
const [turnstileEnabled, setTurnstileEnabled] = useState(false); const [turnstileEnabled, setTurnstileEnabled] = useState(false);
const [turnstileSiteKey, setTurnstileSiteKey] = useState(''); const [turnstileSiteKey, setTurnstileSiteKey] = useState('');
const [turnstileToken, setTurnstileToken] = useState(''); const [turnstileToken, setTurnstileToken] = useState('');
@ -28,6 +27,13 @@ const PersonalSetting = () => {
const [countdown, setCountdown] = useState(30); const [countdown, setCountdown] = useState(30);
const [affLink, setAffLink] = useState(""); const [affLink, setAffLink] = useState("");
const [systemToken, setSystemToken] = useState(""); const [systemToken, setSystemToken] = useState("");
const [userGroup, setUserGroup] = useState(null);
const [quota, setQuota] = useState(null);
const [usedQuota, setUsedQuota] = useState(null);
const [requestCount, setRequestCount] = useState(null);
const [githubID, setGithubID] = useState(null);
useEffect(() => { useEffect(() => {
let status = localStorage.getItem('status'); let status = localStorage.getItem('status');
@ -41,6 +47,50 @@ const PersonalSetting = () => {
} }
}, []); }, []);
// Get user group
useEffect(() => {
(async () => {
const res = await API.get(`/api/user/self`);
if (res.data.success) {
setUserGroup(res.data.data.group);
setQuota(res.data.data.quota);
setUsedQuota(res.data.data.used_quota);
setRequestCount(res.data.data.request_count);
setGithubID(res.data.data.github_id);
} else {
// Handle the error here
}
})();
}, []);
const quotaPerUnit = parseInt(localStorage.getItem("quota_per_unit"));
const transformUserGroup = (group) => {
switch (group) {
case 'default':
return '默认用户';
case 'vip':
return 'VIP用户';
case 'svip':
return 'SVIP用户';
default:
return group;
}
};
const getUserGroupColor = (group) => {
switch (group) {
case 'default':
return 'var(--czl-grayA)';
case 'vip':
return 'var(--czl-success-color)';
case 'svip':
return 'var(--czl-error-color)';
default:
return '';
}
};
useEffect(() => { useEffect(() => {
let countdownInterval = null; let countdownInterval = null;
if (disableButton && countdown > 0) { if (disableButton && countdown > 0) {
@ -58,19 +108,6 @@ const PersonalSetting = () => {
setInputs((inputs) => ({ ...inputs, [name]: value })); setInputs((inputs) => ({ ...inputs, [name]: value }));
}; };
const generateAccessToken = async () => {
const res = await API.get('/api/user/token');
const { success, message, data } = res.data;
if (success) {
setSystemToken(data);
setAffLink("");
await copy(data);
showSuccess(`令牌已重置并已复制到剪贴板`);
} else {
showError(message);
}
};
const getAffLink = async () => { const getAffLink = async () => {
const res = await API.get('/api/user/aff'); const res = await API.get('/api/user/aff');
const { success, message, data } = res.data; const { success, message, data } = res.data;
@ -169,6 +206,26 @@ const PersonalSetting = () => {
return ( return (
<div style={{ lineHeight: '40px' }}> <div style={{ lineHeight: '40px' }}>
<Header as='h3'>使用信息</Header>
{userGroup && (
<Label basic style={{ color: getUserGroupColor(userGroup), borderColor: getUserGroupColor(userGroup) }}>
用户组{transformUserGroup(userGroup)}
</Label>
)}
{quota !== null && quotaPerUnit && (
<Label basic style={{ color: getUserGroupColor(userGroup), borderColor: getUserGroupColor(userGroup) }}>
额度${(quota / quotaPerUnit).toFixed(2)}</Label>
)}
{usedQuota !== null && quotaPerUnit && (
<Label basic style={{ color: getUserGroupColor(userGroup), borderColor: getUserGroupColor(userGroup) }}>
已用额度${(usedQuota / quotaPerUnit).toFixed(2)}</Label>
)}
{requestCount !== null && <Label basic style={{ color: getUserGroupColor(userGroup), borderColor: getUserGroupColor(userGroup) }}>
调用次数{requestCount}</Label>}
<Label basic style={{ color: getUserGroupColor(userGroup), borderColor: getUserGroupColor(userGroup) }}>
GitHub 账号{githubID ? githubID : "未绑定"}
</Label>
<Divider />
<Header as='h3'>通用设置</Header> <Header as='h3'>通用设置</Header>
{/* <Message> {/* <Message>
注意此处生成的令牌用于系统管理而非用于请求 OpenAI 相关的服务请知悉 注意此处生成的令牌用于系统管理而非用于请求 OpenAI 相关的服务请知悉
@ -178,24 +235,21 @@ const PersonalSetting = () => {
</Button> </Button>
{/* <Button onClick={generateAccessToken}>生成系统访问令牌</Button> */} {/* <Button onClick={generateAccessToken}>生成系统访问令牌</Button> */}
<Button onClick={getAffLink}>复制邀请链接</Button> <Button onClick={getAffLink}>复制邀请链接</Button>
<Button onClick={() => {
setShowAccountDeleteModal(true);
}}>删除个人账户</Button>
{systemToken && ( {systemToken && (
<Form.Input <Form.Input
fluid fluid
readOnly readOnly
value={systemToken} value={systemToken}
onClick={handleSystemTokenClick} onClick={handleSystemTokenClick}
style={{ marginTop: '10px' }} style={{ marginTop: '10px' }}
/> />
)} )}
{affLink && ( {affLink && (
<Form.Input <Form.Input
fluid fluid
readOnly readOnly
value={affLink} value={affLink}
onClick={handleAffLinkClick} onClick={handleAffLinkClick}
style={{ marginTop: '10px' }} style={{ marginTop: '10px' }}
/> />
@ -244,7 +298,7 @@ const PersonalSetting = () => {
</Modal> </Modal>
{ {
status.github_oauth && ( status.github_oauth && (
<Button onClick={()=>{onGitHubOAuthClicked(status.github_client_id)}}>绑定 GitHub 账号</Button> <Button onClick={() => { onGitHubOAuthClicked(status.github_client_id) }}>绑定 GitHub 账号</Button>
) )
} }
<Button <Button
@ -294,73 +348,21 @@ const PersonalSetting = () => {
) : ( ) : (
<></> <></>
)} )}
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
<Button
color=''
fluid
size='large'
onClick={bindEmail}
loading={loading}
>
确认绑定
</Button>
<div style={{ width: '1rem' }}></div>
<Button
fluid
size='large'
onClick={() => setShowEmailBindModal(false)}
>
取消
</Button>
</div>
</Form>
</Modal.Description>
</Modal.Content>
</Modal>
<Modal
onClose={() => setShowAccountDeleteModal(false)}
onOpen={() => setShowAccountDeleteModal(true)}
open={showAccountDeleteModal}
size={'tiny'}
style={{ maxWidth: '450px' }}
>
<Modal.Header>危险操作</Modal.Header>
<Modal.Content>
<Message>您正在删除自己的帐户将清空所有数据且不可恢复</Message>
<Modal.Description>
<Form size='large'>
<Form.Input
fluid
placeholder={`输入你的账户名 ${userState?.user?.username} 以确认删除`}
name='self_account_deletion_confirmation'
value={inputs.self_account_deletion_confirmation}
onChange={handleInputChange}
/>
{turnstileEnabled ? (
<Turnstile
sitekey={turnstileSiteKey}
onVerify={(token) => {
setTurnstileToken(token);
}}
/>
) : (
<></>
)}
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}> <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '1rem' }}>
<Button <Button
color='red' color=''
fluid fluid
size='large' size='large'
onClick={deleteAccount} onClick={bindEmail}
loading={loading} loading={loading}
> >
确认删除 确认绑定
</Button> </Button>
<div style={{ width: '1rem' }}></div> <div style={{ width: '1rem' }}></div>
<Button <Button
fluid fluid
size='large' size='large'
onClick={() => setShowAccountDeleteModal(false)} onClick={() => setShowEmailBindModal(false)}
> >
取消 取消
</Button> </Button>

View File

@ -28,7 +28,7 @@ export function getSystemName() {
export function getLogo() { export function getLogo() {
let logo = localStorage.getItem('logo'); let logo = localStorage.getItem('logo');
if (!logo) return 'https://cdn-img-r2.czl.net/2023/06/20/649168ebc2b5d.png'; if (!logo) return '/logo.png';
return logo return logo
} }