feat: admin api
This commit is contained in:
parent
503a4adba9
commit
ca93be0371
|
|
@ -0,0 +1,61 @@
|
||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"twin-api/app/admin/request"
|
||||||
|
"twin-api/app/admin/service"
|
||||||
|
"twin-api/base/config"
|
||||||
|
|
||||||
|
"git.u8t.cn/open/go-server/session"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pkg struct{}
|
||||||
|
|
||||||
|
func (pkg *Pkg) Query(ctx *gin.Context) {
|
||||||
|
var req request.PkgGet
|
||||||
|
if err := ctx.ShouldBind(&req); err != nil {
|
||||||
|
panic(config.ErrParam.New().Append(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
count, res, err := service.NewPkg().Query(&req)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, session.NewListRsp(count, res))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkg *Pkg) Create(ctx *gin.Context) {
|
||||||
|
var req request.PkgCreate
|
||||||
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
|
panic(config.ErrParam.New().Append(err))
|
||||||
|
}
|
||||||
|
if err := service.NewPkg().Create(&req); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, session.NewRspOk())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkg *Pkg) Update(ctx *gin.Context) {
|
||||||
|
var req request.PkgPut
|
||||||
|
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||||
|
panic(config.ErrParam.New().Append(err))
|
||||||
|
}
|
||||||
|
if err := service.NewPkg().Update(&req); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, session.NewRspOk())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pkg *Pkg) Delete(ctx *gin.Context) {
|
||||||
|
var req request.PkgDelete
|
||||||
|
if err := ctx.ShouldBind(&req); err != nil {
|
||||||
|
panic(config.ErrParam.New().Append(err))
|
||||||
|
}
|
||||||
|
if err := service.NewPkg().Delete(cast.ToInt64(strings.TrimSpace(req.Id))); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, session.NewRspOk())
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package request
|
||||||
|
|
||||||
|
import "github.com/spf13/cast"
|
||||||
|
|
||||||
|
const MaxPageSize = 100
|
||||||
|
|
||||||
|
type PkgGet struct {
|
||||||
|
Page string `form:"page" json:"page"`
|
||||||
|
Size string `form:"size" json:"size"`
|
||||||
|
Sort string `form:"sort" json:"sort"`
|
||||||
|
Name string `form:"name" json:"name"`
|
||||||
|
Version string `form:"version" json:"version"`
|
||||||
|
Status string `form:"status" json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PkgPut struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Expire string `json:"expire"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PkgDelete struct {
|
||||||
|
Id string `form:"id" json:"id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PkgCreate struct {
|
||||||
|
Name string `json:"package_name"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Expire string `json:"expire"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PkgGet) Default() {
|
||||||
|
if cast.ToInt(r.Size) == 0 {
|
||||||
|
r.Size = "10"
|
||||||
|
}
|
||||||
|
if cast.ToInt(r.Page) <= 0 {
|
||||||
|
r.Page = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PkgGet) PageInt() int {
|
||||||
|
return cast.ToInt(r.Page)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *PkgGet) SizeInt() int {
|
||||||
|
size := cast.ToInt(r.Size)
|
||||||
|
if size > MaxPageSize {
|
||||||
|
return MaxPageSize
|
||||||
|
}
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
@ -3,9 +3,11 @@ package dao
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
"twin-api/app/common/model"
|
"twin-api/app/common/model"
|
||||||
"twin-api/base/global"
|
"twin-api/base/global"
|
||||||
|
|
||||||
|
"git.u8t.cn/open/go-server/utils"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -31,8 +33,15 @@ func (p *Pkg) Update(m *model.Pkg) error {
|
||||||
return p.db.Table(p.TableName()).Save(m).Error
|
return p.db.Table(p.TableName()).Save(m).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pkg) UpdateCols(m *model.Pkg, cols ...string) error {
|
||||||
|
return p.db.Table(p.TableName()).Select(cols).Updates(m).Error
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pkg) Delete(m *model.Pkg) error {
|
func (p *Pkg) Delete(m *model.Pkg) error {
|
||||||
return p.db.Table(p.TableName()).Where("id = ?", m.Id).Update("status", model.PkgDelete).Error
|
return p.db.Table(p.TableName()).Where("id = ?", m.Id).Updates(map[string]any{
|
||||||
|
"status": model.PkgDelete,
|
||||||
|
"update_time": time.Now().Unix(),
|
||||||
|
}).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pkg) Get(id int64) (*model.Pkg, error) {
|
func (p *Pkg) Get(id int64) (*model.Pkg, error) {
|
||||||
|
|
@ -47,13 +56,24 @@ func (p *Pkg) Get(id int64) (*model.Pkg, error) {
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pkg) GetById(id int64) (*model.Pkg, error) {
|
||||||
|
var res model.Pkg
|
||||||
|
if err := p.db.Table(p.TableName()).Where("id = ?", id).First(&res).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pkg) GetByPkgName(name string) (*model.Pkg, error) {
|
func (p *Pkg) GetByPkgName(name string) (*model.Pkg, error) {
|
||||||
var res model.Pkg
|
var res model.Pkg
|
||||||
tx := p.db.Table(p.TableName()).Where("status = ?", model.PkgNormal)
|
tx := p.db.Table(p.TableName()).Where("status = ?", model.PkgNormal)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
tx = tx.Where("name = ?", name)
|
tx = tx.Where("name = ?", name)
|
||||||
}
|
}
|
||||||
tx.Order("id desc")
|
tx = tx.Order("id desc")
|
||||||
if err := tx.First(&res).Error; err != nil {
|
if err := tx.First(&res).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
@ -63,6 +83,36 @@ func (p *Pkg) GetByPkgName(name string) (*model.Pkg, error) {
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Pkg) GetLatestByName(name string) (*model.Pkg, error) {
|
||||||
|
var list []*model.Pkg
|
||||||
|
if err := p.db.Table(p.TableName()).Where("name = ? AND status = ?", name, model.PkgNormal).Find(&list).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(list) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
latest := list[0]
|
||||||
|
latestVal := utils.VersionToInt(latest.Version)
|
||||||
|
for _, item := range list[1:] {
|
||||||
|
if v := utils.VersionToInt(item.Version); v > latestVal {
|
||||||
|
latest = item
|
||||||
|
latestVal = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return latest, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pkg) GetByNameVersion(name, version string) (*model.Pkg, error) {
|
||||||
|
var res model.Pkg
|
||||||
|
if err := p.db.Table(p.TableName()).Where("name = ? AND version = ?", name, version).First(&res).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Pkg) GetOne(name, version string) (*model.Pkg, error) {
|
func (p *Pkg) GetOne(name, version string) (*model.Pkg, error) {
|
||||||
var res model.Pkg
|
var res model.Pkg
|
||||||
tx := p.db.Table(p.TableName()).Where("status = ?", model.PkgNormal)
|
tx := p.db.Table(p.TableName()).Where("status = ?", model.PkgNormal)
|
||||||
|
|
@ -70,7 +120,7 @@ func (p *Pkg) GetOne(name, version string) (*model.Pkg, error) {
|
||||||
tx = tx.Where("name = ? AND version = ?", name, version)
|
tx = tx.Where("name = ? AND version = ?", name, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.Order("id desc")
|
tx = tx.Order("id desc")
|
||||||
if err := tx.First(&res).Error; err != nil {
|
if err := tx.First(&res).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,29 @@ func (p *UserPkg) GetLatest(userId int64) (*model.UserPkgInfo, error) {
|
||||||
return &res, nil
|
return &res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *UserPkg) CountByPackageIds(packageIds []int64) (map[int64]int64, error) {
|
||||||
|
res := make(map[int64]int64)
|
||||||
|
if len(packageIds) == 0 {
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
type countResult struct {
|
||||||
|
PackageId int64 `gorm:"column:package_id"`
|
||||||
|
Count int64 `gorm:"column:count"`
|
||||||
|
}
|
||||||
|
var rows []countResult
|
||||||
|
if err := p.db.Table(p.TableName()).
|
||||||
|
Select("package_id, count(*) as count").
|
||||||
|
Where("package_id IN ?", packageIds).
|
||||||
|
Group("package_id").
|
||||||
|
Find(&rows).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, row := range rows {
|
||||||
|
res[row.PackageId] = row.Count
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *UserPkg) Query(...any) (any, error) {
|
func (p *UserPkg) Query(...any) (any, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
gsUtils "git.u8t.cn/open/go-server/utils"
|
||||||
|
"github.com/spf13/cast"
|
||||||
|
)
|
||||||
|
|
||||||
type Pkg struct {
|
type Pkg struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
ExpireTime int64 `json:"expire_time"`
|
ExpireTime int64 `json:"expire_time"`
|
||||||
|
|
@ -15,3 +23,51 @@ const (
|
||||||
PkgNormal = 1
|
PkgNormal = 1
|
||||||
PkgDelete = 2
|
PkgDelete = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (p *Pkg) Format() map[string]any {
|
||||||
|
res := make(map[string]any)
|
||||||
|
res["id"] = p.Id
|
||||||
|
res["name"] = p.Name
|
||||||
|
res["version"] = p.Version
|
||||||
|
res["link"] = p.Link
|
||||||
|
res["status"] = p.Status
|
||||||
|
res["expire"] = gsUtils.TimeToDateTime(p.ExpireTime)
|
||||||
|
res["create_date"] = gsUtils.TimeToDateTime(p.CreateTime)
|
||||||
|
res["update_date"] = gsUtils.TimeToDateTime(p.UpdateTime)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Pkg) FormatAdmin(userCount int64) map[string]any {
|
||||||
|
res := p.Format()
|
||||||
|
res["user_count"] = userCount
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseExpire(expire string) (int64, error) {
|
||||||
|
expire = strings.TrimSpace(expire)
|
||||||
|
if expire == "" {
|
||||||
|
return 0, fmt.Errorf("expire is required")
|
||||||
|
}
|
||||||
|
if isUnixTimestamp(expire) {
|
||||||
|
return cast.ToInt64(expire), nil
|
||||||
|
}
|
||||||
|
if ts := gsUtils.DateTimeToTime(expire); ts > 0 {
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
if ts := gsUtils.DateToTime(expire); ts > 0 {
|
||||||
|
return ts, nil
|
||||||
|
}
|
||||||
|
return 0, fmt.Errorf("invalid expire format, supports timestamp or date")
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUnixTimestamp(s string) bool {
|
||||||
|
if len(s) < 10 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
if c < '0' || c > '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cast.ToInt64(s) > 1e9
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@ package routers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
adminController "twin-api/app/admin/controller"
|
||||||
"twin-api/app/api/controller"
|
"twin-api/app/api/controller"
|
||||||
"twin-api/app/common/middle"
|
"twin-api/app/common/middle"
|
||||||
|
|
||||||
gsController "git.u8t.cn/open/go-server/api/controller"
|
gsAdminController "git.u8t.cn/open/go-server/admin/controller"
|
||||||
|
gsApiController "git.u8t.cn/open/go-server/api/controller"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -20,7 +22,7 @@ func InitRouter(engine *gin.Engine) {
|
||||||
|
|
||||||
// 客户端接口路由
|
// 客户端接口路由
|
||||||
func initApiRouter(engine *gin.Engine) {
|
func initApiRouter(engine *gin.Engine) {
|
||||||
base := new(gsController.BaseController)
|
base := new(gsApiController.BaseController)
|
||||||
userGroup := engine.Group("/api/user").Use(base.Recovery).Use(base.Before).Use(base.Token).Use(base.IpLimit).Use(base.Response).Use(middle.UserPkg)
|
userGroup := engine.Group("/api/user").Use(base.Recovery).Use(base.Before).Use(base.Token).Use(base.IpLimit).Use(base.Response).Use(middle.UserPkg)
|
||||||
|
|
||||||
userApi := new(controller.User)
|
userApi := new(controller.User)
|
||||||
|
|
@ -29,4 +31,13 @@ func initApiRouter(engine *gin.Engine) {
|
||||||
|
|
||||||
// 管理接口路由
|
// 管理接口路由
|
||||||
func initAdminRouter(engine *gin.Engine) {
|
func initAdminRouter(engine *gin.Engine) {
|
||||||
|
base := new(gsAdminController.BaseController)
|
||||||
|
adminGroup := engine.Group("/admin")
|
||||||
|
adminGroup.Use(base.Recovery).Use(base.Before).Use(base.Token)
|
||||||
|
|
||||||
|
pkgApi := new(adminController.Pkg)
|
||||||
|
adminGroup.GET("/package", pkgApi.Query)
|
||||||
|
adminGroup.POST("/package", pkgApi.Create)
|
||||||
|
adminGroup.PUT("/package", pkgApi.Update)
|
||||||
|
adminGroup.DELETE("/package", pkgApi.Delete)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue