204 lines
6.0 KiB
Go
204 lines
6.0 KiB
Go
// Copyright 2024 The Devstar Authors. All rights reserved.
|
||
// SPDX-License-Identifier: MIT
|
||
|
||
package appstore
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"code.gitea.io/gitea/models/db"
|
||
"code.gitea.io/gitea/modules/timeutil"
|
||
)
|
||
|
||
// AppStore represents an application in the app store
|
||
type AppStore struct {
|
||
ID int64 `xorm:"pk autoincr"`
|
||
AppID string `xorm:"UNIQUE NOT NULL"` // 应用唯一标识,如 "nginx"
|
||
Name string `xorm:"NOT NULL"` // 应用名称,如 "Nginx Web Server"
|
||
Description string `xorm:"TEXT"` // 应用描述
|
||
Category string `xorm:"INDEX"` // 应用分类,如 "web-server"
|
||
Tags string `xorm:"TEXT"` // 标签,JSON格式存储
|
||
Icon string `xorm:"VARCHAR(2048)"` // 应用图标URL
|
||
Author string `xorm:"VARCHAR(128)"` // 应用作者
|
||
Website string `xorm:"VARCHAR(2048)"` // 应用官网
|
||
Repository string `xorm:"VARCHAR(2048)"` // 应用仓库地址
|
||
License string `xorm:"VARCHAR(64)"` // 许可证类型
|
||
Version string `xorm:"NOT NULL"` // 应用版本
|
||
DeploymentType string `xorm:"VARCHAR(20) NOT NULL DEFAULT 'docker' INDEX"` // 部署类型:docker, kubernetes, both
|
||
JSONData string `xorm:"LONGTEXT NOT NULL"` // 完整的应用JSON描述
|
||
|
||
// 统计信息
|
||
InstallCount int64 `xorm:"NOT NULL DEFAULT 0"` // 安装次数
|
||
|
||
// 状态
|
||
IsActive bool `xorm:"INDEX NOT NULL DEFAULT true"` // 是否激活
|
||
IsOfficial bool `xorm:"NOT NULL DEFAULT false"` // 是否官方应用
|
||
IsVerified bool `xorm:"NOT NULL DEFAULT false"` // 是否已验证
|
||
|
||
// 时间戳
|
||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||
}
|
||
|
||
// TableName returns the table name for AppStore
|
||
func (a *AppStore) TableName() string {
|
||
return "app_store"
|
||
}
|
||
|
||
// BeforeUpdate is called before updating the record
|
||
func (a *AppStore) BeforeUpdate() {
|
||
a.UpdatedUnix = timeutil.TimeStampNow()
|
||
}
|
||
|
||
// BeforeInsert is called before inserting the record
|
||
func (a *AppStore) BeforeInsert() {
|
||
a.CreatedUnix = timeutil.TimeStampNow()
|
||
a.UpdatedUnix = timeutil.TimeStampNow()
|
||
}
|
||
|
||
// GetTagsList returns the tags as a string slice
|
||
func (a *AppStore) GetTagsList() []string {
|
||
if a.Tags == "" {
|
||
return []string{}
|
||
}
|
||
return strings.Split(a.Tags, ",")
|
||
}
|
||
|
||
// SetTagsList sets the tags from a string slice
|
||
func (a *AppStore) SetTagsList(tags []string) {
|
||
a.Tags = strings.Join(tags, ",")
|
||
}
|
||
|
||
// 数据库操作函数
|
||
|
||
// GetAppStoreByID 根据ID获取应用商店记录
|
||
func GetAppStoreByID(ctx context.Context, id int64) (*AppStore, error) {
|
||
app := &AppStore{}
|
||
has, err := db.GetEngine(ctx).ID(id).Get(app)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if !has {
|
||
return nil, fmt.Errorf("app store not found: %d", id)
|
||
}
|
||
return app, nil
|
||
}
|
||
|
||
// GetAppStoreByAppID 根据AppID获取应用商店记录
|
||
func GetAppStoreByAppID(ctx context.Context, appID string) (*AppStore, error) {
|
||
app := &AppStore{}
|
||
has, err := db.GetEngine(ctx).Where("app_id = ?", appID).Get(app)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if !has {
|
||
return nil, fmt.Errorf("app store not found: %s", appID)
|
||
}
|
||
return app, nil
|
||
}
|
||
|
||
// GetAppStoreByName 根据应用名称获取应用商店记录
|
||
func GetAppStoreByName(ctx context.Context, name string) (*AppStore, error) {
|
||
app := &AppStore{}
|
||
has, err := db.GetEngine(ctx).Where("name = ?", name).Get(app)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if !has {
|
||
return nil, fmt.Errorf("app store not found: %s", name)
|
||
}
|
||
return app, nil
|
||
}
|
||
|
||
// ListAppStores 列出应用商店记录
|
||
func ListAppStores(ctx context.Context, opts *db.ListOptions) ([]*AppStore, error) {
|
||
var apps []*AppStore
|
||
sess := db.GetEngine(ctx).Where("is_active = ?", true)
|
||
|
||
if opts != nil {
|
||
sess = db.SetSessionPagination(sess, opts)
|
||
}
|
||
|
||
err := sess.OrderBy("created_unix DESC").Find(&apps)
|
||
return apps, err
|
||
}
|
||
|
||
// CreateAppStore 创建应用商店记录
|
||
func CreateAppStore(ctx context.Context, app *AppStore) error {
|
||
// 检查AppID是否已存在
|
||
has, err := db.GetEngine(ctx).Where("app_id = ?", app.AppID).Exist(&AppStore{})
|
||
if err != nil {
|
||
return err
|
||
}
|
||
if has {
|
||
return fmt.Errorf("app store already exists: %s", app.AppID)
|
||
}
|
||
|
||
_, err = db.GetEngine(ctx).Insert(app)
|
||
return err
|
||
}
|
||
|
||
// UpdateAppStore 更新应用商店记录
|
||
func UpdateAppStore(ctx context.Context, app *AppStore) error {
|
||
_, err := db.GetEngine(ctx).ID(app.ID).Update(app)
|
||
return err
|
||
}
|
||
|
||
// DeleteAppStore 删除应用商店记录
|
||
func DeleteAppStore(ctx context.Context, id int64) error {
|
||
_, err := db.GetEngine(ctx).ID(id).Delete(&AppStore{})
|
||
return err
|
||
}
|
||
|
||
// GetCategories 获取所有应用分类
|
||
func GetCategories(ctx context.Context) ([]string, error) {
|
||
var categories []string
|
||
err := db.GetEngine(ctx).Table("app_store").
|
||
Where("is_active = ?", true).
|
||
Distinct("category").
|
||
Cols("category").
|
||
Find(&categories)
|
||
return categories, err
|
||
}
|
||
|
||
// GetTags 获取所有应用标签
|
||
func GetTags(ctx context.Context) ([]string, error) {
|
||
var tags []string
|
||
if err := db.GetEngine(ctx).Table("app_store").
|
||
Where("is_active = ? AND tags != ''", true).
|
||
Cols("tags").
|
||
Find(&tags); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 解析标签字符串并去重
|
||
tagSet := make(map[string]bool)
|
||
for _, tagStr := range tags {
|
||
tagList := strings.Split(tagStr, ",")
|
||
for _, tag := range tagList {
|
||
if tag != "" {
|
||
tagSet[tag] = true
|
||
}
|
||
}
|
||
}
|
||
|
||
result := make([]string, 0, len(tagSet))
|
||
for tag := range tagSet {
|
||
result = append(result, tag)
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// IncrementInstallCount 增加安装次数
|
||
func IncrementInstallCount(ctx context.Context, appID string) error {
|
||
_, err := db.GetEngine(ctx).Exec("UPDATE app_store SET install_count = install_count + 1 WHERE app_id = ?", appID)
|
||
return err
|
||
}
|
||
|
||
func init() {
|
||
db.RegisterModel(new(AppStore))
|
||
}
|