Skip to content

Commit

Permalink
feat: add new theme berry (#860)
Browse files Browse the repository at this point in the history
* feat: add theme berry

* docs: add development notes

* fix: fix blank page

* chore: update implementation

* fix: fix package.json

* chore: update ui copy

---------

Co-authored-by: JustSong <[email protected]>
  • Loading branch information
MartialBE and songquanpeng authored Jan 7, 2024
1 parent 6227eee commit 48989d4
Show file tree
Hide file tree
Showing 157 changed files with 13,979 additions and 5 deletions.
6 changes: 3 additions & 3 deletions controller/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ func init() {
Id: "PaLM-2",
Object: "model",
Created: 1677649963,
OwnedBy: "google",
OwnedBy: "google palm",
Permission: permission,
Root: "PaLM-2",
Parent: nil,
Expand All @@ -445,7 +445,7 @@ func init() {
Id: "gemini-pro",
Object: "model",
Created: 1677649963,
OwnedBy: "google",
OwnedBy: "google gemini",
Permission: permission,
Root: "gemini-pro",
Parent: nil,
Expand All @@ -454,7 +454,7 @@ func init() {
Id: "gemini-pro-vision",
Object: "model",
Created: 1677649963,
OwnedBy: "google",
OwnedBy: "google gemini",
Permission: permission,
Root: "gemini-pro-vision",
Parent: nil,
Expand Down
24 changes: 24 additions & 0 deletions controller/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"one-api/common"
"one-api/model"
"strconv"
"time"

"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
Expand Down Expand Up @@ -248,6 +249,29 @@ func GetUser(c *gin.Context) {
return
}

func GetUserDashboard(c *gin.Context) {
id := c.GetInt("id")
now := time.Now()
startOfDay := now.Truncate(24*time.Hour).AddDate(0, 0, -6).Unix()
endOfDay := now.Truncate(24 * time.Hour).Add(24*time.Hour - time.Second).Unix()

dashboards, err := model.SearchLogsByDayAndModel(id, int(startOfDay), int(endOfDay))
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "无法获取统计信息",
"data": nil,
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": dashboards,
})
return
}

func GenerateAccessToken(c *gin.Context) {
id := c.GetInt("id")
user, err := model.GetUserById(id, true)
Expand Down
42 changes: 41 additions & 1 deletion model/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package model
import (
"context"
"fmt"
"gorm.io/gorm"
"one-api/common"

"gorm.io/gorm"
)

type Log struct {
Expand Down Expand Up @@ -182,3 +183,42 @@ func DeleteOldLog(targetTimestamp int64) (int64, error) {
result := DB.Where("created_at < ?", targetTimestamp).Delete(&Log{})
return result.RowsAffected, result.Error
}

type LogStatistic struct {
Day string `gorm:"column:day"`
ModelName string `gorm:"column:model_name"`
RequestCount int `gorm:"column:request_count"`
Quota int `gorm:"column:quota"`
PromptTokens int `gorm:"column:prompt_tokens"`
CompletionTokens int `gorm:"column:completion_tokens"`
}

func SearchLogsByDayAndModel(userId, start, end int) (LogStatistics []*LogStatistic, err error) {
groupSelect := "DATE_FORMAT(FROM_UNIXTIME(created_at), '%Y-%m-%d') as day"

if common.UsingPostgreSQL {
groupSelect = "TO_CHAR(date_trunc('day', to_timestamp(created_at)), 'YYYY-MM-DD') as day"
}

if common.UsingSQLite {
groupSelect = "strftime('%Y-%m-%d', datetime(created_at, 'unixepoch')) as day"
}

err = DB.Raw(`
SELECT `+groupSelect+`,
model_name, count(1) as request_count,
sum(quota) as quota,
sum(prompt_tokens) as prompt_tokens,
sum(completion_tokens) as completion_tokens
FROM logs
WHERE type=2
AND userId= ?
AND created_at BETWEEN ? AND ?
GROUP BY day, model_name
ORDER BY day, model_name
`, userId, start, end).Scan(&LogStatistics).Error

fmt.Println(userId, start, end)

return LogStatistics, err
}
1 change: 1 addition & 0 deletions router/api-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func SetApiRouter(router *gin.Engine) {
selfRoute := userRoute.Group("/")
selfRoute.Use(middleware.UserAuth())
{
selfRoute.GET("/dashboard", controller.GetUserDashboard)
selfRoute.GET("/self", controller.GetSelf)
selfRoute.PUT("/self", controller.UpdateSelf)
selfRoute.DELETE("/self", controller.DeleteSelf)
Expand Down
19 changes: 19 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
# One API 的前端界面

> 每个文件夹代表一个主题,欢迎提交你的主题
## 提交新的主题

> 欢迎在页面底部保留你和 One API 的版权信息以及指向链接
1.`web` 文件夹下新建一个文件夹,文件夹名为主题名。
2. 把你的主题文件放到这个文件夹下。
3. 修改 `package.json` 文件,把 `build` 命令改为:`"build": "react-scripts build && mv -f build ../build/default"`,其中 `default` 为你的主题名。

## 主题列表

### 主题:default

默认主题,由 [JustSong](https://github.com/songquanpeng) 开发。

预览:
|![image](https://github.com/songquanpeng/one-api/assets/39998050/ccfbc668-3a7f-4bc1-87da-7eacfd7bf371)|![image](https://github.com/songquanpeng/one-api/assets/39998050/a63ed547-44b9-45db-b43a-ecea07d60840)|
|:---:|:---:|

### 主题:berry

[MartialBE](https://github.com/MartialBE) 开发。

预览:
|||
|:---:|:---:|
|![image](https://github.com/songquanpeng/one-api/assets/42402987/36aff5c6-c5ff-4a90-8e3d-33d5cff34cbf)|![image](https://github.com/songquanpeng/one-api/assets/42402987/9ac63b36-5140-4064-8fad-fc9d25821509)|
|![image](https://github.com/songquanpeng/one-api/assets/42402987/fb2b1c64-ef24-4027-9b80-0cd9d945a47f)|![image](https://github.com/songquanpeng/one-api/assets/42402987/b6b649ec-2888-4324-8b2d-d5e11554eed6)|
|![image](https://github.com/songquanpeng/one-api/assets/42402987/6d3b22e0-436b-4e26-8911-bcc993c6a2bd)|![image](https://github.com/songquanpeng/one-api/assets/42402987/eef1e224-7245-44d7-804e-9d1c8fa3f29c)|

#### 开发说明

请查看 [web/berry/README.md](https://github.com/songquanpeng/one-api/tree/main/web/berry/README.md)
3 changes: 2 additions & 1 deletion web/THEMES
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
default
default
berry
26 changes: 26 additions & 0 deletions web/berry/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.idea
package-lock.json
yarn.lock
61 changes: 61 additions & 0 deletions web/berry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# One API 前端界面

这个项目是 One API 的前端界面,它基于 [Berry Free React Admin Template](https://github.com/codedthemes/berry-free-react-admin-template) 进行开发。

## 使用的开源项目

使用了以下开源项目作为我们项目的一部分:

- [Berry Free React Admin Template](https://github.com/codedthemes/berry-free-react-admin-template)
- [minimal-ui-kit](minimal-ui-kit)

## 开发说明

当添加新的渠道时,需要修改以下地方:

1. `web/berry/src/constants/ChannelConstants.js`

在该文件中的 `CHANNEL_OPTIONS` 添加新的渠道

```js
export const CHANNEL_OPTIONS = {
//key 为渠道ID
1: {
key: 1, // 渠道ID
text: "OpenAI", // 渠道名称
value: 1, // 渠道ID
color: "primary", // 渠道列表显示的颜色
},
};
```

2. `web/berry/src/views/Channel/type/Config.js`

在该文件中的`typeConfig`添加新的渠道配置, 如果无需配置,可以不添加

```js
const typeConfig = {
// key 为渠道ID
3: {
inputLabel: {
// 输入框名称 配置
// 对应的字段名称
base_url: "AZURE_OPENAI_ENDPOINT",
other: "默认 API 版本",
},
prompt: {
// 输入框提示 配置
// 对应的字段名称
base_url: "请填写AZURE_OPENAI_ENDPOINT",

// 注意:通过判断 `other` 是否有值来判断是否需要显示 `other` 输入框, 默认是没有值的
other: "请输入默认API版本,例如:2023-06-01-preview",
},
modelGroup: "openai", // 模型组名称,这个值是给 填入渠道支持模型 按钮使用的。 填入渠道支持模型 按钮会根据这个值来获取模型组,如果填写默认是 openai
},
};
```

## 许可证

本项目中使用的代码遵循 MIT 许可证。
9 changes: 9 additions & 0 deletions web/berry/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"target": "esnext",
"module": "commonjs",
"baseUrl": "src"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
84 changes: 84 additions & 0 deletions web/berry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"name": "one_api_web",
"version": "1.0.0",
"proxy": "http://127.0.0.1:3000",
"private": true,
"homepage": "",
"dependencies": {
"@emotion/cache": "^11.9.3",
"@emotion/react": "^11.9.3",
"@emotion/styled": "^11.9.3",
"@mui/icons-material": "^5.8.4",
"@mui/lab": "^5.0.0-alpha.88",
"@mui/material": "^5.8.6",
"@mui/system": "^5.8.6",
"@mui/utils": "^5.8.6",
"@mui/x-date-pickers": "^6.18.5",
"@tabler/icons-react": "^2.44.0",
"apexcharts": "^3.35.3",
"axios": "^0.27.2",
"dayjs": "^1.11.10",
"formik": "^2.2.9",
"framer-motion": "^6.3.16",
"history": "^5.3.0",
"marked": "^4.1.1",
"material-ui-popup-state": "^4.0.1",
"notistack": "^3.0.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-apexcharts": "^1.4.0",
"react-device-detect": "^2.2.2",
"react-dom": "^18.2.0",
"react-perfect-scrollbar": "^1.5.8",
"react-redux": "^8.0.2",
"react-router": "6.3.0",
"react-router-dom": "6.3.0",
"react-scripts": "^5.0.1",
"react-turnstile": "^1.1.2",
"redux": "^4.2.0",
"yup": "^0.32.11"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && mv -f build ../build/berry",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app"
]
},
"babel": {
"presets": [
"@babel/preset-react"
]
},
"browserslist": {
"production": [
"defaults",
"not IE 11"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/core": "^7.21.4",
"@babel/eslint-parser": "^7.21.3",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-react-app": "^7.0.1",
"eslint-plugin-flowtype": "^8.0.3",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"immutable": "^4.3.0",
"prettier": "^2.8.7",
"sass": "^1.53.0"
}
}
Binary file added web/berry/public/favicon.ico
Binary file not shown.
26 changes: 26 additions & 0 deletions web/berry/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>One API</title>
<link rel="icon" href="/favicon.ico" />
<!-- Meta Tags-->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#2296f3" />
<meta
name="description"
content="OpenAI 接口聚合管理,支持多种渠道包括 Azure,可用于二次分发管理 key,仅单可执行文件,已打包好 Docker 镜像,一键部署,开箱即用"
/>
<link rel="preconnect" href="https://fonts.gstatic.com" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@400;500;600;700&family=Roboto:wght@400;500;700&display=swap"
rel="stylesheet"
/>
</head>

<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>

</body>
</html>
Loading

0 comments on commit 48989d4

Please sign in to comment.