Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
1ea54eb2
authored
Aug 10, 2025
by
t0ng7u
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
🖼
️ chore: format code file
parent
750dea9d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
503 additions
and
505 deletions
+503
-505
common/endpoint_defaults.go
+10
-10
controller/missing_models.go
+15
-15
controller/model_meta.go
+142
-142
controller/prefill_group.go
+66
-66
controller/pricing.go
+8
-8
controller/user.go
+3
-3
controller/vendor_meta.go
+93
-94
model/missing_models.go
+22
-22
model/model_extra.go
+20
-20
model/model_meta.go
+0
-0
model/prefill_group.go
+72
-72
model/pricing.go
+0
-0
model/pricing_refresh.go
+5
-5
model/vendor_meta.go
+47
-48
No files found.
common/endpoint_defaults.go
View file @
1ea54eb2
...
...
@@ -11,22 +11,22 @@ import "one-api/constant"
// 例如:{"path":"/v1/chat/completions","method":"POST"}
type
EndpointInfo
struct
{
Path
string
`json:"path"`
Method
string
`json:"method"`
Path
string
`json:"path"`
Method
string
`json:"method"`
}
// defaultEndpointInfoMap 保存内置端点的默认 Path 与 Method
var
defaultEndpointInfoMap
=
map
[
constant
.
EndpointType
]
EndpointInfo
{
constant
.
EndpointTypeOpenAI
:
{
Path
:
"/v1/chat/completions"
,
Method
:
"POST"
},
constant
.
EndpointTypeOpenAIResponse
:
{
Path
:
"/v1/responses"
,
Method
:
"POST"
},
constant
.
EndpointTypeAnthropic
:
{
Path
:
"/v1/messages"
,
Method
:
"POST"
},
constant
.
EndpointTypeGemini
:
{
Path
:
"/v1beta/models/{model}:generateContent"
,
Method
:
"POST"
},
constant
.
EndpointTypeJinaRerank
:
{
Path
:
"/rerank"
,
Method
:
"POST"
},
constant
.
EndpointTypeImageGeneration
:
{
Path
:
"/v1/images/generations"
,
Method
:
"POST"
},
constant
.
EndpointTypeOpenAI
:
{
Path
:
"/v1/chat/completions"
,
Method
:
"POST"
},
constant
.
EndpointTypeOpenAIResponse
:
{
Path
:
"/v1/responses"
,
Method
:
"POST"
},
constant
.
EndpointTypeAnthropic
:
{
Path
:
"/v1/messages"
,
Method
:
"POST"
},
constant
.
EndpointTypeGemini
:
{
Path
:
"/v1beta/models/{model}:generateContent"
,
Method
:
"POST"
},
constant
.
EndpointTypeJinaRerank
:
{
Path
:
"/rerank"
,
Method
:
"POST"
},
constant
.
EndpointTypeImageGeneration
:
{
Path
:
"/v1/images/generations"
,
Method
:
"POST"
},
}
// GetDefaultEndpointInfo 返回指定端点类型的默认信息以及是否存在
func
GetDefaultEndpointInfo
(
et
constant
.
EndpointType
)
(
EndpointInfo
,
bool
)
{
info
,
ok
:=
defaultEndpointInfoMap
[
et
]
return
info
,
ok
info
,
ok
:=
defaultEndpointInfoMap
[
et
]
return
info
,
ok
}
controller/missing_models.go
View file @
1ea54eb2
package
controller
import
(
"net/http"
"one-api/model"
"net/http"
"one-api/model"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
// GetMissingModels returns the list of model names that are referenced by channels
// but do not have corresponding records in the models meta table.
// This helps administrators quickly discover models that need configuration.
func
GetMissingModels
(
c
*
gin
.
Context
)
{
missing
,
err
:=
model
.
GetMissingModels
()
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
missing
,
err
:=
model
.
GetMissingModels
()
if
err
!=
nil
{
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
false
,
"message"
:
err
.
Error
(),
})
return
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"data"
:
missing
,
})
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"success"
:
true
,
"data"
:
missing
,
})
}
controller/model_meta.go
View file @
1ea54eb2
package
controller
import
(
"encoding/json"
"strconv"
"encoding/json"
"strconv"
"one-api/common"
"one-api/model"
"one-api/common"
"one-api/model"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
// GetAllModelsMeta 获取模型列表(分页)
func
GetAllModelsMeta
(
c
*
gin
.
Context
)
{
pageInfo
:=
common
.
GetPageQuery
(
c
)
modelsMeta
,
err
:=
model
.
GetAllModels
(
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
// 填充附加字段
for
_
,
m
:=
range
modelsMeta
{
fillModelExtra
(
m
)
}
var
total
int64
model
.
DB
.
Model
(
&
model
.
Model
{})
.
Count
(
&
total
)
// 统计供应商计数(全部数据,不受分页影响)
vendorCounts
,
_
:=
model
.
GetVendorModelCounts
()
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
modelsMeta
)
common
.
ApiSuccess
(
c
,
gin
.
H
{
"items"
:
modelsMeta
,
"total"
:
total
,
"page"
:
pageInfo
.
GetPage
(),
"page_size"
:
pageInfo
.
GetPageSize
(),
"vendor_counts"
:
vendorCounts
,
})
pageInfo
:=
common
.
GetPageQuery
(
c
)
modelsMeta
,
err
:=
model
.
GetAllModels
(
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
// 填充附加字段
for
_
,
m
:=
range
modelsMeta
{
fillModelExtra
(
m
)
}
var
total
int64
model
.
DB
.
Model
(
&
model
.
Model
{})
.
Count
(
&
total
)
// 统计供应商计数(全部数据,不受分页影响)
vendorCounts
,
_
:=
model
.
GetVendorModelCounts
()
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
modelsMeta
)
common
.
ApiSuccess
(
c
,
gin
.
H
{
"items"
:
modelsMeta
,
"total"
:
total
,
"page"
:
pageInfo
.
GetPage
(),
"page_size"
:
pageInfo
.
GetPageSize
(),
"vendor_counts"
:
vendorCounts
,
})
}
// SearchModelsMeta 搜索模型列表
func
SearchModelsMeta
(
c
*
gin
.
Context
)
{
keyword
:=
c
.
Query
(
"keyword"
)
vendor
:=
c
.
Query
(
"vendor"
)
pageInfo
:=
common
.
GetPageQuery
(
c
)
modelsMeta
,
total
,
err
:=
model
.
SearchModels
(
keyword
,
vendor
,
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
for
_
,
m
:=
range
modelsMeta
{
fillModelExtra
(
m
)
}
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
modelsMeta
)
common
.
ApiSuccess
(
c
,
pageInfo
)
keyword
:=
c
.
Query
(
"keyword"
)
vendor
:=
c
.
Query
(
"vendor"
)
pageInfo
:=
common
.
GetPageQuery
(
c
)
modelsMeta
,
total
,
err
:=
model
.
SearchModels
(
keyword
,
vendor
,
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
for
_
,
m
:=
range
modelsMeta
{
fillModelExtra
(
m
)
}
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
modelsMeta
)
common
.
ApiSuccess
(
c
,
pageInfo
)
}
// GetModelMeta 根据 ID 获取单条模型信息
func
GetModelMeta
(
c
*
gin
.
Context
)
{
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
var
m
model
.
Model
if
err
:=
model
.
DB
.
First
(
&
m
,
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
fillModelExtra
(
&
m
)
common
.
ApiSuccess
(
c
,
&
m
)
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
var
m
model
.
Model
if
err
:=
model
.
DB
.
First
(
&
m
,
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
fillModelExtra
(
&
m
)
common
.
ApiSuccess
(
c
,
&
m
)
}
// CreateModelMeta 新建模型
func
CreateModelMeta
(
c
*
gin
.
Context
)
{
var
m
model
.
Model
if
err
:=
c
.
ShouldBindJSON
(
&
m
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
m
.
ModelName
==
""
{
common
.
ApiErrorMsg
(
c
,
"模型名称不能为空"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsModelNameDuplicated
(
0
,
m
.
ModelName
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"模型名称已存在"
)
return
}
if
err
:=
m
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
&
m
)
var
m
model
.
Model
if
err
:=
c
.
ShouldBindJSON
(
&
m
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
m
.
ModelName
==
""
{
common
.
ApiErrorMsg
(
c
,
"模型名称不能为空"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsModelNameDuplicated
(
0
,
m
.
ModelName
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"模型名称已存在"
)
return
}
if
err
:=
m
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
&
m
)
}
// UpdateModelMeta 更新模型
func
UpdateModelMeta
(
c
*
gin
.
Context
)
{
statusOnly
:=
c
.
Query
(
"status_only"
)
==
"true"
var
m
model
.
Model
if
err
:=
c
.
ShouldBindJSON
(
&
m
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
m
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少模型 ID"
)
return
}
if
statusOnly
{
// 只更新状态,防止误清空其他字段
if
err
:=
model
.
DB
.
Model
(
&
model
.
Model
{})
.
Where
(
"id = ?"
,
m
.
Id
)
.
Update
(
"status"
,
m
.
Status
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
}
else
{
// 名称冲突检查
if
dup
,
err
:=
model
.
IsModelNameDuplicated
(
m
.
Id
,
m
.
ModelName
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"模型名称已存在"
)
return
}
if
err
:=
m
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
&
m
)
statusOnly
:=
c
.
Query
(
"status_only"
)
==
"true"
var
m
model
.
Model
if
err
:=
c
.
ShouldBindJSON
(
&
m
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
m
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少模型 ID"
)
return
}
if
statusOnly
{
// 只更新状态,防止误清空其他字段
if
err
:=
model
.
DB
.
Model
(
&
model
.
Model
{})
.
Where
(
"id = ?"
,
m
.
Id
)
.
Update
(
"status"
,
m
.
Status
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
}
else
{
// 名称冲突检查
if
dup
,
err
:=
model
.
IsModelNameDuplicated
(
m
.
Id
,
m
.
ModelName
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"模型名称已存在"
)
return
}
if
err
:=
m
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
&
m
)
}
// DeleteModelMeta 删除模型
func
DeleteModelMeta
(
c
*
gin
.
Context
)
{
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DB
.
Delete
(
&
model
.
Model
{},
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
nil
)
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DB
.
Delete
(
&
model
.
Model
{},
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
model
.
RefreshPricing
()
common
.
ApiSuccess
(
c
,
nil
)
}
// 辅助函数:填充 Endpoints 和 BoundChannels 和 EnableGroups
func
fillModelExtra
(
m
*
model
.
Model
)
{
if
m
.
Endpoints
==
""
{
eps
:=
model
.
GetModelSupportEndpointTypes
(
m
.
ModelName
)
if
b
,
err
:=
json
.
Marshal
(
eps
);
err
==
nil
{
m
.
Endpoints
=
string
(
b
)
}
}
if
channels
,
err
:=
model
.
GetBoundChannels
(
m
.
ModelName
);
err
==
nil
{
m
.
BoundChannels
=
channels
}
// 填充启用分组
m
.
EnableGroups
=
model
.
GetModelEnableGroups
(
m
.
ModelName
)
// 填充计费类型
m
.
QuotaType
=
model
.
GetModelQuotaType
(
m
.
ModelName
)
if
m
.
Endpoints
==
""
{
eps
:=
model
.
GetModelSupportEndpointTypes
(
m
.
ModelName
)
if
b
,
err
:=
json
.
Marshal
(
eps
);
err
==
nil
{
m
.
Endpoints
=
string
(
b
)
}
}
if
channels
,
err
:=
model
.
GetBoundChannels
(
m
.
ModelName
);
err
==
nil
{
m
.
BoundChannels
=
channels
}
// 填充启用分组
m
.
EnableGroups
=
model
.
GetModelEnableGroups
(
m
.
ModelName
)
// 填充计费类型
m
.
QuotaType
=
model
.
GetModelQuotaType
(
m
.
ModelName
)
}
controller/prefill_group.go
View file @
1ea54eb2
package
controller
import
(
"strconv"
"strconv"
"one-api/common"
"one-api/model"
"one-api/common"
"one-api/model"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
// GetPrefillGroups 获取预填组列表,可通过 ?type=xxx 过滤
func
GetPrefillGroups
(
c
*
gin
.
Context
)
{
groupType
:=
c
.
Query
(
"type"
)
groups
,
err
:=
model
.
GetAllPrefillGroups
(
groupType
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
groups
)
groupType
:=
c
.
Query
(
"type"
)
groups
,
err
:=
model
.
GetAllPrefillGroups
(
groupType
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
groups
)
}
// CreatePrefillGroup 创建新的预填组
func
CreatePrefillGroup
(
c
*
gin
.
Context
)
{
var
g
model
.
PrefillGroup
if
err
:=
c
.
ShouldBindJSON
(
&
g
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
g
.
Name
==
""
||
g
.
Type
==
""
{
common
.
ApiErrorMsg
(
c
,
"组名称和类型不能为空"
)
return
}
// 创建前检查名称
if
dup
,
err
:=
model
.
IsPrefillGroupNameDuplicated
(
0
,
g
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"组名称已存在"
)
return
}
var
g
model
.
PrefillGroup
if
err
:=
c
.
ShouldBindJSON
(
&
g
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
g
.
Name
==
""
||
g
.
Type
==
""
{
common
.
ApiErrorMsg
(
c
,
"组名称和类型不能为空"
)
return
}
// 创建前检查名称
if
dup
,
err
:=
model
.
IsPrefillGroupNameDuplicated
(
0
,
g
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"组名称已存在"
)
return
}
if
err
:=
g
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
g
)
if
err
:=
g
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
g
)
}
// UpdatePrefillGroup 更新预填组
func
UpdatePrefillGroup
(
c
*
gin
.
Context
)
{
var
g
model
.
PrefillGroup
if
err
:=
c
.
ShouldBindJSON
(
&
g
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
g
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少组 ID"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsPrefillGroupNameDuplicated
(
g
.
Id
,
g
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"组名称已存在"
)
return
}
var
g
model
.
PrefillGroup
if
err
:=
c
.
ShouldBindJSON
(
&
g
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
g
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少组 ID"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsPrefillGroupNameDuplicated
(
g
.
Id
,
g
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"组名称已存在"
)
return
}
if
err
:=
g
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
g
)
if
err
:=
g
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
g
)
}
// DeletePrefillGroup 删除预填组
func
DeletePrefillGroup
(
c
*
gin
.
Context
)
{
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DeletePrefillGroupByID
(
id
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
nil
)
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DeletePrefillGroupByID
(
id
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
nil
)
}
controller/pricing.go
View file @
1ea54eb2
...
...
@@ -39,14 +39,14 @@ func GetPricing(c *gin.Context) {
}
c
.
JSON
(
200
,
gin
.
H
{
"success"
:
true
,
"data"
:
pricing
,
"vendors"
:
model
.
GetVendors
(),
"group_ratio"
:
groupRatio
,
"usable_group"
:
usableGroup
,
"supported_endpoint"
:
model
.
GetSupportedEndpointMap
(),
"auto_groups"
:
setting
.
AutoGroups
,
})
"success"
:
true
,
"data"
:
pricing
,
"vendors"
:
model
.
GetVendors
(),
"group_ratio"
:
groupRatio
,
"usable_group"
:
usableGroup
,
"supported_endpoint"
:
model
.
GetSupportedEndpointMap
(),
"auto_groups"
:
setting
.
AutoGroups
,
})
}
func
ResetModelRatio
(
c
*
gin
.
Context
)
{
...
...
controller/user.go
View file @
1ea54eb2
...
...
@@ -62,7 +62,7 @@ func Login(c *gin.Context) {
})
return
}
// 检查是否启用2FA
if
model
.
IsTwoFAEnabled
(
user
.
Id
)
{
// 设置pending session,等待2FA验证
...
...
@@ -77,7 +77,7 @@ func Login(c *gin.Context) {
})
return
}
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"message"
:
"请输入两步验证码"
,
"success"
:
true
,
...
...
@@ -87,7 +87,7 @@ func Login(c *gin.Context) {
})
return
}
setupLogin
(
&
user
,
c
)
}
...
...
controller/vendor_meta.go
View file @
1ea54eb2
package
controller
import
(
"strconv"
"strconv"
"one-api/common"
"one-api/model"
"one-api/common"
"one-api/model"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
// GetAllVendors 获取供应商列表(分页)
func
GetAllVendors
(
c
*
gin
.
Context
)
{
pageInfo
:=
common
.
GetPageQuery
(
c
)
vendors
,
err
:=
model
.
GetAllVendors
(
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
var
total
int64
model
.
DB
.
Model
(
&
model
.
Vendor
{})
.
Count
(
&
total
)
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
vendors
)
common
.
ApiSuccess
(
c
,
pageInfo
)
pageInfo
:=
common
.
GetPageQuery
(
c
)
vendors
,
err
:=
model
.
GetAllVendors
(
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
var
total
int64
model
.
DB
.
Model
(
&
model
.
Vendor
{})
.
Count
(
&
total
)
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
vendors
)
common
.
ApiSuccess
(
c
,
pageInfo
)
}
// SearchVendors 搜索供应商
func
SearchVendors
(
c
*
gin
.
Context
)
{
keyword
:=
c
.
Query
(
"keyword"
)
pageInfo
:=
common
.
GetPageQuery
(
c
)
vendors
,
total
,
err
:=
model
.
SearchVendors
(
keyword
,
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
vendors
)
common
.
ApiSuccess
(
c
,
pageInfo
)
keyword
:=
c
.
Query
(
"keyword"
)
pageInfo
:=
common
.
GetPageQuery
(
c
)
vendors
,
total
,
err
:=
model
.
SearchVendors
(
keyword
,
pageInfo
.
GetStartIdx
(),
pageInfo
.
GetPageSize
())
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
pageInfo
.
SetTotal
(
int
(
total
))
pageInfo
.
SetItems
(
vendors
)
common
.
ApiSuccess
(
c
,
pageInfo
)
}
// GetVendorMeta 根据 ID 获取供应商
func
GetVendorMeta
(
c
*
gin
.
Context
)
{
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
v
,
err
:=
model
.
GetVendorByID
(
id
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
v
)
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
v
,
err
:=
model
.
GetVendorByID
(
id
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
v
)
}
// CreateVendorMeta 新建供应商
func
CreateVendorMeta
(
c
*
gin
.
Context
)
{
var
v
model
.
Vendor
if
err
:=
c
.
ShouldBindJSON
(
&
v
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
v
.
Name
==
""
{
common
.
ApiErrorMsg
(
c
,
"供应商名称不能为空"
)
return
}
// 创建前先检查名称
if
dup
,
err
:=
model
.
IsVendorNameDuplicated
(
0
,
v
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"供应商名称已存在"
)
return
}
var
v
model
.
Vendor
if
err
:=
c
.
ShouldBindJSON
(
&
v
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
v
.
Name
==
""
{
common
.
ApiErrorMsg
(
c
,
"供应商名称不能为空"
)
return
}
// 创建前先检查名称
if
dup
,
err
:=
model
.
IsVendorNameDuplicated
(
0
,
v
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"供应商名称已存在"
)
return
}
if
err
:=
v
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
v
)
if
err
:=
v
.
Insert
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
v
)
}
// UpdateVendorMeta 更新供应商
func
UpdateVendorMeta
(
c
*
gin
.
Context
)
{
var
v
model
.
Vendor
if
err
:=
c
.
ShouldBindJSON
(
&
v
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
v
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少供应商 ID"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsVendorNameDuplicated
(
v
.
Id
,
v
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"供应商名称已存在"
)
return
}
var
v
model
.
Vendor
if
err
:=
c
.
ShouldBindJSON
(
&
v
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
v
.
Id
==
0
{
common
.
ApiErrorMsg
(
c
,
"缺少供应商 ID"
)
return
}
// 名称冲突检查
if
dup
,
err
:=
model
.
IsVendorNameDuplicated
(
v
.
Id
,
v
.
Name
);
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
else
if
dup
{
common
.
ApiErrorMsg
(
c
,
"供应商名称已存在"
)
return
}
if
err
:=
v
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
v
)
if
err
:=
v
.
Update
();
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
&
v
)
}
// DeleteVendorMeta 删除供应商
func
DeleteVendorMeta
(
c
*
gin
.
Context
)
{
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DB
.
Delete
(
&
model
.
Vendor
{},
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
nil
)
}
\ No newline at end of file
idStr
:=
c
.
Param
(
"id"
)
id
,
err
:=
strconv
.
Atoi
(
idStr
)
if
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
if
err
:=
model
.
DB
.
Delete
(
&
model
.
Vendor
{},
id
)
.
Error
;
err
!=
nil
{
common
.
ApiError
(
c
,
err
)
return
}
common
.
ApiSuccess
(
c
,
nil
)
}
model/missing_models.go
View file @
1ea54eb2
...
...
@@ -2,29 +2,29 @@ package model
// GetMissingModels returns model names that are referenced in the system
func
GetMissingModels
()
([]
string
,
error
)
{
// 1. 获取所有已启用模型(去重)
models
:=
GetEnabledModels
()
if
len
(
models
)
==
0
{
return
[]
string
{},
nil
}
// 1. 获取所有已启用模型(去重)
models
:=
GetEnabledModels
()
if
len
(
models
)
==
0
{
return
[]
string
{},
nil
}
// 2. 查询已有的元数据模型名
var
existing
[]
string
if
err
:=
DB
.
Model
(
&
Model
{})
.
Where
(
"model_name IN ?"
,
models
)
.
Pluck
(
"model_name"
,
&
existing
)
.
Error
;
err
!=
nil
{
return
nil
,
err
}
// 2. 查询已有的元数据模型名
var
existing
[]
string
if
err
:=
DB
.
Model
(
&
Model
{})
.
Where
(
"model_name IN ?"
,
models
)
.
Pluck
(
"model_name"
,
&
existing
)
.
Error
;
err
!=
nil
{
return
nil
,
err
}
existingSet
:=
make
(
map
[
string
]
struct
{},
len
(
existing
))
for
_
,
e
:=
range
existing
{
existingSet
[
e
]
=
struct
{}{}
}
existingSet
:=
make
(
map
[
string
]
struct
{},
len
(
existing
))
for
_
,
e
:=
range
existing
{
existingSet
[
e
]
=
struct
{}{}
}
// 3. 收集缺失模型
var
missing
[]
string
for
_
,
name
:=
range
models
{
if
_
,
ok
:=
existingSet
[
name
];
!
ok
{
missing
=
append
(
missing
,
name
)
}
}
return
missing
,
nil
// 3. 收集缺失模型
var
missing
[]
string
for
_
,
name
:=
range
models
{
if
_
,
ok
:=
existingSet
[
name
];
!
ok
{
missing
=
append
(
missing
,
name
)
}
}
return
missing
,
nil
}
model/model_extra.go
View file @
1ea54eb2
...
...
@@ -3,32 +3,32 @@ package model
// GetModelEnableGroups 返回指定模型名称可用的用户分组列表。
// 使用在 updatePricing() 中维护的缓存映射,O(1) 读取,适合高并发场景。
func
GetModelEnableGroups
(
modelName
string
)
[]
string
{
// 确保缓存最新
GetPricing
()
// 确保缓存最新
GetPricing
()
if
modelName
==
""
{
return
make
([]
string
,
0
)
}
if
modelName
==
""
{
return
make
([]
string
,
0
)
}
modelEnableGroupsLock
.
RLock
()
groups
,
ok
:=
modelEnableGroups
[
modelName
]
modelEnableGroupsLock
.
RUnlock
()
if
!
ok
{
return
make
([]
string
,
0
)
}
return
groups
modelEnableGroupsLock
.
RLock
()
groups
,
ok
:=
modelEnableGroups
[
modelName
]
modelEnableGroupsLock
.
RUnlock
()
if
!
ok
{
return
make
([]
string
,
0
)
}
return
groups
}
// GetModelQuotaType 返回指定模型的计费类型(quota_type)。
// 同样使用缓存映射,避免每次遍历定价切片。
func
GetModelQuotaType
(
modelName
string
)
int
{
GetPricing
()
GetPricing
()
modelEnableGroupsLock
.
RLock
()
quota
,
ok
:=
modelQuotaTypeMap
[
modelName
]
modelEnableGroupsLock
.
RUnlock
()
if
!
ok
{
return
0
}
return
quota
modelEnableGroupsLock
.
RLock
()
quota
,
ok
:=
modelQuotaTypeMap
[
modelName
]
modelEnableGroupsLock
.
RUnlock
()
if
!
ok
{
return
0
}
return
quota
}
model/model_meta.go
View file @
1ea54eb2
This diff is collapsed.
Click to expand it.
model/prefill_group.go
View file @
1ea54eb2
package
model
import
(
"encoding/json
"
"database/sql/driver
"
"one-api/common"
"database/sql/driver
"
"encoding/json
"
"one-api/common"
"gorm.io/gorm"
"gorm.io/gorm"
)
// PrefillGroup 用于存储可复用的“组”信息,例如模型组、标签组、端点组等。
...
...
@@ -20,107 +20,107 @@ type JSONValue json.RawMessage
// Value 实现 driver.Valuer 接口,用于数据库写入
func
(
j
JSONValue
)
Value
()
(
driver
.
Value
,
error
)
{
if
j
==
nil
{
return
nil
,
nil
}
return
[]
byte
(
j
),
nil
if
j
==
nil
{
return
nil
,
nil
}
return
[]
byte
(
j
),
nil
}
// Scan 实现 sql.Scanner 接口,兼容不同驱动返回的类型
func
(
j
*
JSONValue
)
Scan
(
value
interface
{})
error
{
switch
v
:=
value
.
(
type
)
{
case
nil
:
*
j
=
nil
return
nil
case
[]
byte
:
// 拷贝底层字节,避免保留底层缓冲区
b
:=
make
([]
byte
,
len
(
v
))
copy
(
b
,
v
)
*
j
=
JSONValue
(
b
)
return
nil
case
string
:
*
j
=
JSONValue
([]
byte
(
v
))
return
nil
default
:
// 其他类型尝试序列化为 JSON
b
,
err
:=
json
.
Marshal
(
v
)
if
err
!=
nil
{
return
err
}
*
j
=
JSONValue
(
b
)
return
nil
}
switch
v
:=
value
.
(
type
)
{
case
nil
:
*
j
=
nil
return
nil
case
[]
byte
:
// 拷贝底层字节,避免保留底层缓冲区
b
:=
make
([]
byte
,
len
(
v
))
copy
(
b
,
v
)
*
j
=
JSONValue
(
b
)
return
nil
case
string
:
*
j
=
JSONValue
([]
byte
(
v
))
return
nil
default
:
// 其他类型尝试序列化为 JSON
b
,
err
:=
json
.
Marshal
(
v
)
if
err
!=
nil
{
return
err
}
*
j
=
JSONValue
(
b
)
return
nil
}
}
// MarshalJSON 确保在对外编码时与 json.RawMessage 行为一致
func
(
j
JSONValue
)
MarshalJSON
()
([]
byte
,
error
)
{
if
j
==
nil
{
return
[]
byte
(
"null"
),
nil
}
return
j
,
nil
if
j
==
nil
{
return
[]
byte
(
"null"
),
nil
}
return
j
,
nil
}
// UnmarshalJSON 确保在对外解码时与 json.RawMessage 行为一致
func
(
j
*
JSONValue
)
UnmarshalJSON
(
data
[]
byte
)
error
{
if
data
==
nil
{
*
j
=
nil
return
nil
}
b
:=
make
([]
byte
,
len
(
data
))
copy
(
b
,
data
)
*
j
=
JSONValue
(
b
)
return
nil
if
data
==
nil
{
*
j
=
nil
return
nil
}
b
:=
make
([]
byte
,
len
(
data
))
copy
(
b
,
data
)
*
j
=
JSONValue
(
b
)
return
nil
}
type
PrefillGroup
struct
{
Id
int
`json:"id"`
Name
string
`json:"name" gorm:"size:64;not null;uniqueIndex:uk_prefill_name,where:deleted_at IS NULL"`
Type
string
`json:"type" gorm:"size:32;index;not null"`
Items
JSONValue
`json:"items" gorm:"type:json"`
Description
string
`json:"description,omitempty" gorm:"type:varchar(255)"`
CreatedTime
int64
`json:"created_time" gorm:"bigint"`
UpdatedTime
int64
`json:"updated_time" gorm:"bigint"`
DeletedAt
gorm
.
DeletedAt
`json:"-" gorm:"index"`
Id
int
`json:"id"`
Name
string
`json:"name" gorm:"size:64;not null;uniqueIndex:uk_prefill_name,where:deleted_at IS NULL"`
Type
string
`json:"type" gorm:"size:32;index;not null"`
Items
JSONValue
`json:"items" gorm:"type:json"`
Description
string
`json:"description,omitempty" gorm:"type:varchar(255)"`
CreatedTime
int64
`json:"created_time" gorm:"bigint"`
UpdatedTime
int64
`json:"updated_time" gorm:"bigint"`
DeletedAt
gorm
.
DeletedAt
`json:"-" gorm:"index"`
}
// Insert 新建组
func
(
g
*
PrefillGroup
)
Insert
()
error
{
now
:=
common
.
GetTimestamp
()
g
.
CreatedTime
=
now
g
.
UpdatedTime
=
now
return
DB
.
Create
(
g
)
.
Error
now
:=
common
.
GetTimestamp
()
g
.
CreatedTime
=
now
g
.
UpdatedTime
=
now
return
DB
.
Create
(
g
)
.
Error
}
// IsPrefillGroupNameDuplicated 检查组名称是否重复(排除自身 ID)
func
IsPrefillGroupNameDuplicated
(
id
int
,
name
string
)
(
bool
,
error
)
{
if
name
==
""
{
return
false
,
nil
}
var
cnt
int64
err
:=
DB
.
Model
(
&
PrefillGroup
{})
.
Where
(
"name = ? AND id <> ?"
,
name
,
id
)
.
Count
(
&
cnt
)
.
Error
return
cnt
>
0
,
err
if
name
==
""
{
return
false
,
nil
}
var
cnt
int64
err
:=
DB
.
Model
(
&
PrefillGroup
{})
.
Where
(
"name = ? AND id <> ?"
,
name
,
id
)
.
Count
(
&
cnt
)
.
Error
return
cnt
>
0
,
err
}
// Update 更新组
func
(
g
*
PrefillGroup
)
Update
()
error
{
g
.
UpdatedTime
=
common
.
GetTimestamp
()
return
DB
.
Save
(
g
)
.
Error
g
.
UpdatedTime
=
common
.
GetTimestamp
()
return
DB
.
Save
(
g
)
.
Error
}
// DeleteByID 根据 ID 删除组
func
DeletePrefillGroupByID
(
id
int
)
error
{
return
DB
.
Delete
(
&
PrefillGroup
{},
id
)
.
Error
return
DB
.
Delete
(
&
PrefillGroup
{},
id
)
.
Error
}
// GetAllPrefillGroups 获取全部组,可按类型过滤(为空则返回全部)
func
GetAllPrefillGroups
(
groupType
string
)
([]
*
PrefillGroup
,
error
)
{
var
groups
[]
*
PrefillGroup
query
:=
DB
.
Model
(
&
PrefillGroup
{})
if
groupType
!=
""
{
query
=
query
.
Where
(
"type = ?"
,
groupType
)
}
if
err
:=
query
.
Order
(
"updated_time DESC"
)
.
Find
(
&
groups
)
.
Error
;
err
!=
nil
{
return
nil
,
err
}
return
groups
,
nil
var
groups
[]
*
PrefillGroup
query
:=
DB
.
Model
(
&
PrefillGroup
{})
if
groupType
!=
""
{
query
=
query
.
Where
(
"type = ?"
,
groupType
)
}
if
err
:=
query
.
Order
(
"updated_time DESC"
)
.
Find
(
&
groups
)
.
Error
;
err
!=
nil
{
return
nil
,
err
}
return
groups
,
nil
}
model/pricing.go
View file @
1ea54eb2
This diff is collapsed.
Click to expand it.
model/pricing_refresh.go
View file @
1ea54eb2
...
...
@@ -4,11 +4,11 @@ package model
// 该方法用于需要最新数据的内部管理 API,
// 因此会绕过默认的 1 分钟延迟刷新。
func
RefreshPricing
()
{
updatePricingLock
.
Lock
()
defer
updatePricingLock
.
Unlock
()
updatePricingLock
.
Lock
()
defer
updatePricingLock
.
Unlock
()
modelSupportEndpointsLock
.
Lock
()
defer
modelSupportEndpointsLock
.
Unlock
()
modelSupportEndpointsLock
.
Lock
()
defer
modelSupportEndpointsLock
.
Unlock
()
updatePricing
()
updatePricing
()
}
model/vendor_meta.go
View file @
1ea54eb2
package
model
import
(
"one-api/common"
"one-api/common"
"gorm.io/gorm"
"gorm.io/gorm"
)
// Vendor 用于存储供应商信息,供模型引用
...
...
@@ -13,76 +13,76 @@ import (
// 本表同样遵循 3NF 设计范式
type
Vendor
struct
{
Id
int
`json:"id"`
Name
string
`json:"name" gorm:"size:128;not null;uniqueIndex:uk_vendor_name,priority:1"`
Description
string
`json:"description,omitempty" gorm:"type:text"`
Icon
string
`json:"icon,omitempty" gorm:"type:varchar(128)"`
Status
int
`json:"status" gorm:"default:1"`
CreatedTime
int64
`json:"created_time" gorm:"bigint"`
UpdatedTime
int64
`json:"updated_time" gorm:"bigint"`
DeletedAt
gorm
.
DeletedAt
`json:"-" gorm:"index;uniqueIndex:uk_vendor_name,priority:2"`
Id
int
`json:"id"`
Name
string
`json:"name" gorm:"size:128;not null;uniqueIndex:uk_vendor_name,priority:1"`
Description
string
`json:"description,omitempty" gorm:"type:text"`
Icon
string
`json:"icon,omitempty" gorm:"type:varchar(128)"`
Status
int
`json:"status" gorm:"default:1"`
CreatedTime
int64
`json:"created_time" gorm:"bigint"`
UpdatedTime
int64
`json:"updated_time" gorm:"bigint"`
DeletedAt
gorm
.
DeletedAt
`json:"-" gorm:"index;uniqueIndex:uk_vendor_name,priority:2"`
}
// Insert 创建新的供应商记录
func
(
v
*
Vendor
)
Insert
()
error
{
now
:=
common
.
GetTimestamp
()
v
.
CreatedTime
=
now
v
.
UpdatedTime
=
now
return
DB
.
Create
(
v
)
.
Error
now
:=
common
.
GetTimestamp
()
v
.
CreatedTime
=
now
v
.
UpdatedTime
=
now
return
DB
.
Create
(
v
)
.
Error
}
// IsVendorNameDuplicated 检查供应商名称是否重复(排除自身 ID)
func
IsVendorNameDuplicated
(
id
int
,
name
string
)
(
bool
,
error
)
{
if
name
==
""
{
return
false
,
nil
}
var
cnt
int64
err
:=
DB
.
Model
(
&
Vendor
{})
.
Where
(
"name = ? AND id <> ?"
,
name
,
id
)
.
Count
(
&
cnt
)
.
Error
return
cnt
>
0
,
err
if
name
==
""
{
return
false
,
nil
}
var
cnt
int64
err
:=
DB
.
Model
(
&
Vendor
{})
.
Where
(
"name = ? AND id <> ?"
,
name
,
id
)
.
Count
(
&
cnt
)
.
Error
return
cnt
>
0
,
err
}
// Update 更新供应商记录
func
(
v
*
Vendor
)
Update
()
error
{
v
.
UpdatedTime
=
common
.
GetTimestamp
()
return
DB
.
Save
(
v
)
.
Error
v
.
UpdatedTime
=
common
.
GetTimestamp
()
return
DB
.
Save
(
v
)
.
Error
}
// Delete 软删除供应商
func
(
v
*
Vendor
)
Delete
()
error
{
return
DB
.
Delete
(
v
)
.
Error
return
DB
.
Delete
(
v
)
.
Error
}
// GetVendorByID 根据 ID 获取供应商
func
GetVendorByID
(
id
int
)
(
*
Vendor
,
error
)
{
var
v
Vendor
err
:=
DB
.
First
(
&
v
,
id
)
.
Error
if
err
!=
nil
{
return
nil
,
err
}
return
&
v
,
nil
var
v
Vendor
err
:=
DB
.
First
(
&
v
,
id
)
.
Error
if
err
!=
nil
{
return
nil
,
err
}
return
&
v
,
nil
}
// GetAllVendors 获取全部供应商(分页)
func
GetAllVendors
(
offset
int
,
limit
int
)
([]
*
Vendor
,
error
)
{
var
vendors
[]
*
Vendor
err
:=
DB
.
Offset
(
offset
)
.
Limit
(
limit
)
.
Find
(
&
vendors
)
.
Error
return
vendors
,
err
var
vendors
[]
*
Vendor
err
:=
DB
.
Offset
(
offset
)
.
Limit
(
limit
)
.
Find
(
&
vendors
)
.
Error
return
vendors
,
err
}
// SearchVendors 按关键字搜索供应商
func
SearchVendors
(
keyword
string
,
offset
int
,
limit
int
)
([]
*
Vendor
,
int64
,
error
)
{
db
:=
DB
.
Model
(
&
Vendor
{})
if
keyword
!=
""
{
like
:=
"%"
+
keyword
+
"%"
db
=
db
.
Where
(
"name LIKE ? OR description LIKE ?"
,
like
,
like
)
}
var
total
int64
if
err
:=
db
.
Count
(
&
total
)
.
Error
;
err
!=
nil
{
return
nil
,
0
,
err
}
var
vendors
[]
*
Vendor
if
err
:=
db
.
Offset
(
offset
)
.
Limit
(
limit
)
.
Order
(
"id DESC"
)
.
Find
(
&
vendors
)
.
Error
;
err
!=
nil
{
return
nil
,
0
,
err
}
return
vendors
,
total
,
nil
}
\ No newline at end of file
db
:=
DB
.
Model
(
&
Vendor
{})
if
keyword
!=
""
{
like
:=
"%"
+
keyword
+
"%"
db
=
db
.
Where
(
"name LIKE ? OR description LIKE ?"
,
like
,
like
)
}
var
total
int64
if
err
:=
db
.
Count
(
&
total
)
.
Error
;
err
!=
nil
{
return
nil
,
0
,
err
}
var
vendors
[]
*
Vendor
if
err
:=
db
.
Offset
(
offset
)
.
Limit
(
limit
)
.
Order
(
"id DESC"
)
.
Find
(
&
vendors
)
.
Error
;
err
!=
nil
{
return
nil
,
0
,
err
}
return
vendors
,
total
,
nil
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment