1
This commit is contained in:
parent
c5a271dec4
commit
6d9ae196d6
@ -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">
|
||||||
|
@ -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
|
||||||
|
@ -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",
|
||||||
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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"
|
||||||
|
@ -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('无法正常连接至服务器!');
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user