commits
This commit is contained in:
@@ -42,10 +42,17 @@ func (c *ApiSoftwareUpgradeController) Check() {
|
|||||||
|
|
||||||
scheme, host := services.PublicRequestBaseURL(&c.Controller)
|
scheme, host := services.PublicRequestBaseURL(&c.Controller)
|
||||||
dl := services.ResolveSoftwareDownloadURL(scheme, host, row.DownloadURL, row.FileID)
|
dl := services.ResolveSoftwareDownloadURL(scheme, host, row.DownloadURL, row.FileID)
|
||||||
|
dls := services.ResolveSoftwareDownloadURLs(scheme, host, row.DownloadURLs)
|
||||||
|
if platform := strings.ToLower(strings.TrimSpace(c.GetString("platform"))); platform != "" {
|
||||||
|
if platformURL := strings.TrimSpace(dls[platform]); platformURL != "" {
|
||||||
|
dl = platformURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"latestVersion": latest,
|
"latestVersion": latest,
|
||||||
"downloadUrl": dl,
|
"downloadUrl": dl,
|
||||||
|
"downloadUrls": dls,
|
||||||
"forceUpdate": row.ForceUpdate == 1,
|
"forceUpdate": row.ForceUpdate == 1,
|
||||||
"releaseNotes": "",
|
"releaseNotes": "",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,20 +78,23 @@ func (c *PlatformSoftwareUpgradeController) backfillDownloadURL(productID uint64
|
|||||||
func (c *PlatformSoftwareUpgradeController) rowToMap(row *models.SystemSoftwareUpgrade) map[string]interface{} {
|
func (c *PlatformSoftwareUpgradeController) rowToMap(row *models.SystemSoftwareUpgrade) map[string]interface{} {
|
||||||
scheme, host := services.PublicRequestBaseURL(&c.Controller)
|
scheme, host := services.PublicRequestBaseURL(&c.Controller)
|
||||||
resolved := services.ResolveSoftwareDownloadURL(scheme, host, row.DownloadURL, row.FileID)
|
resolved := services.ResolveSoftwareDownloadURL(scheme, host, row.DownloadURL, row.FileID)
|
||||||
|
resolvedMulti := services.ResolveSoftwareDownloadURLs(scheme, host, row.DownloadURLs)
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"id": row.ID,
|
"id": row.ID,
|
||||||
"name": row.Name,
|
"name": row.Name,
|
||||||
"code": row.Code,
|
"code": row.Code,
|
||||||
"latestVersion": row.LatestVersion,
|
"latestVersion": row.LatestVersion,
|
||||||
"fileId": row.FileID,
|
"fileId": row.FileID,
|
||||||
"downloadUrl": row.DownloadURL,
|
"downloadUrl": row.DownloadURL,
|
||||||
"resolvedDownloadUrl": resolved,
|
"downloadUrls": row.DownloadURLs,
|
||||||
"forceUpdate": row.ForceUpdate,
|
"resolvedDownloadUrl": resolved,
|
||||||
"releaseNotes": row.ReleaseNotes,
|
"resolvedDownloadUrls": resolvedMulti,
|
||||||
"status": row.Status,
|
"forceUpdate": row.ForceUpdate,
|
||||||
"sort": row.Sort,
|
"releaseNotes": row.ReleaseNotes,
|
||||||
"createTime": row.CreateTime,
|
"status": row.Status,
|
||||||
"updateTime": row.UpdateTime,
|
"sort": row.Sort,
|
||||||
|
"createTime": row.CreateTime,
|
||||||
|
"updateTime": row.UpdateTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,15 +161,16 @@ func (c *PlatformSoftwareUpgradeController) Detail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type softwareUpgradePayload struct {
|
type softwareUpgradePayload struct {
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
Code *string `json:"code"`
|
Code *string `json:"code"`
|
||||||
LatestVersion *string `json:"latestVersion"`
|
LatestVersion *string `json:"latestVersion"`
|
||||||
FileID *uint64 `json:"fileId"`
|
FileID *uint64 `json:"fileId"`
|
||||||
DownloadURL *string `json:"downloadUrl"`
|
DownloadURL *string `json:"downloadUrl"`
|
||||||
ForceUpdate *int8 `json:"forceUpdate"`
|
DownloadURLs map[string]string `json:"downloadUrls"`
|
||||||
ReleaseNotes *string `json:"releaseNotes"`
|
ForceUpdate *int8 `json:"forceUpdate"`
|
||||||
Status *int8 `json:"status"`
|
ReleaseNotes *string `json:"releaseNotes"`
|
||||||
Sort *int `json:"sort"`
|
Status *int8 `json:"status"`
|
||||||
|
Sort *int `json:"sort"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create POST /platform/softwareupgrade
|
// Create POST /platform/softwareupgrade
|
||||||
@@ -198,6 +202,12 @@ func (c *PlatformSoftwareUpgradeController) Create() {
|
|||||||
Status: 1,
|
Status: 1,
|
||||||
Sort: 0,
|
Sort: 0,
|
||||||
}
|
}
|
||||||
|
if len(p.DownloadURLs) > 0 {
|
||||||
|
if b, err := json.Marshal(p.DownloadURLs); err == nil {
|
||||||
|
s := string(b)
|
||||||
|
row.DownloadURLs = &s
|
||||||
|
}
|
||||||
|
}
|
||||||
if p.ForceUpdate != nil {
|
if p.ForceUpdate != nil {
|
||||||
row.ForceUpdate = *p.ForceUpdate
|
row.ForceUpdate = *p.ForceUpdate
|
||||||
}
|
}
|
||||||
@@ -263,6 +273,22 @@ func (c *PlatformSoftwareUpgradeController) Update() {
|
|||||||
if p.DownloadURL != nil {
|
if p.DownloadURL != nil {
|
||||||
up["download_url"] = strings.TrimSpace(*p.DownloadURL)
|
up["download_url"] = strings.TrimSpace(*p.DownloadURL)
|
||||||
}
|
}
|
||||||
|
if p.DownloadURLs != nil {
|
||||||
|
clean := map[string]string{}
|
||||||
|
for k, v := range p.DownloadURLs {
|
||||||
|
platform := strings.ToLower(strings.TrimSpace(k))
|
||||||
|
url := strings.TrimSpace(v)
|
||||||
|
if platform == "" || url == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
clean[platform] = url
|
||||||
|
}
|
||||||
|
if len(clean) == 0 {
|
||||||
|
up["download_urls"] = nil
|
||||||
|
} else if b, err := json.Marshal(clean); err == nil {
|
||||||
|
up["download_urls"] = string(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
if p.ForceUpdate != nil {
|
if p.ForceUpdate != nil {
|
||||||
up["force_update"] = *p.ForceUpdate
|
up["force_update"] = *p.ForceUpdate
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ CREATE TABLE IF NOT EXISTS `yz_system_software_upgrade` (
|
|||||||
`code` varchar(64) NOT NULL COMMENT '客户端唯一标识,与 check 接口 code 一致',
|
`code` varchar(64) NOT NULL COMMENT '客户端唯一标识,与 check 接口 code 一致',
|
||||||
`latest_version` varchar(32) NOT NULL DEFAULT '0.0.0' COMMENT '当前发布的最新版本号',
|
`latest_version` varchar(32) NOT NULL DEFAULT '0.0.0' COMMENT '当前发布的最新版本号',
|
||||||
`file_id` bigint unsigned DEFAULT NULL COMMENT '关联 yz_system_files.id,安装包',
|
`file_id` bigint unsigned DEFAULT NULL COMMENT '关联 yz_system_files.id,安装包',
|
||||||
`download_url` varchar(512) DEFAULT NULL COMMENT '完整下载地址;为空则用 file_id 对应 src 拼公开 URL',
|
`download_url` varchar(512) DEFAULT NULL COMMENT '兼容旧客户端的单安装包地址;为空则用 file_id 对应 src 拼公开 URL',
|
||||||
|
`download_urls` text DEFAULT NULL COMMENT '多运行环境安装包地址 JSON,如 {"windows":"...","mac":"...","ubuntu":"...","linux":"..."}',
|
||||||
`force_update` tinyint NOT NULL DEFAULT 0 COMMENT '1 建议强制更新',
|
`force_update` tinyint NOT NULL DEFAULT 0 COMMENT '1 建议强制更新',
|
||||||
`release_notes` varchar(2000) DEFAULT NULL COMMENT '更新说明',
|
`release_notes` varchar(2000) DEFAULT NULL COMMENT '更新说明',
|
||||||
`status` tinyint NOT NULL DEFAULT 1 COMMENT '1 启用 0 停用',
|
`status` tinyint NOT NULL DEFAULT 1 COMMENT '1 启用 0 停用',
|
||||||
@@ -19,3 +20,7 @@ CREATE TABLE IF NOT EXISTS `yz_system_software_upgrade` (
|
|||||||
UNIQUE KEY `uk_code` (`code`),
|
UNIQUE KEY `uk_code` (`code`),
|
||||||
KEY `idx_status_delete` (`status`,`delete_time`)
|
KEY `idx_status_delete` (`status`,`delete_time`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='软件升级产品';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='软件升级产品';
|
||||||
|
|
||||||
|
-- 已有表升级:
|
||||||
|
-- ALTER TABLE `yz_system_software_upgrade`
|
||||||
|
-- ADD COLUMN `download_urls` text DEFAULT NULL COMMENT '多运行环境安装包地址 JSON,如 {"windows":"...","mac":"...","ubuntu":"...","linux":"..."}' AFTER `download_url`;
|
||||||
|
|||||||
@@ -4,19 +4,20 @@ import "time"
|
|||||||
|
|
||||||
// SystemSoftwareUpgrade 软件升级产品 yz_system_software_upgrade
|
// SystemSoftwareUpgrade 软件升级产品 yz_system_software_upgrade
|
||||||
type SystemSoftwareUpgrade struct {
|
type SystemSoftwareUpgrade struct {
|
||||||
ID uint64 `orm:"column(id);pk;auto" json:"id"`
|
ID uint64 `orm:"column(id);pk;auto" json:"id"`
|
||||||
Name string `orm:"column(name);size(128)" json:"name"`
|
Name string `orm:"column(name);size(128)" json:"name"`
|
||||||
Code string `orm:"column(code);size(64);unique" json:"code"`
|
Code string `orm:"column(code);size(64);unique" json:"code"`
|
||||||
LatestVersion string `orm:"column(latest_version);size(32)" json:"latestVersion"`
|
LatestVersion string `orm:"column(latest_version);size(32)" json:"latestVersion"`
|
||||||
FileID *uint64 `orm:"column(file_id);null" json:"fileId"`
|
FileID *uint64 `orm:"column(file_id);null" json:"fileId"`
|
||||||
DownloadURL *string `orm:"column(download_url);size(512);null" json:"downloadUrl"`
|
DownloadURL *string `orm:"column(download_url);size(512);null" json:"downloadUrl"`
|
||||||
ForceUpdate int8 `orm:"column(force_update);default(0)" json:"forceUpdate"`
|
DownloadURLs *string `orm:"column(download_urls);type(text);null" json:"downloadUrls"`
|
||||||
ReleaseNotes *string `orm:"column(release_notes);size(2000);null" json:"releaseNotes"`
|
ForceUpdate int8 `orm:"column(force_update);default(0)" json:"forceUpdate"`
|
||||||
Status int8 `orm:"column(status);default(1)" json:"status"`
|
ReleaseNotes *string `orm:"column(release_notes);size(2000);null" json:"releaseNotes"`
|
||||||
Sort int `orm:"column(sort);default(0)" json:"sort"`
|
Status int8 `orm:"column(status);default(1)" json:"status"`
|
||||||
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"`
|
Sort int `orm:"column(sort);default(0)" json:"sort"`
|
||||||
UpdateTime *time.Time `orm:"column(update_time);auto_now;type(datetime);null" json:"updateTime"`
|
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"`
|
||||||
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"deleteTime"`
|
UpdateTime *time.Time `orm:"column(update_time);auto_now;type(datetime);null" json:"updateTime"`
|
||||||
|
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"deleteTime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SystemSoftwareUpgrade) TableName() string {
|
func (m *SystemSoftwareUpgrade) TableName() string {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"server/models"
|
"server/models"
|
||||||
@@ -21,6 +22,49 @@ func PublicRequestBaseURL(c *beego.Controller) (scheme, host string) {
|
|||||||
return scheme, host
|
return scheme, host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveSoftwareDownloadURL 优先使用自定义 download_url;否则根据 file_id 读附件 src 拼完整 URL
|
||||||
|
func ResolveSoftwareDownloadURLs(scheme, host string, downloadURLs *string) map[string]string {
|
||||||
|
result := map[string]string{}
|
||||||
|
if downloadURLs == nil || strings.TrimSpace(*downloadURLs) == "" {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
raw := strings.TrimSpace(*downloadURLs)
|
||||||
|
var values map[string]string
|
||||||
|
if err := json.Unmarshal([]byte(raw), &values); err != nil {
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
for k, v := range values {
|
||||||
|
platform := strings.ToLower(strings.TrimSpace(k))
|
||||||
|
url := strings.TrimSpace(v)
|
||||||
|
if platform == "" || url == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result[platform] = ResolvePublicURL(scheme, host, url)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolvePublicURL 把相对路径拼成公开 URL;http(s) 地址原样返回。
|
||||||
|
func ResolvePublicURL(scheme, host, src string) string {
|
||||||
|
src = strings.TrimSpace(src)
|
||||||
|
if src == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(strings.ToLower(src), "http://") || strings.HasPrefix(strings.ToLower(src), "https://") {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
if host == "" {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
if !strings.HasPrefix(src, "/") {
|
||||||
|
src = "/" + src
|
||||||
|
}
|
||||||
|
if scheme == "" {
|
||||||
|
scheme = "http"
|
||||||
|
}
|
||||||
|
return scheme + "://" + host + src
|
||||||
|
}
|
||||||
|
|
||||||
// ResolveSoftwareDownloadURL 优先使用自定义 download_url;否则根据 file_id 读附件 src 拼完整 URL
|
// ResolveSoftwareDownloadURL 优先使用自定义 download_url;否则根据 file_id 读附件 src 拼完整 URL
|
||||||
func ResolveSoftwareDownloadURL(scheme, host string, downloadURL *string, fileID *uint64) string {
|
func ResolveSoftwareDownloadURL(scheme, host string, downloadURL *string, fileID *uint64) string {
|
||||||
if downloadURL != nil {
|
if downloadURL != nil {
|
||||||
@@ -40,21 +84,5 @@ func ResolveSoftwareDownloadURL(scheme, host string, downloadURL *string, fileID
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
src := strings.TrimSpace(f.Src)
|
return ResolvePublicURL(scheme, host, f.Src)
|
||||||
if src == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(strings.ToLower(src), "http://") || strings.HasPrefix(strings.ToLower(src), "https://") {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
if host == "" {
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
if !strings.HasPrefix(src, "/") {
|
|
||||||
src = "/" + src
|
|
||||||
}
|
|
||||||
if scheme == "" {
|
|
||||||
scheme = "http"
|
|
||||||
}
|
|
||||||
return scheme + "://" + host + src
|
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+86
-58
@@ -597,13 +597,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/core-base": {
|
"node_modules/@intlify/core-base": {
|
||||||
"version": "9.14.4",
|
"version": "9.14.5",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.14.5.tgz",
|
||||||
"integrity": "sha512-vtZCt7NqWhKEtHa3SD/322DlgP5uR9MqWxnE0y8Q0tjDs9H5Lxhss+b5wv8rmuXRoHKLESNgw9d+EN9ybBbj9g==",
|
"integrity": "sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/message-compiler": "9.14.4",
|
"@intlify/message-compiler": "9.14.5",
|
||||||
"@intlify/shared": "9.14.4"
|
"@intlify/shared": "9.14.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
@@ -613,12 +613,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/message-compiler": {
|
"node_modules/@intlify/message-compiler": {
|
||||||
"version": "9.14.4",
|
"version": "9.14.5",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.14.5.tgz",
|
||||||
"integrity": "sha512-vcyCLiVRN628U38c3PbahrhbbXrckrM9zpy0KZVlDk2Z0OnGwv8uQNNXP3twwGtfLsCf4gu3ci6FMIZnPaqZsw==",
|
"integrity": "sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/shared": "9.14.4",
|
"@intlify/shared": "9.14.5",
|
||||||
"source-map-js": "^1.0.2"
|
"source-map-js": "^1.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -629,9 +629,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@intlify/shared": {
|
"node_modules/@intlify/shared": {
|
||||||
"version": "9.14.4",
|
"version": "9.14.5",
|
||||||
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.14.5.tgz",
|
||||||
"integrity": "sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA==",
|
"integrity": "sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 16"
|
"node": ">= 16"
|
||||||
@@ -1589,6 +1589,18 @@
|
|||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/array-buffer-byte-length": {
|
"node_modules/array-buffer-byte-length": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
|
||||||
@@ -1663,14 +1675,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.13.5",
|
"version": "1.18.1",
|
||||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.5.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
|
||||||
"integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==",
|
"integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.11",
|
"follow-redirects": "^1.16.0",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"proxy-from-env": "^1.1.0"
|
"https-proxy-agent": "^5.0.1",
|
||||||
|
"proxy-from-env": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/birpc": {
|
"node_modules/birpc": {
|
||||||
@@ -1943,7 +1956,6 @@
|
|||||||
"version": "4.4.3",
|
"version": "4.4.3",
|
||||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
|
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
|
||||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "^2.1.3"
|
"ms": "^2.1.3"
|
||||||
@@ -2387,9 +2399,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.11",
|
"version": "1.16.0",
|
||||||
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
|
||||||
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
|
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "individual",
|
"type": "individual",
|
||||||
@@ -2422,16 +2434,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
|
||||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
"es-set-tostringtag": "^2.1.0",
|
"es-set-tostringtag": "^2.1.0",
|
||||||
"hasown": "^2.0.2",
|
"hasown": "^2.0.4",
|
||||||
"mime-types": "^2.1.12"
|
"mime-types": "^2.1.35"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
@@ -2676,9 +2688,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
|
||||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"function-bind": "^1.1.2"
|
"function-bind": "^1.1.2"
|
||||||
@@ -2712,6 +2724,19 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/i18next": {
|
"node_modules/i18next": {
|
||||||
"version": "20.6.1",
|
"version": "20.6.1",
|
||||||
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz",
|
"resolved": "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz",
|
||||||
@@ -3212,15 +3237,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.23",
|
"version": "4.18.1",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
|
||||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash-es": {
|
"node_modules/lodash-es": {
|
||||||
"version": "4.17.23",
|
"version": "4.18.1",
|
||||||
"resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.23.tgz",
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
|
||||||
"integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
|
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lodash-unified": {
|
"node_modules/lodash-unified": {
|
||||||
@@ -3421,7 +3446,6 @@
|
|||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/namespace-emitter": {
|
"node_modules/namespace-emitter": {
|
||||||
@@ -3431,9 +3455,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.15",
|
||||||
"resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
|
||||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
"integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@@ -3576,9 +3600,9 @@
|
|||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.4",
|
||||||
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
|
||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -3641,9 +3665,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.15",
|
||||||
"resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
||||||
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
|
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -3660,7 +3684,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.12",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"source-map-js": "^1.2.1"
|
"source-map-js": "^1.2.1"
|
||||||
},
|
},
|
||||||
@@ -3694,10 +3718,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/proxy-from-env": {
|
"node_modules/proxy-from-env": {
|
||||||
"version": "1.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||||
"license": "MIT"
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prr": {
|
"node_modules/prr": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -4646,9 +4673,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "7.3.1",
|
"version": "7.3.5",
|
||||||
"resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz",
|
||||||
"integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==",
|
"integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -4742,13 +4769,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vue-i18n": {
|
"node_modules/vue-i18n": {
|
||||||
"version": "9.14.4",
|
"version": "9.14.5",
|
||||||
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-9.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.5.tgz",
|
||||||
"integrity": "sha512-B934C8yUyWLT0EMud3DySrwSUJI7ZNiWYsEEz2gknTthqKiG4dzWE/WSa8AzCuSQzwBEv4HtG1jZDhgzPfWSKQ==",
|
"integrity": "sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==",
|
||||||
|
"deprecated": "v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@intlify/core-base": "9.14.4",
|
"@intlify/core-base": "9.14.5",
|
||||||
"@intlify/shared": "9.14.4",
|
"@intlify/shared": "9.14.5",
|
||||||
"@vue/devtools-api": "^6.5.0"
|
"@vue/devtools-api": "^6.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
@@ -21,63 +21,75 @@
|
|||||||
<el-input v-model="form.latestVersion" placeholder="如 1.2.0" />
|
<el-input v-model="form.latestVersion" placeholder="如 1.2.0" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="安装包">
|
<el-form-item label="多平台安装包">
|
||||||
<el-upload
|
<div class="platform-package-list">
|
||||||
ref="uploadRef"
|
<p class="hint">
|
||||||
class="pkg-upload"
|
同一个产品 code 可配置多个运行环境安装包;客户端按自身系统读取响应中的
|
||||||
:limit="1"
|
<code>downloadUrls[platform]</code>。
|
||||||
:file-list="displayFileList"
|
</p>
|
||||||
:http-request="handlePackageUpload"
|
<div v-for="item in platformOptions" :key="item.value" class="platform-package-row">
|
||||||
:on-remove="onRemovePackage"
|
<div class="platform-label">
|
||||||
@exceed="onExceedReplace"
|
<el-tag effect="plain">{{ item.label }}</el-tag>
|
||||||
accept=".zip,.exe,.dmg,.msi,.msix,.apk,.deb,.rpm,.7z,.pkg,.tar,.gz"
|
</div>
|
||||||
>
|
<el-input
|
||||||
<el-button type="primary" :loading="uploading">
|
v-model="form.downloadUrls[item.value]"
|
||||||
{{ form.fileId ? "重新上传安装包" : "上传安装包" }}
|
clearable
|
||||||
</el-button>
|
:placeholder="`填写 ${item.label} 下载地址,或上传后自动填写`"
|
||||||
</el-upload>
|
/>
|
||||||
<div v-if="uploadXHRActive" class="upload-progress-wrap">
|
<el-upload
|
||||||
<el-progress
|
:show-file-list="false"
|
||||||
:percentage="uploadPercent"
|
:http-request="(options) => handlePackageUpload(options, item.value)"
|
||||||
:indeterminate="uploadIndeterminate"
|
accept=".zip,.exe,.dmg,.msi,.msix,.apk,.deb,.rpm,.7z,.pkg,.tar,.gz,.appimage,.AppImage"
|
||||||
:stroke-width="10"
|
>
|
||||||
striped
|
<el-button
|
||||||
striped-flow
|
type="primary"
|
||||||
/>
|
plain
|
||||||
<div class="upload-progress-text">
|
:loading="uploading && uploadPlatform === item.value"
|
||||||
<template v-if="!uploadIndeterminate">
|
>
|
||||||
<span>{{ uploadPercent }}%</span>
|
上传
|
||||||
<span class="upload-sep">·</span>
|
</el-button>
|
||||||
<span>{{ uploadSpeedText }}</span>
|
</el-upload>
|
||||||
<template v-if="uploadSizeText">
|
</div>
|
||||||
<span class="upload-sep">·</span>
|
<div v-if="uploadXHRActive" class="upload-progress-wrap">
|
||||||
<span>{{ uploadSizeText }}</span>
|
<el-progress
|
||||||
</template>
|
:percentage="uploadPercent"
|
||||||
</template>
|
:indeterminate="uploadIndeterminate"
|
||||||
<template v-else>
|
:stroke-width="10"
|
||||||
<span>上传中…</span>
|
striped
|
||||||
<template v-if="uploadSpeedText && uploadSpeedText !== '—'">
|
striped-flow
|
||||||
|
/>
|
||||||
|
<div class="upload-progress-text">
|
||||||
|
<template v-if="!uploadIndeterminate">
|
||||||
|
<span>{{ uploadPercent }}%</span>
|
||||||
<span class="upload-sep">·</span>
|
<span class="upload-sep">·</span>
|
||||||
<span>{{ uploadSpeedText }}</span>
|
<span>{{ uploadSpeedText }}</span>
|
||||||
|
<template v-if="uploadSizeText">
|
||||||
|
<span class="upload-sep">·</span>
|
||||||
|
<span>{{ uploadSizeText }}</span>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="uploadSizeText">
|
<template v-else>
|
||||||
<span class="upload-sep">·</span>
|
<span>上传中…</span>
|
||||||
<span>{{ uploadSizeText }}</span>
|
<template v-if="uploadSpeedText && uploadSpeedText !== '—'">
|
||||||
|
<span class="upload-sep">·</span>
|
||||||
|
<span>{{ uploadSpeedText }}</span>
|
||||||
|
</template>
|
||||||
|
<template v-if="uploadSizeText">
|
||||||
|
<span class="upload-sep">·</span>
|
||||||
|
<span>{{ uploadSizeText }}</span>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="form.fileId" class="pkg-meta">
|
|
||||||
<span>文件 ID:<code>{{ form.fileId }}</code></span>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="下载/更新地址">
|
<el-form-item label="兼容下载地址">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="form.downloadUrl"
|
v-model="form.downloadUrl"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
:rows="2"
|
:rows="2"
|
||||||
placeholder="上传后自动填写;可改为 CDN 等完整 URL"
|
placeholder="旧版客户端兼容字段 downloadUrl;新客户端建议使用 downloadUrls"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -96,7 +108,7 @@
|
|||||||
<el-form-item label="排序">
|
<el-form-item label="排序">
|
||||||
<el-input-number v-model="form.sort" :min="0" style="width: 100%" />
|
<el-input-number v-model="form.sort" :min="0" style="width: 100%" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item v-if="!isAdd && resolvedUrl" label="当前解析地址">
|
<el-form-item v-if="!isAdd && resolvedUrl" label="兼容解析地址">
|
||||||
<el-link :href="resolvedUrl" type="primary" target="_blank">{{ resolvedUrl }}</el-link>
|
<el-link :href="resolvedUrl" type="primary" target="_blank">{{ resolvedUrl }}</el-link>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
@@ -125,6 +137,7 @@ const loading = ref(false);
|
|||||||
const saving = ref(false);
|
const saving = ref(false);
|
||||||
const uploading = ref(false);
|
const uploading = ref(false);
|
||||||
const uploadXHRActive = ref(false);
|
const uploadXHRActive = ref(false);
|
||||||
|
const uploadPlatform = ref("");
|
||||||
const uploadPercent = ref(0);
|
const uploadPercent = ref(0);
|
||||||
const uploadIndeterminate = ref(false);
|
const uploadIndeterminate = ref(false);
|
||||||
const uploadSpeedText = ref("—");
|
const uploadSpeedText = ref("—");
|
||||||
@@ -136,6 +149,12 @@ const uploadRef = ref(null);
|
|||||||
const displayFileList = ref([]);
|
const displayFileList = ref([]);
|
||||||
const uploadedLabel = ref("");
|
const uploadedLabel = ref("");
|
||||||
const appsUpgradeCateId = ref(null);
|
const appsUpgradeCateId = ref(null);
|
||||||
|
const platformOptions = [
|
||||||
|
{ label: "Windows", value: "windows" },
|
||||||
|
{ label: "macOS", value: "mac" },
|
||||||
|
{ label: "Ubuntu", value: "ubuntu" },
|
||||||
|
{ label: "Linux", value: "linux" },
|
||||||
|
];
|
||||||
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
id: 0,
|
id: 0,
|
||||||
@@ -144,6 +163,7 @@ const form = reactive({
|
|||||||
latestVersion: "0.0.1",
|
latestVersion: "0.0.1",
|
||||||
fileId: null,
|
fileId: null,
|
||||||
downloadUrl: "",
|
downloadUrl: "",
|
||||||
|
downloadUrls: {},
|
||||||
forceUpdate: 0,
|
forceUpdate: 0,
|
||||||
releaseNotes: "",
|
releaseNotes: "",
|
||||||
status: 1,
|
status: 1,
|
||||||
@@ -203,6 +223,21 @@ async function ensureAppsUpgradeCate() {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeDownloadUrls(value) {
|
||||||
|
if (!value) return {};
|
||||||
|
if (typeof value === "string") {
|
||||||
|
try {
|
||||||
|
return JSON.parse(value) || {};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof value === "object") {
|
||||||
|
return { ...value };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
form.id = 0;
|
form.id = 0;
|
||||||
form.name = "";
|
form.name = "";
|
||||||
@@ -210,6 +245,7 @@ function reset() {
|
|||||||
form.latestVersion = "0.0.1";
|
form.latestVersion = "0.0.1";
|
||||||
form.fileId = null;
|
form.fileId = null;
|
||||||
form.downloadUrl = "";
|
form.downloadUrl = "";
|
||||||
|
form.downloadUrls = {};
|
||||||
form.forceUpdate = 0;
|
form.forceUpdate = 0;
|
||||||
form.releaseNotes = "";
|
form.releaseNotes = "";
|
||||||
form.status = 1;
|
form.status = 1;
|
||||||
@@ -218,6 +254,7 @@ function reset() {
|
|||||||
displayFileList.value = [];
|
displayFileList.value = [];
|
||||||
uploadedLabel.value = "";
|
uploadedLabel.value = "";
|
||||||
uploadXHRActive.value = false;
|
uploadXHRActive.value = false;
|
||||||
|
uploadPlatform.value = "";
|
||||||
uploadPercent.value = 0;
|
uploadPercent.value = 0;
|
||||||
uploadIndeterminate.value = false;
|
uploadIndeterminate.value = false;
|
||||||
uploadSpeedText.value = "—";
|
uploadSpeedText.value = "—";
|
||||||
@@ -250,13 +287,14 @@ function onExceedReplace(files) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handlePackageUpload(options) {
|
async function handlePackageUpload(options, platform = "") {
|
||||||
const file = options.file?.raw != null ? options.file.raw : options.file;
|
const file = options.file?.raw != null ? options.file.raw : options.file;
|
||||||
if (!file) {
|
if (!file) {
|
||||||
options.onError?.(new Error("无文件"));
|
options.onError?.(new Error("无文件"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uploading.value = true;
|
uploading.value = true;
|
||||||
|
uploadPlatform.value = platform;
|
||||||
try {
|
try {
|
||||||
const cateId = await ensureAppsUpgradeCate();
|
const cateId = await ensureAppsUpgradeCate();
|
||||||
if (!cateId) {
|
if (!cateId) {
|
||||||
@@ -307,10 +345,14 @@ async function handlePackageUpload(options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 上传成功
|
// 上传成功
|
||||||
form.fileId = result.id;
|
if (platform) {
|
||||||
form.downloadUrl = result.url;
|
form.downloadUrls[platform] = result.url;
|
||||||
uploadedLabel.value = result.name || file.name || "安装包";
|
} else {
|
||||||
displayFileList.value = [{ name: uploadedLabel.value, uid: `pkg-${form.fileId}-${Date.now()}` }];
|
form.fileId = result.id;
|
||||||
|
form.downloadUrl = result.url;
|
||||||
|
uploadedLabel.value = result.name || file.name || "安装包";
|
||||||
|
displayFileList.value = [{ name: uploadedLabel.value, uid: `pkg-${form.fileId}-${Date.now()}` }];
|
||||||
|
}
|
||||||
ElMessage.success("上传成功");
|
ElMessage.success("上传成功");
|
||||||
options.onSuccess?.(result);
|
options.onSuccess?.(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -318,6 +360,7 @@ async function handlePackageUpload(options) {
|
|||||||
options.onError?.(e);
|
options.onError?.(e);
|
||||||
} finally {
|
} finally {
|
||||||
uploading.value = false;
|
uploading.value = false;
|
||||||
|
uploadPlatform.value = "";
|
||||||
uploadXHRActive.value = false;
|
uploadXHRActive.value = false;
|
||||||
uploadPercent.value = 0;
|
uploadPercent.value = 0;
|
||||||
uploadIndeterminate.value = false;
|
uploadIndeterminate.value = false;
|
||||||
@@ -349,6 +392,7 @@ async function open(id) {
|
|||||||
form.latestVersion = d.latestVersion || "0.0.1";
|
form.latestVersion = d.latestVersion || "0.0.1";
|
||||||
form.fileId = d.fileId != null ? Number(d.fileId) : null;
|
form.fileId = d.fileId != null ? Number(d.fileId) : null;
|
||||||
form.downloadUrl = d.downloadUrl || d.resolvedDownloadUrl || "";
|
form.downloadUrl = d.downloadUrl || d.resolvedDownloadUrl || "";
|
||||||
|
form.downloadUrls = normalizeDownloadUrls(d.downloadUrls || d.resolvedDownloadUrls);
|
||||||
form.forceUpdate = d.forceUpdate ? 1 : 0;
|
form.forceUpdate = d.forceUpdate ? 1 : 0;
|
||||||
form.releaseNotes = d.releaseNotes || "";
|
form.releaseNotes = d.releaseNotes || "";
|
||||||
form.status = d.status !== 0 ? 1 : 0;
|
form.status = d.status !== 0 ? 1 : 0;
|
||||||
@@ -381,11 +425,21 @@ async function submit() {
|
|||||||
} catch {
|
} catch {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const cleanDownloadUrls = {};
|
||||||
|
Object.entries(form.downloadUrls || {}).forEach(([platform, url]) => {
|
||||||
|
const key = String(platform || "").trim().toLowerCase();
|
||||||
|
const value = String(url || "").trim();
|
||||||
|
if (key && value) {
|
||||||
|
cleanDownloadUrls[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
name: form.name.trim(),
|
name: form.name.trim(),
|
||||||
code: form.code.trim(),
|
code: form.code.trim(),
|
||||||
latestVersion: form.latestVersion.trim(),
|
latestVersion: form.latestVersion.trim(),
|
||||||
downloadUrl: form.downloadUrl.trim() || undefined,
|
downloadUrl: form.downloadUrl.trim() || undefined,
|
||||||
|
downloadUrls: cleanDownloadUrls,
|
||||||
forceUpdate: form.forceUpdate,
|
forceUpdate: form.forceUpdate,
|
||||||
releaseNotes: form.releaseNotes.trim() || undefined,
|
releaseNotes: form.releaseNotes.trim() || undefined,
|
||||||
status: form.status,
|
status: form.status,
|
||||||
@@ -432,6 +486,20 @@ defineExpose({ open });
|
|||||||
background: var(--el-fill-color-light);
|
background: var(--el-fill-color-light);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
.platform-package-list {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.platform-package-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 86px 1fr auto;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.platform-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
.pkg-upload {
|
.pkg-upload {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,10 +41,24 @@
|
|||||||
<el-table-column prop="name" label="软件名称" min-width="140" />
|
<el-table-column prop="name" label="软件名称" min-width="140" />
|
||||||
<el-table-column prop="code" label="产品code" width="140" />
|
<el-table-column prop="code" label="产品code" width="140" />
|
||||||
<el-table-column prop="latestVersion" label="最新版本" width="100" align="center" />
|
<el-table-column prop="latestVersion" label="最新版本" width="100" align="center" />
|
||||||
<el-table-column label="文件 ID" width="88" align="center">
|
<el-table-column label="平台包" min-width="260">
|
||||||
<template #default="{ row }">{{ row.fileId ?? "—" }}</template>
|
<template #default="{ row }">
|
||||||
|
<div v-if="Object.keys(normalizeDownloadUrls(row.resolvedDownloadUrls || row.downloadUrls)).length" class="platform-url-list">
|
||||||
|
<el-tag
|
||||||
|
v-for="(url, platform) in normalizeDownloadUrls(row.resolvedDownloadUrls || row.downloadUrls)"
|
||||||
|
:key="platform"
|
||||||
|
effect="plain"
|
||||||
|
class="platform-url-tag"
|
||||||
|
>
|
||||||
|
<el-link :href="url" type="primary" target="_blank" :underline="false">
|
||||||
|
{{ platform }}
|
||||||
|
</el-link>
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<span v-else class="muted">—</span>
|
||||||
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="解析下载地址" min-width="200" show-overflow-tooltip>
|
<el-table-column label="兼容下载地址" min-width="200" show-overflow-tooltip>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-link v-if="row.resolvedDownloadUrl" :href="row.resolvedDownloadUrl" type="primary" target="_blank">
|
<el-link v-if="row.resolvedDownloadUrl" :href="row.resolvedDownloadUrl" type="primary" target="_blank">
|
||||||
{{ row.resolvedDownloadUrl }}
|
{{ row.resolvedDownloadUrl }}
|
||||||
@@ -98,12 +112,14 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><code>code</code>(必填):与后台配置的「产品标识」一致</li>
|
<li><code>code</code>(必填):与后台配置的「产品标识」一致</li>
|
||||||
<li><code>version</code>(可选):当前客户端版本,缺省按 <code>0.0.0</code></li>
|
<li><code>version</code>(可选):当前客户端版本,缺省按 <code>0.0.0</code></li>
|
||||||
|
<li><code>platform</code>(可选):客户端运行环境,如 <code>windows</code>、<code>mac</code>、<code>ubuntu</code>、<code>linux</code>;客户端也可以自行从 <code>downloadUrls</code> 取对应平台 URL</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>响应 <code>data</code> 字段说明:</p>
|
<p>响应 <code>data</code> 字段说明:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>upToDate</code>:是否已是最新(当前版本 ≥ 后台最新版本)</li>
|
<li><code>upToDate</code>:是否已是最新(当前版本 ≥ 后台最新版本)</li>
|
||||||
<li><code>latestVersion</code>:后台配置的最新版本号</li>
|
<li><code>latestVersion</code>:后台配置的最新版本号</li>
|
||||||
<li><code>downloadUrl</code>:安装包地址(自定义 URL 或由文件 ID 解析)</li>
|
<li><code>downloadUrl</code>:兼容旧客户端的单安装包地址(自定义 URL 或由文件 ID 解析)</li>
|
||||||
|
<li><code>downloadUrls</code>:多平台安装包地址,如 <code>windows</code>、<code>mac</code>、<code>ubuntu</code>、<code>linux</code></li>
|
||||||
<li><code>forceUpdate</code>:是否建议强制更新</li>
|
<li><code>forceUpdate</code>:是否建议强制更新</li>
|
||||||
<li><code>releaseNotes</code>:更新说明</li>
|
<li><code>releaseNotes</code>:更新说明</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -147,6 +163,21 @@ const list = ref([]);
|
|||||||
const searchForm = reactive({ keyword: "" });
|
const searchForm = reactive({ keyword: "" });
|
||||||
const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
|
const pagination = reactive({ page: 1, pageSize: 20, total: 0 });
|
||||||
|
|
||||||
|
function normalizeDownloadUrls(value) {
|
||||||
|
if (!value) return {};
|
||||||
|
if (typeof value === "string") {
|
||||||
|
try {
|
||||||
|
return JSON.parse(value) || {};
|
||||||
|
} catch {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof value === "object") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
async function fetchList() {
|
async function fetchList() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
@@ -222,6 +253,14 @@ onMounted(() => {
|
|||||||
.muted {
|
.muted {
|
||||||
color: var(--el-text-color-placeholder);
|
color: var(--el-text-color-placeholder);
|
||||||
}
|
}
|
||||||
|
.platform-url-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.platform-url-tag {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
.api-doc {
|
.api-doc {
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
Reference in New Issue
Block a user