带阿里标识的版本

This commit is contained in:
robin
2026-02-28 18:55:33 +08:00
parent 150799f41d
commit 5d0b7c7e91
477 changed files with 10813 additions and 4044 deletions

View File

@@ -6,8 +6,10 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
"github.com/TeaOSLab/EdgeCommon/pkg/systemconfigs"
"github.com/iwind/TeaGo/actions"
"github.com/iwind/TeaGo/maps"
"github.com/iwind/TeaGo/types"
)
type AppSettingsAction struct {
@@ -52,30 +54,83 @@ func (this *AppSettingsAction) RunGet(params struct {
},
}
clusterResp, err := this.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(this.AdminContext(), &pb.FindAllHTTPDNSClustersRequest{})
if err != nil {
this.ErrorPage(err)
return
}
clusters := make([]maps.Map, 0, len(clusterResp.GetClusters()))
clusterDomainMap := map[int64]string{}
clusterNameMap := map[int64]string{}
defaultPrimaryClusterId := int64(0)
for _, cluster := range clusterResp.GetClusters() {
clusterId := cluster.GetId()
clusterName := cluster.GetName()
clusters = append(clusters, maps.Map{
"id": clusterId,
"name": clusterName,
"serviceDomain": cluster.GetServiceDomain(),
"isDefault": cluster.GetIsDefault(),
})
clusterDomainMap[clusterId] = cluster.GetServiceDomain()
clusterNameMap[clusterId] = clusterName
if defaultPrimaryClusterId <= 0 && cluster.GetIsDefault() {
defaultPrimaryClusterId = clusterId
}
}
defaultBackupClusterId := int64(0)
defaultBackupResp, err := this.RPC().SysSettingRPC().ReadSysSetting(this.AdminContext(), &pb.ReadSysSettingRequest{
Code: string(systemconfigs.SettingCodeHTTPDNSDefaultBackupClusterId),
})
if err != nil {
this.ErrorPage(err)
return
}
if defaultBackupResp != nil && len(defaultBackupResp.GetValueJSON()) > 0 {
defaultBackupClusterId = types.Int64(string(defaultBackupResp.GetValueJSON()))
}
primaryClusterId := app.GetInt64("primaryClusterId")
backupClusterId := app.GetInt64("backupClusterId")
settings := maps.Map{
"appId": app.GetString("appId"),
"appStatus": app.GetBool("isOn"),
"primaryClusterId": app.GetInt64("primaryClusterId"),
"backupClusterId": app.GetInt64("backupClusterId"),
"signEnabled": app.GetBool("signEnabled"),
"signSecretPlain": app.GetString("signSecretPlain"),
"signSecretMasked": app.GetString("signSecretMasked"),
"signSecretUpdatedAt": app.GetString("signSecretUpdated"),
"appId": app.GetString("appId"),
"appStatus": app.GetBool("isOn"),
"primaryClusterId": primaryClusterId,
"backupClusterId": backupClusterId,
"defaultPrimaryClusterId": defaultPrimaryClusterId,
"defaultPrimaryClusterName": clusterNameMap[defaultPrimaryClusterId],
"defaultBackupClusterId": defaultBackupClusterId,
"defaultBackupClusterName": clusterNameMap[defaultBackupClusterId],
"primaryServiceDomain": clusterDomainMap[primaryClusterId],
"backupServiceDomain": clusterDomainMap[backupClusterId],
"signEnabled": app.GetBool("signEnabled"),
"signSecretPlain": app.GetString("signSecretPlain"),
"signSecretMasked": app.GetString("signSecretMasked"),
"signSecretUpdatedAt": app.GetString("signSecretUpdated"),
}
this.Data["app"] = app
this.Data["settings"] = settings
this.Data["clusters"] = clusters
this.Show()
}
func (this *AppSettingsAction) RunPost(params struct {
AppId int64
AppStatus bool
AppStatus bool
PrimaryClusterId int64
BackupClusterId int64
Must *actions.Must
CSRF *actionutils.CSRF
}) {
params.Must.Field("appId", params.AppId).Gt(0, "请选择应用")
if params.PrimaryClusterId > 0 && params.BackupClusterId > 0 && params.PrimaryClusterId == params.BackupClusterId {
this.FailField("backupClusterId", "备用集群不能与主集群相同")
return
}
appResp, err := this.RPC().HTTPDNSAppRPC().FindHTTPDNSApp(this.AdminContext(), &pb.FindHTTPDNSAppRequest{
AppDbId: params.AppId,
@@ -92,8 +147,8 @@ func (this *AppSettingsAction) RunPost(params struct {
_, err = this.RPC().HTTPDNSAppRPC().UpdateHTTPDNSApp(this.AdminContext(), &pb.UpdateHTTPDNSAppRequest{
AppDbId: params.AppId,
Name: appResp.GetApp().GetName(),
PrimaryClusterId: appResp.GetApp().GetPrimaryClusterId(),
BackupClusterId: appResp.GetApp().GetBackupClusterId(),
PrimaryClusterId: params.PrimaryClusterId,
BackupClusterId: params.BackupClusterId,
IsOn: params.AppStatus,
UserId: appResp.GetApp().GetUserId(),
})

View File

@@ -55,6 +55,24 @@ func (this *CreateAction) RunGet(params struct{}) {
}
this.Data["defaultBackupClusterId"] = defaultBackupClusterId
usersResp, err := this.RPC().UserRPC().ListEnabledUsers(this.AdminContext(), &pb.ListEnabledUsersRequest{
Offset: 0,
Size: 10_000,
})
if err != nil {
this.ErrorPage(err)
return
}
users := make([]maps.Map, 0, len(usersResp.GetUsers()))
for _, user := range usersResp.GetUsers() {
users = append(users, maps.Map{
"id": user.GetId(),
"fullname": user.GetFullname(),
"username": user.GetUsername(),
})
}
this.Data["users"] = users
this.Show()
}

View File

@@ -18,6 +18,7 @@ func init() {
Get("/sdk", new(SdkAction)).
GetPost("/sdk/upload", new(SdkUploadAction)).
Post("/sdk/upload/delete", new(SdkUploadDeleteAction)).
Get("/sdk/check", new(SdkCheckAction)).
Get("/sdk/download", new(SdkDownloadAction)).
Get("/sdk/doc", new(SdkDocAction)).
GetPost("/app/settings", new(AppSettingsAction)).

View File

@@ -7,11 +7,20 @@ import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
timeutil "github.com/iwind/TeaGo/utils/time"
"github.com/iwind/TeaGo/maps"
timeutil "github.com/iwind/TeaGo/utils/time"
)
func listAppMaps(parent *actionutils.ParentAction, keyword string) ([]maps.Map, error) {
clusterNameMap, err := loadHTTPDNSClusterNameMap(parent)
if err != nil {
return nil, err
}
userMapByID, err := loadHTTPDNSUserMap(parent)
if err != nil {
return nil, err
}
resp, err := parent.RPC().HTTPDNSAppRPC().ListHTTPDNSApps(parent.AdminContext(), &pb.ListHTTPDNSAppsRequest{
Offset: 0,
Size: 10_000,
@@ -30,13 +39,22 @@ func listAppMaps(parent *actionutils.ParentAction, keyword string) ([]maps.Map,
return nil, err
}
result = append(result, appPBToMap(app, int64(len(domainResp.GetDomains()))))
result = append(result, appPBToMap(app, int64(len(domainResp.GetDomains())), clusterNameMap, userMapByID))
}
return result, nil
}
func findAppMap(parent *actionutils.ParentAction, appDbId int64) (maps.Map, error) {
clusterNameMap, err := loadHTTPDNSClusterNameMap(parent)
if err != nil {
return nil, err
}
userMapByID, err := loadHTTPDNSUserMap(parent)
if err != nil {
return nil, err
}
if appDbId > 0 {
resp, err := parent.RPC().HTTPDNSAppRPC().FindHTTPDNSApp(parent.AdminContext(), &pb.FindHTTPDNSAppRequest{
AppDbId: appDbId,
@@ -51,7 +69,7 @@ func findAppMap(parent *actionutils.ParentAction, appDbId int64) (maps.Map, erro
if err != nil {
return nil, err
}
return appPBToMap(resp.GetApp(), int64(len(domainResp.GetDomains()))), nil
return appPBToMap(resp.GetApp(), int64(len(domainResp.GetDomains())), clusterNameMap, userMapByID), nil
}
}
@@ -259,16 +277,37 @@ func toggleCustomRule(parent *actionutils.ParentAction, ruleId int64, isOn bool)
return err
}
func appPBToMap(app *pb.HTTPDNSApp, domainCount int64) maps.Map {
func appPBToMap(app *pb.HTTPDNSApp, domainCount int64, clusterNameMap map[int64]string, userMapByID map[int64]maps.Map) maps.Map {
signSecret := app.GetSignSecret()
primaryClusterID := app.GetPrimaryClusterId()
backupClusterID := app.GetBackupClusterId()
primaryClusterMap := maps.Map{"id": primaryClusterID, "name": clusterNameMap[primaryClusterID]}
backupClusterMap := maps.Map{"id": backupClusterID, "name": clusterNameMap[backupClusterID]}
var userMap maps.Map
if app.GetUserId() > 0 {
userMap = userMapByID[app.GetUserId()]
if userMap == nil {
userMap = maps.Map{
"id": app.GetUserId(),
"fullname": "用户#" + strconv.FormatInt(app.GetUserId(), 10),
"username": "-",
}
}
}
return maps.Map{
"id": app.GetId(),
"name": app.GetName(),
"appId": app.GetAppId(),
"clusterId": app.GetPrimaryClusterId(),
"primaryClusterId": app.GetPrimaryClusterId(),
"backupClusterId": app.GetBackupClusterId(),
"clusterId": primaryClusterID,
"primaryClusterId": primaryClusterID,
"backupClusterId": backupClusterID,
"primaryCluster": primaryClusterMap,
"backupCluster": backupClusterMap,
"userId": app.GetUserId(),
"user": userMap,
"isOn": app.GetIsOn(),
"domainCount": domainCount,
"sniPolicyText": "隐匿 SNI",
@@ -279,6 +318,39 @@ func appPBToMap(app *pb.HTTPDNSApp, domainCount int64) maps.Map {
}
}
func loadHTTPDNSClusterNameMap(parent *actionutils.ParentAction) (map[int64]string, error) {
resp, err := parent.RPC().HTTPDNSClusterRPC().FindAllHTTPDNSClusters(parent.AdminContext(), &pb.FindAllHTTPDNSClustersRequest{})
if err != nil {
return nil, err
}
result := map[int64]string{}
for _, cluster := range resp.GetClusters() {
result[cluster.GetId()] = cluster.GetName()
}
return result, nil
}
func loadHTTPDNSUserMap(parent *actionutils.ParentAction) (map[int64]maps.Map, error) {
resp, err := parent.RPC().UserRPC().ListEnabledUsers(parent.AdminContext(), &pb.ListEnabledUsersRequest{
Offset: 0,
Size: 10_000,
})
if err != nil {
return nil, err
}
result := map[int64]maps.Map{}
for _, user := range resp.GetUsers() {
result[user.GetId()] = maps.Map{
"id": user.GetId(),
"fullname": user.GetFullname(),
"username": user.GetUsername(),
}
}
return result, nil
}
func defaultLineField(value string) string {
value = strings.TrimSpace(value)
if len(value) == 0 {

View File

@@ -0,0 +1,67 @@
package apps
import (
"net/url"
"strings"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
)
type SdkCheckAction struct {
actionutils.ParentAction
}
func (this *SdkCheckAction) Init() {
this.Nav("", "", "")
}
func (this *SdkCheckAction) RunGet(params struct {
Platform string
Version string
Type string
}) {
platform, _, _, filename, err := resolveSDKPlatform(params.Platform)
if err != nil {
this.Data["exists"] = false
this.Data["message"] = err.Error()
this.Success()
return
}
t := strings.ToLower(strings.TrimSpace(params.Type))
if t == "doc" {
docPath := findUploadedSDKDocPath(platform, params.Version)
if len(docPath) == 0 {
this.Data["exists"] = false
this.Data["message"] = "Documentation is unavailable, please upload first"
this.Success()
return
}
downloadURL := "/httpdns/apps/sdk/doc?platform=" + url.QueryEscape(platform)
if len(strings.TrimSpace(params.Version)) > 0 {
downloadURL += "&version=" + url.QueryEscape(strings.TrimSpace(params.Version))
}
this.Data["exists"] = true
this.Data["url"] = downloadURL
this.Success()
return
}
archivePath := findSDKArchivePath(filename, params.Version)
if len(archivePath) == 0 {
this.Data["exists"] = false
this.Data["message"] = "SDK package is unavailable, please upload first"
this.Success()
return
}
downloadURL := "/httpdns/apps/sdk/download?platform=" + url.QueryEscape(platform)
if len(strings.TrimSpace(params.Version)) > 0 {
downloadURL += "&version=" + url.QueryEscape(strings.TrimSpace(params.Version))
}
downloadURL += "&raw=1"
this.Data["exists"] = true
this.Data["url"] = downloadURL
this.Success()
}

View File

@@ -1,10 +1,11 @@
package apps
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"os"
"path/filepath"
"strings"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
)
type SdkDocAction struct {
@@ -17,15 +18,18 @@ func (this *SdkDocAction) Init() {
func (this *SdkDocAction) RunGet(params struct {
Platform string
Version string
}) {
platform, _, readmeRelativePath, _, err := resolveSDKPlatform(params.Platform)
if err != nil {
this.Fail(err.Error())
this.Data["exists"] = false
this.Data["message"] = err.Error()
this.Success()
return
}
var data []byte
uploadedDocPath := findUploadedSDKDocPath(platform)
uploadedDocPath := findUploadedSDKDocPath(platform, params.Version)
if len(uploadedDocPath) > 0 {
data, err = os.ReadFile(uploadedDocPath)
}
@@ -44,11 +48,18 @@ func (this *SdkDocAction) RunGet(params struct {
}
if len(data) == 0 || err != nil {
this.Fail("当前服务器未找到 SDK 集成文档请先在“SDK 集成”页面上传对应平台文档")
this.Data["exists"] = false
this.Data["message"] = "SDK documentation is not found on server, please upload first"
this.Success()
return
}
downloadName := filepath.Base(uploadedDocPath)
if len(downloadName) == 0 || downloadName == "." || downloadName == string(filepath.Separator) {
downloadName = "httpdns-sdk-" + strings.ToLower(platform) + ".md"
}
this.AddHeader("Content-Type", "text/markdown; charset=utf-8")
this.AddHeader("Content-Disposition", "attachment; filename=\"httpdns-sdk-"+strings.ToLower(platform)+"-README.md\";")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";")
_, _ = this.ResponseWriter.Write(data)
}

View File

@@ -1,9 +1,11 @@
package apps
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"io"
"os"
"path/filepath"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
)
type SdkDownloadAction struct {
@@ -16,30 +18,48 @@ func (this *SdkDownloadAction) Init() {
func (this *SdkDownloadAction) RunGet(params struct {
Platform string
Version string
Raw int
}) {
_, _, _, filename, err := resolveSDKPlatform(params.Platform)
if err != nil {
this.Fail(err.Error())
this.Data["exists"] = false
this.Data["message"] = err.Error()
this.Success()
return
}
archivePath := findSDKArchivePath(filename)
archivePath := findSDKArchivePath(filename, params.Version)
if len(archivePath) == 0 {
this.Fail("当前服务器未找到 SDK 包请先在“SDK 集成”页面上传对应平台包: " + filename)
this.Data["exists"] = false
this.Data["message"] = "SDK archive not found on server, please upload first: " + filename
this.Success()
return
}
fp, err := os.Open(archivePath)
if err != nil {
this.Fail("打开 SDK 包失败: " + err.Error())
this.Data["exists"] = false
this.Data["message"] = "failed to open SDK archive: " + err.Error()
this.Success()
return
}
defer func() {
_ = fp.Close()
}()
this.AddHeader("Content-Type", "application/zip")
this.AddHeader("Content-Disposition", "attachment; filename=\""+filename+"\";")
downloadName := filepath.Base(archivePath)
if len(downloadName) == 0 || downloadName == "." || downloadName == string(filepath.Separator) {
downloadName = filename
}
if params.Raw == 1 {
this.AddHeader("Content-Type", "application/octet-stream")
this.AddHeader("X-SDK-Filename", downloadName)
} else {
this.AddHeader("Content-Type", "application/zip")
this.AddHeader("Content-Disposition", "attachment; filename=\""+downloadName+"\";")
}
this.AddHeader("X-Accel-Buffering", "no")
_, _ = io.Copy(this.ResponseWriter, fp)
}

View File

@@ -2,18 +2,58 @@ package apps
import (
"errors"
"github.com/iwind/TeaGo/Tea"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/iwind/TeaGo/Tea"
)
func sdkUploadDir() string {
dirs := sdkUploadDirs()
if len(dirs) > 0 {
return dirs[0]
}
return filepath.Clean(Tea.Root + "/data/httpdns/sdk")
}
func sdkUploadDirs() []string {
candidates := []string{
filepath.Clean(Tea.Root + "/../data/httpdns/sdk"),
filepath.Clean(Tea.Root + "/data/httpdns/sdk"),
filepath.Clean(Tea.Root + "/../edge-admin/data/httpdns/sdk"),
filepath.Clean(Tea.Root + "/../edge-user/data/httpdns/sdk"),
filepath.Clean(Tea.Root + "/../../data/httpdns/sdk"),
}
results := make([]string, 0, len(candidates))
seen := map[string]bool{}
for _, dir := range candidates {
if len(dir) == 0 || seen[dir] {
continue
}
seen[dir] = true
results = append(results, dir)
}
return results
}
func sdkUploadSearchDirs() []string {
dirs := sdkUploadDirs()
results := make([]string, 0, len(dirs))
for _, dir := range dirs {
stat, err := os.Stat(dir)
if err == nil && stat.IsDir() {
results = append(results, dir)
}
}
if len(results) == 0 {
results = append(results, sdkUploadDir())
}
return results
}
func findFirstExistingDir(paths []string) string {
for _, path := range paths {
stat, err := os.Stat(path)
@@ -27,7 +67,7 @@ func findFirstExistingDir(paths []string) string {
func findFirstExistingFile(paths []string) string {
for _, path := range paths {
stat, err := os.Stat(path)
if err == nil && !stat.IsDir() {
if err == nil && !stat.IsDir() && stat.Size() > 0 {
return path
}
}
@@ -45,6 +85,9 @@ func findNewestExistingFile(paths []string) string {
if err != nil || stat.IsDir() {
continue
}
if stat.Size() <= 0 {
continue
}
if len(result.path) == 0 || stat.ModTime().After(result.modTime) || (stat.ModTime().Equal(result.modTime) && path > result.path) {
result.path = path
result.modTime = stat.ModTime()
@@ -85,22 +128,23 @@ func resolveSDKPlatform(platform string) (key string, relativeDir string, readme
}
}
func findSDKArchivePath(downloadFilename string) string {
searchDirs := []string{sdkUploadDir()}
func findSDKArchivePath(downloadFilename string, version string) string {
searchDirs := sdkUploadSearchDirs()
// 1) Exact filename first.
exactFiles := []string{}
for _, dir := range searchDirs {
exactFiles = append(exactFiles, filepath.Join(dir, downloadFilename))
}
path := findFirstExistingFile(exactFiles)
if len(path) > 0 {
return path
}
// 2) Version-suffixed archives, e.g. httpdns-sdk-android-v1.4.8.zip
normalizedVersion := strings.TrimSpace(version)
base := strings.TrimSuffix(downloadFilename, ".zip")
patternName := base + "-*.zip"
if len(normalizedVersion) > 0 {
versionFiles := []string{}
for _, dir := range searchDirs {
versionFiles = append(versionFiles, filepath.Join(dir, base+"-v"+normalizedVersion+".zip"))
}
if path := findFirstExistingFile(versionFiles); len(path) > 0 {
return path
}
return ""
}
patternName := base + "-v*.zip"
matches := []string{}
for _, dir := range searchDirs {
found, _ := filepath.Glob(filepath.Join(dir, patternName))
@@ -115,28 +159,52 @@ func findSDKArchivePath(downloadFilename string) string {
return findNewestExistingFile(matches)
}
exactFiles := []string{}
for _, dir := range searchDirs {
exactFiles = append(exactFiles, filepath.Join(dir, downloadFilename))
}
if path := findFirstExistingFile(exactFiles); len(path) > 0 {
return path
}
return ""
}
func findUploadedSDKDocPath(platform string) string {
func findUploadedSDKDocPath(platform string, version string) string {
platform = strings.ToLower(strings.TrimSpace(platform))
if len(platform) == 0 {
return ""
}
searchDir := sdkUploadDir()
exact := filepath.Join(searchDir, "httpdns-sdk-"+platform+".md")
if file := findFirstExistingFile([]string{exact}); len(file) > 0 {
return file
}
pattern := filepath.Join(searchDir, "httpdns-sdk-"+platform+"-*.md")
matches, _ := filepath.Glob(pattern)
if len(matches) == 0 {
searchDirs := sdkUploadSearchDirs()
normalizedVersion := strings.TrimSpace(version)
if len(normalizedVersion) > 0 {
exactVersion := []string{}
for _, dir := range searchDirs {
exactVersion = append(exactVersion, filepath.Join(dir, "httpdns-sdk-"+platform+"-v"+normalizedVersion+".md"))
}
if file := findFirstExistingFile(exactVersion); len(file) > 0 {
return file
}
return ""
}
sort.Strings(matches)
return findNewestExistingFile(matches)
matches := []string{}
for _, dir := range searchDirs {
pattern := filepath.Join(dir, "httpdns-sdk-"+platform+"-v*.md")
found, _ := filepath.Glob(pattern)
matches = append(matches, found...)
}
if len(matches) > 0 {
sort.Strings(matches)
return findNewestExistingFile(matches)
}
exact := []string{}
for _, dir := range searchDirs {
exact = append(exact, filepath.Join(dir, "httpdns-sdk-"+platform+".md"))
}
return findFirstExistingFile(exact)
}
func findLocalSDKDocPath(platform string) string {

View File

@@ -2,15 +2,16 @@ package apps
import (
"errors"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils"
"github.com/iwind/TeaGo/actions"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
"time"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/httpdns/httpdnsutils"
"github.com/iwind/TeaGo/actions"
)
type SdkUploadAction struct {
@@ -44,7 +45,7 @@ func (this *SdkUploadAction) RunPost(params struct {
AppId int64
Platform string
Version string
SDKFile *actions.File
SdkFile *actions.File
DocFile *actions.File
Must *actions.Must
@@ -63,7 +64,7 @@ func (this *SdkUploadAction) RunPost(params struct {
return
}
if params.SDKFile == nil && params.DocFile == nil {
if params.SdkFile == nil && params.DocFile == nil {
this.Fail("请至少上传一个文件")
return
}
@@ -75,24 +76,25 @@ func (this *SdkUploadAction) RunPost(params struct {
return
}
if params.SDKFile != nil {
filename := strings.ToLower(strings.TrimSpace(params.SDKFile.Filename))
if params.SdkFile != nil {
filename := strings.ToLower(strings.TrimSpace(params.SdkFile.Filename))
if !strings.HasSuffix(filename, ".zip") {
this.Fail("SDK 包仅支持 .zip 文件")
return
}
sdkData, readErr := params.SDKFile.Read()
sdkData, readErr := params.SdkFile.Read()
if readErr != nil {
this.Fail("读取 SDK 包失败: " + readErr.Error())
return
}
if len(sdkData) == 0 {
this.Fail("SDK 包文件为空,请重新上传")
return
}
baseName := strings.TrimSuffix(downloadFilename, ".zip")
err = saveSDKUploadFile(uploadDir, downloadFilename, sdkData)
if err == nil {
err = saveSDKUploadFile(uploadDir, baseName+"-v"+version+".zip", sdkData)
}
err = saveSDKUploadFile(uploadDir, baseName+"-v"+version+".zip", sdkData)
if err != nil {
this.Fail("保存 SDK 包失败: " + err.Error())
return
@@ -111,12 +113,12 @@ func (this *SdkUploadAction) RunPost(params struct {
this.Fail("读取集成文档失败: " + readErr.Error())
return
}
filename := "httpdns-sdk-" + platform + ".md"
err = saveSDKUploadFile(uploadDir, filename, docData)
if err == nil {
err = saveSDKUploadFile(uploadDir, "httpdns-sdk-"+platform+"-v"+version+".md", docData)
if len(docData) == 0 {
this.Fail("集成文档文件为空,请重新上传")
return
}
err = saveSDKUploadFile(uploadDir, "httpdns-sdk-"+platform+"-v"+version+".md", docData)
if err != nil {
this.Fail("保存集成文档失败: " + err.Error())
return
@@ -151,12 +153,6 @@ func saveSDKUploadFile(baseDir string, filename string, data []byte) error {
}
func listUploadedSDKFiles() []map[string]interface{} {
dir := sdkUploadDir()
entries, err := os.ReadDir(dir)
if err != nil {
return []map[string]interface{}{}
}
type item struct {
Name string
Platform string
@@ -166,30 +162,45 @@ func listUploadedSDKFiles() []map[string]interface{} {
UpdatedAt int64
}
items := make([]item, 0)
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
platform, version, fileType, ok := parseSDKUploadFilename(name)
if !ok {
byName := map[string]item{}
for _, dir := range sdkUploadSearchDirs() {
entries, err := os.ReadDir(dir)
if err != nil {
continue
}
for _, entry := range entries {
if entry.IsDir() {
continue
}
name := entry.Name()
platform, version, fileType, ok := parseSDKUploadFilename(name)
if !ok {
continue
}
info, statErr := entry.Info()
if statErr != nil {
continue
}
info, statErr := entry.Info()
if statErr != nil {
continue
}
items = append(items, item{
Name: name,
Platform: platform,
FileType: fileType,
Version: version,
SizeBytes: info.Size(),
UpdatedAt: info.ModTime().Unix(),
})
current := item{
Name: name,
Platform: platform,
FileType: fileType,
Version: version,
SizeBytes: info.Size(),
UpdatedAt: info.ModTime().Unix(),
}
old, exists := byName[name]
if !exists || current.UpdatedAt >= old.UpdatedAt {
byName[name] = current
}
}
}
items := make([]item, 0, len(byName))
for _, it := range byName {
items = append(items, it)
}
sort.Slice(items, func(i, j int) bool {
@@ -200,14 +211,14 @@ func listUploadedSDKFiles() []map[string]interface{} {
})
result := make([]map[string]interface{}, 0, len(items))
for _, item := range items {
for _, it := range items {
result = append(result, map[string]interface{}{
"name": item.Name,
"platform": item.Platform,
"fileType": item.FileType,
"version": item.Version,
"sizeText": formatSDKFileSize(item.SizeBytes),
"updatedAt": time.Unix(item.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
"name": it.Name,
"platform": it.Platform,
"fileType": it.FileType,
"version": it.Version,
"sizeText": formatSDKFileSize(it.SizeBytes),
"updatedAt": time.Unix(it.UpdatedAt, 0).Format("2006-01-02 15:04:05"),
})
}
return result
@@ -231,7 +242,7 @@ func parseSDKUploadFilename(filename string) (platform string, version string, f
}
main := strings.TrimSuffix(strings.TrimPrefix(filename, "httpdns-sdk-"), ext)
version = "latest"
version = ""
if idx := strings.Index(main, "-v"); idx > 0 && idx+2 < len(main) {
version = main[idx+2:]
main = main[:idx]
@@ -241,6 +252,9 @@ func parseSDKUploadFilename(filename string) (platform string, version string, f
switch main {
case "android", "ios", "flutter":
platform = main
if len(version) == 0 {
version = "-"
}
return platform, version, fileType, true
default:
return "", "", "", false

View File

@@ -1,10 +1,11 @@
package apps
import (
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
"os"
"path/filepath"
"strings"
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
)
type SdkUploadDeleteAction struct {
@@ -42,15 +43,16 @@ func (this *SdkUploadDeleteAction) RunPost(params struct {
return
}
fullPath := filepath.Join(sdkUploadDir(), filename)
_, err := os.Stat(fullPath)
if err != nil {
this.Success()
return
}
if err = os.Remove(fullPath); err != nil {
this.Fail("删除失败: " + err.Error())
return
for _, dir := range sdkUploadDirs() {
fullPath := filepath.Join(dir, filename)
_, err := os.Stat(fullPath)
if err != nil {
continue
}
if err = os.Remove(fullPath); err != nil {
this.Fail("删除失败: " + err.Error())
return
}
}
this.Success()